xref: /dpdk/app/test-pmd/cmdline_flow.c (revision 665b49c51639a10c553433bc2bcd85c7331c631e)
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 <stdlib.h>
10 #include <inttypes.h>
11 #include <errno.h>
12 #include <ctype.h>
13 #include <string.h>
14 
15 #include <rte_string_fns.h>
16 #include <rte_common.h>
17 #include <rte_ethdev.h>
18 #include <rte_byteorder.h>
19 #include <cmdline_parse.h>
20 #include <cmdline_parse_etheraddr.h>
21 #include <cmdline_parse_string.h>
22 #include <cmdline_parse_num.h>
23 #include <rte_flow.h>
24 #include <rte_hexdump.h>
25 #include <rte_vxlan.h>
26 #include <rte_gre.h>
27 #include <rte_mpls.h>
28 #include <rte_gtp.h>
29 #include <rte_geneve.h>
30 
31 #include "testpmd.h"
32 
33 /** Parser token indices. */
34 enum index {
35 	/* Special tokens. */
36 	ZERO = 0,
37 	END,
38 	START_SET,
39 	END_SET,
40 
41 	/* Common tokens. */
42 	COMMON_INTEGER,
43 	COMMON_UNSIGNED,
44 	COMMON_PREFIX,
45 	COMMON_BOOLEAN,
46 	COMMON_STRING,
47 	COMMON_HEX,
48 	COMMON_FILE_PATH,
49 	COMMON_MAC_ADDR,
50 	COMMON_IPV4_ADDR,
51 	COMMON_IPV6_ADDR,
52 	COMMON_RULE_ID,
53 	COMMON_PORT_ID,
54 	COMMON_GROUP_ID,
55 	COMMON_PRIORITY_LEVEL,
56 	COMMON_INDIRECT_ACTION_ID,
57 	COMMON_PROFILE_ID,
58 	COMMON_POLICY_ID,
59 	COMMON_FLEX_HANDLE,
60 	COMMON_FLEX_TOKEN,
61 	COMMON_PATTERN_TEMPLATE_ID,
62 	COMMON_ACTIONS_TEMPLATE_ID,
63 	COMMON_TABLE_ID,
64 	COMMON_QUEUE_ID,
65 
66 	/* TOP-level command. */
67 	ADD,
68 
69 	/* Top-level command. */
70 	SET,
71 	/* Sub-leve commands. */
72 	SET_RAW_ENCAP,
73 	SET_RAW_DECAP,
74 	SET_RAW_INDEX,
75 	SET_SAMPLE_ACTIONS,
76 	SET_SAMPLE_INDEX,
77 
78 	/* Top-level command. */
79 	FLOW,
80 	/* Sub-level commands. */
81 	INFO,
82 	CONFIGURE,
83 	PATTERN_TEMPLATE,
84 	ACTIONS_TEMPLATE,
85 	TABLE,
86 	INDIRECT_ACTION,
87 	VALIDATE,
88 	CREATE,
89 	DESTROY,
90 	FLUSH,
91 	DUMP,
92 	QUERY,
93 	LIST,
94 	AGED,
95 	ISOLATE,
96 	TUNNEL,
97 	FLEX,
98 	QUEUE,
99 	PUSH,
100 	PULL,
101 
102 	/* Flex arguments */
103 	FLEX_ITEM_INIT,
104 	FLEX_ITEM_CREATE,
105 	FLEX_ITEM_DESTROY,
106 
107 	/* Pattern template arguments. */
108 	PATTERN_TEMPLATE_CREATE,
109 	PATTERN_TEMPLATE_DESTROY,
110 	PATTERN_TEMPLATE_CREATE_ID,
111 	PATTERN_TEMPLATE_DESTROY_ID,
112 	PATTERN_TEMPLATE_RELAXED_MATCHING,
113 	PATTERN_TEMPLATE_INGRESS,
114 	PATTERN_TEMPLATE_EGRESS,
115 	PATTERN_TEMPLATE_TRANSFER,
116 	PATTERN_TEMPLATE_SPEC,
117 
118 	/* Actions template arguments. */
119 	ACTIONS_TEMPLATE_CREATE,
120 	ACTIONS_TEMPLATE_DESTROY,
121 	ACTIONS_TEMPLATE_CREATE_ID,
122 	ACTIONS_TEMPLATE_DESTROY_ID,
123 	ACTIONS_TEMPLATE_INGRESS,
124 	ACTIONS_TEMPLATE_EGRESS,
125 	ACTIONS_TEMPLATE_TRANSFER,
126 	ACTIONS_TEMPLATE_SPEC,
127 	ACTIONS_TEMPLATE_MASK,
128 
129 	/* Queue arguments. */
130 	QUEUE_CREATE,
131 	QUEUE_DESTROY,
132 	QUEUE_AGED,
133 	QUEUE_INDIRECT_ACTION,
134 
135 	/* Queue create arguments. */
136 	QUEUE_CREATE_POSTPONE,
137 	QUEUE_TEMPLATE_TABLE,
138 	QUEUE_PATTERN_TEMPLATE,
139 	QUEUE_ACTIONS_TEMPLATE,
140 	QUEUE_RULE_ID,
141 
142 	/* Queue destroy arguments. */
143 	QUEUE_DESTROY_ID,
144 	QUEUE_DESTROY_POSTPONE,
145 
146 	/* Queue indirect action arguments */
147 	QUEUE_INDIRECT_ACTION_CREATE,
148 	QUEUE_INDIRECT_ACTION_UPDATE,
149 	QUEUE_INDIRECT_ACTION_DESTROY,
150 	QUEUE_INDIRECT_ACTION_QUERY,
151 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
152 
153 	/* Queue indirect action create arguments */
154 	QUEUE_INDIRECT_ACTION_CREATE_ID,
155 	QUEUE_INDIRECT_ACTION_INGRESS,
156 	QUEUE_INDIRECT_ACTION_EGRESS,
157 	QUEUE_INDIRECT_ACTION_TRANSFER,
158 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
159 	QUEUE_INDIRECT_ACTION_SPEC,
160 
161 	/* Queue indirect action update arguments */
162 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
163 
164 	/* Queue indirect action destroy arguments */
165 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
166 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
167 
168 	/* Queue indirect action query arguments */
169 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
170 
171 	/* Queue indirect action query_update arguments */
172 	QUEUE_INDIRECT_ACTION_QU_MODE,
173 
174 	/* Push arguments. */
175 	PUSH_QUEUE,
176 
177 	/* Pull arguments. */
178 	PULL_QUEUE,
179 
180 	/* Table arguments. */
181 	TABLE_CREATE,
182 	TABLE_DESTROY,
183 	TABLE_CREATE_ID,
184 	TABLE_DESTROY_ID,
185 	TABLE_INSERTION_TYPE,
186 	TABLE_INSERTION_TYPE_NAME,
187 	TABLE_HASH_FUNC,
188 	TABLE_HASH_FUNC_NAME,
189 	TABLE_GROUP,
190 	TABLE_PRIORITY,
191 	TABLE_INGRESS,
192 	TABLE_EGRESS,
193 	TABLE_TRANSFER,
194 	TABLE_TRANSFER_WIRE_ORIG,
195 	TABLE_TRANSFER_VPORT_ORIG,
196 	TABLE_RULES_NUMBER,
197 	TABLE_PATTERN_TEMPLATE,
198 	TABLE_ACTIONS_TEMPLATE,
199 
200 	/* Tunnel arguments. */
201 	TUNNEL_CREATE,
202 	TUNNEL_CREATE_TYPE,
203 	TUNNEL_LIST,
204 	TUNNEL_DESTROY,
205 	TUNNEL_DESTROY_ID,
206 
207 	/* Destroy arguments. */
208 	DESTROY_RULE,
209 
210 	/* Query arguments. */
211 	QUERY_ACTION,
212 
213 	/* List arguments. */
214 	LIST_GROUP,
215 
216 	/* Destroy aged flow arguments. */
217 	AGED_DESTROY,
218 
219 	/* Validate/create arguments. */
220 	VC_GROUP,
221 	VC_PRIORITY,
222 	VC_INGRESS,
223 	VC_EGRESS,
224 	VC_TRANSFER,
225 	VC_TUNNEL_SET,
226 	VC_TUNNEL_MATCH,
227 
228 	/* Dump arguments */
229 	DUMP_ALL,
230 	DUMP_ONE,
231 
232 	/* Configure arguments */
233 	CONFIG_QUEUES_NUMBER,
234 	CONFIG_QUEUES_SIZE,
235 	CONFIG_COUNTERS_NUMBER,
236 	CONFIG_AGING_OBJECTS_NUMBER,
237 	CONFIG_METERS_NUMBER,
238 	CONFIG_CONN_TRACK_NUMBER,
239 	CONFIG_QUOTAS_NUMBER,
240 	CONFIG_FLAGS,
241 	CONFIG_HOST_PORT,
242 
243 	/* Indirect action arguments */
244 	INDIRECT_ACTION_CREATE,
245 	INDIRECT_ACTION_UPDATE,
246 	INDIRECT_ACTION_DESTROY,
247 	INDIRECT_ACTION_QUERY,
248 	INDIRECT_ACTION_QUERY_UPDATE,
249 
250 	/* Indirect action create arguments */
251 	INDIRECT_ACTION_CREATE_ID,
252 	INDIRECT_ACTION_INGRESS,
253 	INDIRECT_ACTION_EGRESS,
254 	INDIRECT_ACTION_TRANSFER,
255 	INDIRECT_ACTION_SPEC,
256 
257 	/* Indirect action destroy arguments */
258 	INDIRECT_ACTION_DESTROY_ID,
259 
260 	/* Indirect action query-and-update arguments */
261 	INDIRECT_ACTION_QU_MODE,
262 	INDIRECT_ACTION_QU_MODE_NAME,
263 
264 	/* Validate/create pattern. */
265 	ITEM_PATTERN,
266 	ITEM_PARAM_IS,
267 	ITEM_PARAM_SPEC,
268 	ITEM_PARAM_LAST,
269 	ITEM_PARAM_MASK,
270 	ITEM_PARAM_PREFIX,
271 	ITEM_NEXT,
272 	ITEM_END,
273 	ITEM_VOID,
274 	ITEM_INVERT,
275 	ITEM_ANY,
276 	ITEM_ANY_NUM,
277 	ITEM_PORT_ID,
278 	ITEM_PORT_ID_ID,
279 	ITEM_MARK,
280 	ITEM_MARK_ID,
281 	ITEM_RAW,
282 	ITEM_RAW_RELATIVE,
283 	ITEM_RAW_SEARCH,
284 	ITEM_RAW_OFFSET,
285 	ITEM_RAW_LIMIT,
286 	ITEM_RAW_PATTERN,
287 	ITEM_RAW_PATTERN_HEX,
288 	ITEM_ETH,
289 	ITEM_ETH_DST,
290 	ITEM_ETH_SRC,
291 	ITEM_ETH_TYPE,
292 	ITEM_ETH_HAS_VLAN,
293 	ITEM_VLAN,
294 	ITEM_VLAN_TCI,
295 	ITEM_VLAN_PCP,
296 	ITEM_VLAN_DEI,
297 	ITEM_VLAN_VID,
298 	ITEM_VLAN_INNER_TYPE,
299 	ITEM_VLAN_HAS_MORE_VLAN,
300 	ITEM_IPV4,
301 	ITEM_IPV4_VER_IHL,
302 	ITEM_IPV4_TOS,
303 	ITEM_IPV4_ID,
304 	ITEM_IPV4_FRAGMENT_OFFSET,
305 	ITEM_IPV4_TTL,
306 	ITEM_IPV4_PROTO,
307 	ITEM_IPV4_SRC,
308 	ITEM_IPV4_DST,
309 	ITEM_IPV6,
310 	ITEM_IPV6_TC,
311 	ITEM_IPV6_FLOW,
312 	ITEM_IPV6_PROTO,
313 	ITEM_IPV6_HOP,
314 	ITEM_IPV6_SRC,
315 	ITEM_IPV6_DST,
316 	ITEM_IPV6_HAS_FRAG_EXT,
317 	ITEM_IPV6_ROUTING_EXT,
318 	ITEM_IPV6_ROUTING_EXT_TYPE,
319 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
320 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
321 	ITEM_ICMP,
322 	ITEM_ICMP_TYPE,
323 	ITEM_ICMP_CODE,
324 	ITEM_ICMP_IDENT,
325 	ITEM_ICMP_SEQ,
326 	ITEM_UDP,
327 	ITEM_UDP_SRC,
328 	ITEM_UDP_DST,
329 	ITEM_TCP,
330 	ITEM_TCP_SRC,
331 	ITEM_TCP_DST,
332 	ITEM_TCP_FLAGS,
333 	ITEM_SCTP,
334 	ITEM_SCTP_SRC,
335 	ITEM_SCTP_DST,
336 	ITEM_SCTP_TAG,
337 	ITEM_SCTP_CKSUM,
338 	ITEM_VXLAN,
339 	ITEM_VXLAN_VNI,
340 	ITEM_VXLAN_LAST_RSVD,
341 	ITEM_E_TAG,
342 	ITEM_E_TAG_GRP_ECID_B,
343 	ITEM_NVGRE,
344 	ITEM_NVGRE_TNI,
345 	ITEM_MPLS,
346 	ITEM_MPLS_LABEL,
347 	ITEM_MPLS_TC,
348 	ITEM_MPLS_S,
349 	ITEM_GRE,
350 	ITEM_GRE_PROTO,
351 	ITEM_GRE_C_RSVD0_VER,
352 	ITEM_GRE_C_BIT,
353 	ITEM_GRE_K_BIT,
354 	ITEM_GRE_S_BIT,
355 	ITEM_FUZZY,
356 	ITEM_FUZZY_THRESH,
357 	ITEM_GTP,
358 	ITEM_GTP_FLAGS,
359 	ITEM_GTP_MSG_TYPE,
360 	ITEM_GTP_TEID,
361 	ITEM_GTPC,
362 	ITEM_GTPU,
363 	ITEM_GENEVE,
364 	ITEM_GENEVE_VNI,
365 	ITEM_GENEVE_PROTO,
366 	ITEM_GENEVE_OPTLEN,
367 	ITEM_VXLAN_GPE,
368 	ITEM_VXLAN_GPE_VNI,
369 	ITEM_ARP_ETH_IPV4,
370 	ITEM_ARP_ETH_IPV4_SHA,
371 	ITEM_ARP_ETH_IPV4_SPA,
372 	ITEM_ARP_ETH_IPV4_THA,
373 	ITEM_ARP_ETH_IPV4_TPA,
374 	ITEM_IPV6_EXT,
375 	ITEM_IPV6_EXT_NEXT_HDR,
376 	ITEM_IPV6_FRAG_EXT,
377 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
378 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
379 	ITEM_IPV6_FRAG_EXT_ID,
380 	ITEM_ICMP6,
381 	ITEM_ICMP6_TYPE,
382 	ITEM_ICMP6_CODE,
383 	ITEM_ICMP6_ECHO_REQUEST,
384 	ITEM_ICMP6_ECHO_REQUEST_ID,
385 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
386 	ITEM_ICMP6_ECHO_REPLY,
387 	ITEM_ICMP6_ECHO_REPLY_ID,
388 	ITEM_ICMP6_ECHO_REPLY_SEQ,
389 	ITEM_ICMP6_ND_NS,
390 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
391 	ITEM_ICMP6_ND_NA,
392 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
393 	ITEM_ICMP6_ND_OPT,
394 	ITEM_ICMP6_ND_OPT_TYPE,
395 	ITEM_ICMP6_ND_OPT_SLA_ETH,
396 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
397 	ITEM_ICMP6_ND_OPT_TLA_ETH,
398 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
399 	ITEM_META,
400 	ITEM_META_DATA,
401 	ITEM_GRE_KEY,
402 	ITEM_GRE_KEY_VALUE,
403 	ITEM_GRE_OPTION,
404 	ITEM_GRE_OPTION_CHECKSUM,
405 	ITEM_GRE_OPTION_KEY,
406 	ITEM_GRE_OPTION_SEQUENCE,
407 	ITEM_GTP_PSC,
408 	ITEM_GTP_PSC_QFI,
409 	ITEM_GTP_PSC_PDU_T,
410 	ITEM_PPPOES,
411 	ITEM_PPPOED,
412 	ITEM_PPPOE_SEID,
413 	ITEM_PPPOE_PROTO_ID,
414 	ITEM_HIGIG2,
415 	ITEM_HIGIG2_CLASSIFICATION,
416 	ITEM_HIGIG2_VID,
417 	ITEM_TAG,
418 	ITEM_TAG_DATA,
419 	ITEM_TAG_INDEX,
420 	ITEM_L2TPV3OIP,
421 	ITEM_L2TPV3OIP_SESSION_ID,
422 	ITEM_ESP,
423 	ITEM_ESP_SPI,
424 	ITEM_AH,
425 	ITEM_AH_SPI,
426 	ITEM_PFCP,
427 	ITEM_PFCP_S_FIELD,
428 	ITEM_PFCP_SEID,
429 	ITEM_ECPRI,
430 	ITEM_ECPRI_COMMON,
431 	ITEM_ECPRI_COMMON_TYPE,
432 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
433 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
434 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
435 	ITEM_ECPRI_MSG_IQ_DATA_PCID,
436 	ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
437 	ITEM_ECPRI_MSG_DLY_MSR_MSRID,
438 	ITEM_GENEVE_OPT,
439 	ITEM_GENEVE_OPT_CLASS,
440 	ITEM_GENEVE_OPT_TYPE,
441 	ITEM_GENEVE_OPT_LENGTH,
442 	ITEM_GENEVE_OPT_DATA,
443 	ITEM_INTEGRITY,
444 	ITEM_INTEGRITY_LEVEL,
445 	ITEM_INTEGRITY_VALUE,
446 	ITEM_CONNTRACK,
447 	ITEM_POL_PORT,
448 	ITEM_POL_METER,
449 	ITEM_POL_POLICY,
450 	ITEM_PORT_REPRESENTOR,
451 	ITEM_PORT_REPRESENTOR_PORT_ID,
452 	ITEM_REPRESENTED_PORT,
453 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
454 	ITEM_FLEX,
455 	ITEM_FLEX_ITEM_HANDLE,
456 	ITEM_FLEX_PATTERN_HANDLE,
457 	ITEM_L2TPV2,
458 	ITEM_L2TPV2_TYPE,
459 	ITEM_L2TPV2_TYPE_DATA,
460 	ITEM_L2TPV2_TYPE_DATA_L,
461 	ITEM_L2TPV2_TYPE_DATA_S,
462 	ITEM_L2TPV2_TYPE_DATA_O,
463 	ITEM_L2TPV2_TYPE_DATA_L_S,
464 	ITEM_L2TPV2_TYPE_CTRL,
465 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
466 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
467 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
468 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
469 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
470 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
471 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
472 	ITEM_L2TPV2_MSG_DATA_S_NS,
473 	ITEM_L2TPV2_MSG_DATA_S_NR,
474 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
475 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
476 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
477 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
478 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
479 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
480 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
481 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
482 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
483 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
484 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
485 	ITEM_L2TPV2_MSG_CTRL_NS,
486 	ITEM_L2TPV2_MSG_CTRL_NR,
487 	ITEM_PPP,
488 	ITEM_PPP_ADDR,
489 	ITEM_PPP_CTRL,
490 	ITEM_PPP_PROTO_ID,
491 	ITEM_METER,
492 	ITEM_METER_COLOR,
493 	ITEM_METER_COLOR_NAME,
494 	ITEM_QUOTA,
495 	ITEM_QUOTA_STATE,
496 	ITEM_QUOTA_STATE_NAME,
497 	ITEM_AGGR_AFFINITY,
498 	ITEM_AGGR_AFFINITY_VALUE,
499 
500 	/* Validate/create actions. */
501 	ACTIONS,
502 	ACTION_NEXT,
503 	ACTION_END,
504 	ACTION_VOID,
505 	ACTION_PASSTHRU,
506 	ACTION_SKIP_CMAN,
507 	ACTION_JUMP,
508 	ACTION_JUMP_GROUP,
509 	ACTION_MARK,
510 	ACTION_MARK_ID,
511 	ACTION_FLAG,
512 	ACTION_QUEUE,
513 	ACTION_QUEUE_INDEX,
514 	ACTION_DROP,
515 	ACTION_COUNT,
516 	ACTION_COUNT_ID,
517 	ACTION_RSS,
518 	ACTION_RSS_FUNC,
519 	ACTION_RSS_LEVEL,
520 	ACTION_RSS_FUNC_DEFAULT,
521 	ACTION_RSS_FUNC_TOEPLITZ,
522 	ACTION_RSS_FUNC_SIMPLE_XOR,
523 	ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
524 	ACTION_RSS_TYPES,
525 	ACTION_RSS_TYPE,
526 	ACTION_RSS_KEY,
527 	ACTION_RSS_KEY_LEN,
528 	ACTION_RSS_QUEUES,
529 	ACTION_RSS_QUEUE,
530 	ACTION_PF,
531 	ACTION_VF,
532 	ACTION_VF_ORIGINAL,
533 	ACTION_VF_ID,
534 	ACTION_PORT_ID,
535 	ACTION_PORT_ID_ORIGINAL,
536 	ACTION_PORT_ID_ID,
537 	ACTION_METER,
538 	ACTION_METER_COLOR,
539 	ACTION_METER_COLOR_TYPE,
540 	ACTION_METER_COLOR_GREEN,
541 	ACTION_METER_COLOR_YELLOW,
542 	ACTION_METER_COLOR_RED,
543 	ACTION_METER_ID,
544 	ACTION_METER_MARK,
545 	ACTION_METER_PROFILE,
546 	ACTION_METER_PROFILE_ID2PTR,
547 	ACTION_METER_POLICY,
548 	ACTION_METER_POLICY_ID2PTR,
549 	ACTION_METER_COLOR_MODE,
550 	ACTION_METER_INIT_COLOR,
551 	ACTION_METER_STATE,
552 	ACTION_OF_DEC_NW_TTL,
553 	ACTION_OF_POP_VLAN,
554 	ACTION_OF_PUSH_VLAN,
555 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
556 	ACTION_OF_SET_VLAN_VID,
557 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
558 	ACTION_OF_SET_VLAN_PCP,
559 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
560 	ACTION_OF_POP_MPLS,
561 	ACTION_OF_POP_MPLS_ETHERTYPE,
562 	ACTION_OF_PUSH_MPLS,
563 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
564 	ACTION_VXLAN_ENCAP,
565 	ACTION_VXLAN_DECAP,
566 	ACTION_NVGRE_ENCAP,
567 	ACTION_NVGRE_DECAP,
568 	ACTION_L2_ENCAP,
569 	ACTION_L2_DECAP,
570 	ACTION_MPLSOGRE_ENCAP,
571 	ACTION_MPLSOGRE_DECAP,
572 	ACTION_MPLSOUDP_ENCAP,
573 	ACTION_MPLSOUDP_DECAP,
574 	ACTION_SET_IPV4_SRC,
575 	ACTION_SET_IPV4_SRC_IPV4_SRC,
576 	ACTION_SET_IPV4_DST,
577 	ACTION_SET_IPV4_DST_IPV4_DST,
578 	ACTION_SET_IPV6_SRC,
579 	ACTION_SET_IPV6_SRC_IPV6_SRC,
580 	ACTION_SET_IPV6_DST,
581 	ACTION_SET_IPV6_DST_IPV6_DST,
582 	ACTION_SET_TP_SRC,
583 	ACTION_SET_TP_SRC_TP_SRC,
584 	ACTION_SET_TP_DST,
585 	ACTION_SET_TP_DST_TP_DST,
586 	ACTION_MAC_SWAP,
587 	ACTION_DEC_TTL,
588 	ACTION_SET_TTL,
589 	ACTION_SET_TTL_TTL,
590 	ACTION_SET_MAC_SRC,
591 	ACTION_SET_MAC_SRC_MAC_SRC,
592 	ACTION_SET_MAC_DST,
593 	ACTION_SET_MAC_DST_MAC_DST,
594 	ACTION_INC_TCP_SEQ,
595 	ACTION_INC_TCP_SEQ_VALUE,
596 	ACTION_DEC_TCP_SEQ,
597 	ACTION_DEC_TCP_SEQ_VALUE,
598 	ACTION_INC_TCP_ACK,
599 	ACTION_INC_TCP_ACK_VALUE,
600 	ACTION_DEC_TCP_ACK,
601 	ACTION_DEC_TCP_ACK_VALUE,
602 	ACTION_RAW_ENCAP,
603 	ACTION_RAW_DECAP,
604 	ACTION_RAW_ENCAP_INDEX,
605 	ACTION_RAW_ENCAP_INDEX_VALUE,
606 	ACTION_RAW_DECAP_INDEX,
607 	ACTION_RAW_DECAP_INDEX_VALUE,
608 	ACTION_SET_TAG,
609 	ACTION_SET_TAG_DATA,
610 	ACTION_SET_TAG_INDEX,
611 	ACTION_SET_TAG_MASK,
612 	ACTION_SET_META,
613 	ACTION_SET_META_DATA,
614 	ACTION_SET_META_MASK,
615 	ACTION_SET_IPV4_DSCP,
616 	ACTION_SET_IPV4_DSCP_VALUE,
617 	ACTION_SET_IPV6_DSCP,
618 	ACTION_SET_IPV6_DSCP_VALUE,
619 	ACTION_AGE,
620 	ACTION_AGE_TIMEOUT,
621 	ACTION_AGE_UPDATE,
622 	ACTION_AGE_UPDATE_TIMEOUT,
623 	ACTION_AGE_UPDATE_TOUCH,
624 	ACTION_SAMPLE,
625 	ACTION_SAMPLE_RATIO,
626 	ACTION_SAMPLE_INDEX,
627 	ACTION_SAMPLE_INDEX_VALUE,
628 	ACTION_INDIRECT,
629 	ACTION_SHARED_INDIRECT,
630 	INDIRECT_ACTION_PORT,
631 	INDIRECT_ACTION_ID2PTR,
632 	ACTION_MODIFY_FIELD,
633 	ACTION_MODIFY_FIELD_OP,
634 	ACTION_MODIFY_FIELD_OP_VALUE,
635 	ACTION_MODIFY_FIELD_DST_TYPE,
636 	ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
637 	ACTION_MODIFY_FIELD_DST_LEVEL,
638 	ACTION_MODIFY_FIELD_DST_LEVEL_VALUE,
639 	ACTION_MODIFY_FIELD_DST_OFFSET,
640 	ACTION_MODIFY_FIELD_SRC_TYPE,
641 	ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
642 	ACTION_MODIFY_FIELD_SRC_LEVEL,
643 	ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE,
644 	ACTION_MODIFY_FIELD_SRC_OFFSET,
645 	ACTION_MODIFY_FIELD_SRC_VALUE,
646 	ACTION_MODIFY_FIELD_SRC_POINTER,
647 	ACTION_MODIFY_FIELD_WIDTH,
648 	ACTION_CONNTRACK,
649 	ACTION_CONNTRACK_UPDATE,
650 	ACTION_CONNTRACK_UPDATE_DIR,
651 	ACTION_CONNTRACK_UPDATE_CTX,
652 	ACTION_POL_G,
653 	ACTION_POL_Y,
654 	ACTION_POL_R,
655 	ACTION_PORT_REPRESENTOR,
656 	ACTION_PORT_REPRESENTOR_PORT_ID,
657 	ACTION_REPRESENTED_PORT,
658 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
659 	ACTION_SEND_TO_KERNEL,
660 	ACTION_QUOTA_CREATE,
661 	ACTION_QUOTA_CREATE_LIMIT,
662 	ACTION_QUOTA_CREATE_MODE,
663 	ACTION_QUOTA_CREATE_MODE_NAME,
664 	ACTION_QUOTA_QU,
665 	ACTION_QUOTA_QU_LIMIT,
666 	ACTION_QUOTA_QU_UPDATE_OP,
667 	ACTION_QUOTA_QU_UPDATE_OP_NAME,
668 };
669 
670 /** Maximum size for pattern in struct rte_flow_item_raw. */
671 #define ITEM_RAW_PATTERN_SIZE 512
672 
673 /** Maximum size for GENEVE option data pattern in bytes. */
674 #define ITEM_GENEVE_OPT_DATA_SIZE 124
675 
676 /** Storage size for struct rte_flow_item_raw including pattern. */
677 #define ITEM_RAW_SIZE \
678 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
679 
680 /** Maximum size for external pattern in struct rte_flow_action_modify_data. */
681 #define ACTION_MODIFY_PATTERN_SIZE 32
682 
683 /** Storage size for struct rte_flow_action_modify_field including pattern. */
684 #define ACTION_MODIFY_SIZE \
685 	(sizeof(struct rte_flow_action_modify_field) + \
686 	ACTION_MODIFY_PATTERN_SIZE)
687 
688 /** Maximum number of queue indices in struct rte_flow_action_rss. */
689 #define ACTION_RSS_QUEUE_NUM 128
690 
691 /** Storage for struct rte_flow_action_rss including external data. */
692 struct action_rss_data {
693 	struct rte_flow_action_rss conf;
694 	uint8_t key[RSS_HASH_KEY_LENGTH];
695 	uint16_t queue[ACTION_RSS_QUEUE_NUM];
696 };
697 
698 /** Maximum data size in struct rte_flow_action_raw_encap. */
699 #define ACTION_RAW_ENCAP_MAX_DATA 512
700 #define RAW_ENCAP_CONFS_MAX_NUM 8
701 
702 /** Storage for struct rte_flow_action_raw_encap. */
703 struct raw_encap_conf {
704 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
705 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
706 	size_t size;
707 };
708 
709 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
710 
711 /** Storage for struct rte_flow_action_raw_encap including external data. */
712 struct action_raw_encap_data {
713 	struct rte_flow_action_raw_encap conf;
714 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
715 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
716 	uint16_t idx;
717 };
718 
719 /** Storage for struct rte_flow_action_raw_decap. */
720 struct raw_decap_conf {
721 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
722 	size_t size;
723 };
724 
725 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
726 
727 /** Storage for struct rte_flow_action_raw_decap including external data. */
728 struct action_raw_decap_data {
729 	struct rte_flow_action_raw_decap conf;
730 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
731 	uint16_t idx;
732 };
733 
734 struct vxlan_encap_conf vxlan_encap_conf = {
735 	.select_ipv4 = 1,
736 	.select_vlan = 0,
737 	.select_tos_ttl = 0,
738 	.vni = "\x00\x00\x00",
739 	.udp_src = 0,
740 	.udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
741 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
742 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
743 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
744 		"\x00\x00\x00\x00\x00\x00\x00\x01",
745 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
746 		"\x00\x00\x00\x00\x00\x00\x11\x11",
747 	.vlan_tci = 0,
748 	.ip_tos = 0,
749 	.ip_ttl = 255,
750 	.eth_src = "\x00\x00\x00\x00\x00\x00",
751 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
752 };
753 
754 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
755 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
756 
757 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
758 struct action_vxlan_encap_data {
759 	struct rte_flow_action_vxlan_encap conf;
760 	struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
761 	struct rte_flow_item_eth item_eth;
762 	struct rte_flow_item_vlan item_vlan;
763 	union {
764 		struct rte_flow_item_ipv4 item_ipv4;
765 		struct rte_flow_item_ipv6 item_ipv6;
766 	};
767 	struct rte_flow_item_udp item_udp;
768 	struct rte_flow_item_vxlan item_vxlan;
769 };
770 
771 struct nvgre_encap_conf nvgre_encap_conf = {
772 	.select_ipv4 = 1,
773 	.select_vlan = 0,
774 	.tni = "\x00\x00\x00",
775 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
776 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
777 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
778 		"\x00\x00\x00\x00\x00\x00\x00\x01",
779 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
780 		"\x00\x00\x00\x00\x00\x00\x11\x11",
781 	.vlan_tci = 0,
782 	.eth_src = "\x00\x00\x00\x00\x00\x00",
783 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
784 };
785 
786 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
787 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
788 
789 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
790 struct action_nvgre_encap_data {
791 	struct rte_flow_action_nvgre_encap conf;
792 	struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
793 	struct rte_flow_item_eth item_eth;
794 	struct rte_flow_item_vlan item_vlan;
795 	union {
796 		struct rte_flow_item_ipv4 item_ipv4;
797 		struct rte_flow_item_ipv6 item_ipv6;
798 	};
799 	struct rte_flow_item_nvgre item_nvgre;
800 };
801 
802 struct l2_encap_conf l2_encap_conf;
803 
804 struct l2_decap_conf l2_decap_conf;
805 
806 struct mplsogre_encap_conf mplsogre_encap_conf;
807 
808 struct mplsogre_decap_conf mplsogre_decap_conf;
809 
810 struct mplsoudp_encap_conf mplsoudp_encap_conf;
811 
812 struct mplsoudp_decap_conf mplsoudp_decap_conf;
813 
814 struct rte_flow_action_conntrack conntrack_context;
815 
816 #define ACTION_SAMPLE_ACTIONS_NUM 10
817 #define RAW_SAMPLE_CONFS_MAX_NUM 8
818 /** Storage for struct rte_flow_action_sample including external data. */
819 struct action_sample_data {
820 	struct rte_flow_action_sample conf;
821 	uint32_t idx;
822 };
823 /** Storage for struct rte_flow_action_sample. */
824 struct raw_sample_conf {
825 	struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
826 };
827 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
828 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
829 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
830 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
831 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
832 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
833 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
834 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
835 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
836 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
837 struct rte_flow_action_ethdev sample_port_representor[RAW_SAMPLE_CONFS_MAX_NUM];
838 struct rte_flow_action_ethdev sample_represented_port[RAW_SAMPLE_CONFS_MAX_NUM];
839 
840 static const char *const modify_field_ops[] = {
841 	"set", "add", "sub", NULL
842 };
843 
844 static const char *const modify_field_ids[] = {
845 	"start", "mac_dst", "mac_src",
846 	"vlan_type", "vlan_id", "mac_type",
847 	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
848 	"ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
849 	"tcp_port_src", "tcp_port_dst",
850 	"tcp_seq_num", "tcp_ack_num", "tcp_flags",
851 	"udp_port_src", "udp_port_dst",
852 	"vxlan_vni", "geneve_vni", "gtp_teid",
853 	"tag", "mark", "meta", "pointer", "value",
854 	"ipv4_ecn", "ipv6_ecn", "gtp_psc_qfi", "meter_color",
855 	"ipv6_proto",
856 	"flex_item",
857 	"hash_result", NULL
858 };
859 
860 static const char *const meter_colors[] = {
861 	"green", "yellow", "red", "all", NULL
862 };
863 
864 static const char *const table_insertion_types[] = {
865 	"pattern", "index", NULL
866 };
867 
868 static const char *const table_hash_funcs[] = {
869 	"default", "linear", "crc32", "crc16", NULL
870 };
871 
872 #define RAW_IPSEC_CONFS_MAX_NUM 8
873 
874 /** Maximum number of subsequent tokens and arguments on the stack. */
875 #define CTX_STACK_SIZE 16
876 
877 /** Parser context. */
878 struct context {
879 	/** Stack of subsequent token lists to process. */
880 	const enum index *next[CTX_STACK_SIZE];
881 	/** Arguments for stacked tokens. */
882 	const void *args[CTX_STACK_SIZE];
883 	enum index curr; /**< Current token index. */
884 	enum index prev; /**< Index of the last token seen. */
885 	int next_num; /**< Number of entries in next[]. */
886 	int args_num; /**< Number of entries in args[]. */
887 	uint32_t eol:1; /**< EOL has been detected. */
888 	uint32_t last:1; /**< No more arguments. */
889 	portid_t port; /**< Current port ID (for completions). */
890 	uint32_t objdata; /**< Object-specific data. */
891 	void *object; /**< Address of current object for relative offsets. */
892 	void *objmask; /**< Object a full mask must be written to. */
893 };
894 
895 /** Token argument. */
896 struct arg {
897 	uint32_t hton:1; /**< Use network byte ordering. */
898 	uint32_t sign:1; /**< Value is signed. */
899 	uint32_t bounded:1; /**< Value is bounded. */
900 	uintmax_t min; /**< Minimum value if bounded. */
901 	uintmax_t max; /**< Maximum value if bounded. */
902 	uint32_t offset; /**< Relative offset from ctx->object. */
903 	uint32_t size; /**< Field size. */
904 	const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
905 };
906 
907 /** Parser token definition. */
908 struct token {
909 	/** Type displayed during completion (defaults to "TOKEN"). */
910 	const char *type;
911 	/** Help displayed during completion (defaults to token name). */
912 	const char *help;
913 	/** Private data used by parser functions. */
914 	const void *priv;
915 	/**
916 	 * Lists of subsequent tokens to push on the stack. Each call to the
917 	 * parser consumes the last entry of that stack.
918 	 */
919 	const enum index *const *next;
920 	/** Arguments stack for subsequent tokens that need them. */
921 	const struct arg *const *args;
922 	/**
923 	 * Token-processing callback, returns -1 in case of error, the
924 	 * length of the matched string otherwise. If NULL, attempts to
925 	 * match the token name.
926 	 *
927 	 * If buf is not NULL, the result should be stored in it according
928 	 * to context. An error is returned if not large enough.
929 	 */
930 	int (*call)(struct context *ctx, const struct token *token,
931 		    const char *str, unsigned int len,
932 		    void *buf, unsigned int size);
933 	/**
934 	 * Callback that provides possible values for this token, used for
935 	 * completion. Returns -1 in case of error, the number of possible
936 	 * values otherwise. If NULL, the token name is used.
937 	 *
938 	 * If buf is not NULL, entry index ent is written to buf and the
939 	 * full length of the entry is returned (same behavior as
940 	 * snprintf()).
941 	 */
942 	int (*comp)(struct context *ctx, const struct token *token,
943 		    unsigned int ent, char *buf, unsigned int size);
944 	/** Mandatory token name, no default value. */
945 	const char *name;
946 };
947 
948 /** Static initializer for the next field. */
949 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
950 
951 /** Static initializer for a NEXT() entry. */
952 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
953 
954 /** Static initializer for the args field. */
955 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
956 
957 /** Static initializer for ARGS() to target a field. */
958 #define ARGS_ENTRY(s, f) \
959 	(&(const struct arg){ \
960 		.offset = offsetof(s, f), \
961 		.size = sizeof(((s *)0)->f), \
962 	})
963 
964 /** Static initializer for ARGS() to target a bit-field. */
965 #define ARGS_ENTRY_BF(s, f, b) \
966 	(&(const struct arg){ \
967 		.size = sizeof(s), \
968 		.mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
969 	})
970 
971 /** Static initializer for ARGS() to target a field with limits. */
972 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
973 	(&(const struct arg){ \
974 		.bounded = 1, \
975 		.min = (i), \
976 		.max = (a), \
977 		.offset = offsetof(s, f), \
978 		.size = sizeof(((s *)0)->f), \
979 	})
980 
981 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
982 #define ARGS_ENTRY_MASK(s, f, m) \
983 	(&(const struct arg){ \
984 		.offset = offsetof(s, f), \
985 		.size = sizeof(((s *)0)->f), \
986 		.mask = (const void *)(m), \
987 	})
988 
989 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
990 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
991 	(&(const struct arg){ \
992 		.hton = 1, \
993 		.offset = offsetof(s, f), \
994 		.size = sizeof(((s *)0)->f), \
995 		.mask = (const void *)(m), \
996 	})
997 
998 /** Static initializer for ARGS() to target a pointer. */
999 #define ARGS_ENTRY_PTR(s, f) \
1000 	(&(const struct arg){ \
1001 		.size = sizeof(*((s *)0)->f), \
1002 	})
1003 
1004 /** Static initializer for ARGS() with arbitrary offset and size. */
1005 #define ARGS_ENTRY_ARB(o, s) \
1006 	(&(const struct arg){ \
1007 		.offset = (o), \
1008 		.size = (s), \
1009 	})
1010 
1011 /** Same as ARGS_ENTRY_ARB() with bounded values. */
1012 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
1013 	(&(const struct arg){ \
1014 		.bounded = 1, \
1015 		.min = (i), \
1016 		.max = (a), \
1017 		.offset = (o), \
1018 		.size = (s), \
1019 	})
1020 
1021 /** Same as ARGS_ENTRY() using network byte ordering. */
1022 #define ARGS_ENTRY_HTON(s, f) \
1023 	(&(const struct arg){ \
1024 		.hton = 1, \
1025 		.offset = offsetof(s, f), \
1026 		.size = sizeof(((s *)0)->f), \
1027 	})
1028 
1029 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
1030 #define ARG_ENTRY_HTON(s) \
1031 	(&(const struct arg){ \
1032 		.hton = 1, \
1033 		.offset = 0, \
1034 		.size = sizeof(s), \
1035 	})
1036 
1037 /** Parser output buffer layout expected by cmd_flow_parsed(). */
1038 struct buffer {
1039 	enum index command; /**< Flow command. */
1040 	portid_t port; /**< Affected port ID. */
1041 	queueid_t queue; /** Async queue ID. */
1042 	bool postpone; /** Postpone async operation */
1043 	union {
1044 		struct {
1045 			struct rte_flow_port_attr port_attr;
1046 			uint32_t nb_queue;
1047 			struct rte_flow_queue_attr queue_attr;
1048 		} configure; /**< Configuration arguments. */
1049 		struct {
1050 			uint32_t *template_id;
1051 			uint32_t template_id_n;
1052 		} templ_destroy; /**< Template destroy arguments. */
1053 		struct {
1054 			uint32_t id;
1055 			struct rte_flow_template_table_attr attr;
1056 			uint32_t *pat_templ_id;
1057 			uint32_t pat_templ_id_n;
1058 			uint32_t *act_templ_id;
1059 			uint32_t act_templ_id_n;
1060 		} table; /**< Table arguments. */
1061 		struct {
1062 			uint32_t *table_id;
1063 			uint32_t table_id_n;
1064 		} table_destroy; /**< Template destroy arguments. */
1065 		struct {
1066 			uint32_t *action_id;
1067 			uint32_t action_id_n;
1068 		} ia_destroy; /**< Indirect action destroy arguments. */
1069 		struct {
1070 			uint32_t action_id;
1071 			enum rte_flow_query_update_mode qu_mode;
1072 		} ia; /* Indirect action query arguments */
1073 		struct {
1074 			uint32_t table_id;
1075 			uint32_t pat_templ_id;
1076 			uint32_t rule_id;
1077 			uint32_t act_templ_id;
1078 			struct rte_flow_attr attr;
1079 			struct tunnel_ops tunnel_ops;
1080 			struct rte_flow_item *pattern;
1081 			struct rte_flow_action *actions;
1082 			struct rte_flow_action *masks;
1083 			uint32_t pattern_n;
1084 			uint32_t actions_n;
1085 			uint8_t *data;
1086 		} vc; /**< Validate/create arguments. */
1087 		struct {
1088 			uint32_t *rule;
1089 			uint32_t rule_n;
1090 		} destroy; /**< Destroy arguments. */
1091 		struct {
1092 			char file[128];
1093 			bool mode;
1094 			uint32_t rule;
1095 		} dump; /**< Dump arguments. */
1096 		struct {
1097 			uint32_t rule;
1098 			struct rte_flow_action action;
1099 		} query; /**< Query arguments. */
1100 		struct {
1101 			uint32_t *group;
1102 			uint32_t group_n;
1103 		} list; /**< List arguments. */
1104 		struct {
1105 			int set;
1106 		} isolate; /**< Isolated mode arguments. */
1107 		struct {
1108 			int destroy;
1109 		} aged; /**< Aged arguments. */
1110 		struct {
1111 			uint32_t policy_id;
1112 		} policy;/**< Policy arguments. */
1113 		struct {
1114 			uint16_t token;
1115 			uintptr_t uintptr;
1116 			char filename[128];
1117 		} flex; /**< Flex arguments*/
1118 	} args; /**< Command arguments. */
1119 };
1120 
1121 /** Private data for pattern items. */
1122 struct parse_item_priv {
1123 	enum rte_flow_item_type type; /**< Item type. */
1124 	uint32_t size; /**< Size of item specification structure. */
1125 };
1126 
1127 #define PRIV_ITEM(t, s) \
1128 	(&(const struct parse_item_priv){ \
1129 		.type = RTE_FLOW_ITEM_TYPE_ ## t, \
1130 		.size = s, \
1131 	})
1132 
1133 /** Private data for actions. */
1134 struct parse_action_priv {
1135 	enum rte_flow_action_type type; /**< Action type. */
1136 	uint32_t size; /**< Size of action configuration structure. */
1137 };
1138 
1139 #define PRIV_ACTION(t, s) \
1140 	(&(const struct parse_action_priv){ \
1141 		.type = RTE_FLOW_ACTION_TYPE_ ## t, \
1142 		.size = s, \
1143 	})
1144 
1145 static const enum index next_flex_item[] = {
1146 	FLEX_ITEM_INIT,
1147 	FLEX_ITEM_CREATE,
1148 	FLEX_ITEM_DESTROY,
1149 	ZERO,
1150 };
1151 
1152 static const enum index next_config_attr[] = {
1153 	CONFIG_QUEUES_NUMBER,
1154 	CONFIG_QUEUES_SIZE,
1155 	CONFIG_COUNTERS_NUMBER,
1156 	CONFIG_AGING_OBJECTS_NUMBER,
1157 	CONFIG_METERS_NUMBER,
1158 	CONFIG_CONN_TRACK_NUMBER,
1159 	CONFIG_QUOTAS_NUMBER,
1160 	CONFIG_FLAGS,
1161 	CONFIG_HOST_PORT,
1162 	END,
1163 	ZERO,
1164 };
1165 
1166 static const enum index next_pt_subcmd[] = {
1167 	PATTERN_TEMPLATE_CREATE,
1168 	PATTERN_TEMPLATE_DESTROY,
1169 	ZERO,
1170 };
1171 
1172 static const enum index next_pt_attr[] = {
1173 	PATTERN_TEMPLATE_CREATE_ID,
1174 	PATTERN_TEMPLATE_RELAXED_MATCHING,
1175 	PATTERN_TEMPLATE_INGRESS,
1176 	PATTERN_TEMPLATE_EGRESS,
1177 	PATTERN_TEMPLATE_TRANSFER,
1178 	PATTERN_TEMPLATE_SPEC,
1179 	ZERO,
1180 };
1181 
1182 static const enum index next_pt_destroy_attr[] = {
1183 	PATTERN_TEMPLATE_DESTROY_ID,
1184 	END,
1185 	ZERO,
1186 };
1187 
1188 static const enum index next_at_subcmd[] = {
1189 	ACTIONS_TEMPLATE_CREATE,
1190 	ACTIONS_TEMPLATE_DESTROY,
1191 	ZERO,
1192 };
1193 
1194 static const enum index next_at_attr[] = {
1195 	ACTIONS_TEMPLATE_CREATE_ID,
1196 	ACTIONS_TEMPLATE_INGRESS,
1197 	ACTIONS_TEMPLATE_EGRESS,
1198 	ACTIONS_TEMPLATE_TRANSFER,
1199 	ACTIONS_TEMPLATE_SPEC,
1200 	ZERO,
1201 };
1202 
1203 static const enum index next_at_destroy_attr[] = {
1204 	ACTIONS_TEMPLATE_DESTROY_ID,
1205 	END,
1206 	ZERO,
1207 };
1208 
1209 static const enum index next_table_subcmd[] = {
1210 	TABLE_CREATE,
1211 	TABLE_DESTROY,
1212 	ZERO,
1213 };
1214 
1215 static const enum index next_table_attr[] = {
1216 	TABLE_CREATE_ID,
1217 	TABLE_GROUP,
1218 	TABLE_INSERTION_TYPE,
1219 	TABLE_HASH_FUNC,
1220 	TABLE_PRIORITY,
1221 	TABLE_INGRESS,
1222 	TABLE_EGRESS,
1223 	TABLE_TRANSFER,
1224 	TABLE_TRANSFER_WIRE_ORIG,
1225 	TABLE_TRANSFER_VPORT_ORIG,
1226 	TABLE_RULES_NUMBER,
1227 	TABLE_PATTERN_TEMPLATE,
1228 	TABLE_ACTIONS_TEMPLATE,
1229 	END,
1230 	ZERO,
1231 };
1232 
1233 static const enum index next_table_destroy_attr[] = {
1234 	TABLE_DESTROY_ID,
1235 	END,
1236 	ZERO,
1237 };
1238 
1239 static const enum index next_queue_subcmd[] = {
1240 	QUEUE_CREATE,
1241 	QUEUE_DESTROY,
1242 	QUEUE_AGED,
1243 	QUEUE_INDIRECT_ACTION,
1244 	ZERO,
1245 };
1246 
1247 static const enum index next_queue_destroy_attr[] = {
1248 	QUEUE_DESTROY_ID,
1249 	END,
1250 	ZERO,
1251 };
1252 
1253 static const enum index next_qia_subcmd[] = {
1254 	QUEUE_INDIRECT_ACTION_CREATE,
1255 	QUEUE_INDIRECT_ACTION_UPDATE,
1256 	QUEUE_INDIRECT_ACTION_DESTROY,
1257 	QUEUE_INDIRECT_ACTION_QUERY,
1258 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
1259 	ZERO,
1260 };
1261 
1262 static const enum index next_qia_create_attr[] = {
1263 	QUEUE_INDIRECT_ACTION_CREATE_ID,
1264 	QUEUE_INDIRECT_ACTION_INGRESS,
1265 	QUEUE_INDIRECT_ACTION_EGRESS,
1266 	QUEUE_INDIRECT_ACTION_TRANSFER,
1267 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
1268 	QUEUE_INDIRECT_ACTION_SPEC,
1269 	ZERO,
1270 };
1271 
1272 static const enum index next_qia_update_attr[] = {
1273 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1274 	QUEUE_INDIRECT_ACTION_SPEC,
1275 	ZERO,
1276 };
1277 
1278 static const enum index next_qia_destroy_attr[] = {
1279 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
1280 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
1281 	END,
1282 	ZERO,
1283 };
1284 
1285 static const enum index next_qia_query_attr[] = {
1286 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
1287 	END,
1288 	ZERO,
1289 };
1290 
1291 static const enum index next_ia_create_attr[] = {
1292 	INDIRECT_ACTION_CREATE_ID,
1293 	INDIRECT_ACTION_INGRESS,
1294 	INDIRECT_ACTION_EGRESS,
1295 	INDIRECT_ACTION_TRANSFER,
1296 	INDIRECT_ACTION_SPEC,
1297 	ZERO,
1298 };
1299 
1300 static const enum index next_ia[] = {
1301 	INDIRECT_ACTION_ID2PTR,
1302 	ACTION_NEXT,
1303 	ZERO
1304 };
1305 
1306 static const enum index next_qia_qu_attr[] = {
1307 	QUEUE_INDIRECT_ACTION_QU_MODE,
1308 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1309 	INDIRECT_ACTION_SPEC,
1310 	ZERO
1311 };
1312 
1313 static const enum index next_ia_qu_attr[] = {
1314 	INDIRECT_ACTION_QU_MODE,
1315 	INDIRECT_ACTION_SPEC,
1316 	ZERO
1317 };
1318 
1319 static const enum index next_dump_subcmd[] = {
1320 	DUMP_ALL,
1321 	DUMP_ONE,
1322 	ZERO,
1323 };
1324 
1325 static const enum index next_ia_subcmd[] = {
1326 	INDIRECT_ACTION_CREATE,
1327 	INDIRECT_ACTION_UPDATE,
1328 	INDIRECT_ACTION_DESTROY,
1329 	INDIRECT_ACTION_QUERY,
1330 	INDIRECT_ACTION_QUERY_UPDATE,
1331 	ZERO,
1332 };
1333 
1334 static const enum index next_vc_attr[] = {
1335 	VC_GROUP,
1336 	VC_PRIORITY,
1337 	VC_INGRESS,
1338 	VC_EGRESS,
1339 	VC_TRANSFER,
1340 	VC_TUNNEL_SET,
1341 	VC_TUNNEL_MATCH,
1342 	ITEM_PATTERN,
1343 	ZERO,
1344 };
1345 
1346 static const enum index next_destroy_attr[] = {
1347 	DESTROY_RULE,
1348 	END,
1349 	ZERO,
1350 };
1351 
1352 static const enum index next_dump_attr[] = {
1353 	COMMON_FILE_PATH,
1354 	END,
1355 	ZERO,
1356 };
1357 
1358 static const enum index next_list_attr[] = {
1359 	LIST_GROUP,
1360 	END,
1361 	ZERO,
1362 };
1363 
1364 static const enum index next_aged_attr[] = {
1365 	AGED_DESTROY,
1366 	END,
1367 	ZERO,
1368 };
1369 
1370 static const enum index next_ia_destroy_attr[] = {
1371 	INDIRECT_ACTION_DESTROY_ID,
1372 	END,
1373 	ZERO,
1374 };
1375 
1376 static const enum index next_async_insert_subcmd[] = {
1377 	QUEUE_PATTERN_TEMPLATE,
1378 	QUEUE_RULE_ID,
1379 	ZERO,
1380 };
1381 
1382 static const enum index item_param[] = {
1383 	ITEM_PARAM_IS,
1384 	ITEM_PARAM_SPEC,
1385 	ITEM_PARAM_LAST,
1386 	ITEM_PARAM_MASK,
1387 	ITEM_PARAM_PREFIX,
1388 	ZERO,
1389 };
1390 
1391 static const enum index next_item[] = {
1392 	ITEM_END,
1393 	ITEM_VOID,
1394 	ITEM_INVERT,
1395 	ITEM_ANY,
1396 	ITEM_PORT_ID,
1397 	ITEM_MARK,
1398 	ITEM_RAW,
1399 	ITEM_ETH,
1400 	ITEM_VLAN,
1401 	ITEM_IPV4,
1402 	ITEM_IPV6,
1403 	ITEM_ICMP,
1404 	ITEM_UDP,
1405 	ITEM_TCP,
1406 	ITEM_SCTP,
1407 	ITEM_VXLAN,
1408 	ITEM_E_TAG,
1409 	ITEM_NVGRE,
1410 	ITEM_MPLS,
1411 	ITEM_GRE,
1412 	ITEM_FUZZY,
1413 	ITEM_GTP,
1414 	ITEM_GTPC,
1415 	ITEM_GTPU,
1416 	ITEM_GENEVE,
1417 	ITEM_VXLAN_GPE,
1418 	ITEM_ARP_ETH_IPV4,
1419 	ITEM_IPV6_EXT,
1420 	ITEM_IPV6_FRAG_EXT,
1421 	ITEM_IPV6_ROUTING_EXT,
1422 	ITEM_ICMP6,
1423 	ITEM_ICMP6_ECHO_REQUEST,
1424 	ITEM_ICMP6_ECHO_REPLY,
1425 	ITEM_ICMP6_ND_NS,
1426 	ITEM_ICMP6_ND_NA,
1427 	ITEM_ICMP6_ND_OPT,
1428 	ITEM_ICMP6_ND_OPT_SLA_ETH,
1429 	ITEM_ICMP6_ND_OPT_TLA_ETH,
1430 	ITEM_META,
1431 	ITEM_GRE_KEY,
1432 	ITEM_GRE_OPTION,
1433 	ITEM_GTP_PSC,
1434 	ITEM_PPPOES,
1435 	ITEM_PPPOED,
1436 	ITEM_PPPOE_PROTO_ID,
1437 	ITEM_HIGIG2,
1438 	ITEM_TAG,
1439 	ITEM_L2TPV3OIP,
1440 	ITEM_ESP,
1441 	ITEM_AH,
1442 	ITEM_PFCP,
1443 	ITEM_ECPRI,
1444 	ITEM_GENEVE_OPT,
1445 	ITEM_INTEGRITY,
1446 	ITEM_CONNTRACK,
1447 	ITEM_PORT_REPRESENTOR,
1448 	ITEM_REPRESENTED_PORT,
1449 	ITEM_FLEX,
1450 	ITEM_L2TPV2,
1451 	ITEM_PPP,
1452 	ITEM_METER,
1453 	ITEM_QUOTA,
1454 	ITEM_AGGR_AFFINITY,
1455 	END_SET,
1456 	ZERO,
1457 };
1458 
1459 static const enum index item_fuzzy[] = {
1460 	ITEM_FUZZY_THRESH,
1461 	ITEM_NEXT,
1462 	ZERO,
1463 };
1464 
1465 static const enum index item_any[] = {
1466 	ITEM_ANY_NUM,
1467 	ITEM_NEXT,
1468 	ZERO,
1469 };
1470 
1471 static const enum index item_port_id[] = {
1472 	ITEM_PORT_ID_ID,
1473 	ITEM_NEXT,
1474 	ZERO,
1475 };
1476 
1477 static const enum index item_mark[] = {
1478 	ITEM_MARK_ID,
1479 	ITEM_NEXT,
1480 	ZERO,
1481 };
1482 
1483 static const enum index item_raw[] = {
1484 	ITEM_RAW_RELATIVE,
1485 	ITEM_RAW_SEARCH,
1486 	ITEM_RAW_OFFSET,
1487 	ITEM_RAW_LIMIT,
1488 	ITEM_RAW_PATTERN,
1489 	ITEM_RAW_PATTERN_HEX,
1490 	ITEM_NEXT,
1491 	ZERO,
1492 };
1493 
1494 static const enum index item_eth[] = {
1495 	ITEM_ETH_DST,
1496 	ITEM_ETH_SRC,
1497 	ITEM_ETH_TYPE,
1498 	ITEM_ETH_HAS_VLAN,
1499 	ITEM_NEXT,
1500 	ZERO,
1501 };
1502 
1503 static const enum index item_vlan[] = {
1504 	ITEM_VLAN_TCI,
1505 	ITEM_VLAN_PCP,
1506 	ITEM_VLAN_DEI,
1507 	ITEM_VLAN_VID,
1508 	ITEM_VLAN_INNER_TYPE,
1509 	ITEM_VLAN_HAS_MORE_VLAN,
1510 	ITEM_NEXT,
1511 	ZERO,
1512 };
1513 
1514 static const enum index item_ipv4[] = {
1515 	ITEM_IPV4_VER_IHL,
1516 	ITEM_IPV4_TOS,
1517 	ITEM_IPV4_ID,
1518 	ITEM_IPV4_FRAGMENT_OFFSET,
1519 	ITEM_IPV4_TTL,
1520 	ITEM_IPV4_PROTO,
1521 	ITEM_IPV4_SRC,
1522 	ITEM_IPV4_DST,
1523 	ITEM_NEXT,
1524 	ZERO,
1525 };
1526 
1527 static const enum index item_ipv6[] = {
1528 	ITEM_IPV6_TC,
1529 	ITEM_IPV6_FLOW,
1530 	ITEM_IPV6_PROTO,
1531 	ITEM_IPV6_HOP,
1532 	ITEM_IPV6_SRC,
1533 	ITEM_IPV6_DST,
1534 	ITEM_IPV6_HAS_FRAG_EXT,
1535 	ITEM_IPV6_ROUTING_EXT,
1536 	ITEM_NEXT,
1537 	ZERO,
1538 };
1539 
1540 static const enum index item_ipv6_routing_ext[] = {
1541 	ITEM_IPV6_ROUTING_EXT_TYPE,
1542 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
1543 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
1544 	ITEM_NEXT,
1545 	ZERO,
1546 };
1547 
1548 static const enum index item_icmp[] = {
1549 	ITEM_ICMP_TYPE,
1550 	ITEM_ICMP_CODE,
1551 	ITEM_ICMP_IDENT,
1552 	ITEM_ICMP_SEQ,
1553 	ITEM_NEXT,
1554 	ZERO,
1555 };
1556 
1557 static const enum index item_udp[] = {
1558 	ITEM_UDP_SRC,
1559 	ITEM_UDP_DST,
1560 	ITEM_NEXT,
1561 	ZERO,
1562 };
1563 
1564 static const enum index item_tcp[] = {
1565 	ITEM_TCP_SRC,
1566 	ITEM_TCP_DST,
1567 	ITEM_TCP_FLAGS,
1568 	ITEM_NEXT,
1569 	ZERO,
1570 };
1571 
1572 static const enum index item_sctp[] = {
1573 	ITEM_SCTP_SRC,
1574 	ITEM_SCTP_DST,
1575 	ITEM_SCTP_TAG,
1576 	ITEM_SCTP_CKSUM,
1577 	ITEM_NEXT,
1578 	ZERO,
1579 };
1580 
1581 static const enum index item_vxlan[] = {
1582 	ITEM_VXLAN_VNI,
1583 	ITEM_VXLAN_LAST_RSVD,
1584 	ITEM_NEXT,
1585 	ZERO,
1586 };
1587 
1588 static const enum index item_e_tag[] = {
1589 	ITEM_E_TAG_GRP_ECID_B,
1590 	ITEM_NEXT,
1591 	ZERO,
1592 };
1593 
1594 static const enum index item_nvgre[] = {
1595 	ITEM_NVGRE_TNI,
1596 	ITEM_NEXT,
1597 	ZERO,
1598 };
1599 
1600 static const enum index item_mpls[] = {
1601 	ITEM_MPLS_LABEL,
1602 	ITEM_MPLS_TC,
1603 	ITEM_MPLS_S,
1604 	ITEM_NEXT,
1605 	ZERO,
1606 };
1607 
1608 static const enum index item_gre[] = {
1609 	ITEM_GRE_PROTO,
1610 	ITEM_GRE_C_RSVD0_VER,
1611 	ITEM_GRE_C_BIT,
1612 	ITEM_GRE_K_BIT,
1613 	ITEM_GRE_S_BIT,
1614 	ITEM_NEXT,
1615 	ZERO,
1616 };
1617 
1618 static const enum index item_gre_key[] = {
1619 	ITEM_GRE_KEY_VALUE,
1620 	ITEM_NEXT,
1621 	ZERO,
1622 };
1623 
1624 static const enum index item_gre_option[] = {
1625 	ITEM_GRE_OPTION_CHECKSUM,
1626 	ITEM_GRE_OPTION_KEY,
1627 	ITEM_GRE_OPTION_SEQUENCE,
1628 	ITEM_NEXT,
1629 	ZERO,
1630 };
1631 
1632 static const enum index item_gtp[] = {
1633 	ITEM_GTP_FLAGS,
1634 	ITEM_GTP_MSG_TYPE,
1635 	ITEM_GTP_TEID,
1636 	ITEM_NEXT,
1637 	ZERO,
1638 };
1639 
1640 static const enum index item_geneve[] = {
1641 	ITEM_GENEVE_VNI,
1642 	ITEM_GENEVE_PROTO,
1643 	ITEM_GENEVE_OPTLEN,
1644 	ITEM_NEXT,
1645 	ZERO,
1646 };
1647 
1648 static const enum index item_vxlan_gpe[] = {
1649 	ITEM_VXLAN_GPE_VNI,
1650 	ITEM_NEXT,
1651 	ZERO,
1652 };
1653 
1654 static const enum index item_arp_eth_ipv4[] = {
1655 	ITEM_ARP_ETH_IPV4_SHA,
1656 	ITEM_ARP_ETH_IPV4_SPA,
1657 	ITEM_ARP_ETH_IPV4_THA,
1658 	ITEM_ARP_ETH_IPV4_TPA,
1659 	ITEM_NEXT,
1660 	ZERO,
1661 };
1662 
1663 static const enum index item_ipv6_ext[] = {
1664 	ITEM_IPV6_EXT_NEXT_HDR,
1665 	ITEM_NEXT,
1666 	ZERO,
1667 };
1668 
1669 static const enum index item_ipv6_frag_ext[] = {
1670 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1671 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1672 	ITEM_IPV6_FRAG_EXT_ID,
1673 	ITEM_NEXT,
1674 	ZERO,
1675 };
1676 
1677 static const enum index item_icmp6[] = {
1678 	ITEM_ICMP6_TYPE,
1679 	ITEM_ICMP6_CODE,
1680 	ITEM_NEXT,
1681 	ZERO,
1682 };
1683 
1684 static const enum index item_icmp6_echo_request[] = {
1685 	ITEM_ICMP6_ECHO_REQUEST_ID,
1686 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
1687 	ITEM_NEXT,
1688 	ZERO,
1689 };
1690 
1691 static const enum index item_icmp6_echo_reply[] = {
1692 	ITEM_ICMP6_ECHO_REPLY_ID,
1693 	ITEM_ICMP6_ECHO_REPLY_SEQ,
1694 	ITEM_NEXT,
1695 	ZERO,
1696 };
1697 
1698 static const enum index item_icmp6_nd_ns[] = {
1699 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
1700 	ITEM_NEXT,
1701 	ZERO,
1702 };
1703 
1704 static const enum index item_icmp6_nd_na[] = {
1705 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
1706 	ITEM_NEXT,
1707 	ZERO,
1708 };
1709 
1710 static const enum index item_icmp6_nd_opt[] = {
1711 	ITEM_ICMP6_ND_OPT_TYPE,
1712 	ITEM_NEXT,
1713 	ZERO,
1714 };
1715 
1716 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1717 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1718 	ITEM_NEXT,
1719 	ZERO,
1720 };
1721 
1722 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1723 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1724 	ITEM_NEXT,
1725 	ZERO,
1726 };
1727 
1728 static const enum index item_meta[] = {
1729 	ITEM_META_DATA,
1730 	ITEM_NEXT,
1731 	ZERO,
1732 };
1733 
1734 static const enum index item_gtp_psc[] = {
1735 	ITEM_GTP_PSC_QFI,
1736 	ITEM_GTP_PSC_PDU_T,
1737 	ITEM_NEXT,
1738 	ZERO,
1739 };
1740 
1741 static const enum index item_pppoed[] = {
1742 	ITEM_PPPOE_SEID,
1743 	ITEM_NEXT,
1744 	ZERO,
1745 };
1746 
1747 static const enum index item_pppoes[] = {
1748 	ITEM_PPPOE_SEID,
1749 	ITEM_NEXT,
1750 	ZERO,
1751 };
1752 
1753 static const enum index item_pppoe_proto_id[] = {
1754 	ITEM_NEXT,
1755 	ZERO,
1756 };
1757 
1758 static const enum index item_higig2[] = {
1759 	ITEM_HIGIG2_CLASSIFICATION,
1760 	ITEM_HIGIG2_VID,
1761 	ITEM_NEXT,
1762 	ZERO,
1763 };
1764 
1765 static const enum index item_esp[] = {
1766 	ITEM_ESP_SPI,
1767 	ITEM_NEXT,
1768 	ZERO,
1769 };
1770 
1771 static const enum index item_ah[] = {
1772 	ITEM_AH_SPI,
1773 	ITEM_NEXT,
1774 	ZERO,
1775 };
1776 
1777 static const enum index item_pfcp[] = {
1778 	ITEM_PFCP_S_FIELD,
1779 	ITEM_PFCP_SEID,
1780 	ITEM_NEXT,
1781 	ZERO,
1782 };
1783 
1784 static const enum index next_set_raw[] = {
1785 	SET_RAW_INDEX,
1786 	ITEM_ETH,
1787 	ZERO,
1788 };
1789 
1790 static const enum index item_tag[] = {
1791 	ITEM_TAG_DATA,
1792 	ITEM_TAG_INDEX,
1793 	ITEM_NEXT,
1794 	ZERO,
1795 };
1796 
1797 static const enum index item_l2tpv3oip[] = {
1798 	ITEM_L2TPV3OIP_SESSION_ID,
1799 	ITEM_NEXT,
1800 	ZERO,
1801 };
1802 
1803 static const enum index item_ecpri[] = {
1804 	ITEM_ECPRI_COMMON,
1805 	ITEM_NEXT,
1806 	ZERO,
1807 };
1808 
1809 static const enum index item_ecpri_common[] = {
1810 	ITEM_ECPRI_COMMON_TYPE,
1811 	ZERO,
1812 };
1813 
1814 static const enum index item_ecpri_common_type[] = {
1815 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
1816 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
1817 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
1818 	ZERO,
1819 };
1820 
1821 static const enum index item_geneve_opt[] = {
1822 	ITEM_GENEVE_OPT_CLASS,
1823 	ITEM_GENEVE_OPT_TYPE,
1824 	ITEM_GENEVE_OPT_LENGTH,
1825 	ITEM_GENEVE_OPT_DATA,
1826 	ITEM_NEXT,
1827 	ZERO,
1828 };
1829 
1830 static const enum index item_integrity[] = {
1831 	ITEM_INTEGRITY_LEVEL,
1832 	ITEM_INTEGRITY_VALUE,
1833 	ZERO,
1834 };
1835 
1836 static const enum index item_integrity_lv[] = {
1837 	ITEM_INTEGRITY_LEVEL,
1838 	ITEM_INTEGRITY_VALUE,
1839 	ITEM_NEXT,
1840 	ZERO,
1841 };
1842 
1843 static const enum index item_port_representor[] = {
1844 	ITEM_PORT_REPRESENTOR_PORT_ID,
1845 	ITEM_NEXT,
1846 	ZERO,
1847 };
1848 
1849 static const enum index item_represented_port[] = {
1850 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
1851 	ITEM_NEXT,
1852 	ZERO,
1853 };
1854 
1855 static const enum index item_flex[] = {
1856 	ITEM_FLEX_PATTERN_HANDLE,
1857 	ITEM_FLEX_ITEM_HANDLE,
1858 	ITEM_NEXT,
1859 	ZERO,
1860 };
1861 
1862 static const enum index item_l2tpv2[] = {
1863 	ITEM_L2TPV2_TYPE,
1864 	ITEM_NEXT,
1865 	ZERO,
1866 };
1867 
1868 static const enum index item_l2tpv2_type[] = {
1869 	ITEM_L2TPV2_TYPE_DATA,
1870 	ITEM_L2TPV2_TYPE_DATA_L,
1871 	ITEM_L2TPV2_TYPE_DATA_S,
1872 	ITEM_L2TPV2_TYPE_DATA_O,
1873 	ITEM_L2TPV2_TYPE_DATA_L_S,
1874 	ITEM_L2TPV2_TYPE_CTRL,
1875 	ZERO,
1876 };
1877 
1878 static const enum index item_l2tpv2_type_data[] = {
1879 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
1880 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
1881 	ITEM_NEXT,
1882 	ZERO,
1883 };
1884 
1885 static const enum index item_l2tpv2_type_data_l[] = {
1886 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
1887 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
1888 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
1889 	ITEM_NEXT,
1890 	ZERO,
1891 };
1892 
1893 static const enum index item_l2tpv2_type_data_s[] = {
1894 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
1895 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
1896 	ITEM_L2TPV2_MSG_DATA_S_NS,
1897 	ITEM_L2TPV2_MSG_DATA_S_NR,
1898 	ITEM_NEXT,
1899 	ZERO,
1900 };
1901 
1902 static const enum index item_l2tpv2_type_data_o[] = {
1903 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
1904 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
1905 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
1906 	ITEM_NEXT,
1907 	ZERO,
1908 };
1909 
1910 static const enum index item_l2tpv2_type_data_l_s[] = {
1911 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
1912 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
1913 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
1914 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
1915 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
1916 	ITEM_NEXT,
1917 	ZERO,
1918 };
1919 
1920 static const enum index item_l2tpv2_type_ctrl[] = {
1921 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
1922 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
1923 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
1924 	ITEM_L2TPV2_MSG_CTRL_NS,
1925 	ITEM_L2TPV2_MSG_CTRL_NR,
1926 	ITEM_NEXT,
1927 	ZERO,
1928 };
1929 
1930 static const enum index item_ppp[] = {
1931 	ITEM_PPP_ADDR,
1932 	ITEM_PPP_CTRL,
1933 	ITEM_PPP_PROTO_ID,
1934 	ITEM_NEXT,
1935 	ZERO,
1936 };
1937 
1938 static const enum index item_meter[] = {
1939 	ITEM_METER_COLOR,
1940 	ITEM_NEXT,
1941 	ZERO,
1942 };
1943 
1944 static const enum index item_quota[] = {
1945 	ITEM_QUOTA_STATE,
1946 	ITEM_NEXT,
1947 	ZERO,
1948 };
1949 
1950 static const enum index item_aggr_affinity[] = {
1951 	ITEM_AGGR_AFFINITY_VALUE,
1952 	ITEM_NEXT,
1953 	ZERO,
1954 };
1955 
1956 static const enum index next_action[] = {
1957 	ACTION_END,
1958 	ACTION_VOID,
1959 	ACTION_PASSTHRU,
1960 	ACTION_SKIP_CMAN,
1961 	ACTION_JUMP,
1962 	ACTION_MARK,
1963 	ACTION_FLAG,
1964 	ACTION_QUEUE,
1965 	ACTION_DROP,
1966 	ACTION_COUNT,
1967 	ACTION_RSS,
1968 	ACTION_PF,
1969 	ACTION_VF,
1970 	ACTION_PORT_ID,
1971 	ACTION_METER,
1972 	ACTION_METER_COLOR,
1973 	ACTION_METER_MARK,
1974 	ACTION_OF_DEC_NW_TTL,
1975 	ACTION_OF_POP_VLAN,
1976 	ACTION_OF_PUSH_VLAN,
1977 	ACTION_OF_SET_VLAN_VID,
1978 	ACTION_OF_SET_VLAN_PCP,
1979 	ACTION_OF_POP_MPLS,
1980 	ACTION_OF_PUSH_MPLS,
1981 	ACTION_VXLAN_ENCAP,
1982 	ACTION_VXLAN_DECAP,
1983 	ACTION_NVGRE_ENCAP,
1984 	ACTION_NVGRE_DECAP,
1985 	ACTION_L2_ENCAP,
1986 	ACTION_L2_DECAP,
1987 	ACTION_MPLSOGRE_ENCAP,
1988 	ACTION_MPLSOGRE_DECAP,
1989 	ACTION_MPLSOUDP_ENCAP,
1990 	ACTION_MPLSOUDP_DECAP,
1991 	ACTION_SET_IPV4_SRC,
1992 	ACTION_SET_IPV4_DST,
1993 	ACTION_SET_IPV6_SRC,
1994 	ACTION_SET_IPV6_DST,
1995 	ACTION_SET_TP_SRC,
1996 	ACTION_SET_TP_DST,
1997 	ACTION_MAC_SWAP,
1998 	ACTION_DEC_TTL,
1999 	ACTION_SET_TTL,
2000 	ACTION_SET_MAC_SRC,
2001 	ACTION_SET_MAC_DST,
2002 	ACTION_INC_TCP_SEQ,
2003 	ACTION_DEC_TCP_SEQ,
2004 	ACTION_INC_TCP_ACK,
2005 	ACTION_DEC_TCP_ACK,
2006 	ACTION_RAW_ENCAP,
2007 	ACTION_RAW_DECAP,
2008 	ACTION_SET_TAG,
2009 	ACTION_SET_META,
2010 	ACTION_SET_IPV4_DSCP,
2011 	ACTION_SET_IPV6_DSCP,
2012 	ACTION_AGE,
2013 	ACTION_AGE_UPDATE,
2014 	ACTION_SAMPLE,
2015 	ACTION_INDIRECT,
2016 	ACTION_SHARED_INDIRECT,
2017 	ACTION_MODIFY_FIELD,
2018 	ACTION_CONNTRACK,
2019 	ACTION_CONNTRACK_UPDATE,
2020 	ACTION_PORT_REPRESENTOR,
2021 	ACTION_REPRESENTED_PORT,
2022 	ACTION_SEND_TO_KERNEL,
2023 	ACTION_QUOTA_CREATE,
2024 	ACTION_QUOTA_QU,
2025 	ZERO,
2026 };
2027 
2028 static const enum index action_quota_create[] = {
2029 	ACTION_QUOTA_CREATE_LIMIT,
2030 	ACTION_QUOTA_CREATE_MODE,
2031 	ACTION_NEXT,
2032 	ZERO
2033 };
2034 
2035 static const enum index action_quota_update[] = {
2036 	ACTION_QUOTA_QU_LIMIT,
2037 	ACTION_QUOTA_QU_UPDATE_OP,
2038 	ACTION_NEXT,
2039 	ZERO
2040 };
2041 
2042 static const enum index action_mark[] = {
2043 	ACTION_MARK_ID,
2044 	ACTION_NEXT,
2045 	ZERO,
2046 };
2047 
2048 static const enum index action_queue[] = {
2049 	ACTION_QUEUE_INDEX,
2050 	ACTION_NEXT,
2051 	ZERO,
2052 };
2053 
2054 static const enum index action_count[] = {
2055 	ACTION_COUNT_ID,
2056 	ACTION_NEXT,
2057 	ZERO,
2058 };
2059 
2060 static const enum index action_rss[] = {
2061 	ACTION_RSS_FUNC,
2062 	ACTION_RSS_LEVEL,
2063 	ACTION_RSS_TYPES,
2064 	ACTION_RSS_KEY,
2065 	ACTION_RSS_KEY_LEN,
2066 	ACTION_RSS_QUEUES,
2067 	ACTION_NEXT,
2068 	ZERO,
2069 };
2070 
2071 static const enum index action_vf[] = {
2072 	ACTION_VF_ORIGINAL,
2073 	ACTION_VF_ID,
2074 	ACTION_NEXT,
2075 	ZERO,
2076 };
2077 
2078 static const enum index action_port_id[] = {
2079 	ACTION_PORT_ID_ORIGINAL,
2080 	ACTION_PORT_ID_ID,
2081 	ACTION_NEXT,
2082 	ZERO,
2083 };
2084 
2085 static const enum index action_meter[] = {
2086 	ACTION_METER_ID,
2087 	ACTION_NEXT,
2088 	ZERO,
2089 };
2090 
2091 static const enum index action_meter_color[] = {
2092 	ACTION_METER_COLOR_TYPE,
2093 	ACTION_NEXT,
2094 	ZERO,
2095 };
2096 
2097 static const enum index action_meter_mark[] = {
2098 	ACTION_METER_PROFILE,
2099 	ACTION_METER_POLICY,
2100 	ACTION_METER_COLOR_MODE,
2101 	ACTION_METER_INIT_COLOR,
2102 	ACTION_METER_STATE,
2103 	ACTION_NEXT,
2104 	ZERO,
2105 };
2106 
2107 static const enum index action_of_push_vlan[] = {
2108 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
2109 	ACTION_NEXT,
2110 	ZERO,
2111 };
2112 
2113 static const enum index action_of_set_vlan_vid[] = {
2114 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
2115 	ACTION_NEXT,
2116 	ZERO,
2117 };
2118 
2119 static const enum index action_of_set_vlan_pcp[] = {
2120 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
2121 	ACTION_NEXT,
2122 	ZERO,
2123 };
2124 
2125 static const enum index action_of_pop_mpls[] = {
2126 	ACTION_OF_POP_MPLS_ETHERTYPE,
2127 	ACTION_NEXT,
2128 	ZERO,
2129 };
2130 
2131 static const enum index action_of_push_mpls[] = {
2132 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
2133 	ACTION_NEXT,
2134 	ZERO,
2135 };
2136 
2137 static const enum index action_set_ipv4_src[] = {
2138 	ACTION_SET_IPV4_SRC_IPV4_SRC,
2139 	ACTION_NEXT,
2140 	ZERO,
2141 };
2142 
2143 static const enum index action_set_mac_src[] = {
2144 	ACTION_SET_MAC_SRC_MAC_SRC,
2145 	ACTION_NEXT,
2146 	ZERO,
2147 };
2148 
2149 static const enum index action_set_ipv4_dst[] = {
2150 	ACTION_SET_IPV4_DST_IPV4_DST,
2151 	ACTION_NEXT,
2152 	ZERO,
2153 };
2154 
2155 static const enum index action_set_ipv6_src[] = {
2156 	ACTION_SET_IPV6_SRC_IPV6_SRC,
2157 	ACTION_NEXT,
2158 	ZERO,
2159 };
2160 
2161 static const enum index action_set_ipv6_dst[] = {
2162 	ACTION_SET_IPV6_DST_IPV6_DST,
2163 	ACTION_NEXT,
2164 	ZERO,
2165 };
2166 
2167 static const enum index action_set_tp_src[] = {
2168 	ACTION_SET_TP_SRC_TP_SRC,
2169 	ACTION_NEXT,
2170 	ZERO,
2171 };
2172 
2173 static const enum index action_set_tp_dst[] = {
2174 	ACTION_SET_TP_DST_TP_DST,
2175 	ACTION_NEXT,
2176 	ZERO,
2177 };
2178 
2179 static const enum index action_set_ttl[] = {
2180 	ACTION_SET_TTL_TTL,
2181 	ACTION_NEXT,
2182 	ZERO,
2183 };
2184 
2185 static const enum index action_jump[] = {
2186 	ACTION_JUMP_GROUP,
2187 	ACTION_NEXT,
2188 	ZERO,
2189 };
2190 
2191 static const enum index action_set_mac_dst[] = {
2192 	ACTION_SET_MAC_DST_MAC_DST,
2193 	ACTION_NEXT,
2194 	ZERO,
2195 };
2196 
2197 static const enum index action_inc_tcp_seq[] = {
2198 	ACTION_INC_TCP_SEQ_VALUE,
2199 	ACTION_NEXT,
2200 	ZERO,
2201 };
2202 
2203 static const enum index action_dec_tcp_seq[] = {
2204 	ACTION_DEC_TCP_SEQ_VALUE,
2205 	ACTION_NEXT,
2206 	ZERO,
2207 };
2208 
2209 static const enum index action_inc_tcp_ack[] = {
2210 	ACTION_INC_TCP_ACK_VALUE,
2211 	ACTION_NEXT,
2212 	ZERO,
2213 };
2214 
2215 static const enum index action_dec_tcp_ack[] = {
2216 	ACTION_DEC_TCP_ACK_VALUE,
2217 	ACTION_NEXT,
2218 	ZERO,
2219 };
2220 
2221 static const enum index action_raw_encap[] = {
2222 	ACTION_RAW_ENCAP_INDEX,
2223 	ACTION_NEXT,
2224 	ZERO,
2225 };
2226 
2227 static const enum index action_raw_decap[] = {
2228 	ACTION_RAW_DECAP_INDEX,
2229 	ACTION_NEXT,
2230 	ZERO,
2231 };
2232 
2233 static const enum index action_set_tag[] = {
2234 	ACTION_SET_TAG_DATA,
2235 	ACTION_SET_TAG_INDEX,
2236 	ACTION_SET_TAG_MASK,
2237 	ACTION_NEXT,
2238 	ZERO,
2239 };
2240 
2241 static const enum index action_set_meta[] = {
2242 	ACTION_SET_META_DATA,
2243 	ACTION_SET_META_MASK,
2244 	ACTION_NEXT,
2245 	ZERO,
2246 };
2247 
2248 static const enum index action_set_ipv4_dscp[] = {
2249 	ACTION_SET_IPV4_DSCP_VALUE,
2250 	ACTION_NEXT,
2251 	ZERO,
2252 };
2253 
2254 static const enum index action_set_ipv6_dscp[] = {
2255 	ACTION_SET_IPV6_DSCP_VALUE,
2256 	ACTION_NEXT,
2257 	ZERO,
2258 };
2259 
2260 static const enum index action_age[] = {
2261 	ACTION_AGE,
2262 	ACTION_AGE_TIMEOUT,
2263 	ACTION_NEXT,
2264 	ZERO,
2265 };
2266 
2267 static const enum index action_age_update[] = {
2268 	ACTION_AGE_UPDATE,
2269 	ACTION_AGE_UPDATE_TIMEOUT,
2270 	ACTION_AGE_UPDATE_TOUCH,
2271 	ACTION_NEXT,
2272 	ZERO,
2273 };
2274 
2275 static const enum index action_sample[] = {
2276 	ACTION_SAMPLE,
2277 	ACTION_SAMPLE_RATIO,
2278 	ACTION_SAMPLE_INDEX,
2279 	ACTION_NEXT,
2280 	ZERO,
2281 };
2282 
2283 static const enum index next_action_sample[] = {
2284 	ACTION_QUEUE,
2285 	ACTION_RSS,
2286 	ACTION_MARK,
2287 	ACTION_COUNT,
2288 	ACTION_PORT_ID,
2289 	ACTION_RAW_ENCAP,
2290 	ACTION_VXLAN_ENCAP,
2291 	ACTION_NVGRE_ENCAP,
2292 	ACTION_NEXT,
2293 	ZERO,
2294 };
2295 
2296 static const enum index action_modify_field_dst[] = {
2297 	ACTION_MODIFY_FIELD_DST_LEVEL,
2298 	ACTION_MODIFY_FIELD_DST_OFFSET,
2299 	ACTION_MODIFY_FIELD_SRC_TYPE,
2300 	ZERO,
2301 };
2302 
2303 static const enum index action_modify_field_src[] = {
2304 	ACTION_MODIFY_FIELD_SRC_LEVEL,
2305 	ACTION_MODIFY_FIELD_SRC_OFFSET,
2306 	ACTION_MODIFY_FIELD_SRC_VALUE,
2307 	ACTION_MODIFY_FIELD_SRC_POINTER,
2308 	ACTION_MODIFY_FIELD_WIDTH,
2309 	ZERO,
2310 };
2311 
2312 static const enum index action_update_conntrack[] = {
2313 	ACTION_CONNTRACK_UPDATE_DIR,
2314 	ACTION_CONNTRACK_UPDATE_CTX,
2315 	ACTION_NEXT,
2316 	ZERO,
2317 };
2318 
2319 static const enum index action_port_representor[] = {
2320 	ACTION_PORT_REPRESENTOR_PORT_ID,
2321 	ACTION_NEXT,
2322 	ZERO,
2323 };
2324 
2325 static const enum index action_represented_port[] = {
2326 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
2327 	ACTION_NEXT,
2328 	ZERO,
2329 };
2330 
2331 static int parse_set_raw_encap_decap(struct context *, const struct token *,
2332 				     const char *, unsigned int,
2333 				     void *, unsigned int);
2334 static int parse_set_sample_action(struct context *, const struct token *,
2335 				   const char *, unsigned int,
2336 				   void *, unsigned int);
2337 static int parse_set_init(struct context *, const struct token *,
2338 			  const char *, unsigned int,
2339 			  void *, unsigned int);
2340 static int
2341 parse_flex_handle(struct context *, const struct token *,
2342 		  const char *, unsigned int, void *, unsigned int);
2343 static int parse_init(struct context *, const struct token *,
2344 		      const char *, unsigned int,
2345 		      void *, unsigned int);
2346 static int parse_vc(struct context *, const struct token *,
2347 		    const char *, unsigned int,
2348 		    void *, unsigned int);
2349 static int parse_vc_spec(struct context *, const struct token *,
2350 			 const char *, unsigned int, void *, unsigned int);
2351 static int parse_vc_conf(struct context *, const struct token *,
2352 			 const char *, unsigned int, void *, unsigned int);
2353 static int parse_vc_conf_timeout(struct context *, const struct token *,
2354 				 const char *, unsigned int, void *,
2355 				 unsigned int);
2356 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
2357 				    const char *, unsigned int,
2358 				    void *, unsigned int);
2359 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *,
2360 				    const char *, unsigned int,
2361 				    void *, unsigned int);
2362 static int parse_vc_action_meter_color_type(struct context *,
2363 					const struct token *,
2364 					const char *, unsigned int, void *,
2365 					unsigned int);
2366 static int parse_vc_action_rss(struct context *, const struct token *,
2367 			       const char *, unsigned int, void *,
2368 			       unsigned int);
2369 static int parse_vc_action_rss_func(struct context *, const struct token *,
2370 				    const char *, unsigned int, void *,
2371 				    unsigned int);
2372 static int parse_vc_action_rss_type(struct context *, const struct token *,
2373 				    const char *, unsigned int, void *,
2374 				    unsigned int);
2375 static int parse_vc_action_rss_queue(struct context *, const struct token *,
2376 				     const char *, unsigned int, void *,
2377 				     unsigned int);
2378 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
2379 				       const char *, unsigned int, void *,
2380 				       unsigned int);
2381 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
2382 				       const char *, unsigned int, void *,
2383 				       unsigned int);
2384 static int parse_vc_action_l2_encap(struct context *, const struct token *,
2385 				    const char *, unsigned int, void *,
2386 				    unsigned int);
2387 static int parse_vc_action_l2_decap(struct context *, const struct token *,
2388 				    const char *, unsigned int, void *,
2389 				    unsigned int);
2390 static int parse_vc_action_mplsogre_encap(struct context *,
2391 					  const struct token *, const char *,
2392 					  unsigned int, void *, unsigned int);
2393 static int parse_vc_action_mplsogre_decap(struct context *,
2394 					  const struct token *, const char *,
2395 					  unsigned int, void *, unsigned int);
2396 static int parse_vc_action_mplsoudp_encap(struct context *,
2397 					  const struct token *, const char *,
2398 					  unsigned int, void *, unsigned int);
2399 static int parse_vc_action_mplsoudp_decap(struct context *,
2400 					  const struct token *, const char *,
2401 					  unsigned int, void *, unsigned int);
2402 static int parse_vc_action_raw_encap(struct context *,
2403 				     const struct token *, const char *,
2404 				     unsigned int, void *, unsigned int);
2405 static int parse_vc_action_raw_decap(struct context *,
2406 				     const struct token *, const char *,
2407 				     unsigned int, void *, unsigned int);
2408 static int parse_vc_action_raw_encap_index(struct context *,
2409 					   const struct token *, const char *,
2410 					   unsigned int, void *, unsigned int);
2411 static int parse_vc_action_raw_decap_index(struct context *,
2412 					   const struct token *, const char *,
2413 					   unsigned int, void *, unsigned int);
2414 static int parse_vc_action_set_meta(struct context *ctx,
2415 				    const struct token *token, const char *str,
2416 				    unsigned int len, void *buf,
2417 					unsigned int size);
2418 static int parse_vc_action_sample(struct context *ctx,
2419 				    const struct token *token, const char *str,
2420 				    unsigned int len, void *buf,
2421 				    unsigned int size);
2422 static int
2423 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
2424 				const char *str, unsigned int len, void *buf,
2425 				unsigned int size);
2426 static int
2427 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
2428 				const char *str, unsigned int len, void *buf,
2429 				unsigned int size);
2430 static int
2431 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
2432 				const char *str, unsigned int len, void *buf,
2433 				unsigned int size);
2434 static int
2435 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
2436 				const char *str, unsigned int len, void *buf,
2437 				unsigned int size);
2438 static int
2439 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
2440 			 const char *str, unsigned int len, void *buf,
2441 			 unsigned int size);
2442 static int parse_destroy(struct context *, const struct token *,
2443 			 const char *, unsigned int,
2444 			 void *, unsigned int);
2445 static int parse_flush(struct context *, const struct token *,
2446 		       const char *, unsigned int,
2447 		       void *, unsigned int);
2448 static int parse_dump(struct context *, const struct token *,
2449 		      const char *, unsigned int,
2450 		      void *, unsigned int);
2451 static int parse_query(struct context *, const struct token *,
2452 		       const char *, unsigned int,
2453 		       void *, unsigned int);
2454 static int parse_action(struct context *, const struct token *,
2455 			const char *, unsigned int,
2456 			void *, unsigned int);
2457 static int parse_list(struct context *, const struct token *,
2458 		      const char *, unsigned int,
2459 		      void *, unsigned int);
2460 static int parse_aged(struct context *, const struct token *,
2461 		      const char *, unsigned int,
2462 		      void *, unsigned int);
2463 static int parse_isolate(struct context *, const struct token *,
2464 			 const char *, unsigned int,
2465 			 void *, unsigned int);
2466 static int parse_configure(struct context *, const struct token *,
2467 			   const char *, unsigned int,
2468 			   void *, unsigned int);
2469 static int parse_template(struct context *, const struct token *,
2470 			  const char *, unsigned int,
2471 			  void *, unsigned int);
2472 static int parse_template_destroy(struct context *, const struct token *,
2473 				  const char *, unsigned int,
2474 				  void *, unsigned int);
2475 static int parse_table(struct context *, const struct token *,
2476 		       const char *, unsigned int, void *, unsigned int);
2477 static int parse_table_destroy(struct context *, const struct token *,
2478 			       const char *, unsigned int,
2479 			       void *, unsigned int);
2480 static int parse_qo(struct context *, const struct token *,
2481 		    const char *, unsigned int,
2482 		    void *, unsigned int);
2483 static int parse_qo_destroy(struct context *, const struct token *,
2484 			    const char *, unsigned int,
2485 			    void *, unsigned int);
2486 static int parse_qia(struct context *, const struct token *,
2487 		     const char *, unsigned int,
2488 		     void *, unsigned int);
2489 static int parse_qia_destroy(struct context *, const struct token *,
2490 			     const char *, unsigned int,
2491 			     void *, unsigned int);
2492 static int parse_push(struct context *, const struct token *,
2493 		      const char *, unsigned int,
2494 		      void *, unsigned int);
2495 static int parse_pull(struct context *, const struct token *,
2496 		      const char *, unsigned int,
2497 		      void *, unsigned int);
2498 static int parse_tunnel(struct context *, const struct token *,
2499 			const char *, unsigned int,
2500 			void *, unsigned int);
2501 static int parse_flex(struct context *, const struct token *,
2502 		      const char *, unsigned int, void *, unsigned int);
2503 static int parse_int(struct context *, const struct token *,
2504 		     const char *, unsigned int,
2505 		     void *, unsigned int);
2506 static int parse_prefix(struct context *, const struct token *,
2507 			const char *, unsigned int,
2508 			void *, unsigned int);
2509 static int parse_boolean(struct context *, const struct token *,
2510 			 const char *, unsigned int,
2511 			 void *, unsigned int);
2512 static int parse_string(struct context *, const struct token *,
2513 			const char *, unsigned int,
2514 			void *, unsigned int);
2515 static int parse_hex(struct context *ctx, const struct token *token,
2516 			const char *str, unsigned int len,
2517 			void *buf, unsigned int size);
2518 static int parse_string0(struct context *, const struct token *,
2519 			const char *, unsigned int,
2520 			void *, unsigned int);
2521 static int parse_mac_addr(struct context *, const struct token *,
2522 			  const char *, unsigned int,
2523 			  void *, unsigned int);
2524 static int parse_ipv4_addr(struct context *, const struct token *,
2525 			   const char *, unsigned int,
2526 			   void *, unsigned int);
2527 static int parse_ipv6_addr(struct context *, const struct token *,
2528 			   const char *, unsigned int,
2529 			   void *, unsigned int);
2530 static int parse_port(struct context *, const struct token *,
2531 		      const char *, unsigned int,
2532 		      void *, unsigned int);
2533 static int parse_ia(struct context *, const struct token *,
2534 		    const char *, unsigned int,
2535 		    void *, unsigned int);
2536 static int parse_ia_destroy(struct context *ctx, const struct token *token,
2537 			    const char *str, unsigned int len,
2538 			    void *buf, unsigned int size);
2539 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
2540 			   const char *str, unsigned int len, void *buf,
2541 			   unsigned int size);
2542 static int parse_ia_port(struct context *ctx, const struct token *token,
2543 			 const char *str, unsigned int len, void *buf,
2544 			 unsigned int size);
2545 static int parse_mp(struct context *, const struct token *,
2546 		    const char *, unsigned int,
2547 		    void *, unsigned int);
2548 static int parse_meter_profile_id2ptr(struct context *ctx,
2549 				      const struct token *token,
2550 				      const char *str, unsigned int len,
2551 				      void *buf, unsigned int size);
2552 static int parse_meter_policy_id2ptr(struct context *ctx,
2553 				     const struct token *token,
2554 				     const char *str, unsigned int len,
2555 				     void *buf, unsigned int size);
2556 static int parse_meter_color(struct context *ctx, const struct token *token,
2557 			     const char *str, unsigned int len, void *buf,
2558 			     unsigned int size);
2559 static int parse_insertion_table_type(struct context *ctx, const struct token *token,
2560 				      const char *str, unsigned int len, void *buf,
2561 				      unsigned int size);
2562 static int parse_hash_table_type(struct context *ctx, const struct token *token,
2563 				 const char *str, unsigned int len, void *buf,
2564 				 unsigned int size);
2565 static int
2566 parse_quota_state_name(struct context *ctx, const struct token *token,
2567 		       const char *str, unsigned int len, void *buf,
2568 		       unsigned int size);
2569 static int
2570 parse_quota_mode_name(struct context *ctx, const struct token *token,
2571 		      const char *str, unsigned int len, void *buf,
2572 		      unsigned int size);
2573 static int
2574 parse_quota_update_name(struct context *ctx, const struct token *token,
2575 			const char *str, unsigned int len, void *buf,
2576 			unsigned int size);
2577 static int
2578 parse_qu_mode_name(struct context *ctx, const struct token *token,
2579 		   const char *str, unsigned int len, void *buf,
2580 		   unsigned int size);
2581 static int comp_none(struct context *, const struct token *,
2582 		     unsigned int, char *, unsigned int);
2583 static int comp_boolean(struct context *, const struct token *,
2584 			unsigned int, char *, unsigned int);
2585 static int comp_action(struct context *, const struct token *,
2586 		       unsigned int, char *, unsigned int);
2587 static int comp_port(struct context *, const struct token *,
2588 		     unsigned int, char *, unsigned int);
2589 static int comp_rule_id(struct context *, const struct token *,
2590 			unsigned int, char *, unsigned int);
2591 static int comp_vc_action_rss_type(struct context *, const struct token *,
2592 				   unsigned int, char *, unsigned int);
2593 static int comp_vc_action_rss_queue(struct context *, const struct token *,
2594 				    unsigned int, char *, unsigned int);
2595 static int comp_set_raw_index(struct context *, const struct token *,
2596 			      unsigned int, char *, unsigned int);
2597 static int comp_set_sample_index(struct context *, const struct token *,
2598 			      unsigned int, char *, unsigned int);
2599 static int comp_set_modify_field_op(struct context *, const struct token *,
2600 			      unsigned int, char *, unsigned int);
2601 static int comp_set_modify_field_id(struct context *, const struct token *,
2602 			      unsigned int, char *, unsigned int);
2603 static int comp_pattern_template_id(struct context *, const struct token *,
2604 				    unsigned int, char *, unsigned int);
2605 static int comp_actions_template_id(struct context *, const struct token *,
2606 				    unsigned int, char *, unsigned int);
2607 static int comp_table_id(struct context *, const struct token *,
2608 			 unsigned int, char *, unsigned int);
2609 static int comp_queue_id(struct context *, const struct token *,
2610 			 unsigned int, char *, unsigned int);
2611 static int comp_meter_color(struct context *, const struct token *,
2612 			    unsigned int, char *, unsigned int);
2613 static int comp_insertion_table_type(struct context *, const struct token *,
2614 				     unsigned int, char *, unsigned int);
2615 static int comp_hash_table_type(struct context *, const struct token *,
2616 				unsigned int, char *, unsigned int);
2617 static int
2618 comp_quota_state_name(struct context *ctx, const struct token *token,
2619 		      unsigned int ent, char *buf, unsigned int size);
2620 static int
2621 comp_quota_mode_name(struct context *ctx, const struct token *token,
2622 		     unsigned int ent, char *buf, unsigned int size);
2623 static int
2624 comp_quota_update_name(struct context *ctx, const struct token *token,
2625 		       unsigned int ent, char *buf, unsigned int size);
2626 static int
2627 comp_qu_mode_name(struct context *ctx, const struct token *token,
2628 		  unsigned int ent, char *buf, unsigned int size);
2629 
2630 /** Token definitions. */
2631 static const struct token token_list[] = {
2632 	/* Special tokens. */
2633 	[ZERO] = {
2634 		.name = "ZERO",
2635 		.help = "null entry, abused as the entry point",
2636 		.next = NEXT(NEXT_ENTRY(FLOW, ADD)),
2637 	},
2638 	[END] = {
2639 		.name = "",
2640 		.type = "RETURN",
2641 		.help = "command may end here",
2642 	},
2643 	[START_SET] = {
2644 		.name = "START_SET",
2645 		.help = "null entry, abused as the entry point for set",
2646 		.next = NEXT(NEXT_ENTRY(SET)),
2647 	},
2648 	[END_SET] = {
2649 		.name = "end_set",
2650 		.type = "RETURN",
2651 		.help = "set command may end here",
2652 	},
2653 	/* Common tokens. */
2654 	[COMMON_INTEGER] = {
2655 		.name = "{int}",
2656 		.type = "INTEGER",
2657 		.help = "integer value",
2658 		.call = parse_int,
2659 		.comp = comp_none,
2660 	},
2661 	[COMMON_UNSIGNED] = {
2662 		.name = "{unsigned}",
2663 		.type = "UNSIGNED",
2664 		.help = "unsigned integer value",
2665 		.call = parse_int,
2666 		.comp = comp_none,
2667 	},
2668 	[COMMON_PREFIX] = {
2669 		.name = "{prefix}",
2670 		.type = "PREFIX",
2671 		.help = "prefix length for bit-mask",
2672 		.call = parse_prefix,
2673 		.comp = comp_none,
2674 	},
2675 	[COMMON_BOOLEAN] = {
2676 		.name = "{boolean}",
2677 		.type = "BOOLEAN",
2678 		.help = "any boolean value",
2679 		.call = parse_boolean,
2680 		.comp = comp_boolean,
2681 	},
2682 	[COMMON_STRING] = {
2683 		.name = "{string}",
2684 		.type = "STRING",
2685 		.help = "fixed string",
2686 		.call = parse_string,
2687 		.comp = comp_none,
2688 	},
2689 	[COMMON_HEX] = {
2690 		.name = "{hex}",
2691 		.type = "HEX",
2692 		.help = "fixed string",
2693 		.call = parse_hex,
2694 	},
2695 	[COMMON_FILE_PATH] = {
2696 		.name = "{file path}",
2697 		.type = "STRING",
2698 		.help = "file path",
2699 		.call = parse_string0,
2700 		.comp = comp_none,
2701 	},
2702 	[COMMON_MAC_ADDR] = {
2703 		.name = "{MAC address}",
2704 		.type = "MAC-48",
2705 		.help = "standard MAC address notation",
2706 		.call = parse_mac_addr,
2707 		.comp = comp_none,
2708 	},
2709 	[COMMON_IPV4_ADDR] = {
2710 		.name = "{IPv4 address}",
2711 		.type = "IPV4 ADDRESS",
2712 		.help = "standard IPv4 address notation",
2713 		.call = parse_ipv4_addr,
2714 		.comp = comp_none,
2715 	},
2716 	[COMMON_IPV6_ADDR] = {
2717 		.name = "{IPv6 address}",
2718 		.type = "IPV6 ADDRESS",
2719 		.help = "standard IPv6 address notation",
2720 		.call = parse_ipv6_addr,
2721 		.comp = comp_none,
2722 	},
2723 	[COMMON_RULE_ID] = {
2724 		.name = "{rule id}",
2725 		.type = "RULE ID",
2726 		.help = "rule identifier",
2727 		.call = parse_int,
2728 		.comp = comp_rule_id,
2729 	},
2730 	[COMMON_PORT_ID] = {
2731 		.name = "{port_id}",
2732 		.type = "PORT ID",
2733 		.help = "port identifier",
2734 		.call = parse_port,
2735 		.comp = comp_port,
2736 	},
2737 	[COMMON_GROUP_ID] = {
2738 		.name = "{group_id}",
2739 		.type = "GROUP ID",
2740 		.help = "group identifier",
2741 		.call = parse_int,
2742 		.comp = comp_none,
2743 	},
2744 	[COMMON_PRIORITY_LEVEL] = {
2745 		.name = "{level}",
2746 		.type = "PRIORITY",
2747 		.help = "priority level",
2748 		.call = parse_int,
2749 		.comp = comp_none,
2750 	},
2751 	[COMMON_INDIRECT_ACTION_ID] = {
2752 		.name = "{indirect_action_id}",
2753 		.type = "INDIRECT_ACTION_ID",
2754 		.help = "indirect action id",
2755 		.call = parse_int,
2756 		.comp = comp_none,
2757 	},
2758 	[COMMON_PROFILE_ID] = {
2759 		.name = "{profile_id}",
2760 		.type = "PROFILE_ID",
2761 		.help = "profile id",
2762 		.call = parse_int,
2763 		.comp = comp_none,
2764 	},
2765 	[COMMON_POLICY_ID] = {
2766 		.name = "{policy_id}",
2767 		.type = "POLICY_ID",
2768 		.help = "policy id",
2769 		.call = parse_int,
2770 		.comp = comp_none,
2771 	},
2772 	[COMMON_FLEX_TOKEN] = {
2773 		.name = "{flex token}",
2774 		.type = "flex token",
2775 		.help = "flex token",
2776 		.call = parse_int,
2777 		.comp = comp_none,
2778 	},
2779 	[COMMON_FLEX_HANDLE] = {
2780 		.name = "{flex handle}",
2781 		.type = "FLEX HANDLE",
2782 		.help = "fill flex item data",
2783 		.call = parse_flex_handle,
2784 		.comp = comp_none,
2785 	},
2786 	[COMMON_PATTERN_TEMPLATE_ID] = {
2787 		.name = "{pattern_template_id}",
2788 		.type = "PATTERN_TEMPLATE_ID",
2789 		.help = "pattern template id",
2790 		.call = parse_int,
2791 		.comp = comp_pattern_template_id,
2792 	},
2793 	[COMMON_ACTIONS_TEMPLATE_ID] = {
2794 		.name = "{actions_template_id}",
2795 		.type = "ACTIONS_TEMPLATE_ID",
2796 		.help = "actions template id",
2797 		.call = parse_int,
2798 		.comp = comp_actions_template_id,
2799 	},
2800 	[COMMON_TABLE_ID] = {
2801 		.name = "{table_id}",
2802 		.type = "TABLE_ID",
2803 		.help = "table id",
2804 		.call = parse_int,
2805 		.comp = comp_table_id,
2806 	},
2807 	[COMMON_QUEUE_ID] = {
2808 		.name = "{queue_id}",
2809 		.type = "QUEUE_ID",
2810 		.help = "queue id",
2811 		.call = parse_int,
2812 		.comp = comp_queue_id,
2813 	},
2814 	/* Top-level command. */
2815 	[FLOW] = {
2816 		.name = "flow",
2817 		.type = "{command} {port_id} [{arg} [...]]",
2818 		.help = "manage ingress/egress flow rules",
2819 		.next = NEXT(NEXT_ENTRY
2820 			     (INFO,
2821 			      CONFIGURE,
2822 			      PATTERN_TEMPLATE,
2823 			      ACTIONS_TEMPLATE,
2824 			      TABLE,
2825 			      INDIRECT_ACTION,
2826 			      VALIDATE,
2827 			      CREATE,
2828 			      DESTROY,
2829 			      FLUSH,
2830 			      DUMP,
2831 			      LIST,
2832 			      AGED,
2833 			      QUERY,
2834 			      ISOLATE,
2835 			      TUNNEL,
2836 			      FLEX,
2837 			      QUEUE,
2838 			      PUSH,
2839 			      PULL)),
2840 		.call = parse_init,
2841 	},
2842 	/* Top-level command. */
2843 	[INFO] = {
2844 		.name = "info",
2845 		.help = "get information about flow engine",
2846 		.next = NEXT(NEXT_ENTRY(END),
2847 			     NEXT_ENTRY(COMMON_PORT_ID)),
2848 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
2849 		.call = parse_configure,
2850 	},
2851 	/* Top-level command. */
2852 	[CONFIGURE] = {
2853 		.name = "configure",
2854 		.help = "configure flow engine",
2855 		.next = NEXT(next_config_attr,
2856 			     NEXT_ENTRY(COMMON_PORT_ID)),
2857 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
2858 		.call = parse_configure,
2859 	},
2860 	/* Configure arguments. */
2861 	[CONFIG_QUEUES_NUMBER] = {
2862 		.name = "queues_number",
2863 		.help = "number of queues",
2864 		.next = NEXT(next_config_attr,
2865 			     NEXT_ENTRY(COMMON_UNSIGNED)),
2866 		.args = ARGS(ARGS_ENTRY(struct buffer,
2867 					args.configure.nb_queue)),
2868 	},
2869 	[CONFIG_QUEUES_SIZE] = {
2870 		.name = "queues_size",
2871 		.help = "number of elements in queues",
2872 		.next = NEXT(next_config_attr,
2873 			     NEXT_ENTRY(COMMON_UNSIGNED)),
2874 		.args = ARGS(ARGS_ENTRY(struct buffer,
2875 					args.configure.queue_attr.size)),
2876 	},
2877 	[CONFIG_COUNTERS_NUMBER] = {
2878 		.name = "counters_number",
2879 		.help = "number of counters",
2880 		.next = NEXT(next_config_attr,
2881 			     NEXT_ENTRY(COMMON_UNSIGNED)),
2882 		.args = ARGS(ARGS_ENTRY(struct buffer,
2883 					args.configure.port_attr.nb_counters)),
2884 	},
2885 	[CONFIG_AGING_OBJECTS_NUMBER] = {
2886 		.name = "aging_counters_number",
2887 		.help = "number of aging objects",
2888 		.next = NEXT(next_config_attr,
2889 			     NEXT_ENTRY(COMMON_UNSIGNED)),
2890 		.args = ARGS(ARGS_ENTRY(struct buffer,
2891 					args.configure.port_attr.nb_aging_objects)),
2892 	},
2893 	[CONFIG_QUOTAS_NUMBER] = {
2894 		.name = "quotas_number",
2895 		.help = "number of quotas",
2896 		.next = NEXT(next_config_attr,
2897 			     NEXT_ENTRY(COMMON_UNSIGNED)),
2898 		.args = ARGS(ARGS_ENTRY(struct buffer,
2899 				     args.configure.port_attr.nb_quotas)),
2900 	},
2901 	[CONFIG_METERS_NUMBER] = {
2902 		.name = "meters_number",
2903 		.help = "number of meters",
2904 		.next = NEXT(next_config_attr,
2905 			     NEXT_ENTRY(COMMON_UNSIGNED)),
2906 		.args = ARGS(ARGS_ENTRY(struct buffer,
2907 					args.configure.port_attr.nb_meters)),
2908 	},
2909 	[CONFIG_CONN_TRACK_NUMBER] = {
2910 		.name = "conn_tracks_number",
2911 		.help = "number of connection trackings",
2912 		.next = NEXT(next_config_attr,
2913 			     NEXT_ENTRY(COMMON_UNSIGNED)),
2914 		.args = ARGS(ARGS_ENTRY(struct buffer,
2915 					args.configure.port_attr.nb_conn_tracks)),
2916 	},
2917 	[CONFIG_FLAGS] = {
2918 		.name = "flags",
2919 		.help = "configuration flags",
2920 		.next = NEXT(next_config_attr,
2921 			     NEXT_ENTRY(COMMON_UNSIGNED)),
2922 		.args = ARGS(ARGS_ENTRY(struct buffer,
2923 					args.configure.port_attr.flags)),
2924 	},
2925 	[CONFIG_HOST_PORT] = {
2926 		.name = "host_port",
2927 		.help = "host port for shared objects",
2928 		.next = NEXT(next_config_attr,
2929 			     NEXT_ENTRY(COMMON_UNSIGNED)),
2930 		.args = ARGS(ARGS_ENTRY(struct buffer,
2931 					args.configure.port_attr.host_port_id)),
2932 	},
2933 	/* Top-level command. */
2934 	[PATTERN_TEMPLATE] = {
2935 		.name = "pattern_template",
2936 		.type = "{command} {port_id} [{arg} [...]]",
2937 		.help = "manage pattern templates",
2938 		.next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2939 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
2940 		.call = parse_template,
2941 	},
2942 	/* Sub-level commands. */
2943 	[PATTERN_TEMPLATE_CREATE] = {
2944 		.name = "create",
2945 		.help = "create pattern template",
2946 		.next = NEXT(next_pt_attr),
2947 		.call = parse_template,
2948 	},
2949 	[PATTERN_TEMPLATE_DESTROY] = {
2950 		.name = "destroy",
2951 		.help = "destroy pattern template",
2952 		.next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)),
2953 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
2954 		.call = parse_template_destroy,
2955 	},
2956 	/* Pattern template arguments. */
2957 	[PATTERN_TEMPLATE_CREATE_ID] = {
2958 		.name = "pattern_template_id",
2959 		.help = "specify a pattern template id to create",
2960 		.next = NEXT(next_pt_attr,
2961 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
2962 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)),
2963 	},
2964 	[PATTERN_TEMPLATE_DESTROY_ID] = {
2965 		.name = "pattern_template",
2966 		.help = "specify a pattern template id to destroy",
2967 		.next = NEXT(next_pt_destroy_attr,
2968 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
2969 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2970 					    args.templ_destroy.template_id)),
2971 		.call = parse_template_destroy,
2972 	},
2973 	[PATTERN_TEMPLATE_RELAXED_MATCHING] = {
2974 		.name = "relaxed",
2975 		.help = "is matching relaxed",
2976 		.next = NEXT(next_pt_attr,
2977 			     NEXT_ENTRY(COMMON_BOOLEAN)),
2978 		.args = ARGS(ARGS_ENTRY_BF(struct buffer,
2979 			     args.vc.attr.reserved, 1)),
2980 	},
2981 	[PATTERN_TEMPLATE_INGRESS] = {
2982 		.name = "ingress",
2983 		.help = "attribute pattern to ingress",
2984 		.next = NEXT(next_pt_attr),
2985 		.call = parse_template,
2986 	},
2987 	[PATTERN_TEMPLATE_EGRESS] = {
2988 		.name = "egress",
2989 		.help = "attribute pattern to egress",
2990 		.next = NEXT(next_pt_attr),
2991 		.call = parse_template,
2992 	},
2993 	[PATTERN_TEMPLATE_TRANSFER] = {
2994 		.name = "transfer",
2995 		.help = "attribute pattern to transfer",
2996 		.next = NEXT(next_pt_attr),
2997 		.call = parse_template,
2998 	},
2999 	[PATTERN_TEMPLATE_SPEC] = {
3000 		.name = "template",
3001 		.help = "specify item to create pattern template",
3002 		.next = NEXT(next_item),
3003 	},
3004 	/* Top-level command. */
3005 	[ACTIONS_TEMPLATE] = {
3006 		.name = "actions_template",
3007 		.type = "{command} {port_id} [{arg} [...]]",
3008 		.help = "manage actions templates",
3009 		.next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3010 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3011 		.call = parse_template,
3012 	},
3013 	/* Sub-level commands. */
3014 	[ACTIONS_TEMPLATE_CREATE] = {
3015 		.name = "create",
3016 		.help = "create actions template",
3017 		.next = NEXT(next_at_attr),
3018 		.call = parse_template,
3019 	},
3020 	[ACTIONS_TEMPLATE_DESTROY] = {
3021 		.name = "destroy",
3022 		.help = "destroy actions template",
3023 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)),
3024 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3025 		.call = parse_template_destroy,
3026 	},
3027 	/* Actions template arguments. */
3028 	[ACTIONS_TEMPLATE_CREATE_ID] = {
3029 		.name = "actions_template_id",
3030 		.help = "specify an actions template id to create",
3031 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK),
3032 			     NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC),
3033 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3034 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)),
3035 	},
3036 	[ACTIONS_TEMPLATE_DESTROY_ID] = {
3037 		.name = "actions_template",
3038 		.help = "specify an actions template id to destroy",
3039 		.next = NEXT(next_at_destroy_attr,
3040 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3041 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3042 					    args.templ_destroy.template_id)),
3043 		.call = parse_template_destroy,
3044 	},
3045 	[ACTIONS_TEMPLATE_INGRESS] = {
3046 		.name = "ingress",
3047 		.help = "attribute actions to ingress",
3048 		.next = NEXT(next_at_attr),
3049 		.call = parse_template,
3050 	},
3051 	[ACTIONS_TEMPLATE_EGRESS] = {
3052 		.name = "egress",
3053 		.help = "attribute actions to egress",
3054 		.next = NEXT(next_at_attr),
3055 		.call = parse_template,
3056 	},
3057 	[ACTIONS_TEMPLATE_TRANSFER] = {
3058 		.name = "transfer",
3059 		.help = "attribute actions to transfer",
3060 		.next = NEXT(next_at_attr),
3061 		.call = parse_template,
3062 	},
3063 	[ACTIONS_TEMPLATE_SPEC] = {
3064 		.name = "template",
3065 		.help = "specify action to create actions template",
3066 		.next = NEXT(next_action),
3067 		.call = parse_template,
3068 	},
3069 	[ACTIONS_TEMPLATE_MASK] = {
3070 		.name = "mask",
3071 		.help = "specify action mask to create actions template",
3072 		.next = NEXT(next_action),
3073 		.call = parse_template,
3074 	},
3075 	/* Top-level command. */
3076 	[TABLE] = {
3077 		.name = "template_table",
3078 		.type = "{command} {port_id} [{arg} [...]]",
3079 		.help = "manage template tables",
3080 		.next = NEXT(next_table_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3081 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3082 		.call = parse_table,
3083 	},
3084 	/* Sub-level commands. */
3085 	[TABLE_CREATE] = {
3086 		.name = "create",
3087 		.help = "create template table",
3088 		.next = NEXT(next_table_attr),
3089 		.call = parse_table,
3090 	},
3091 	[TABLE_DESTROY] = {
3092 		.name = "destroy",
3093 		.help = "destroy template table",
3094 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3095 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3096 		.call = parse_table_destroy,
3097 	},
3098 	/* Table  arguments. */
3099 	[TABLE_CREATE_ID] = {
3100 		.name = "table_id",
3101 		.help = "specify table id to create",
3102 		.next = NEXT(next_table_attr,
3103 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3104 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3105 	},
3106 	[TABLE_DESTROY_ID] = {
3107 		.name = "table",
3108 		.help = "specify table id to destroy",
3109 		.next = NEXT(next_table_destroy_attr,
3110 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3111 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3112 					    args.table_destroy.table_id)),
3113 		.call = parse_table_destroy,
3114 	},
3115 	[TABLE_INSERTION_TYPE] = {
3116 		.name = "insertion_type",
3117 		.help = "specify insertion type",
3118 		.next = NEXT(next_table_attr,
3119 			     NEXT_ENTRY(TABLE_INSERTION_TYPE_NAME)),
3120 		.args = ARGS(ARGS_ENTRY(struct buffer,
3121 					args.table.attr.insertion_type)),
3122 	},
3123 	[TABLE_INSERTION_TYPE_NAME] = {
3124 		.name = "insertion_type_name",
3125 		.help = "insertion type name",
3126 		.call = parse_insertion_table_type,
3127 		.comp = comp_insertion_table_type,
3128 	},
3129 	[TABLE_HASH_FUNC] = {
3130 		.name = "hash_func",
3131 		.help = "specify hash calculation function",
3132 		.next = NEXT(next_table_attr,
3133 			     NEXT_ENTRY(TABLE_HASH_FUNC_NAME)),
3134 		.args = ARGS(ARGS_ENTRY(struct buffer,
3135 					args.table.attr.hash_func)),
3136 	},
3137 	[TABLE_HASH_FUNC_NAME] = {
3138 		.name = "hash_func_name",
3139 		.help = "hash calculation function name",
3140 		.call = parse_hash_table_type,
3141 		.comp = comp_hash_table_type,
3142 	},
3143 	[TABLE_GROUP] = {
3144 		.name = "group",
3145 		.help = "specify a group",
3146 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3147 		.args = ARGS(ARGS_ENTRY(struct buffer,
3148 					args.table.attr.flow_attr.group)),
3149 	},
3150 	[TABLE_PRIORITY] = {
3151 		.name = "priority",
3152 		.help = "specify a priority level",
3153 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
3154 		.args = ARGS(ARGS_ENTRY(struct buffer,
3155 					args.table.attr.flow_attr.priority)),
3156 	},
3157 	[TABLE_EGRESS] = {
3158 		.name = "egress",
3159 		.help = "affect rule to egress",
3160 		.next = NEXT(next_table_attr),
3161 		.call = parse_table,
3162 	},
3163 	[TABLE_INGRESS] = {
3164 		.name = "ingress",
3165 		.help = "affect rule to ingress",
3166 		.next = NEXT(next_table_attr),
3167 		.call = parse_table,
3168 	},
3169 	[TABLE_TRANSFER] = {
3170 		.name = "transfer",
3171 		.help = "affect rule to transfer",
3172 		.next = NEXT(next_table_attr),
3173 		.call = parse_table,
3174 	},
3175 	[TABLE_TRANSFER_WIRE_ORIG] = {
3176 		.name = "wire_orig",
3177 		.help = "affect rule direction to transfer",
3178 		.next = NEXT(next_table_attr),
3179 		.call = parse_table,
3180 	},
3181 	[TABLE_TRANSFER_VPORT_ORIG] = {
3182 		.name = "vport_orig",
3183 		.help = "affect rule direction to transfer",
3184 		.next = NEXT(next_table_attr),
3185 		.call = parse_table,
3186 	},
3187 	[TABLE_RULES_NUMBER] = {
3188 		.name = "rules_number",
3189 		.help = "number of rules in table",
3190 		.next = NEXT(next_table_attr,
3191 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3192 		.args = ARGS(ARGS_ENTRY(struct buffer,
3193 					args.table.attr.nb_flows)),
3194 	},
3195 	[TABLE_PATTERN_TEMPLATE] = {
3196 		.name = "pattern_template",
3197 		.help = "specify pattern template id",
3198 		.next = NEXT(next_table_attr,
3199 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3200 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3201 					    args.table.pat_templ_id)),
3202 		.call = parse_table,
3203 	},
3204 	[TABLE_ACTIONS_TEMPLATE] = {
3205 		.name = "actions_template",
3206 		.help = "specify actions template id",
3207 		.next = NEXT(next_table_attr,
3208 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3209 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3210 					    args.table.act_templ_id)),
3211 		.call = parse_table,
3212 	},
3213 	/* Top-level command. */
3214 	[QUEUE] = {
3215 		.name = "queue",
3216 		.help = "queue a flow rule operation",
3217 		.next = NEXT(next_queue_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3218 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3219 		.call = parse_qo,
3220 	},
3221 	/* Sub-level commands. */
3222 	[QUEUE_CREATE] = {
3223 		.name = "create",
3224 		.help = "create a flow rule",
3225 		.next = NEXT(NEXT_ENTRY(QUEUE_TEMPLATE_TABLE),
3226 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3227 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3228 		.call = parse_qo,
3229 	},
3230 	[QUEUE_DESTROY] = {
3231 		.name = "destroy",
3232 		.help = "destroy a flow rule",
3233 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3234 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3235 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3236 		.call = parse_qo_destroy,
3237 	},
3238 	[QUEUE_AGED] = {
3239 		.name = "aged",
3240 		.help = "list and destroy aged flows",
3241 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_QUEUE_ID)),
3242 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3243 		.call = parse_aged,
3244 	},
3245 	[QUEUE_INDIRECT_ACTION] = {
3246 		.name = "indirect_action",
3247 		.help = "queue indirect actions",
3248 		.next = NEXT(next_qia_subcmd, NEXT_ENTRY(COMMON_QUEUE_ID)),
3249 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3250 		.call = parse_qia,
3251 	},
3252 	/* Queue  arguments. */
3253 	[QUEUE_TEMPLATE_TABLE] = {
3254 		.name = "template_table",
3255 		.help = "specify table id",
3256 		.next = NEXT(next_async_insert_subcmd,
3257 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3258 		.args = ARGS(ARGS_ENTRY(struct buffer,
3259 					args.vc.table_id)),
3260 		.call = parse_qo,
3261 	},
3262 	[QUEUE_PATTERN_TEMPLATE] = {
3263 		.name = "pattern_template",
3264 		.help = "specify pattern template index",
3265 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3266 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3267 		.args = ARGS(ARGS_ENTRY(struct buffer,
3268 					args.vc.pat_templ_id)),
3269 		.call = parse_qo,
3270 	},
3271 	[QUEUE_ACTIONS_TEMPLATE] = {
3272 		.name = "actions_template",
3273 		.help = "specify actions template index",
3274 		.next = NEXT(NEXT_ENTRY(QUEUE_CREATE_POSTPONE),
3275 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3276 		.args = ARGS(ARGS_ENTRY(struct buffer,
3277 					args.vc.act_templ_id)),
3278 		.call = parse_qo,
3279 	},
3280 	[QUEUE_RULE_ID] = {
3281 		.name = "rule_index",
3282 		.help = "specify flow rule index",
3283 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3284 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3285 		.args = ARGS(ARGS_ENTRY(struct buffer,
3286 					args.vc.rule_id)),
3287 		.call = parse_qo,
3288 	},
3289 	[QUEUE_CREATE_POSTPONE] = {
3290 		.name = "postpone",
3291 		.help = "postpone create operation",
3292 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
3293 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3294 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3295 		.call = parse_qo,
3296 	},
3297 	[QUEUE_DESTROY_POSTPONE] = {
3298 		.name = "postpone",
3299 		.help = "postpone destroy operation",
3300 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3301 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3302 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3303 		.call = parse_qo_destroy,
3304 	},
3305 	[QUEUE_DESTROY_ID] = {
3306 		.name = "rule",
3307 		.help = "specify rule id to destroy",
3308 		.next = NEXT(next_queue_destroy_attr,
3309 			NEXT_ENTRY(COMMON_UNSIGNED)),
3310 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3311 					    args.destroy.rule)),
3312 		.call = parse_qo_destroy,
3313 	},
3314 	/* Queue indirect action arguments */
3315 	[QUEUE_INDIRECT_ACTION_CREATE] = {
3316 		.name = "create",
3317 		.help = "create indirect action",
3318 		.next = NEXT(next_qia_create_attr),
3319 		.call = parse_qia,
3320 	},
3321 	[QUEUE_INDIRECT_ACTION_UPDATE] = {
3322 		.name = "update",
3323 		.help = "update indirect action",
3324 		.next = NEXT(next_qia_update_attr,
3325 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3326 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3327 		.call = parse_qia,
3328 	},
3329 	[QUEUE_INDIRECT_ACTION_DESTROY] = {
3330 		.name = "destroy",
3331 		.help = "destroy indirect action",
3332 		.next = NEXT(next_qia_destroy_attr),
3333 		.call = parse_qia_destroy,
3334 	},
3335 	[QUEUE_INDIRECT_ACTION_QUERY] = {
3336 		.name = "query",
3337 		.help = "query indirect action",
3338 		.next = NEXT(next_qia_query_attr,
3339 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3340 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3341 		.call = parse_qia,
3342 	},
3343 	/* Indirect action destroy arguments. */
3344 	[QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE] = {
3345 		.name = "postpone",
3346 		.help = "postpone destroy operation",
3347 		.next = NEXT(next_qia_destroy_attr,
3348 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3349 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3350 	},
3351 	[QUEUE_INDIRECT_ACTION_DESTROY_ID] = {
3352 		.name = "action_id",
3353 		.help = "specify a indirect action id to destroy",
3354 		.next = NEXT(next_qia_destroy_attr,
3355 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3356 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3357 					    args.ia_destroy.action_id)),
3358 		.call = parse_qia_destroy,
3359 	},
3360 	[QUEUE_INDIRECT_ACTION_QUERY_UPDATE] = {
3361 		.name = "query_update",
3362 		.help = "indirect query [and|or] update action",
3363 		.next = NEXT(next_qia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3364 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3365 		.call = parse_qia
3366 	},
3367 	[QUEUE_INDIRECT_ACTION_QU_MODE] = {
3368 		.name = "mode",
3369 		.help = "indirect query [and|or] update action",
3370 		.next = NEXT(next_qia_qu_attr,
3371 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
3372 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
3373 		.call = parse_qia
3374 	},
3375 	/* Indirect action update arguments. */
3376 	[QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE] = {
3377 		.name = "postpone",
3378 		.help = "postpone update operation",
3379 		.next = NEXT(next_qia_update_attr,
3380 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3381 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3382 	},
3383 	/* Indirect action update arguments. */
3384 	[QUEUE_INDIRECT_ACTION_QUERY_POSTPONE] = {
3385 		.name = "postpone",
3386 		.help = "postpone query operation",
3387 		.next = NEXT(next_qia_query_attr,
3388 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3389 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3390 	},
3391 	/* Indirect action create arguments. */
3392 	[QUEUE_INDIRECT_ACTION_CREATE_ID] = {
3393 		.name = "action_id",
3394 		.help = "specify a indirect action id to create",
3395 		.next = NEXT(next_qia_create_attr,
3396 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3397 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3398 	},
3399 	[QUEUE_INDIRECT_ACTION_INGRESS] = {
3400 		.name = "ingress",
3401 		.help = "affect rule to ingress",
3402 		.next = NEXT(next_qia_create_attr),
3403 		.call = parse_qia,
3404 	},
3405 	[QUEUE_INDIRECT_ACTION_EGRESS] = {
3406 		.name = "egress",
3407 		.help = "affect rule to egress",
3408 		.next = NEXT(next_qia_create_attr),
3409 		.call = parse_qia,
3410 	},
3411 	[QUEUE_INDIRECT_ACTION_TRANSFER] = {
3412 		.name = "transfer",
3413 		.help = "affect rule to transfer",
3414 		.next = NEXT(next_qia_create_attr),
3415 		.call = parse_qia,
3416 	},
3417 	[QUEUE_INDIRECT_ACTION_CREATE_POSTPONE] = {
3418 		.name = "postpone",
3419 		.help = "postpone create operation",
3420 		.next = NEXT(next_qia_create_attr,
3421 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3422 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3423 	},
3424 	[QUEUE_INDIRECT_ACTION_SPEC] = {
3425 		.name = "action",
3426 		.help = "specify action to create indirect handle",
3427 		.next = NEXT(next_action),
3428 	},
3429 	/* Top-level command. */
3430 	[PUSH] = {
3431 		.name = "push",
3432 		.help = "push enqueued operations",
3433 		.next = NEXT(NEXT_ENTRY(PUSH_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3434 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3435 		.call = parse_push,
3436 	},
3437 	/* Sub-level commands. */
3438 	[PUSH_QUEUE] = {
3439 		.name = "queue",
3440 		.help = "specify queue id",
3441 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3442 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3443 	},
3444 	/* Top-level command. */
3445 	[PULL] = {
3446 		.name = "pull",
3447 		.help = "pull flow operations results",
3448 		.next = NEXT(NEXT_ENTRY(PULL_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3449 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3450 		.call = parse_pull,
3451 	},
3452 	/* Sub-level commands. */
3453 	[PULL_QUEUE] = {
3454 		.name = "queue",
3455 		.help = "specify queue id",
3456 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3457 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3458 	},
3459 	/* Top-level command. */
3460 	[INDIRECT_ACTION] = {
3461 		.name = "indirect_action",
3462 		.type = "{command} {port_id} [{arg} [...]]",
3463 		.help = "manage indirect actions",
3464 		.next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3465 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3466 		.call = parse_ia,
3467 	},
3468 	/* Sub-level commands. */
3469 	[INDIRECT_ACTION_CREATE] = {
3470 		.name = "create",
3471 		.help = "create indirect action",
3472 		.next = NEXT(next_ia_create_attr),
3473 		.call = parse_ia,
3474 	},
3475 	[INDIRECT_ACTION_UPDATE] = {
3476 		.name = "update",
3477 		.help = "update indirect action",
3478 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
3479 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3480 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3481 		.call = parse_ia,
3482 	},
3483 	[INDIRECT_ACTION_DESTROY] = {
3484 		.name = "destroy",
3485 		.help = "destroy indirect action",
3486 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
3487 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3488 		.call = parse_ia_destroy,
3489 	},
3490 	[INDIRECT_ACTION_QUERY] = {
3491 		.name = "query",
3492 		.help = "query indirect action",
3493 		.next = NEXT(NEXT_ENTRY(END),
3494 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3495 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3496 		.call = parse_ia,
3497 	},
3498 	[INDIRECT_ACTION_QUERY_UPDATE] = {
3499 		.name = "query_update",
3500 		.help = "query [and|or] update",
3501 		.next = NEXT(next_ia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3502 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3503 		.call = parse_ia
3504 	},
3505 	[INDIRECT_ACTION_QU_MODE] = {
3506 		.name = "mode",
3507 		.help = "query_update mode",
3508 		.next = NEXT(next_ia_qu_attr,
3509 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
3510 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
3511 		.call = parse_ia,
3512 	},
3513 	[INDIRECT_ACTION_QU_MODE_NAME] = {
3514 		.name = "mode_name",
3515 		.help = "query-update mode name",
3516 		.call = parse_qu_mode_name,
3517 		.comp = comp_qu_mode_name,
3518 	},
3519 	[VALIDATE] = {
3520 		.name = "validate",
3521 		.help = "check whether a flow rule can be created",
3522 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
3523 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3524 		.call = parse_vc,
3525 	},
3526 	[CREATE] = {
3527 		.name = "create",
3528 		.help = "create a flow rule",
3529 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
3530 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3531 		.call = parse_vc,
3532 	},
3533 	[DESTROY] = {
3534 		.name = "destroy",
3535 		.help = "destroy specific flow rules",
3536 		.next = NEXT(NEXT_ENTRY(DESTROY_RULE),
3537 			     NEXT_ENTRY(COMMON_PORT_ID)),
3538 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3539 		.call = parse_destroy,
3540 	},
3541 	[FLUSH] = {
3542 		.name = "flush",
3543 		.help = "destroy all flow rules",
3544 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
3545 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3546 		.call = parse_flush,
3547 	},
3548 	[DUMP] = {
3549 		.name = "dump",
3550 		.help = "dump single/all flow rules to file",
3551 		.next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3552 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3553 		.call = parse_dump,
3554 	},
3555 	[QUERY] = {
3556 		.name = "query",
3557 		.help = "query an existing flow rule",
3558 		.next = NEXT(NEXT_ENTRY(QUERY_ACTION),
3559 			     NEXT_ENTRY(COMMON_RULE_ID),
3560 			     NEXT_ENTRY(COMMON_PORT_ID)),
3561 		.args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
3562 			     ARGS_ENTRY(struct buffer, args.query.rule),
3563 			     ARGS_ENTRY(struct buffer, port)),
3564 		.call = parse_query,
3565 	},
3566 	[LIST] = {
3567 		.name = "list",
3568 		.help = "list existing flow rules",
3569 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
3570 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3571 		.call = parse_list,
3572 	},
3573 	[AGED] = {
3574 		.name = "aged",
3575 		.help = "list and destroy aged flows",
3576 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
3577 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3578 		.call = parse_aged,
3579 	},
3580 	[ISOLATE] = {
3581 		.name = "isolate",
3582 		.help = "restrict ingress traffic to the defined flow rules",
3583 		.next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
3584 			     NEXT_ENTRY(COMMON_PORT_ID)),
3585 		.args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
3586 			     ARGS_ENTRY(struct buffer, port)),
3587 		.call = parse_isolate,
3588 	},
3589 	[FLEX] = {
3590 		.name = "flex_item",
3591 		.help = "flex item API",
3592 		.next = NEXT(next_flex_item),
3593 		.call = parse_flex,
3594 	},
3595 	[FLEX_ITEM_INIT] = {
3596 		.name = "init",
3597 		.help = "flex item init",
3598 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
3599 			     ARGS_ENTRY(struct buffer, port)),
3600 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
3601 			     NEXT_ENTRY(COMMON_PORT_ID)),
3602 		.call = parse_flex
3603 	},
3604 	[FLEX_ITEM_CREATE] = {
3605 		.name = "create",
3606 		.help = "flex item create",
3607 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename),
3608 			     ARGS_ENTRY(struct buffer, args.flex.token),
3609 			     ARGS_ENTRY(struct buffer, port)),
3610 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH),
3611 			     NEXT_ENTRY(COMMON_FLEX_TOKEN),
3612 			     NEXT_ENTRY(COMMON_PORT_ID)),
3613 		.call = parse_flex
3614 	},
3615 	[FLEX_ITEM_DESTROY] = {
3616 		.name = "destroy",
3617 		.help = "flex item destroy",
3618 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
3619 			     ARGS_ENTRY(struct buffer, port)),
3620 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
3621 			     NEXT_ENTRY(COMMON_PORT_ID)),
3622 		.call = parse_flex
3623 	},
3624 	[TUNNEL] = {
3625 		.name = "tunnel",
3626 		.help = "new tunnel API",
3627 		.next = NEXT(NEXT_ENTRY
3628 			     (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
3629 		.call = parse_tunnel,
3630 	},
3631 	/* Tunnel arguments. */
3632 	[TUNNEL_CREATE] = {
3633 		.name = "create",
3634 		.help = "create new tunnel object",
3635 		.next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
3636 			     NEXT_ENTRY(COMMON_PORT_ID)),
3637 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3638 		.call = parse_tunnel,
3639 	},
3640 	[TUNNEL_CREATE_TYPE] = {
3641 		.name = "type",
3642 		.help = "create new tunnel",
3643 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
3644 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
3645 		.call = parse_tunnel,
3646 	},
3647 	[TUNNEL_DESTROY] = {
3648 		.name = "destroy",
3649 		.help = "destroy tunnel",
3650 		.next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
3651 			     NEXT_ENTRY(COMMON_PORT_ID)),
3652 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3653 		.call = parse_tunnel,
3654 	},
3655 	[TUNNEL_DESTROY_ID] = {
3656 		.name = "id",
3657 		.help = "tunnel identifier to destroy",
3658 		.next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
3659 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
3660 		.call = parse_tunnel,
3661 	},
3662 	[TUNNEL_LIST] = {
3663 		.name = "list",
3664 		.help = "list existing tunnels",
3665 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
3666 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3667 		.call = parse_tunnel,
3668 	},
3669 	/* Destroy arguments. */
3670 	[DESTROY_RULE] = {
3671 		.name = "rule",
3672 		.help = "specify a rule identifier",
3673 		.next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
3674 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
3675 		.call = parse_destroy,
3676 	},
3677 	/* Dump arguments. */
3678 	[DUMP_ALL] = {
3679 		.name = "all",
3680 		.help = "dump all",
3681 		.next = NEXT(next_dump_attr),
3682 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
3683 		.call = parse_dump,
3684 	},
3685 	[DUMP_ONE] = {
3686 		.name = "rule",
3687 		.help = "dump one rule",
3688 		.next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
3689 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
3690 				ARGS_ENTRY(struct buffer, args.dump.rule)),
3691 		.call = parse_dump,
3692 	},
3693 	/* Query arguments. */
3694 	[QUERY_ACTION] = {
3695 		.name = "{action}",
3696 		.type = "ACTION",
3697 		.help = "action to query, must be part of the rule",
3698 		.call = parse_action,
3699 		.comp = comp_action,
3700 	},
3701 	/* List arguments. */
3702 	[LIST_GROUP] = {
3703 		.name = "group",
3704 		.help = "specify a group",
3705 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3706 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
3707 		.call = parse_list,
3708 	},
3709 	[AGED_DESTROY] = {
3710 		.name = "destroy",
3711 		.help = "specify aged flows need be destroyed",
3712 		.call = parse_aged,
3713 		.comp = comp_none,
3714 	},
3715 	/* Validate/create attributes. */
3716 	[VC_GROUP] = {
3717 		.name = "group",
3718 		.help = "specify a group",
3719 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3720 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
3721 		.call = parse_vc,
3722 	},
3723 	[VC_PRIORITY] = {
3724 		.name = "priority",
3725 		.help = "specify a priority level",
3726 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
3727 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
3728 		.call = parse_vc,
3729 	},
3730 	[VC_INGRESS] = {
3731 		.name = "ingress",
3732 		.help = "affect rule to ingress",
3733 		.next = NEXT(next_vc_attr),
3734 		.call = parse_vc,
3735 	},
3736 	[VC_EGRESS] = {
3737 		.name = "egress",
3738 		.help = "affect rule to egress",
3739 		.next = NEXT(next_vc_attr),
3740 		.call = parse_vc,
3741 	},
3742 	[VC_TRANSFER] = {
3743 		.name = "transfer",
3744 		.help = "apply rule directly to endpoints found in pattern",
3745 		.next = NEXT(next_vc_attr),
3746 		.call = parse_vc,
3747 	},
3748 	[VC_TUNNEL_SET] = {
3749 		.name = "tunnel_set",
3750 		.help = "tunnel steer rule",
3751 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
3752 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
3753 		.call = parse_vc,
3754 	},
3755 	[VC_TUNNEL_MATCH] = {
3756 		.name = "tunnel_match",
3757 		.help = "tunnel match rule",
3758 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
3759 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
3760 		.call = parse_vc,
3761 	},
3762 	/* Validate/create pattern. */
3763 	[ITEM_PATTERN] = {
3764 		.name = "pattern",
3765 		.help = "submit a list of pattern items",
3766 		.next = NEXT(next_item),
3767 		.call = parse_vc,
3768 	},
3769 	[ITEM_PARAM_IS] = {
3770 		.name = "is",
3771 		.help = "match value perfectly (with full bit-mask)",
3772 		.call = parse_vc_spec,
3773 	},
3774 	[ITEM_PARAM_SPEC] = {
3775 		.name = "spec",
3776 		.help = "match value according to configured bit-mask",
3777 		.call = parse_vc_spec,
3778 	},
3779 	[ITEM_PARAM_LAST] = {
3780 		.name = "last",
3781 		.help = "specify upper bound to establish a range",
3782 		.call = parse_vc_spec,
3783 	},
3784 	[ITEM_PARAM_MASK] = {
3785 		.name = "mask",
3786 		.help = "specify bit-mask with relevant bits set to one",
3787 		.call = parse_vc_spec,
3788 	},
3789 	[ITEM_PARAM_PREFIX] = {
3790 		.name = "prefix",
3791 		.help = "generate bit-mask from a prefix length",
3792 		.call = parse_vc_spec,
3793 	},
3794 	[ITEM_NEXT] = {
3795 		.name = "/",
3796 		.help = "specify next pattern item",
3797 		.next = NEXT(next_item),
3798 	},
3799 	[ITEM_END] = {
3800 		.name = "end",
3801 		.help = "end list of pattern items",
3802 		.priv = PRIV_ITEM(END, 0),
3803 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
3804 		.call = parse_vc,
3805 	},
3806 	[ITEM_VOID] = {
3807 		.name = "void",
3808 		.help = "no-op pattern item",
3809 		.priv = PRIV_ITEM(VOID, 0),
3810 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
3811 		.call = parse_vc,
3812 	},
3813 	[ITEM_INVERT] = {
3814 		.name = "invert",
3815 		.help = "perform actions when pattern does not match",
3816 		.priv = PRIV_ITEM(INVERT, 0),
3817 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
3818 		.call = parse_vc,
3819 	},
3820 	[ITEM_ANY] = {
3821 		.name = "any",
3822 		.help = "match any protocol for the current layer",
3823 		.priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
3824 		.next = NEXT(item_any),
3825 		.call = parse_vc,
3826 	},
3827 	[ITEM_ANY_NUM] = {
3828 		.name = "num",
3829 		.help = "number of layers covered",
3830 		.next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3831 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
3832 	},
3833 	[ITEM_PORT_ID] = {
3834 		.name = "port_id",
3835 		.help = "match traffic from/to a given DPDK port ID",
3836 		.priv = PRIV_ITEM(PORT_ID,
3837 				  sizeof(struct rte_flow_item_port_id)),
3838 		.next = NEXT(item_port_id),
3839 		.call = parse_vc,
3840 	},
3841 	[ITEM_PORT_ID_ID] = {
3842 		.name = "id",
3843 		.help = "DPDK port ID",
3844 		.next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
3845 			     item_param),
3846 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
3847 	},
3848 	[ITEM_MARK] = {
3849 		.name = "mark",
3850 		.help = "match traffic against value set in previously matched rule",
3851 		.priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
3852 		.next = NEXT(item_mark),
3853 		.call = parse_vc,
3854 	},
3855 	[ITEM_MARK_ID] = {
3856 		.name = "id",
3857 		.help = "Integer value to match against",
3858 		.next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
3859 			     item_param),
3860 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
3861 	},
3862 	[ITEM_RAW] = {
3863 		.name = "raw",
3864 		.help = "match an arbitrary byte string",
3865 		.priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
3866 		.next = NEXT(item_raw),
3867 		.call = parse_vc,
3868 	},
3869 	[ITEM_RAW_RELATIVE] = {
3870 		.name = "relative",
3871 		.help = "look for pattern after the previous item",
3872 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3873 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
3874 					   relative, 1)),
3875 	},
3876 	[ITEM_RAW_SEARCH] = {
3877 		.name = "search",
3878 		.help = "search pattern from offset (see also limit)",
3879 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3880 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
3881 					   search, 1)),
3882 	},
3883 	[ITEM_RAW_OFFSET] = {
3884 		.name = "offset",
3885 		.help = "absolute or relative offset for pattern",
3886 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
3887 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
3888 	},
3889 	[ITEM_RAW_LIMIT] = {
3890 		.name = "limit",
3891 		.help = "search area limit for start of pattern",
3892 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3893 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
3894 	},
3895 	[ITEM_RAW_PATTERN] = {
3896 		.name = "pattern",
3897 		.help = "byte string to look for",
3898 		.next = NEXT(item_raw,
3899 			     NEXT_ENTRY(COMMON_STRING),
3900 			     NEXT_ENTRY(ITEM_PARAM_IS,
3901 					ITEM_PARAM_SPEC,
3902 					ITEM_PARAM_MASK)),
3903 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
3904 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
3905 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
3906 					    ITEM_RAW_PATTERN_SIZE)),
3907 	},
3908 	[ITEM_RAW_PATTERN_HEX] = {
3909 		.name = "pattern_hex",
3910 		.help = "hex string to look for",
3911 		.next = NEXT(item_raw,
3912 			     NEXT_ENTRY(COMMON_HEX),
3913 			     NEXT_ENTRY(ITEM_PARAM_IS,
3914 					ITEM_PARAM_SPEC,
3915 					ITEM_PARAM_MASK)),
3916 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
3917 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
3918 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
3919 					    ITEM_RAW_PATTERN_SIZE)),
3920 	},
3921 	[ITEM_ETH] = {
3922 		.name = "eth",
3923 		.help = "match Ethernet header",
3924 		.priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
3925 		.next = NEXT(item_eth),
3926 		.call = parse_vc,
3927 	},
3928 	[ITEM_ETH_DST] = {
3929 		.name = "dst",
3930 		.help = "destination MAC",
3931 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3932 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.dst_addr)),
3933 	},
3934 	[ITEM_ETH_SRC] = {
3935 		.name = "src",
3936 		.help = "source MAC",
3937 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3938 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.src_addr)),
3939 	},
3940 	[ITEM_ETH_TYPE] = {
3941 		.name = "type",
3942 		.help = "EtherType",
3943 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3944 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.ether_type)),
3945 	},
3946 	[ITEM_ETH_HAS_VLAN] = {
3947 		.name = "has_vlan",
3948 		.help = "packet header contains VLAN",
3949 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3950 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
3951 					   has_vlan, 1)),
3952 	},
3953 	[ITEM_VLAN] = {
3954 		.name = "vlan",
3955 		.help = "match 802.1Q/ad VLAN tag",
3956 		.priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
3957 		.next = NEXT(item_vlan),
3958 		.call = parse_vc,
3959 	},
3960 	[ITEM_VLAN_TCI] = {
3961 		.name = "tci",
3962 		.help = "tag control information",
3963 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3964 			     item_param),
3965 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, hdr.vlan_tci)),
3966 	},
3967 	[ITEM_VLAN_PCP] = {
3968 		.name = "pcp",
3969 		.help = "priority code point",
3970 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3971 			     item_param),
3972 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
3973 						  hdr.vlan_tci, "\xe0\x00")),
3974 	},
3975 	[ITEM_VLAN_DEI] = {
3976 		.name = "dei",
3977 		.help = "drop eligible indicator",
3978 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3979 			     item_param),
3980 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
3981 						  hdr.vlan_tci, "\x10\x00")),
3982 	},
3983 	[ITEM_VLAN_VID] = {
3984 		.name = "vid",
3985 		.help = "VLAN identifier",
3986 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3987 			     item_param),
3988 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
3989 						  hdr.vlan_tci, "\x0f\xff")),
3990 	},
3991 	[ITEM_VLAN_INNER_TYPE] = {
3992 		.name = "inner_type",
3993 		.help = "inner EtherType",
3994 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3995 			     item_param),
3996 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
3997 					     hdr.eth_proto)),
3998 	},
3999 	[ITEM_VLAN_HAS_MORE_VLAN] = {
4000 		.name = "has_more_vlan",
4001 		.help = "packet header contains another VLAN",
4002 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4003 			     item_param),
4004 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
4005 					   has_more_vlan, 1)),
4006 	},
4007 	[ITEM_IPV4] = {
4008 		.name = "ipv4",
4009 		.help = "match IPv4 header",
4010 		.priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
4011 		.next = NEXT(item_ipv4),
4012 		.call = parse_vc,
4013 	},
4014 	[ITEM_IPV4_VER_IHL] = {
4015 		.name = "version_ihl",
4016 		.help = "match header length",
4017 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4018 			     item_param),
4019 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
4020 				     hdr.version_ihl)),
4021 	},
4022 	[ITEM_IPV4_TOS] = {
4023 		.name = "tos",
4024 		.help = "type of service",
4025 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4026 			     item_param),
4027 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4028 					     hdr.type_of_service)),
4029 	},
4030 	[ITEM_IPV4_ID] = {
4031 		.name = "packet_id",
4032 		.help = "fragment packet id",
4033 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4034 			     item_param),
4035 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4036 					     hdr.packet_id)),
4037 	},
4038 	[ITEM_IPV4_FRAGMENT_OFFSET] = {
4039 		.name = "fragment_offset",
4040 		.help = "fragmentation flags and fragment offset",
4041 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4042 			     item_param),
4043 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4044 					     hdr.fragment_offset)),
4045 	},
4046 	[ITEM_IPV4_TTL] = {
4047 		.name = "ttl",
4048 		.help = "time to live",
4049 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4050 			     item_param),
4051 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4052 					     hdr.time_to_live)),
4053 	},
4054 	[ITEM_IPV4_PROTO] = {
4055 		.name = "proto",
4056 		.help = "next protocol ID",
4057 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4058 			     item_param),
4059 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4060 					     hdr.next_proto_id)),
4061 	},
4062 	[ITEM_IPV4_SRC] = {
4063 		.name = "src",
4064 		.help = "source address",
4065 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4066 			     item_param),
4067 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4068 					     hdr.src_addr)),
4069 	},
4070 	[ITEM_IPV4_DST] = {
4071 		.name = "dst",
4072 		.help = "destination address",
4073 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4074 			     item_param),
4075 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4076 					     hdr.dst_addr)),
4077 	},
4078 	[ITEM_IPV6] = {
4079 		.name = "ipv6",
4080 		.help = "match IPv6 header",
4081 		.priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
4082 		.next = NEXT(item_ipv6),
4083 		.call = parse_vc,
4084 	},
4085 	[ITEM_IPV6_TC] = {
4086 		.name = "tc",
4087 		.help = "traffic class",
4088 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4089 			     item_param),
4090 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4091 						  hdr.vtc_flow,
4092 						  "\x0f\xf0\x00\x00")),
4093 	},
4094 	[ITEM_IPV6_FLOW] = {
4095 		.name = "flow",
4096 		.help = "flow label",
4097 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4098 			     item_param),
4099 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4100 						  hdr.vtc_flow,
4101 						  "\x00\x0f\xff\xff")),
4102 	},
4103 	[ITEM_IPV6_PROTO] = {
4104 		.name = "proto",
4105 		.help = "protocol (next header)",
4106 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4107 			     item_param),
4108 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4109 					     hdr.proto)),
4110 	},
4111 	[ITEM_IPV6_HOP] = {
4112 		.name = "hop",
4113 		.help = "hop limit",
4114 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4115 			     item_param),
4116 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4117 					     hdr.hop_limits)),
4118 	},
4119 	[ITEM_IPV6_SRC] = {
4120 		.name = "src",
4121 		.help = "source address",
4122 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4123 			     item_param),
4124 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4125 					     hdr.src_addr)),
4126 	},
4127 	[ITEM_IPV6_DST] = {
4128 		.name = "dst",
4129 		.help = "destination address",
4130 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4131 			     item_param),
4132 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4133 					     hdr.dst_addr)),
4134 	},
4135 	[ITEM_IPV6_HAS_FRAG_EXT] = {
4136 		.name = "has_frag_ext",
4137 		.help = "fragment packet attribute",
4138 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4139 			     item_param),
4140 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
4141 					   has_frag_ext, 1)),
4142 	},
4143 	[ITEM_IPV6_ROUTING_EXT] = {
4144 		.name = "ipv6_routing_ext",
4145 		.help = "match IPv6 routing extension header",
4146 		.priv = PRIV_ITEM(IPV6_ROUTING_EXT,
4147 				  sizeof(struct rte_flow_item_ipv6_routing_ext)),
4148 		.next = NEXT(item_ipv6_routing_ext),
4149 		.call = parse_vc,
4150 	},
4151 	[ITEM_IPV6_ROUTING_EXT_TYPE] = {
4152 		.name = "ext_type",
4153 		.help = "match IPv6 routing extension header type",
4154 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4155 			     item_param),
4156 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4157 					     hdr.type)),
4158 	},
4159 	[ITEM_IPV6_ROUTING_EXT_NEXT_HDR] = {
4160 		.name = "ext_next_hdr",
4161 		.help = "match IPv6 routing extension header next header type",
4162 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4163 			     item_param),
4164 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4165 					     hdr.next_hdr)),
4166 	},
4167 	[ITEM_IPV6_ROUTING_EXT_SEG_LEFT] = {
4168 		.name = "ext_seg_left",
4169 		.help = "match IPv6 routing extension header segment left",
4170 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4171 			     item_param),
4172 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4173 					     hdr.segments_left)),
4174 	},
4175 	[ITEM_ICMP] = {
4176 		.name = "icmp",
4177 		.help = "match ICMP header",
4178 		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
4179 		.next = NEXT(item_icmp),
4180 		.call = parse_vc,
4181 	},
4182 	[ITEM_ICMP_TYPE] = {
4183 		.name = "type",
4184 		.help = "ICMP packet type",
4185 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4186 			     item_param),
4187 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4188 					     hdr.icmp_type)),
4189 	},
4190 	[ITEM_ICMP_CODE] = {
4191 		.name = "code",
4192 		.help = "ICMP packet code",
4193 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4194 			     item_param),
4195 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4196 					     hdr.icmp_code)),
4197 	},
4198 	[ITEM_ICMP_IDENT] = {
4199 		.name = "ident",
4200 		.help = "ICMP packet identifier",
4201 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4202 			     item_param),
4203 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4204 					     hdr.icmp_ident)),
4205 	},
4206 	[ITEM_ICMP_SEQ] = {
4207 		.name = "seq",
4208 		.help = "ICMP packet sequence number",
4209 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4210 			     item_param),
4211 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4212 					     hdr.icmp_seq_nb)),
4213 	},
4214 	[ITEM_UDP] = {
4215 		.name = "udp",
4216 		.help = "match UDP header",
4217 		.priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
4218 		.next = NEXT(item_udp),
4219 		.call = parse_vc,
4220 	},
4221 	[ITEM_UDP_SRC] = {
4222 		.name = "src",
4223 		.help = "UDP source port",
4224 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
4225 			     item_param),
4226 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4227 					     hdr.src_port)),
4228 	},
4229 	[ITEM_UDP_DST] = {
4230 		.name = "dst",
4231 		.help = "UDP destination port",
4232 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4233 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4234 					     hdr.dst_port)),
4235 	},
4236 	[ITEM_TCP] = {
4237 		.name = "tcp",
4238 		.help = "match TCP header",
4239 		.priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
4240 		.next = NEXT(item_tcp),
4241 		.call = parse_vc,
4242 	},
4243 	[ITEM_TCP_SRC] = {
4244 		.name = "src",
4245 		.help = "TCP source port",
4246 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4247 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4248 					     hdr.src_port)),
4249 	},
4250 	[ITEM_TCP_DST] = {
4251 		.name = "dst",
4252 		.help = "TCP destination port",
4253 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4254 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4255 					     hdr.dst_port)),
4256 	},
4257 	[ITEM_TCP_FLAGS] = {
4258 		.name = "flags",
4259 		.help = "TCP flags",
4260 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4261 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4262 					     hdr.tcp_flags)),
4263 	},
4264 	[ITEM_SCTP] = {
4265 		.name = "sctp",
4266 		.help = "match SCTP header",
4267 		.priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
4268 		.next = NEXT(item_sctp),
4269 		.call = parse_vc,
4270 	},
4271 	[ITEM_SCTP_SRC] = {
4272 		.name = "src",
4273 		.help = "SCTP source port",
4274 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4275 			     item_param),
4276 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4277 					     hdr.src_port)),
4278 	},
4279 	[ITEM_SCTP_DST] = {
4280 		.name = "dst",
4281 		.help = "SCTP destination port",
4282 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4283 			     item_param),
4284 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4285 					     hdr.dst_port)),
4286 	},
4287 	[ITEM_SCTP_TAG] = {
4288 		.name = "tag",
4289 		.help = "validation tag",
4290 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4291 			     item_param),
4292 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4293 					     hdr.tag)),
4294 	},
4295 	[ITEM_SCTP_CKSUM] = {
4296 		.name = "cksum",
4297 		.help = "checksum",
4298 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4299 			     item_param),
4300 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4301 					     hdr.cksum)),
4302 	},
4303 	[ITEM_VXLAN] = {
4304 		.name = "vxlan",
4305 		.help = "match VXLAN header",
4306 		.priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
4307 		.next = NEXT(item_vxlan),
4308 		.call = parse_vc,
4309 	},
4310 	[ITEM_VXLAN_VNI] = {
4311 		.name = "vni",
4312 		.help = "VXLAN identifier",
4313 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4314 			     item_param),
4315 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, hdr.vni)),
4316 	},
4317 	[ITEM_VXLAN_LAST_RSVD] = {
4318 		.name = "last_rsvd",
4319 		.help = "VXLAN last reserved bits",
4320 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4321 			     item_param),
4322 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
4323 					     hdr.rsvd1)),
4324 	},
4325 	[ITEM_E_TAG] = {
4326 		.name = "e_tag",
4327 		.help = "match E-Tag header",
4328 		.priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
4329 		.next = NEXT(item_e_tag),
4330 		.call = parse_vc,
4331 	},
4332 	[ITEM_E_TAG_GRP_ECID_B] = {
4333 		.name = "grp_ecid_b",
4334 		.help = "GRP and E-CID base",
4335 		.next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
4336 			     item_param),
4337 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
4338 						  rsvd_grp_ecid_b,
4339 						  "\x3f\xff")),
4340 	},
4341 	[ITEM_NVGRE] = {
4342 		.name = "nvgre",
4343 		.help = "match NVGRE header",
4344 		.priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
4345 		.next = NEXT(item_nvgre),
4346 		.call = parse_vc,
4347 	},
4348 	[ITEM_NVGRE_TNI] = {
4349 		.name = "tni",
4350 		.help = "virtual subnet ID",
4351 		.next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
4352 			     item_param),
4353 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
4354 	},
4355 	[ITEM_MPLS] = {
4356 		.name = "mpls",
4357 		.help = "match MPLS header",
4358 		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
4359 		.next = NEXT(item_mpls),
4360 		.call = parse_vc,
4361 	},
4362 	[ITEM_MPLS_LABEL] = {
4363 		.name = "label",
4364 		.help = "MPLS label",
4365 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4366 			     item_param),
4367 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4368 						  label_tc_s,
4369 						  "\xff\xff\xf0")),
4370 	},
4371 	[ITEM_MPLS_TC] = {
4372 		.name = "tc",
4373 		.help = "MPLS Traffic Class",
4374 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4375 			     item_param),
4376 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4377 						  label_tc_s,
4378 						  "\x00\x00\x0e")),
4379 	},
4380 	[ITEM_MPLS_S] = {
4381 		.name = "s",
4382 		.help = "MPLS Bottom-of-Stack",
4383 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4384 			     item_param),
4385 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4386 						  label_tc_s,
4387 						  "\x00\x00\x01")),
4388 	},
4389 	[ITEM_GRE] = {
4390 		.name = "gre",
4391 		.help = "match GRE header",
4392 		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
4393 		.next = NEXT(item_gre),
4394 		.call = parse_vc,
4395 	},
4396 	[ITEM_GRE_PROTO] = {
4397 		.name = "protocol",
4398 		.help = "GRE protocol type",
4399 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
4400 			     item_param),
4401 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
4402 					     protocol)),
4403 	},
4404 	[ITEM_GRE_C_RSVD0_VER] = {
4405 		.name = "c_rsvd0_ver",
4406 		.help =
4407 			"checksum (1b), undefined (1b), key bit (1b),"
4408 			" sequence number (1b), reserved 0 (9b),"
4409 			" version (3b)",
4410 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
4411 			     item_param),
4412 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
4413 					     c_rsvd0_ver)),
4414 	},
4415 	[ITEM_GRE_C_BIT] = {
4416 		.name = "c_bit",
4417 		.help = "checksum bit (C)",
4418 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
4419 			     item_param),
4420 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
4421 						  c_rsvd0_ver,
4422 						  "\x80\x00\x00\x00")),
4423 	},
4424 	[ITEM_GRE_S_BIT] = {
4425 		.name = "s_bit",
4426 		.help = "sequence number bit (S)",
4427 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4428 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
4429 						  c_rsvd0_ver,
4430 						  "\x10\x00\x00\x00")),
4431 	},
4432 	[ITEM_GRE_K_BIT] = {
4433 		.name = "k_bit",
4434 		.help = "key bit (K)",
4435 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4436 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
4437 						  c_rsvd0_ver,
4438 						  "\x20\x00\x00\x00")),
4439 	},
4440 	[ITEM_FUZZY] = {
4441 		.name = "fuzzy",
4442 		.help = "fuzzy pattern match, expect faster than default",
4443 		.priv = PRIV_ITEM(FUZZY,
4444 				sizeof(struct rte_flow_item_fuzzy)),
4445 		.next = NEXT(item_fuzzy),
4446 		.call = parse_vc,
4447 	},
4448 	[ITEM_FUZZY_THRESH] = {
4449 		.name = "thresh",
4450 		.help = "match accuracy threshold",
4451 		.next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
4452 			     item_param),
4453 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
4454 					thresh)),
4455 	},
4456 	[ITEM_GTP] = {
4457 		.name = "gtp",
4458 		.help = "match GTP header",
4459 		.priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
4460 		.next = NEXT(item_gtp),
4461 		.call = parse_vc,
4462 	},
4463 	[ITEM_GTP_FLAGS] = {
4464 		.name = "v_pt_rsv_flags",
4465 		.help = "GTP flags",
4466 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4467 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
4468 					hdr.gtp_hdr_info)),
4469 	},
4470 	[ITEM_GTP_MSG_TYPE] = {
4471 		.name = "msg_type",
4472 		.help = "GTP message type",
4473 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4474 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, hdr.msg_type)),
4475 	},
4476 	[ITEM_GTP_TEID] = {
4477 		.name = "teid",
4478 		.help = "tunnel endpoint identifier",
4479 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4480 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, hdr.teid)),
4481 	},
4482 	[ITEM_GTPC] = {
4483 		.name = "gtpc",
4484 		.help = "match GTP header",
4485 		.priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
4486 		.next = NEXT(item_gtp),
4487 		.call = parse_vc,
4488 	},
4489 	[ITEM_GTPU] = {
4490 		.name = "gtpu",
4491 		.help = "match GTP header",
4492 		.priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
4493 		.next = NEXT(item_gtp),
4494 		.call = parse_vc,
4495 	},
4496 	[ITEM_GENEVE] = {
4497 		.name = "geneve",
4498 		.help = "match GENEVE header",
4499 		.priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
4500 		.next = NEXT(item_geneve),
4501 		.call = parse_vc,
4502 	},
4503 	[ITEM_GENEVE_VNI] = {
4504 		.name = "vni",
4505 		.help = "virtual network identifier",
4506 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
4507 			     item_param),
4508 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
4509 	},
4510 	[ITEM_GENEVE_PROTO] = {
4511 		.name = "protocol",
4512 		.help = "GENEVE protocol type",
4513 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
4514 			     item_param),
4515 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
4516 					     protocol)),
4517 	},
4518 	[ITEM_GENEVE_OPTLEN] = {
4519 		.name = "optlen",
4520 		.help = "GENEVE options length in dwords",
4521 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
4522 			     item_param),
4523 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
4524 						  ver_opt_len_o_c_rsvd0,
4525 						  "\x3f\x00")),
4526 	},
4527 	[ITEM_VXLAN_GPE] = {
4528 		.name = "vxlan-gpe",
4529 		.help = "match VXLAN-GPE header",
4530 		.priv = PRIV_ITEM(VXLAN_GPE,
4531 				  sizeof(struct rte_flow_item_vxlan_gpe)),
4532 		.next = NEXT(item_vxlan_gpe),
4533 		.call = parse_vc,
4534 	},
4535 	[ITEM_VXLAN_GPE_VNI] = {
4536 		.name = "vni",
4537 		.help = "VXLAN-GPE identifier",
4538 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
4539 			     item_param),
4540 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
4541 					     hdr.vni)),
4542 	},
4543 	[ITEM_ARP_ETH_IPV4] = {
4544 		.name = "arp_eth_ipv4",
4545 		.help = "match ARP header for Ethernet/IPv4",
4546 		.priv = PRIV_ITEM(ARP_ETH_IPV4,
4547 				  sizeof(struct rte_flow_item_arp_eth_ipv4)),
4548 		.next = NEXT(item_arp_eth_ipv4),
4549 		.call = parse_vc,
4550 	},
4551 	[ITEM_ARP_ETH_IPV4_SHA] = {
4552 		.name = "sha",
4553 		.help = "sender hardware address",
4554 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
4555 			     item_param),
4556 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4557 					     hdr.arp_data.arp_sha)),
4558 	},
4559 	[ITEM_ARP_ETH_IPV4_SPA] = {
4560 		.name = "spa",
4561 		.help = "sender IPv4 address",
4562 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4563 			     item_param),
4564 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4565 					     hdr.arp_data.arp_sip)),
4566 	},
4567 	[ITEM_ARP_ETH_IPV4_THA] = {
4568 		.name = "tha",
4569 		.help = "target hardware address",
4570 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
4571 			     item_param),
4572 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4573 					     hdr.arp_data.arp_tha)),
4574 	},
4575 	[ITEM_ARP_ETH_IPV4_TPA] = {
4576 		.name = "tpa",
4577 		.help = "target IPv4 address",
4578 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4579 			     item_param),
4580 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4581 					     hdr.arp_data.arp_tip)),
4582 	},
4583 	[ITEM_IPV6_EXT] = {
4584 		.name = "ipv6_ext",
4585 		.help = "match presence of any IPv6 extension header",
4586 		.priv = PRIV_ITEM(IPV6_EXT,
4587 				  sizeof(struct rte_flow_item_ipv6_ext)),
4588 		.next = NEXT(item_ipv6_ext),
4589 		.call = parse_vc,
4590 	},
4591 	[ITEM_IPV6_EXT_NEXT_HDR] = {
4592 		.name = "next_hdr",
4593 		.help = "next header",
4594 		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4595 			     item_param),
4596 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
4597 					     next_hdr)),
4598 	},
4599 	[ITEM_IPV6_FRAG_EXT] = {
4600 		.name = "ipv6_frag_ext",
4601 		.help = "match presence of IPv6 fragment extension header",
4602 		.priv = PRIV_ITEM(IPV6_FRAG_EXT,
4603 				sizeof(struct rte_flow_item_ipv6_frag_ext)),
4604 		.next = NEXT(item_ipv6_frag_ext),
4605 		.call = parse_vc,
4606 	},
4607 	[ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
4608 		.name = "next_hdr",
4609 		.help = "next header",
4610 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4611 			     item_param),
4612 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
4613 					hdr.next_header)),
4614 	},
4615 	[ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
4616 		.name = "frag_data",
4617 		.help = "fragment flags and offset",
4618 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4619 			     item_param),
4620 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
4621 					     hdr.frag_data)),
4622 	},
4623 	[ITEM_IPV6_FRAG_EXT_ID] = {
4624 		.name = "packet_id",
4625 		.help = "fragment packet id",
4626 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4627 			     item_param),
4628 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
4629 					     hdr.id)),
4630 	},
4631 	[ITEM_ICMP6] = {
4632 		.name = "icmp6",
4633 		.help = "match any ICMPv6 header",
4634 		.priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
4635 		.next = NEXT(item_icmp6),
4636 		.call = parse_vc,
4637 	},
4638 	[ITEM_ICMP6_TYPE] = {
4639 		.name = "type",
4640 		.help = "ICMPv6 type",
4641 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
4642 			     item_param),
4643 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
4644 					     type)),
4645 	},
4646 	[ITEM_ICMP6_CODE] = {
4647 		.name = "code",
4648 		.help = "ICMPv6 code",
4649 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
4650 			     item_param),
4651 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
4652 					     code)),
4653 	},
4654 	[ITEM_ICMP6_ECHO_REQUEST] = {
4655 		.name = "icmp6_echo_request",
4656 		.help = "match ICMPv6 echo request",
4657 		.priv = PRIV_ITEM(ICMP6_ECHO_REQUEST,
4658 				  sizeof(struct rte_flow_item_icmp6_echo)),
4659 		.next = NEXT(item_icmp6_echo_request),
4660 		.call = parse_vc,
4661 	},
4662 	[ITEM_ICMP6_ECHO_REQUEST_ID] = {
4663 		.name = "ident",
4664 		.help = "ICMPv6 echo request identifier",
4665 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
4666 			     item_param),
4667 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
4668 					     hdr.identifier)),
4669 	},
4670 	[ITEM_ICMP6_ECHO_REQUEST_SEQ] = {
4671 		.name = "seq",
4672 		.help = "ICMPv6 echo request sequence",
4673 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
4674 			     item_param),
4675 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
4676 					     hdr.sequence)),
4677 	},
4678 	[ITEM_ICMP6_ECHO_REPLY] = {
4679 		.name = "icmp6_echo_reply",
4680 		.help = "match ICMPv6 echo reply",
4681 		.priv = PRIV_ITEM(ICMP6_ECHO_REPLY,
4682 				  sizeof(struct rte_flow_item_icmp6_echo)),
4683 		.next = NEXT(item_icmp6_echo_reply),
4684 		.call = parse_vc,
4685 	},
4686 	[ITEM_ICMP6_ECHO_REPLY_ID] = {
4687 		.name = "ident",
4688 		.help = "ICMPv6 echo reply identifier",
4689 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
4690 			     item_param),
4691 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
4692 					     hdr.identifier)),
4693 	},
4694 	[ITEM_ICMP6_ECHO_REPLY_SEQ] = {
4695 		.name = "seq",
4696 		.help = "ICMPv6 echo reply sequence",
4697 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
4698 			     item_param),
4699 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
4700 					     hdr.sequence)),
4701 	},
4702 	[ITEM_ICMP6_ND_NS] = {
4703 		.name = "icmp6_nd_ns",
4704 		.help = "match ICMPv6 neighbor discovery solicitation",
4705 		.priv = PRIV_ITEM(ICMP6_ND_NS,
4706 				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
4707 		.next = NEXT(item_icmp6_nd_ns),
4708 		.call = parse_vc,
4709 	},
4710 	[ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
4711 		.name = "target_addr",
4712 		.help = "target address",
4713 		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
4714 			     item_param),
4715 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
4716 					     target_addr)),
4717 	},
4718 	[ITEM_ICMP6_ND_NA] = {
4719 		.name = "icmp6_nd_na",
4720 		.help = "match ICMPv6 neighbor discovery advertisement",
4721 		.priv = PRIV_ITEM(ICMP6_ND_NA,
4722 				  sizeof(struct rte_flow_item_icmp6_nd_na)),
4723 		.next = NEXT(item_icmp6_nd_na),
4724 		.call = parse_vc,
4725 	},
4726 	[ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
4727 		.name = "target_addr",
4728 		.help = "target address",
4729 		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
4730 			     item_param),
4731 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
4732 					     target_addr)),
4733 	},
4734 	[ITEM_ICMP6_ND_OPT] = {
4735 		.name = "icmp6_nd_opt",
4736 		.help = "match presence of any ICMPv6 neighbor discovery"
4737 			" option",
4738 		.priv = PRIV_ITEM(ICMP6_ND_OPT,
4739 				  sizeof(struct rte_flow_item_icmp6_nd_opt)),
4740 		.next = NEXT(item_icmp6_nd_opt),
4741 		.call = parse_vc,
4742 	},
4743 	[ITEM_ICMP6_ND_OPT_TYPE] = {
4744 		.name = "type",
4745 		.help = "ND option type",
4746 		.next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
4747 			     item_param),
4748 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
4749 					     type)),
4750 	},
4751 	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
4752 		.name = "icmp6_nd_opt_sla_eth",
4753 		.help = "match ICMPv6 neighbor discovery source Ethernet"
4754 			" link-layer address option",
4755 		.priv = PRIV_ITEM
4756 			(ICMP6_ND_OPT_SLA_ETH,
4757 			 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
4758 		.next = NEXT(item_icmp6_nd_opt_sla_eth),
4759 		.call = parse_vc,
4760 	},
4761 	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
4762 		.name = "sla",
4763 		.help = "source Ethernet LLA",
4764 		.next = NEXT(item_icmp6_nd_opt_sla_eth,
4765 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4766 		.args = ARGS(ARGS_ENTRY_HTON
4767 			     (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
4768 	},
4769 	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
4770 		.name = "icmp6_nd_opt_tla_eth",
4771 		.help = "match ICMPv6 neighbor discovery target Ethernet"
4772 			" link-layer address option",
4773 		.priv = PRIV_ITEM
4774 			(ICMP6_ND_OPT_TLA_ETH,
4775 			 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
4776 		.next = NEXT(item_icmp6_nd_opt_tla_eth),
4777 		.call = parse_vc,
4778 	},
4779 	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
4780 		.name = "tla",
4781 		.help = "target Ethernet LLA",
4782 		.next = NEXT(item_icmp6_nd_opt_tla_eth,
4783 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4784 		.args = ARGS(ARGS_ENTRY_HTON
4785 			     (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
4786 	},
4787 	[ITEM_META] = {
4788 		.name = "meta",
4789 		.help = "match metadata header",
4790 		.priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
4791 		.next = NEXT(item_meta),
4792 		.call = parse_vc,
4793 	},
4794 	[ITEM_META_DATA] = {
4795 		.name = "data",
4796 		.help = "metadata value",
4797 		.next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
4798 			     item_param),
4799 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
4800 					     data, "\xff\xff\xff\xff")),
4801 	},
4802 	[ITEM_GRE_KEY] = {
4803 		.name = "gre_key",
4804 		.help = "match GRE key",
4805 		.priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
4806 		.next = NEXT(item_gre_key),
4807 		.call = parse_vc,
4808 	},
4809 	[ITEM_GRE_KEY_VALUE] = {
4810 		.name = "value",
4811 		.help = "key value",
4812 		.next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
4813 			     item_param),
4814 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4815 	},
4816 	[ITEM_GRE_OPTION] = {
4817 		.name = "gre_option",
4818 		.help = "match GRE optional fields",
4819 		.priv = PRIV_ITEM(GRE_OPTION,
4820 				  sizeof(struct rte_flow_item_gre_opt)),
4821 		.next = NEXT(item_gre_option),
4822 		.call = parse_vc,
4823 	},
4824 	[ITEM_GRE_OPTION_CHECKSUM] = {
4825 		.name = "checksum",
4826 		.help = "match GRE checksum",
4827 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
4828 			     item_param),
4829 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
4830 					     checksum_rsvd.checksum)),
4831 	},
4832 	[ITEM_GRE_OPTION_KEY] = {
4833 		.name = "key",
4834 		.help = "match GRE key",
4835 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
4836 			     item_param),
4837 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
4838 					     key.key)),
4839 	},
4840 	[ITEM_GRE_OPTION_SEQUENCE] = {
4841 		.name = "sequence",
4842 		.help = "match GRE sequence",
4843 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
4844 			     item_param),
4845 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
4846 					     sequence.sequence)),
4847 	},
4848 	[ITEM_GTP_PSC] = {
4849 		.name = "gtp_psc",
4850 		.help = "match GTP extension header with type 0x85",
4851 		.priv = PRIV_ITEM(GTP_PSC,
4852 				sizeof(struct rte_flow_item_gtp_psc)),
4853 		.next = NEXT(item_gtp_psc),
4854 		.call = parse_vc,
4855 	},
4856 	[ITEM_GTP_PSC_QFI] = {
4857 		.name = "qfi",
4858 		.help = "QoS flow identifier",
4859 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
4860 			     item_param),
4861 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
4862 					hdr.qfi, 6)),
4863 	},
4864 	[ITEM_GTP_PSC_PDU_T] = {
4865 		.name = "pdu_t",
4866 		.help = "PDU type",
4867 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
4868 			     item_param),
4869 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
4870 					hdr.type, 4)),
4871 	},
4872 	[ITEM_PPPOES] = {
4873 		.name = "pppoes",
4874 		.help = "match PPPoE session header",
4875 		.priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
4876 		.next = NEXT(item_pppoes),
4877 		.call = parse_vc,
4878 	},
4879 	[ITEM_PPPOED] = {
4880 		.name = "pppoed",
4881 		.help = "match PPPoE discovery header",
4882 		.priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
4883 		.next = NEXT(item_pppoed),
4884 		.call = parse_vc,
4885 	},
4886 	[ITEM_PPPOE_SEID] = {
4887 		.name = "seid",
4888 		.help = "session identifier",
4889 		.next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
4890 			     item_param),
4891 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
4892 					session_id)),
4893 	},
4894 	[ITEM_PPPOE_PROTO_ID] = {
4895 		.name = "pppoe_proto_id",
4896 		.help = "match PPPoE session protocol identifier",
4897 		.priv = PRIV_ITEM(PPPOE_PROTO_ID,
4898 				sizeof(struct rte_flow_item_pppoe_proto_id)),
4899 		.next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
4900 			     item_param),
4901 		.args = ARGS(ARGS_ENTRY_HTON
4902 			     (struct rte_flow_item_pppoe_proto_id, proto_id)),
4903 		.call = parse_vc,
4904 	},
4905 	[ITEM_HIGIG2] = {
4906 		.name = "higig2",
4907 		.help = "matches higig2 header",
4908 		.priv = PRIV_ITEM(HIGIG2,
4909 				sizeof(struct rte_flow_item_higig2_hdr)),
4910 		.next = NEXT(item_higig2),
4911 		.call = parse_vc,
4912 	},
4913 	[ITEM_HIGIG2_CLASSIFICATION] = {
4914 		.name = "classification",
4915 		.help = "matches classification of higig2 header",
4916 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
4917 			     item_param),
4918 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
4919 					hdr.ppt1.classification)),
4920 	},
4921 	[ITEM_HIGIG2_VID] = {
4922 		.name = "vid",
4923 		.help = "matches vid of higig2 header",
4924 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
4925 			     item_param),
4926 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
4927 					hdr.ppt1.vid)),
4928 	},
4929 	[ITEM_TAG] = {
4930 		.name = "tag",
4931 		.help = "match tag value",
4932 		.priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
4933 		.next = NEXT(item_tag),
4934 		.call = parse_vc,
4935 	},
4936 	[ITEM_TAG_DATA] = {
4937 		.name = "data",
4938 		.help = "tag value to match",
4939 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4940 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
4941 	},
4942 	[ITEM_TAG_INDEX] = {
4943 		.name = "index",
4944 		.help = "index of tag array to match",
4945 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
4946 			     NEXT_ENTRY(ITEM_PARAM_IS)),
4947 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
4948 	},
4949 	[ITEM_L2TPV3OIP] = {
4950 		.name = "l2tpv3oip",
4951 		.help = "match L2TPv3 over IP header",
4952 		.priv = PRIV_ITEM(L2TPV3OIP,
4953 				  sizeof(struct rte_flow_item_l2tpv3oip)),
4954 		.next = NEXT(item_l2tpv3oip),
4955 		.call = parse_vc,
4956 	},
4957 	[ITEM_L2TPV3OIP_SESSION_ID] = {
4958 		.name = "session_id",
4959 		.help = "session identifier",
4960 		.next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
4961 			     item_param),
4962 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
4963 					     session_id)),
4964 	},
4965 	[ITEM_ESP] = {
4966 		.name = "esp",
4967 		.help = "match ESP header",
4968 		.priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
4969 		.next = NEXT(item_esp),
4970 		.call = parse_vc,
4971 	},
4972 	[ITEM_ESP_SPI] = {
4973 		.name = "spi",
4974 		.help = "security policy index",
4975 		.next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4976 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
4977 				hdr.spi)),
4978 	},
4979 	[ITEM_AH] = {
4980 		.name = "ah",
4981 		.help = "match AH header",
4982 		.priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
4983 		.next = NEXT(item_ah),
4984 		.call = parse_vc,
4985 	},
4986 	[ITEM_AH_SPI] = {
4987 		.name = "spi",
4988 		.help = "security parameters index",
4989 		.next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4990 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
4991 	},
4992 	[ITEM_PFCP] = {
4993 		.name = "pfcp",
4994 		.help = "match pfcp header",
4995 		.priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
4996 		.next = NEXT(item_pfcp),
4997 		.call = parse_vc,
4998 	},
4999 	[ITEM_PFCP_S_FIELD] = {
5000 		.name = "s_field",
5001 		.help = "S field",
5002 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5003 			     item_param),
5004 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
5005 				s_field)),
5006 	},
5007 	[ITEM_PFCP_SEID] = {
5008 		.name = "seid",
5009 		.help = "session endpoint identifier",
5010 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5011 			     item_param),
5012 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
5013 	},
5014 	[ITEM_ECPRI] = {
5015 		.name = "ecpri",
5016 		.help = "match eCPRI header",
5017 		.priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
5018 		.next = NEXT(item_ecpri),
5019 		.call = parse_vc,
5020 	},
5021 	[ITEM_ECPRI_COMMON] = {
5022 		.name = "common",
5023 		.help = "eCPRI common header",
5024 		.next = NEXT(item_ecpri_common),
5025 	},
5026 	[ITEM_ECPRI_COMMON_TYPE] = {
5027 		.name = "type",
5028 		.help = "type of common header",
5029 		.next = NEXT(item_ecpri_common_type),
5030 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
5031 	},
5032 	[ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
5033 		.name = "iq_data",
5034 		.help = "Type #0: IQ Data",
5035 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5036 					ITEM_NEXT)),
5037 		.call = parse_vc_item_ecpri_type,
5038 	},
5039 	[ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
5040 		.name = "pc_id",
5041 		.help = "Physical Channel ID",
5042 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5043 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5044 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5045 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5046 				hdr.type0.pc_id)),
5047 	},
5048 	[ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
5049 		.name = "rtc_ctrl",
5050 		.help = "Type #2: Real-Time Control Data",
5051 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5052 					ITEM_NEXT)),
5053 		.call = parse_vc_item_ecpri_type,
5054 	},
5055 	[ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
5056 		.name = "rtc_id",
5057 		.help = "Real-Time Control Data ID",
5058 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5059 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5060 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5061 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5062 				hdr.type2.rtc_id)),
5063 	},
5064 	[ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
5065 		.name = "delay_measure",
5066 		.help = "Type #5: One-Way Delay Measurement",
5067 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5068 					ITEM_NEXT)),
5069 		.call = parse_vc_item_ecpri_type,
5070 	},
5071 	[ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
5072 		.name = "msr_id",
5073 		.help = "Measurement ID",
5074 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5075 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5076 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5077 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5078 				hdr.type5.msr_id)),
5079 	},
5080 	[ITEM_GENEVE_OPT] = {
5081 		.name = "geneve-opt",
5082 		.help = "GENEVE header option",
5083 		.priv = PRIV_ITEM(GENEVE_OPT,
5084 				  sizeof(struct rte_flow_item_geneve_opt) +
5085 				  ITEM_GENEVE_OPT_DATA_SIZE),
5086 		.next = NEXT(item_geneve_opt),
5087 		.call = parse_vc,
5088 	},
5089 	[ITEM_GENEVE_OPT_CLASS]	= {
5090 		.name = "class",
5091 		.help = "GENEVE option class",
5092 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5093 			     item_param),
5094 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
5095 					     option_class)),
5096 	},
5097 	[ITEM_GENEVE_OPT_TYPE] = {
5098 		.name = "type",
5099 		.help = "GENEVE option type",
5100 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5101 			     item_param),
5102 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
5103 					option_type)),
5104 	},
5105 	[ITEM_GENEVE_OPT_LENGTH] = {
5106 		.name = "length",
5107 		.help = "GENEVE option data length (in 32b words)",
5108 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5109 			     item_param),
5110 		.args = ARGS(ARGS_ENTRY_BOUNDED(
5111 				struct rte_flow_item_geneve_opt, option_len,
5112 				0, 31)),
5113 	},
5114 	[ITEM_GENEVE_OPT_DATA] = {
5115 		.name = "data",
5116 		.help = "GENEVE option data pattern",
5117 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
5118 			     item_param),
5119 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
5120 			     ARGS_ENTRY_ARB(0, 0),
5121 			     ARGS_ENTRY_ARB
5122 				(sizeof(struct rte_flow_item_geneve_opt),
5123 				ITEM_GENEVE_OPT_DATA_SIZE)),
5124 	},
5125 	[ITEM_INTEGRITY] = {
5126 		.name = "integrity",
5127 		.help = "match packet integrity",
5128 		.priv = PRIV_ITEM(INTEGRITY,
5129 				  sizeof(struct rte_flow_item_integrity)),
5130 		.next = NEXT(item_integrity),
5131 		.call = parse_vc,
5132 	},
5133 	[ITEM_INTEGRITY_LEVEL] = {
5134 		.name = "level",
5135 		.help = "integrity level",
5136 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5137 			     item_param),
5138 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
5139 	},
5140 	[ITEM_INTEGRITY_VALUE] = {
5141 		.name = "value",
5142 		.help = "integrity value",
5143 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5144 			     item_param),
5145 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
5146 	},
5147 	[ITEM_CONNTRACK] = {
5148 		.name = "conntrack",
5149 		.help = "conntrack state",
5150 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
5151 			     item_param),
5152 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
5153 	},
5154 	[ITEM_PORT_REPRESENTOR] = {
5155 		.name = "port_representor",
5156 		.help = "match traffic entering the embedded switch from the given ethdev",
5157 		.priv = PRIV_ITEM(PORT_REPRESENTOR,
5158 				  sizeof(struct rte_flow_item_ethdev)),
5159 		.next = NEXT(item_port_representor),
5160 		.call = parse_vc,
5161 	},
5162 	[ITEM_PORT_REPRESENTOR_PORT_ID] = {
5163 		.name = "port_id",
5164 		.help = "ethdev port ID",
5165 		.next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
5166 			     item_param),
5167 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5168 	},
5169 	[ITEM_REPRESENTED_PORT] = {
5170 		.name = "represented_port",
5171 		.help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
5172 		.priv = PRIV_ITEM(REPRESENTED_PORT,
5173 				  sizeof(struct rte_flow_item_ethdev)),
5174 		.next = NEXT(item_represented_port),
5175 		.call = parse_vc,
5176 	},
5177 	[ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
5178 		.name = "ethdev_port_id",
5179 		.help = "ethdev port ID",
5180 		.next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
5181 			     item_param),
5182 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5183 	},
5184 	[ITEM_FLEX] = {
5185 		.name = "flex",
5186 		.help = "match flex header",
5187 		.priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
5188 		.next = NEXT(item_flex),
5189 		.call = parse_vc,
5190 	},
5191 	[ITEM_FLEX_ITEM_HANDLE] = {
5192 		.name = "item",
5193 		.help = "flex item handle",
5194 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5195 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5196 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
5197 	},
5198 	[ITEM_FLEX_PATTERN_HANDLE] = {
5199 		.name = "pattern",
5200 		.help = "flex pattern handle",
5201 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5202 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5203 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
5204 	},
5205 	[ITEM_L2TPV2] = {
5206 		.name = "l2tpv2",
5207 		.help = "match L2TPv2 header",
5208 		.priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
5209 		.next = NEXT(item_l2tpv2),
5210 		.call = parse_vc,
5211 	},
5212 	[ITEM_L2TPV2_TYPE] = {
5213 		.name = "type",
5214 		.help = "type of l2tpv2",
5215 		.next = NEXT(item_l2tpv2_type),
5216 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
5217 	},
5218 	[ITEM_L2TPV2_TYPE_DATA] = {
5219 		.name = "data",
5220 		.help = "Type #7: data message without any options",
5221 		.next = NEXT(item_l2tpv2_type_data),
5222 		.call = parse_vc_item_l2tpv2_type,
5223 	},
5224 	[ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
5225 		.name = "tunnel_id",
5226 		.help = "tunnel identifier",
5227 		.next = NEXT(item_l2tpv2_type_data,
5228 			     NEXT_ENTRY(COMMON_UNSIGNED),
5229 			     item_param),
5230 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5231 					     hdr.type7.tunnel_id)),
5232 	},
5233 	[ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
5234 		.name = "session_id",
5235 		.help = "session identifier",
5236 		.next = NEXT(item_l2tpv2_type_data,
5237 			     NEXT_ENTRY(COMMON_UNSIGNED),
5238 			     item_param),
5239 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5240 					     hdr.type7.session_id)),
5241 	},
5242 	[ITEM_L2TPV2_TYPE_DATA_L] = {
5243 		.name = "data_l",
5244 		.help = "Type #6: data message with length option",
5245 		.next = NEXT(item_l2tpv2_type_data_l),
5246 		.call = parse_vc_item_l2tpv2_type,
5247 	},
5248 	[ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
5249 		.name = "length",
5250 		.help = "message length",
5251 		.next = NEXT(item_l2tpv2_type_data_l,
5252 			     NEXT_ENTRY(COMMON_UNSIGNED),
5253 			     item_param),
5254 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5255 					     hdr.type6.length)),
5256 	},
5257 	[ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
5258 		.name = "tunnel_id",
5259 		.help = "tunnel identifier",
5260 		.next = NEXT(item_l2tpv2_type_data_l,
5261 			     NEXT_ENTRY(COMMON_UNSIGNED),
5262 			     item_param),
5263 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5264 					     hdr.type6.tunnel_id)),
5265 	},
5266 	[ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
5267 		.name = "session_id",
5268 		.help = "session identifier",
5269 		.next = NEXT(item_l2tpv2_type_data_l,
5270 			     NEXT_ENTRY(COMMON_UNSIGNED),
5271 			     item_param),
5272 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5273 					     hdr.type6.session_id)),
5274 	},
5275 	[ITEM_L2TPV2_TYPE_DATA_S] = {
5276 		.name = "data_s",
5277 		.help = "Type #5: data message with ns, nr option",
5278 		.next = NEXT(item_l2tpv2_type_data_s),
5279 		.call = parse_vc_item_l2tpv2_type,
5280 	},
5281 	[ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
5282 		.name = "tunnel_id",
5283 		.help = "tunnel identifier",
5284 		.next = NEXT(item_l2tpv2_type_data_s,
5285 			     NEXT_ENTRY(COMMON_UNSIGNED),
5286 			     item_param),
5287 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5288 					     hdr.type5.tunnel_id)),
5289 	},
5290 	[ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
5291 		.name = "session_id",
5292 		.help = "session identifier",
5293 		.next = NEXT(item_l2tpv2_type_data_s,
5294 			     NEXT_ENTRY(COMMON_UNSIGNED),
5295 			     item_param),
5296 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5297 					     hdr.type5.session_id)),
5298 	},
5299 	[ITEM_L2TPV2_MSG_DATA_S_NS] = {
5300 		.name = "ns",
5301 		.help = "sequence number for message",
5302 		.next = NEXT(item_l2tpv2_type_data_s,
5303 			     NEXT_ENTRY(COMMON_UNSIGNED),
5304 			     item_param),
5305 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5306 					     hdr.type5.ns)),
5307 	},
5308 	[ITEM_L2TPV2_MSG_DATA_S_NR] = {
5309 		.name = "nr",
5310 		.help = "sequence number for next receive message",
5311 		.next = NEXT(item_l2tpv2_type_data_s,
5312 			     NEXT_ENTRY(COMMON_UNSIGNED),
5313 			     item_param),
5314 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5315 					     hdr.type5.nr)),
5316 	},
5317 	[ITEM_L2TPV2_TYPE_DATA_O] = {
5318 		.name = "data_o",
5319 		.help = "Type #4: data message with offset option",
5320 		.next = NEXT(item_l2tpv2_type_data_o),
5321 		.call = parse_vc_item_l2tpv2_type,
5322 	},
5323 	[ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
5324 		.name = "tunnel_id",
5325 		.help = "tunnel identifier",
5326 		.next = NEXT(item_l2tpv2_type_data_o,
5327 			     NEXT_ENTRY(COMMON_UNSIGNED),
5328 			     item_param),
5329 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5330 					     hdr.type4.tunnel_id)),
5331 	},
5332 	[ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
5333 		.name = "session_id",
5334 		.help = "session identifier",
5335 		.next = NEXT(item_l2tpv2_type_data_o,
5336 			     NEXT_ENTRY(COMMON_UNSIGNED),
5337 			     item_param),
5338 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5339 					     hdr.type5.session_id)),
5340 	},
5341 	[ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
5342 		.name = "offset_size",
5343 		.help = "the size of offset padding",
5344 		.next = NEXT(item_l2tpv2_type_data_o,
5345 			     NEXT_ENTRY(COMMON_UNSIGNED),
5346 			     item_param),
5347 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5348 					     hdr.type4.offset_size)),
5349 	},
5350 	[ITEM_L2TPV2_TYPE_DATA_L_S] = {
5351 		.name = "data_l_s",
5352 		.help = "Type #3: data message contains length, ns, nr "
5353 			"options",
5354 		.next = NEXT(item_l2tpv2_type_data_l_s),
5355 		.call = parse_vc_item_l2tpv2_type,
5356 	},
5357 	[ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
5358 		.name = "length",
5359 		.help = "message length",
5360 		.next = NEXT(item_l2tpv2_type_data_l_s,
5361 			     NEXT_ENTRY(COMMON_UNSIGNED),
5362 			     item_param),
5363 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5364 					     hdr.type3.length)),
5365 	},
5366 	[ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
5367 		.name = "tunnel_id",
5368 		.help = "tunnel identifier",
5369 		.next = NEXT(item_l2tpv2_type_data_l_s,
5370 			     NEXT_ENTRY(COMMON_UNSIGNED),
5371 			     item_param),
5372 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5373 					     hdr.type3.tunnel_id)),
5374 	},
5375 	[ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
5376 		.name = "session_id",
5377 		.help = "session identifier",
5378 		.next = NEXT(item_l2tpv2_type_data_l_s,
5379 			     NEXT_ENTRY(COMMON_UNSIGNED),
5380 			     item_param),
5381 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5382 					     hdr.type3.session_id)),
5383 	},
5384 	[ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
5385 		.name = "ns",
5386 		.help = "sequence number for message",
5387 		.next = NEXT(item_l2tpv2_type_data_l_s,
5388 			     NEXT_ENTRY(COMMON_UNSIGNED),
5389 			     item_param),
5390 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5391 					     hdr.type3.ns)),
5392 	},
5393 	[ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
5394 		.name = "nr",
5395 		.help = "sequence number for next receive message",
5396 		.next = NEXT(item_l2tpv2_type_data_l_s,
5397 			     NEXT_ENTRY(COMMON_UNSIGNED),
5398 			     item_param),
5399 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5400 					     hdr.type3.nr)),
5401 	},
5402 	[ITEM_L2TPV2_TYPE_CTRL] = {
5403 		.name = "control",
5404 		.help = "Type #3: conrtol message contains length, ns, nr "
5405 			"options",
5406 		.next = NEXT(item_l2tpv2_type_ctrl),
5407 		.call = parse_vc_item_l2tpv2_type,
5408 	},
5409 	[ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
5410 		.name = "length",
5411 		.help = "message length",
5412 		.next = NEXT(item_l2tpv2_type_ctrl,
5413 			     NEXT_ENTRY(COMMON_UNSIGNED),
5414 			     item_param),
5415 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5416 					     hdr.type3.length)),
5417 	},
5418 	[ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
5419 		.name = "tunnel_id",
5420 		.help = "tunnel identifier",
5421 		.next = NEXT(item_l2tpv2_type_ctrl,
5422 			     NEXT_ENTRY(COMMON_UNSIGNED),
5423 			     item_param),
5424 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5425 					     hdr.type3.tunnel_id)),
5426 	},
5427 	[ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
5428 		.name = "session_id",
5429 		.help = "session identifier",
5430 		.next = NEXT(item_l2tpv2_type_ctrl,
5431 			     NEXT_ENTRY(COMMON_UNSIGNED),
5432 			     item_param),
5433 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5434 					     hdr.type3.session_id)),
5435 	},
5436 	[ITEM_L2TPV2_MSG_CTRL_NS] = {
5437 		.name = "ns",
5438 		.help = "sequence number for message",
5439 		.next = NEXT(item_l2tpv2_type_ctrl,
5440 			     NEXT_ENTRY(COMMON_UNSIGNED),
5441 			     item_param),
5442 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5443 					     hdr.type3.ns)),
5444 	},
5445 	[ITEM_L2TPV2_MSG_CTRL_NR] = {
5446 		.name = "nr",
5447 		.help = "sequence number for next receive message",
5448 		.next = NEXT(item_l2tpv2_type_ctrl,
5449 			     NEXT_ENTRY(COMMON_UNSIGNED),
5450 			     item_param),
5451 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5452 					     hdr.type3.nr)),
5453 	},
5454 	[ITEM_PPP] = {
5455 		.name = "ppp",
5456 		.help = "match PPP header",
5457 		.priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
5458 		.next = NEXT(item_ppp),
5459 		.call = parse_vc,
5460 	},
5461 	[ITEM_PPP_ADDR] = {
5462 		.name = "addr",
5463 		.help = "PPP address",
5464 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
5465 			     item_param),
5466 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
5467 	},
5468 	[ITEM_PPP_CTRL] = {
5469 		.name = "ctrl",
5470 		.help = "PPP control",
5471 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
5472 			     item_param),
5473 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
5474 	},
5475 	[ITEM_PPP_PROTO_ID] = {
5476 		.name = "proto_id",
5477 		.help = "PPP protocol identifier",
5478 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
5479 			     item_param),
5480 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
5481 					hdr.proto_id)),
5482 	},
5483 	[ITEM_METER] = {
5484 		.name = "meter",
5485 		.help = "match meter color",
5486 		.priv = PRIV_ITEM(METER_COLOR,
5487 				  sizeof(struct rte_flow_item_meter_color)),
5488 		.next = NEXT(item_meter),
5489 		.call = parse_vc,
5490 	},
5491 	[ITEM_METER_COLOR] = {
5492 		.name = "color",
5493 		.help = "meter color",
5494 		.next = NEXT(item_meter,
5495 			     NEXT_ENTRY(ITEM_METER_COLOR_NAME),
5496 			     item_param),
5497 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_meter_color,
5498 					color)),
5499 	},
5500 	[ITEM_METER_COLOR_NAME] = {
5501 		.name = "color_name",
5502 		.help = "meter color name",
5503 		.call = parse_meter_color,
5504 		.comp = comp_meter_color,
5505 	},
5506 	[ITEM_QUOTA] = {
5507 		.name = "quota",
5508 		.help = "match quota",
5509 		.priv = PRIV_ITEM(QUOTA, sizeof(struct rte_flow_item_quota)),
5510 		.next = NEXT(item_quota),
5511 		.call = parse_vc
5512 	},
5513 	[ITEM_QUOTA_STATE] = {
5514 		.name = "quota_state",
5515 		.help = "quota state",
5516 		.next = NEXT(item_quota, NEXT_ENTRY(ITEM_QUOTA_STATE_NAME),
5517 			     NEXT_ENTRY(ITEM_PARAM_SPEC, ITEM_PARAM_MASK)),
5518 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_quota, state))
5519 	},
5520 	[ITEM_QUOTA_STATE_NAME] = {
5521 		.name = "state_name",
5522 		.help = "quota state name",
5523 		.call = parse_quota_state_name,
5524 		.comp = comp_quota_state_name
5525 	},
5526 	/* Validate/create actions. */
5527 	[ACTIONS] = {
5528 		.name = "actions",
5529 		.help = "submit a list of associated actions",
5530 		.next = NEXT(next_action),
5531 		.call = parse_vc,
5532 	},
5533 	[ACTION_NEXT] = {
5534 		.name = "/",
5535 		.help = "specify next action",
5536 		.next = NEXT(next_action),
5537 	},
5538 	[ACTION_END] = {
5539 		.name = "end",
5540 		.help = "end list of actions",
5541 		.priv = PRIV_ACTION(END, 0),
5542 		.call = parse_vc,
5543 	},
5544 	[ACTION_VOID] = {
5545 		.name = "void",
5546 		.help = "no-op action",
5547 		.priv = PRIV_ACTION(VOID, 0),
5548 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5549 		.call = parse_vc,
5550 	},
5551 	[ACTION_PASSTHRU] = {
5552 		.name = "passthru",
5553 		.help = "let subsequent rule process matched packets",
5554 		.priv = PRIV_ACTION(PASSTHRU, 0),
5555 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5556 		.call = parse_vc,
5557 	},
5558 	[ACTION_SKIP_CMAN] = {
5559 		.name = "skip_cman",
5560 		.help = "bypass cman on received packets",
5561 		.priv = PRIV_ACTION(SKIP_CMAN, 0),
5562 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5563 		.call = parse_vc,
5564 	},
5565 	[ACTION_JUMP] = {
5566 		.name = "jump",
5567 		.help = "redirect traffic to a given group",
5568 		.priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
5569 		.next = NEXT(action_jump),
5570 		.call = parse_vc,
5571 	},
5572 	[ACTION_JUMP_GROUP] = {
5573 		.name = "group",
5574 		.help = "group to redirect traffic to",
5575 		.next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
5576 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
5577 		.call = parse_vc_conf,
5578 	},
5579 	[ACTION_MARK] = {
5580 		.name = "mark",
5581 		.help = "attach 32 bit value to packets",
5582 		.priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
5583 		.next = NEXT(action_mark),
5584 		.call = parse_vc,
5585 	},
5586 	[ACTION_MARK_ID] = {
5587 		.name = "id",
5588 		.help = "32 bit value to return with packets",
5589 		.next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
5590 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
5591 		.call = parse_vc_conf,
5592 	},
5593 	[ACTION_FLAG] = {
5594 		.name = "flag",
5595 		.help = "flag packets",
5596 		.priv = PRIV_ACTION(FLAG, 0),
5597 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5598 		.call = parse_vc,
5599 	},
5600 	[ACTION_QUEUE] = {
5601 		.name = "queue",
5602 		.help = "assign packets to a given queue index",
5603 		.priv = PRIV_ACTION(QUEUE,
5604 				    sizeof(struct rte_flow_action_queue)),
5605 		.next = NEXT(action_queue),
5606 		.call = parse_vc,
5607 	},
5608 	[ACTION_QUEUE_INDEX] = {
5609 		.name = "index",
5610 		.help = "queue index to use",
5611 		.next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
5612 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
5613 		.call = parse_vc_conf,
5614 	},
5615 	[ACTION_DROP] = {
5616 		.name = "drop",
5617 		.help = "drop packets (note: passthru has priority)",
5618 		.priv = PRIV_ACTION(DROP, 0),
5619 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5620 		.call = parse_vc,
5621 	},
5622 	[ACTION_COUNT] = {
5623 		.name = "count",
5624 		.help = "enable counters for this rule",
5625 		.priv = PRIV_ACTION(COUNT,
5626 				    sizeof(struct rte_flow_action_count)),
5627 		.next = NEXT(action_count),
5628 		.call = parse_vc,
5629 	},
5630 	[ACTION_COUNT_ID] = {
5631 		.name = "identifier",
5632 		.help = "counter identifier to use",
5633 		.next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
5634 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
5635 		.call = parse_vc_conf,
5636 	},
5637 	[ACTION_RSS] = {
5638 		.name = "rss",
5639 		.help = "spread packets among several queues",
5640 		.priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
5641 		.next = NEXT(action_rss),
5642 		.call = parse_vc_action_rss,
5643 	},
5644 	[ACTION_RSS_FUNC] = {
5645 		.name = "func",
5646 		.help = "RSS hash function to apply",
5647 		.next = NEXT(action_rss,
5648 			     NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
5649 					ACTION_RSS_FUNC_TOEPLITZ,
5650 					ACTION_RSS_FUNC_SIMPLE_XOR,
5651 					ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
5652 	},
5653 	[ACTION_RSS_FUNC_DEFAULT] = {
5654 		.name = "default",
5655 		.help = "default hash function",
5656 		.call = parse_vc_action_rss_func,
5657 	},
5658 	[ACTION_RSS_FUNC_TOEPLITZ] = {
5659 		.name = "toeplitz",
5660 		.help = "Toeplitz hash function",
5661 		.call = parse_vc_action_rss_func,
5662 	},
5663 	[ACTION_RSS_FUNC_SIMPLE_XOR] = {
5664 		.name = "simple_xor",
5665 		.help = "simple XOR hash function",
5666 		.call = parse_vc_action_rss_func,
5667 	},
5668 	[ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
5669 		.name = "symmetric_toeplitz",
5670 		.help = "Symmetric Toeplitz hash function",
5671 		.call = parse_vc_action_rss_func,
5672 	},
5673 	[ACTION_RSS_LEVEL] = {
5674 		.name = "level",
5675 		.help = "encapsulation level for \"types\"",
5676 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
5677 		.args = ARGS(ARGS_ENTRY_ARB
5678 			     (offsetof(struct action_rss_data, conf) +
5679 			      offsetof(struct rte_flow_action_rss, level),
5680 			      sizeof(((struct rte_flow_action_rss *)0)->
5681 				     level))),
5682 	},
5683 	[ACTION_RSS_TYPES] = {
5684 		.name = "types",
5685 		.help = "specific RSS hash types",
5686 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
5687 	},
5688 	[ACTION_RSS_TYPE] = {
5689 		.name = "{type}",
5690 		.help = "RSS hash type",
5691 		.call = parse_vc_action_rss_type,
5692 		.comp = comp_vc_action_rss_type,
5693 	},
5694 	[ACTION_RSS_KEY] = {
5695 		.name = "key",
5696 		.help = "RSS hash key",
5697 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
5698 		.args = ARGS(ARGS_ENTRY_ARB
5699 			     (offsetof(struct action_rss_data, conf) +
5700 			      offsetof(struct rte_flow_action_rss, key),
5701 			      sizeof(((struct rte_flow_action_rss *)0)->key)),
5702 			     ARGS_ENTRY_ARB
5703 			     (offsetof(struct action_rss_data, conf) +
5704 			      offsetof(struct rte_flow_action_rss, key_len),
5705 			      sizeof(((struct rte_flow_action_rss *)0)->
5706 				     key_len)),
5707 			     ARGS_ENTRY(struct action_rss_data, key)),
5708 	},
5709 	[ACTION_RSS_KEY_LEN] = {
5710 		.name = "key_len",
5711 		.help = "RSS hash key length in bytes",
5712 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
5713 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5714 			     (offsetof(struct action_rss_data, conf) +
5715 			      offsetof(struct rte_flow_action_rss, key_len),
5716 			      sizeof(((struct rte_flow_action_rss *)0)->
5717 				     key_len),
5718 			      0,
5719 			      RSS_HASH_KEY_LENGTH)),
5720 	},
5721 	[ACTION_RSS_QUEUES] = {
5722 		.name = "queues",
5723 		.help = "queue indices to use",
5724 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
5725 		.call = parse_vc_conf,
5726 	},
5727 	[ACTION_RSS_QUEUE] = {
5728 		.name = "{queue}",
5729 		.help = "queue index",
5730 		.call = parse_vc_action_rss_queue,
5731 		.comp = comp_vc_action_rss_queue,
5732 	},
5733 	[ACTION_PF] = {
5734 		.name = "pf",
5735 		.help = "direct traffic to physical function",
5736 		.priv = PRIV_ACTION(PF, 0),
5737 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5738 		.call = parse_vc,
5739 	},
5740 	[ACTION_VF] = {
5741 		.name = "vf",
5742 		.help = "direct traffic to a virtual function ID",
5743 		.priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
5744 		.next = NEXT(action_vf),
5745 		.call = parse_vc,
5746 	},
5747 	[ACTION_VF_ORIGINAL] = {
5748 		.name = "original",
5749 		.help = "use original VF ID if possible",
5750 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
5751 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
5752 					   original, 1)),
5753 		.call = parse_vc_conf,
5754 	},
5755 	[ACTION_VF_ID] = {
5756 		.name = "id",
5757 		.help = "VF ID",
5758 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
5759 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
5760 		.call = parse_vc_conf,
5761 	},
5762 	[ACTION_PORT_ID] = {
5763 		.name = "port_id",
5764 		.help = "direct matching traffic to a given DPDK port ID",
5765 		.priv = PRIV_ACTION(PORT_ID,
5766 				    sizeof(struct rte_flow_action_port_id)),
5767 		.next = NEXT(action_port_id),
5768 		.call = parse_vc,
5769 	},
5770 	[ACTION_PORT_ID_ORIGINAL] = {
5771 		.name = "original",
5772 		.help = "use original DPDK port ID if possible",
5773 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
5774 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
5775 					   original, 1)),
5776 		.call = parse_vc_conf,
5777 	},
5778 	[ACTION_PORT_ID_ID] = {
5779 		.name = "id",
5780 		.help = "DPDK port ID",
5781 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
5782 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
5783 		.call = parse_vc_conf,
5784 	},
5785 	[ACTION_METER] = {
5786 		.name = "meter",
5787 		.help = "meter the directed packets at given id",
5788 		.priv = PRIV_ACTION(METER,
5789 				    sizeof(struct rte_flow_action_meter)),
5790 		.next = NEXT(action_meter),
5791 		.call = parse_vc,
5792 	},
5793 	[ACTION_METER_COLOR] = {
5794 		.name = "color",
5795 		.help = "meter color for the packets",
5796 		.priv = PRIV_ACTION(METER_COLOR,
5797 				sizeof(struct rte_flow_action_meter_color)),
5798 		.next = NEXT(action_meter_color),
5799 		.call = parse_vc,
5800 	},
5801 	[ACTION_METER_COLOR_TYPE] = {
5802 		.name = "type",
5803 		.help = "specific meter color",
5804 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
5805 				NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
5806 					ACTION_METER_COLOR_YELLOW,
5807 					ACTION_METER_COLOR_RED)),
5808 	},
5809 	[ACTION_METER_COLOR_GREEN] = {
5810 		.name = "green",
5811 		.help = "meter color green",
5812 		.call = parse_vc_action_meter_color_type,
5813 	},
5814 	[ACTION_METER_COLOR_YELLOW] = {
5815 		.name = "yellow",
5816 		.help = "meter color yellow",
5817 		.call = parse_vc_action_meter_color_type,
5818 	},
5819 	[ACTION_METER_COLOR_RED] = {
5820 		.name = "red",
5821 		.help = "meter color red",
5822 		.call = parse_vc_action_meter_color_type,
5823 	},
5824 	[ACTION_METER_ID] = {
5825 		.name = "mtr_id",
5826 		.help = "meter id to use",
5827 		.next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
5828 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
5829 		.call = parse_vc_conf,
5830 	},
5831 	[ACTION_METER_MARK] = {
5832 		.name = "meter_mark",
5833 		.help = "meter the directed packets using profile and policy",
5834 		.priv = PRIV_ACTION(METER_MARK,
5835 				    sizeof(struct rte_flow_action_meter_mark)),
5836 		.next = NEXT(action_meter_mark),
5837 		.call = parse_vc,
5838 	},
5839 	[ACTION_METER_PROFILE] = {
5840 		.name = "mtr_profile",
5841 		.help = "meter profile id to use",
5842 		.next = NEXT(NEXT_ENTRY(ACTION_METER_PROFILE_ID2PTR)),
5843 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
5844 	},
5845 	[ACTION_METER_PROFILE_ID2PTR] = {
5846 		.name = "{mtr_profile_id}",
5847 		.type = "PROFILE_ID",
5848 		.help = "meter profile id",
5849 		.next = NEXT(action_meter_mark),
5850 		.call = parse_meter_profile_id2ptr,
5851 		.comp = comp_none,
5852 	},
5853 	[ACTION_METER_POLICY] = {
5854 		.name = "mtr_policy",
5855 		.help = "meter policy id to use",
5856 		.next = NEXT(NEXT_ENTRY(ACTION_METER_POLICY_ID2PTR)),
5857 		ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
5858 	},
5859 	[ACTION_METER_POLICY_ID2PTR] = {
5860 		.name = "{mtr_policy_id}",
5861 		.type = "POLICY_ID",
5862 		.help = "meter policy id",
5863 		.next = NEXT(action_meter_mark),
5864 		.call = parse_meter_policy_id2ptr,
5865 		.comp = comp_none,
5866 	},
5867 	[ACTION_METER_COLOR_MODE] = {
5868 		.name = "mtr_color_mode",
5869 		.help = "meter color awareness mode",
5870 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
5871 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, color_mode)),
5872 		.call = parse_vc_conf,
5873 	},
5874 	[ACTION_METER_INIT_COLOR] = {
5875 		.name = "mtr_init_color",
5876 		.help = "meter initial color",
5877 		.next = NEXT(action_meter_mark, NEXT_ENTRY(ITEM_METER_COLOR_NAME)),
5878 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, init_color)),
5879 	},
5880 	[ACTION_METER_STATE] = {
5881 		.name = "mtr_state",
5882 		.help = "meter state",
5883 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
5884 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, state)),
5885 		.call = parse_vc_conf,
5886 	},
5887 	[ACTION_OF_DEC_NW_TTL] = {
5888 		.name = "of_dec_nw_ttl",
5889 		.help = "OpenFlow's OFPAT_DEC_NW_TTL",
5890 		.priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
5891 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5892 		.call = parse_vc,
5893 	},
5894 	[ACTION_OF_POP_VLAN] = {
5895 		.name = "of_pop_vlan",
5896 		.help = "OpenFlow's OFPAT_POP_VLAN",
5897 		.priv = PRIV_ACTION(OF_POP_VLAN, 0),
5898 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5899 		.call = parse_vc,
5900 	},
5901 	[ACTION_OF_PUSH_VLAN] = {
5902 		.name = "of_push_vlan",
5903 		.help = "OpenFlow's OFPAT_PUSH_VLAN",
5904 		.priv = PRIV_ACTION
5905 			(OF_PUSH_VLAN,
5906 			 sizeof(struct rte_flow_action_of_push_vlan)),
5907 		.next = NEXT(action_of_push_vlan),
5908 		.call = parse_vc,
5909 	},
5910 	[ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
5911 		.name = "ethertype",
5912 		.help = "EtherType",
5913 		.next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
5914 		.args = ARGS(ARGS_ENTRY_HTON
5915 			     (struct rte_flow_action_of_push_vlan,
5916 			      ethertype)),
5917 		.call = parse_vc_conf,
5918 	},
5919 	[ACTION_OF_SET_VLAN_VID] = {
5920 		.name = "of_set_vlan_vid",
5921 		.help = "OpenFlow's OFPAT_SET_VLAN_VID",
5922 		.priv = PRIV_ACTION
5923 			(OF_SET_VLAN_VID,
5924 			 sizeof(struct rte_flow_action_of_set_vlan_vid)),
5925 		.next = NEXT(action_of_set_vlan_vid),
5926 		.call = parse_vc,
5927 	},
5928 	[ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
5929 		.name = "vlan_vid",
5930 		.help = "VLAN id",
5931 		.next = NEXT(action_of_set_vlan_vid,
5932 			     NEXT_ENTRY(COMMON_UNSIGNED)),
5933 		.args = ARGS(ARGS_ENTRY_HTON
5934 			     (struct rte_flow_action_of_set_vlan_vid,
5935 			      vlan_vid)),
5936 		.call = parse_vc_conf,
5937 	},
5938 	[ACTION_OF_SET_VLAN_PCP] = {
5939 		.name = "of_set_vlan_pcp",
5940 		.help = "OpenFlow's OFPAT_SET_VLAN_PCP",
5941 		.priv = PRIV_ACTION
5942 			(OF_SET_VLAN_PCP,
5943 			 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
5944 		.next = NEXT(action_of_set_vlan_pcp),
5945 		.call = parse_vc,
5946 	},
5947 	[ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
5948 		.name = "vlan_pcp",
5949 		.help = "VLAN priority",
5950 		.next = NEXT(action_of_set_vlan_pcp,
5951 			     NEXT_ENTRY(COMMON_UNSIGNED)),
5952 		.args = ARGS(ARGS_ENTRY_HTON
5953 			     (struct rte_flow_action_of_set_vlan_pcp,
5954 			      vlan_pcp)),
5955 		.call = parse_vc_conf,
5956 	},
5957 	[ACTION_OF_POP_MPLS] = {
5958 		.name = "of_pop_mpls",
5959 		.help = "OpenFlow's OFPAT_POP_MPLS",
5960 		.priv = PRIV_ACTION(OF_POP_MPLS,
5961 				    sizeof(struct rte_flow_action_of_pop_mpls)),
5962 		.next = NEXT(action_of_pop_mpls),
5963 		.call = parse_vc,
5964 	},
5965 	[ACTION_OF_POP_MPLS_ETHERTYPE] = {
5966 		.name = "ethertype",
5967 		.help = "EtherType",
5968 		.next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
5969 		.args = ARGS(ARGS_ENTRY_HTON
5970 			     (struct rte_flow_action_of_pop_mpls,
5971 			      ethertype)),
5972 		.call = parse_vc_conf,
5973 	},
5974 	[ACTION_OF_PUSH_MPLS] = {
5975 		.name = "of_push_mpls",
5976 		.help = "OpenFlow's OFPAT_PUSH_MPLS",
5977 		.priv = PRIV_ACTION
5978 			(OF_PUSH_MPLS,
5979 			 sizeof(struct rte_flow_action_of_push_mpls)),
5980 		.next = NEXT(action_of_push_mpls),
5981 		.call = parse_vc,
5982 	},
5983 	[ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
5984 		.name = "ethertype",
5985 		.help = "EtherType",
5986 		.next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
5987 		.args = ARGS(ARGS_ENTRY_HTON
5988 			     (struct rte_flow_action_of_push_mpls,
5989 			      ethertype)),
5990 		.call = parse_vc_conf,
5991 	},
5992 	[ACTION_VXLAN_ENCAP] = {
5993 		.name = "vxlan_encap",
5994 		.help = "VXLAN encapsulation, uses configuration set by \"set"
5995 			" vxlan\"",
5996 		.priv = PRIV_ACTION(VXLAN_ENCAP,
5997 				    sizeof(struct action_vxlan_encap_data)),
5998 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5999 		.call = parse_vc_action_vxlan_encap,
6000 	},
6001 	[ACTION_VXLAN_DECAP] = {
6002 		.name = "vxlan_decap",
6003 		.help = "Performs a decapsulation action by stripping all"
6004 			" headers of the VXLAN tunnel network overlay from the"
6005 			" matched flow.",
6006 		.priv = PRIV_ACTION(VXLAN_DECAP, 0),
6007 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6008 		.call = parse_vc,
6009 	},
6010 	[ACTION_NVGRE_ENCAP] = {
6011 		.name = "nvgre_encap",
6012 		.help = "NVGRE encapsulation, uses configuration set by \"set"
6013 			" nvgre\"",
6014 		.priv = PRIV_ACTION(NVGRE_ENCAP,
6015 				    sizeof(struct action_nvgre_encap_data)),
6016 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6017 		.call = parse_vc_action_nvgre_encap,
6018 	},
6019 	[ACTION_NVGRE_DECAP] = {
6020 		.name = "nvgre_decap",
6021 		.help = "Performs a decapsulation action by stripping all"
6022 			" headers of the NVGRE tunnel network overlay from the"
6023 			" matched flow.",
6024 		.priv = PRIV_ACTION(NVGRE_DECAP, 0),
6025 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6026 		.call = parse_vc,
6027 	},
6028 	[ACTION_L2_ENCAP] = {
6029 		.name = "l2_encap",
6030 		.help = "l2 encap, uses configuration set by"
6031 			" \"set l2_encap\"",
6032 		.priv = PRIV_ACTION(RAW_ENCAP,
6033 				    sizeof(struct action_raw_encap_data)),
6034 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6035 		.call = parse_vc_action_l2_encap,
6036 	},
6037 	[ACTION_L2_DECAP] = {
6038 		.name = "l2_decap",
6039 		.help = "l2 decap, uses configuration set by"
6040 			" \"set l2_decap\"",
6041 		.priv = PRIV_ACTION(RAW_DECAP,
6042 				    sizeof(struct action_raw_decap_data)),
6043 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6044 		.call = parse_vc_action_l2_decap,
6045 	},
6046 	[ACTION_MPLSOGRE_ENCAP] = {
6047 		.name = "mplsogre_encap",
6048 		.help = "mplsogre encapsulation, uses configuration set by"
6049 			" \"set mplsogre_encap\"",
6050 		.priv = PRIV_ACTION(RAW_ENCAP,
6051 				    sizeof(struct action_raw_encap_data)),
6052 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6053 		.call = parse_vc_action_mplsogre_encap,
6054 	},
6055 	[ACTION_MPLSOGRE_DECAP] = {
6056 		.name = "mplsogre_decap",
6057 		.help = "mplsogre decapsulation, uses configuration set by"
6058 			" \"set mplsogre_decap\"",
6059 		.priv = PRIV_ACTION(RAW_DECAP,
6060 				    sizeof(struct action_raw_decap_data)),
6061 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6062 		.call = parse_vc_action_mplsogre_decap,
6063 	},
6064 	[ACTION_MPLSOUDP_ENCAP] = {
6065 		.name = "mplsoudp_encap",
6066 		.help = "mplsoudp encapsulation, uses configuration set by"
6067 			" \"set mplsoudp_encap\"",
6068 		.priv = PRIV_ACTION(RAW_ENCAP,
6069 				    sizeof(struct action_raw_encap_data)),
6070 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6071 		.call = parse_vc_action_mplsoudp_encap,
6072 	},
6073 	[ACTION_MPLSOUDP_DECAP] = {
6074 		.name = "mplsoudp_decap",
6075 		.help = "mplsoudp decapsulation, uses configuration set by"
6076 			" \"set mplsoudp_decap\"",
6077 		.priv = PRIV_ACTION(RAW_DECAP,
6078 				    sizeof(struct action_raw_decap_data)),
6079 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6080 		.call = parse_vc_action_mplsoudp_decap,
6081 	},
6082 	[ACTION_SET_IPV4_SRC] = {
6083 		.name = "set_ipv4_src",
6084 		.help = "Set a new IPv4 source address in the outermost"
6085 			" IPv4 header",
6086 		.priv = PRIV_ACTION(SET_IPV4_SRC,
6087 			sizeof(struct rte_flow_action_set_ipv4)),
6088 		.next = NEXT(action_set_ipv4_src),
6089 		.call = parse_vc,
6090 	},
6091 	[ACTION_SET_IPV4_SRC_IPV4_SRC] = {
6092 		.name = "ipv4_addr",
6093 		.help = "new IPv4 source address to set",
6094 		.next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
6095 		.args = ARGS(ARGS_ENTRY_HTON
6096 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
6097 		.call = parse_vc_conf,
6098 	},
6099 	[ACTION_SET_IPV4_DST] = {
6100 		.name = "set_ipv4_dst",
6101 		.help = "Set a new IPv4 destination address in the outermost"
6102 			" IPv4 header",
6103 		.priv = PRIV_ACTION(SET_IPV4_DST,
6104 			sizeof(struct rte_flow_action_set_ipv4)),
6105 		.next = NEXT(action_set_ipv4_dst),
6106 		.call = parse_vc,
6107 	},
6108 	[ACTION_SET_IPV4_DST_IPV4_DST] = {
6109 		.name = "ipv4_addr",
6110 		.help = "new IPv4 destination address to set",
6111 		.next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
6112 		.args = ARGS(ARGS_ENTRY_HTON
6113 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
6114 		.call = parse_vc_conf,
6115 	},
6116 	[ACTION_SET_IPV6_SRC] = {
6117 		.name = "set_ipv6_src",
6118 		.help = "Set a new IPv6 source address in the outermost"
6119 			" IPv6 header",
6120 		.priv = PRIV_ACTION(SET_IPV6_SRC,
6121 			sizeof(struct rte_flow_action_set_ipv6)),
6122 		.next = NEXT(action_set_ipv6_src),
6123 		.call = parse_vc,
6124 	},
6125 	[ACTION_SET_IPV6_SRC_IPV6_SRC] = {
6126 		.name = "ipv6_addr",
6127 		.help = "new IPv6 source address to set",
6128 		.next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
6129 		.args = ARGS(ARGS_ENTRY_HTON
6130 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
6131 		.call = parse_vc_conf,
6132 	},
6133 	[ACTION_SET_IPV6_DST] = {
6134 		.name = "set_ipv6_dst",
6135 		.help = "Set a new IPv6 destination address in the outermost"
6136 			" IPv6 header",
6137 		.priv = PRIV_ACTION(SET_IPV6_DST,
6138 			sizeof(struct rte_flow_action_set_ipv6)),
6139 		.next = NEXT(action_set_ipv6_dst),
6140 		.call = parse_vc,
6141 	},
6142 	[ACTION_SET_IPV6_DST_IPV6_DST] = {
6143 		.name = "ipv6_addr",
6144 		.help = "new IPv6 destination address to set",
6145 		.next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
6146 		.args = ARGS(ARGS_ENTRY_HTON
6147 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
6148 		.call = parse_vc_conf,
6149 	},
6150 	[ACTION_SET_TP_SRC] = {
6151 		.name = "set_tp_src",
6152 		.help = "set a new source port number in the outermost"
6153 			" TCP/UDP header",
6154 		.priv = PRIV_ACTION(SET_TP_SRC,
6155 			sizeof(struct rte_flow_action_set_tp)),
6156 		.next = NEXT(action_set_tp_src),
6157 		.call = parse_vc,
6158 	},
6159 	[ACTION_SET_TP_SRC_TP_SRC] = {
6160 		.name = "port",
6161 		.help = "new source port number to set",
6162 		.next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
6163 		.args = ARGS(ARGS_ENTRY_HTON
6164 			     (struct rte_flow_action_set_tp, port)),
6165 		.call = parse_vc_conf,
6166 	},
6167 	[ACTION_SET_TP_DST] = {
6168 		.name = "set_tp_dst",
6169 		.help = "set a new destination port number in the outermost"
6170 			" TCP/UDP header",
6171 		.priv = PRIV_ACTION(SET_TP_DST,
6172 			sizeof(struct rte_flow_action_set_tp)),
6173 		.next = NEXT(action_set_tp_dst),
6174 		.call = parse_vc,
6175 	},
6176 	[ACTION_SET_TP_DST_TP_DST] = {
6177 		.name = "port",
6178 		.help = "new destination port number to set",
6179 		.next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
6180 		.args = ARGS(ARGS_ENTRY_HTON
6181 			     (struct rte_flow_action_set_tp, port)),
6182 		.call = parse_vc_conf,
6183 	},
6184 	[ACTION_MAC_SWAP] = {
6185 		.name = "mac_swap",
6186 		.help = "Swap the source and destination MAC addresses"
6187 			" in the outermost Ethernet header",
6188 		.priv = PRIV_ACTION(MAC_SWAP, 0),
6189 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6190 		.call = parse_vc,
6191 	},
6192 	[ACTION_DEC_TTL] = {
6193 		.name = "dec_ttl",
6194 		.help = "decrease network TTL if available",
6195 		.priv = PRIV_ACTION(DEC_TTL, 0),
6196 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6197 		.call = parse_vc,
6198 	},
6199 	[ACTION_SET_TTL] = {
6200 		.name = "set_ttl",
6201 		.help = "set ttl value",
6202 		.priv = PRIV_ACTION(SET_TTL,
6203 			sizeof(struct rte_flow_action_set_ttl)),
6204 		.next = NEXT(action_set_ttl),
6205 		.call = parse_vc,
6206 	},
6207 	[ACTION_SET_TTL_TTL] = {
6208 		.name = "ttl_value",
6209 		.help = "new ttl value to set",
6210 		.next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
6211 		.args = ARGS(ARGS_ENTRY_HTON
6212 			     (struct rte_flow_action_set_ttl, ttl_value)),
6213 		.call = parse_vc_conf,
6214 	},
6215 	[ACTION_SET_MAC_SRC] = {
6216 		.name = "set_mac_src",
6217 		.help = "set source mac address",
6218 		.priv = PRIV_ACTION(SET_MAC_SRC,
6219 			sizeof(struct rte_flow_action_set_mac)),
6220 		.next = NEXT(action_set_mac_src),
6221 		.call = parse_vc,
6222 	},
6223 	[ACTION_SET_MAC_SRC_MAC_SRC] = {
6224 		.name = "mac_addr",
6225 		.help = "new source mac address",
6226 		.next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
6227 		.args = ARGS(ARGS_ENTRY_HTON
6228 			     (struct rte_flow_action_set_mac, mac_addr)),
6229 		.call = parse_vc_conf,
6230 	},
6231 	[ACTION_SET_MAC_DST] = {
6232 		.name = "set_mac_dst",
6233 		.help = "set destination mac address",
6234 		.priv = PRIV_ACTION(SET_MAC_DST,
6235 			sizeof(struct rte_flow_action_set_mac)),
6236 		.next = NEXT(action_set_mac_dst),
6237 		.call = parse_vc,
6238 	},
6239 	[ACTION_SET_MAC_DST_MAC_DST] = {
6240 		.name = "mac_addr",
6241 		.help = "new destination mac address to set",
6242 		.next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
6243 		.args = ARGS(ARGS_ENTRY_HTON
6244 			     (struct rte_flow_action_set_mac, mac_addr)),
6245 		.call = parse_vc_conf,
6246 	},
6247 	[ACTION_INC_TCP_SEQ] = {
6248 		.name = "inc_tcp_seq",
6249 		.help = "increase TCP sequence number",
6250 		.priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
6251 		.next = NEXT(action_inc_tcp_seq),
6252 		.call = parse_vc,
6253 	},
6254 	[ACTION_INC_TCP_SEQ_VALUE] = {
6255 		.name = "value",
6256 		.help = "the value to increase TCP sequence number by",
6257 		.next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
6258 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
6259 		.call = parse_vc_conf,
6260 	},
6261 	[ACTION_DEC_TCP_SEQ] = {
6262 		.name = "dec_tcp_seq",
6263 		.help = "decrease TCP sequence number",
6264 		.priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
6265 		.next = NEXT(action_dec_tcp_seq),
6266 		.call = parse_vc,
6267 	},
6268 	[ACTION_DEC_TCP_SEQ_VALUE] = {
6269 		.name = "value",
6270 		.help = "the value to decrease TCP sequence number by",
6271 		.next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
6272 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
6273 		.call = parse_vc_conf,
6274 	},
6275 	[ACTION_INC_TCP_ACK] = {
6276 		.name = "inc_tcp_ack",
6277 		.help = "increase TCP acknowledgment number",
6278 		.priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
6279 		.next = NEXT(action_inc_tcp_ack),
6280 		.call = parse_vc,
6281 	},
6282 	[ACTION_INC_TCP_ACK_VALUE] = {
6283 		.name = "value",
6284 		.help = "the value to increase TCP acknowledgment number by",
6285 		.next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
6286 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
6287 		.call = parse_vc_conf,
6288 	},
6289 	[ACTION_DEC_TCP_ACK] = {
6290 		.name = "dec_tcp_ack",
6291 		.help = "decrease TCP acknowledgment number",
6292 		.priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
6293 		.next = NEXT(action_dec_tcp_ack),
6294 		.call = parse_vc,
6295 	},
6296 	[ACTION_DEC_TCP_ACK_VALUE] = {
6297 		.name = "value",
6298 		.help = "the value to decrease TCP acknowledgment number by",
6299 		.next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
6300 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
6301 		.call = parse_vc_conf,
6302 	},
6303 	[ACTION_RAW_ENCAP] = {
6304 		.name = "raw_encap",
6305 		.help = "encapsulation data, defined by set raw_encap",
6306 		.priv = PRIV_ACTION(RAW_ENCAP,
6307 			sizeof(struct action_raw_encap_data)),
6308 		.next = NEXT(action_raw_encap),
6309 		.call = parse_vc_action_raw_encap,
6310 	},
6311 	[ACTION_RAW_ENCAP_INDEX] = {
6312 		.name = "index",
6313 		.help = "the index of raw_encap_confs",
6314 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
6315 	},
6316 	[ACTION_RAW_ENCAP_INDEX_VALUE] = {
6317 		.name = "{index}",
6318 		.type = "UNSIGNED",
6319 		.help = "unsigned integer value",
6320 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6321 		.call = parse_vc_action_raw_encap_index,
6322 		.comp = comp_set_raw_index,
6323 	},
6324 	[ACTION_RAW_DECAP] = {
6325 		.name = "raw_decap",
6326 		.help = "decapsulation data, defined by set raw_encap",
6327 		.priv = PRIV_ACTION(RAW_DECAP,
6328 			sizeof(struct action_raw_decap_data)),
6329 		.next = NEXT(action_raw_decap),
6330 		.call = parse_vc_action_raw_decap,
6331 	},
6332 	[ACTION_RAW_DECAP_INDEX] = {
6333 		.name = "index",
6334 		.help = "the index of raw_encap_confs",
6335 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
6336 	},
6337 	[ACTION_RAW_DECAP_INDEX_VALUE] = {
6338 		.name = "{index}",
6339 		.type = "UNSIGNED",
6340 		.help = "unsigned integer value",
6341 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6342 		.call = parse_vc_action_raw_decap_index,
6343 		.comp = comp_set_raw_index,
6344 	},
6345 	[ACTION_MODIFY_FIELD] = {
6346 		.name = "modify_field",
6347 		.help = "modify destination field with data from source field",
6348 		.priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
6349 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
6350 		.call = parse_vc,
6351 	},
6352 	[ACTION_MODIFY_FIELD_OP] = {
6353 		.name = "op",
6354 		.help = "operation type",
6355 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
6356 			NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
6357 		.call = parse_vc_conf,
6358 	},
6359 	[ACTION_MODIFY_FIELD_OP_VALUE] = {
6360 		.name = "{operation}",
6361 		.help = "operation type value",
6362 		.call = parse_vc_modify_field_op,
6363 		.comp = comp_set_modify_field_op,
6364 	},
6365 	[ACTION_MODIFY_FIELD_DST_TYPE] = {
6366 		.name = "dst_type",
6367 		.help = "destination field type",
6368 		.next = NEXT(action_modify_field_dst,
6369 			NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
6370 		.call = parse_vc_conf,
6371 	},
6372 	[ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
6373 		.name = "{dst_type}",
6374 		.help = "destination field type value",
6375 		.call = parse_vc_modify_field_id,
6376 		.comp = comp_set_modify_field_id,
6377 	},
6378 	[ACTION_MODIFY_FIELD_DST_LEVEL] = {
6379 		.name = "dst_level",
6380 		.help = "destination field level",
6381 		.next = NEXT(action_modify_field_dst,
6382 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)),
6383 		.call = parse_vc_conf,
6384 	},
6385 	[ACTION_MODIFY_FIELD_DST_LEVEL_VALUE] = {
6386 		.name = "{dst_level}",
6387 		.help = "destination field level value",
6388 		.call = parse_vc_modify_field_level,
6389 		.comp = comp_none,
6390 	},
6391 	[ACTION_MODIFY_FIELD_DST_OFFSET] = {
6392 		.name = "dst_offset",
6393 		.help = "destination field bit offset",
6394 		.next = NEXT(action_modify_field_dst,
6395 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6396 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
6397 					dst.offset)),
6398 		.call = parse_vc_conf,
6399 	},
6400 	[ACTION_MODIFY_FIELD_SRC_TYPE] = {
6401 		.name = "src_type",
6402 		.help = "source field type",
6403 		.next = NEXT(action_modify_field_src,
6404 			NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
6405 		.call = parse_vc_conf,
6406 	},
6407 	[ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
6408 		.name = "{src_type}",
6409 		.help = "source field type value",
6410 		.call = parse_vc_modify_field_id,
6411 		.comp = comp_set_modify_field_id,
6412 	},
6413 	[ACTION_MODIFY_FIELD_SRC_LEVEL] = {
6414 		.name = "src_level",
6415 		.help = "source field level",
6416 		.next = NEXT(action_modify_field_src,
6417 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)),
6418 		.call = parse_vc_conf,
6419 	},
6420 	[ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE] = {
6421 		.name = "{src_level}",
6422 		.help = "source field level value",
6423 		.call = parse_vc_modify_field_level,
6424 		.comp = comp_none,
6425 	},
6426 	[ACTION_MODIFY_FIELD_SRC_OFFSET] = {
6427 		.name = "src_offset",
6428 		.help = "source field bit offset",
6429 		.next = NEXT(action_modify_field_src,
6430 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6431 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
6432 					src.offset)),
6433 		.call = parse_vc_conf,
6434 	},
6435 	[ACTION_MODIFY_FIELD_SRC_VALUE] = {
6436 		.name = "src_value",
6437 		.help = "source immediate value",
6438 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
6439 			     NEXT_ENTRY(COMMON_HEX)),
6440 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
6441 			     ARGS_ENTRY_ARB(0, 0),
6442 			     ARGS_ENTRY(struct rte_flow_action_modify_field,
6443 					src.value)),
6444 		.call = parse_vc_conf,
6445 	},
6446 	[ACTION_MODIFY_FIELD_SRC_POINTER] = {
6447 		.name = "src_ptr",
6448 		.help = "pointer to source immediate value",
6449 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
6450 			     NEXT_ENTRY(COMMON_HEX)),
6451 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
6452 					src.pvalue),
6453 			     ARGS_ENTRY_ARB(0, 0),
6454 			     ARGS_ENTRY_ARB
6455 				(sizeof(struct rte_flow_action_modify_field),
6456 				 ACTION_MODIFY_PATTERN_SIZE)),
6457 		.call = parse_vc_conf,
6458 	},
6459 	[ACTION_MODIFY_FIELD_WIDTH] = {
6460 		.name = "width",
6461 		.help = "number of bits to copy",
6462 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
6463 			NEXT_ENTRY(COMMON_UNSIGNED)),
6464 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
6465 					width)),
6466 		.call = parse_vc_conf,
6467 	},
6468 	[ACTION_SEND_TO_KERNEL] = {
6469 		.name = "send_to_kernel",
6470 		.help = "send packets to kernel",
6471 		.priv = PRIV_ACTION(SEND_TO_KERNEL, 0),
6472 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6473 		.call = parse_vc,
6474 	},
6475 	/* Top level command. */
6476 	[SET] = {
6477 		.name = "set",
6478 		.help = "set raw encap/decap/sample data",
6479 		.type = "set raw_encap|raw_decap <index> <pattern>"
6480 				" or set sample_actions <index> <action>",
6481 		.next = NEXT(NEXT_ENTRY
6482 			     (SET_RAW_ENCAP,
6483 			      SET_RAW_DECAP,
6484 			      SET_SAMPLE_ACTIONS)),
6485 		.call = parse_set_init,
6486 	},
6487 	/* Sub-level commands. */
6488 	[SET_RAW_ENCAP] = {
6489 		.name = "raw_encap",
6490 		.help = "set raw encap data",
6491 		.next = NEXT(next_set_raw),
6492 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
6493 				(offsetof(struct buffer, port),
6494 				 sizeof(((struct buffer *)0)->port),
6495 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
6496 		.call = parse_set_raw_encap_decap,
6497 	},
6498 	[SET_RAW_DECAP] = {
6499 		.name = "raw_decap",
6500 		.help = "set raw decap data",
6501 		.next = NEXT(next_set_raw),
6502 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
6503 				(offsetof(struct buffer, port),
6504 				 sizeof(((struct buffer *)0)->port),
6505 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
6506 		.call = parse_set_raw_encap_decap,
6507 	},
6508 	[SET_RAW_INDEX] = {
6509 		.name = "{index}",
6510 		.type = "COMMON_UNSIGNED",
6511 		.help = "index of raw_encap/raw_decap data",
6512 		.next = NEXT(next_item),
6513 		.call = parse_port,
6514 	},
6515 	[SET_SAMPLE_INDEX] = {
6516 		.name = "{index}",
6517 		.type = "UNSIGNED",
6518 		.help = "index of sample actions",
6519 		.next = NEXT(next_action_sample),
6520 		.call = parse_port,
6521 	},
6522 	[SET_SAMPLE_ACTIONS] = {
6523 		.name = "sample_actions",
6524 		.help = "set sample actions list",
6525 		.next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
6526 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
6527 				(offsetof(struct buffer, port),
6528 				 sizeof(((struct buffer *)0)->port),
6529 				 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
6530 		.call = parse_set_sample_action,
6531 	},
6532 	[ACTION_SET_TAG] = {
6533 		.name = "set_tag",
6534 		.help = "set tag",
6535 		.priv = PRIV_ACTION(SET_TAG,
6536 			sizeof(struct rte_flow_action_set_tag)),
6537 		.next = NEXT(action_set_tag),
6538 		.call = parse_vc,
6539 	},
6540 	[ACTION_SET_TAG_INDEX] = {
6541 		.name = "index",
6542 		.help = "index of tag array",
6543 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
6544 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
6545 		.call = parse_vc_conf,
6546 	},
6547 	[ACTION_SET_TAG_DATA] = {
6548 		.name = "data",
6549 		.help = "tag value",
6550 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
6551 		.args = ARGS(ARGS_ENTRY
6552 			     (struct rte_flow_action_set_tag, data)),
6553 		.call = parse_vc_conf,
6554 	},
6555 	[ACTION_SET_TAG_MASK] = {
6556 		.name = "mask",
6557 		.help = "mask for tag value",
6558 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
6559 		.args = ARGS(ARGS_ENTRY
6560 			     (struct rte_flow_action_set_tag, mask)),
6561 		.call = parse_vc_conf,
6562 	},
6563 	[ACTION_SET_META] = {
6564 		.name = "set_meta",
6565 		.help = "set metadata",
6566 		.priv = PRIV_ACTION(SET_META,
6567 			sizeof(struct rte_flow_action_set_meta)),
6568 		.next = NEXT(action_set_meta),
6569 		.call = parse_vc_action_set_meta,
6570 	},
6571 	[ACTION_SET_META_DATA] = {
6572 		.name = "data",
6573 		.help = "metadata value",
6574 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
6575 		.args = ARGS(ARGS_ENTRY
6576 			     (struct rte_flow_action_set_meta, data)),
6577 		.call = parse_vc_conf,
6578 	},
6579 	[ACTION_SET_META_MASK] = {
6580 		.name = "mask",
6581 		.help = "mask for metadata value",
6582 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
6583 		.args = ARGS(ARGS_ENTRY
6584 			     (struct rte_flow_action_set_meta, mask)),
6585 		.call = parse_vc_conf,
6586 	},
6587 	[ACTION_SET_IPV4_DSCP] = {
6588 		.name = "set_ipv4_dscp",
6589 		.help = "set DSCP value",
6590 		.priv = PRIV_ACTION(SET_IPV4_DSCP,
6591 			sizeof(struct rte_flow_action_set_dscp)),
6592 		.next = NEXT(action_set_ipv4_dscp),
6593 		.call = parse_vc,
6594 	},
6595 	[ACTION_SET_IPV4_DSCP_VALUE] = {
6596 		.name = "dscp_value",
6597 		.help = "new IPv4 DSCP value to set",
6598 		.next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
6599 		.args = ARGS(ARGS_ENTRY
6600 			     (struct rte_flow_action_set_dscp, dscp)),
6601 		.call = parse_vc_conf,
6602 	},
6603 	[ACTION_SET_IPV6_DSCP] = {
6604 		.name = "set_ipv6_dscp",
6605 		.help = "set DSCP value",
6606 		.priv = PRIV_ACTION(SET_IPV6_DSCP,
6607 			sizeof(struct rte_flow_action_set_dscp)),
6608 		.next = NEXT(action_set_ipv6_dscp),
6609 		.call = parse_vc,
6610 	},
6611 	[ACTION_SET_IPV6_DSCP_VALUE] = {
6612 		.name = "dscp_value",
6613 		.help = "new IPv6 DSCP value to set",
6614 		.next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
6615 		.args = ARGS(ARGS_ENTRY
6616 			     (struct rte_flow_action_set_dscp, dscp)),
6617 		.call = parse_vc_conf,
6618 	},
6619 	[ACTION_AGE] = {
6620 		.name = "age",
6621 		.help = "set a specific metadata header",
6622 		.next = NEXT(action_age),
6623 		.priv = PRIV_ACTION(AGE,
6624 			sizeof(struct rte_flow_action_age)),
6625 		.call = parse_vc,
6626 	},
6627 	[ACTION_AGE_TIMEOUT] = {
6628 		.name = "timeout",
6629 		.help = "flow age timeout value",
6630 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
6631 					   timeout, 24)),
6632 		.next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
6633 		.call = parse_vc_conf,
6634 	},
6635 	[ACTION_AGE_UPDATE] = {
6636 		.name = "age_update",
6637 		.help = "update aging parameter",
6638 		.next = NEXT(action_age_update),
6639 		.priv = PRIV_ACTION(AGE,
6640 				    sizeof(struct rte_flow_update_age)),
6641 		.call = parse_vc,
6642 	},
6643 	[ACTION_AGE_UPDATE_TIMEOUT] = {
6644 		.name = "timeout",
6645 		.help = "age timeout update value",
6646 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
6647 					   timeout, 24)),
6648 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_UNSIGNED)),
6649 		.call = parse_vc_conf_timeout,
6650 	},
6651 	[ACTION_AGE_UPDATE_TOUCH] = {
6652 		.name = "touch",
6653 		.help = "this flow is touched",
6654 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_BOOLEAN)),
6655 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
6656 					   touch, 1)),
6657 		.call = parse_vc_conf,
6658 	},
6659 	[ACTION_SAMPLE] = {
6660 		.name = "sample",
6661 		.help = "set a sample action",
6662 		.next = NEXT(action_sample),
6663 		.priv = PRIV_ACTION(SAMPLE,
6664 			sizeof(struct action_sample_data)),
6665 		.call = parse_vc_action_sample,
6666 	},
6667 	[ACTION_SAMPLE_RATIO] = {
6668 		.name = "ratio",
6669 		.help = "flow sample ratio value",
6670 		.next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
6671 		.args = ARGS(ARGS_ENTRY_ARB
6672 			     (offsetof(struct action_sample_data, conf) +
6673 			      offsetof(struct rte_flow_action_sample, ratio),
6674 			      sizeof(((struct rte_flow_action_sample *)0)->
6675 				     ratio))),
6676 	},
6677 	[ACTION_SAMPLE_INDEX] = {
6678 		.name = "index",
6679 		.help = "the index of sample actions list",
6680 		.next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
6681 	},
6682 	[ACTION_SAMPLE_INDEX_VALUE] = {
6683 		.name = "{index}",
6684 		.type = "COMMON_UNSIGNED",
6685 		.help = "unsigned integer value",
6686 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6687 		.call = parse_vc_action_sample_index,
6688 		.comp = comp_set_sample_index,
6689 	},
6690 	[ACTION_CONNTRACK] = {
6691 		.name = "conntrack",
6692 		.help = "create a conntrack object",
6693 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6694 		.priv = PRIV_ACTION(CONNTRACK,
6695 				    sizeof(struct rte_flow_action_conntrack)),
6696 		.call = parse_vc,
6697 	},
6698 	[ACTION_CONNTRACK_UPDATE] = {
6699 		.name = "conntrack_update",
6700 		.help = "update a conntrack object",
6701 		.next = NEXT(action_update_conntrack),
6702 		.priv = PRIV_ACTION(CONNTRACK,
6703 				    sizeof(struct rte_flow_modify_conntrack)),
6704 		.call = parse_vc,
6705 	},
6706 	[ACTION_CONNTRACK_UPDATE_DIR] = {
6707 		.name = "dir",
6708 		.help = "update a conntrack object direction",
6709 		.next = NEXT(action_update_conntrack),
6710 		.call = parse_vc_action_conntrack_update,
6711 	},
6712 	[ACTION_CONNTRACK_UPDATE_CTX] = {
6713 		.name = "ctx",
6714 		.help = "update a conntrack object context",
6715 		.next = NEXT(action_update_conntrack),
6716 		.call = parse_vc_action_conntrack_update,
6717 	},
6718 	[ACTION_PORT_REPRESENTOR] = {
6719 		.name = "port_representor",
6720 		.help = "at embedded switch level, send matching traffic to the given ethdev",
6721 		.priv = PRIV_ACTION(PORT_REPRESENTOR,
6722 				    sizeof(struct rte_flow_action_ethdev)),
6723 		.next = NEXT(action_port_representor),
6724 		.call = parse_vc,
6725 	},
6726 	[ACTION_PORT_REPRESENTOR_PORT_ID] = {
6727 		.name = "port_id",
6728 		.help = "ethdev port ID",
6729 		.next = NEXT(action_port_representor,
6730 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6731 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
6732 					port_id)),
6733 		.call = parse_vc_conf,
6734 	},
6735 	[ACTION_REPRESENTED_PORT] = {
6736 		.name = "represented_port",
6737 		.help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
6738 		.priv = PRIV_ACTION(REPRESENTED_PORT,
6739 				sizeof(struct rte_flow_action_ethdev)),
6740 		.next = NEXT(action_represented_port),
6741 		.call = parse_vc,
6742 	},
6743 	[ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
6744 		.name = "ethdev_port_id",
6745 		.help = "ethdev port ID",
6746 		.next = NEXT(action_represented_port,
6747 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6748 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
6749 					port_id)),
6750 		.call = parse_vc_conf,
6751 	},
6752 	/* Indirect action destroy arguments. */
6753 	[INDIRECT_ACTION_DESTROY_ID] = {
6754 		.name = "action_id",
6755 		.help = "specify a indirect action id to destroy",
6756 		.next = NEXT(next_ia_destroy_attr,
6757 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
6758 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
6759 					    args.ia_destroy.action_id)),
6760 		.call = parse_ia_destroy,
6761 	},
6762 	/* Indirect action create arguments. */
6763 	[INDIRECT_ACTION_CREATE_ID] = {
6764 		.name = "action_id",
6765 		.help = "specify a indirect action id to create",
6766 		.next = NEXT(next_ia_create_attr,
6767 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
6768 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
6769 	},
6770 	[ACTION_INDIRECT] = {
6771 		.name = "indirect",
6772 		.help = "apply indirect action by id",
6773 		.priv = PRIV_ACTION(INDIRECT, 0),
6774 		.next = NEXT(next_ia),
6775 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6776 		.call = parse_vc,
6777 	},
6778 	[ACTION_SHARED_INDIRECT] = {
6779 		.name = "shared_indirect",
6780 		.help = "apply indirect action by id and port",
6781 		.priv = PRIV_ACTION(INDIRECT, 0),
6782 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_PORT)),
6783 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t)),
6784 			     ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6785 		.call = parse_vc,
6786 	},
6787 	[INDIRECT_ACTION_PORT] = {
6788 		.name = "{indirect_action_port}",
6789 		.type = "INDIRECT_ACTION_PORT",
6790 		.help = "indirect action port",
6791 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
6792 		.call = parse_ia_port,
6793 		.comp = comp_none,
6794 	},
6795 	[INDIRECT_ACTION_ID2PTR] = {
6796 		.name = "{action_id}",
6797 		.type = "INDIRECT_ACTION_ID",
6798 		.help = "indirect action id",
6799 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6800 		.call = parse_ia_id2ptr,
6801 		.comp = comp_none,
6802 	},
6803 	[INDIRECT_ACTION_INGRESS] = {
6804 		.name = "ingress",
6805 		.help = "affect rule to ingress",
6806 		.next = NEXT(next_ia_create_attr),
6807 		.call = parse_ia,
6808 	},
6809 	[INDIRECT_ACTION_EGRESS] = {
6810 		.name = "egress",
6811 		.help = "affect rule to egress",
6812 		.next = NEXT(next_ia_create_attr),
6813 		.call = parse_ia,
6814 	},
6815 	[INDIRECT_ACTION_TRANSFER] = {
6816 		.name = "transfer",
6817 		.help = "affect rule to transfer",
6818 		.next = NEXT(next_ia_create_attr),
6819 		.call = parse_ia,
6820 	},
6821 	[INDIRECT_ACTION_SPEC] = {
6822 		.name = "action",
6823 		.help = "specify action to create indirect handle",
6824 		.next = NEXT(next_action),
6825 	},
6826 	[ACTION_POL_G] = {
6827 		.name = "g_actions",
6828 		.help = "submit a list of associated actions for green",
6829 		.next = NEXT(next_action),
6830 		.call = parse_mp,
6831 	},
6832 	[ACTION_POL_Y] = {
6833 		.name = "y_actions",
6834 		.help = "submit a list of associated actions for yellow",
6835 		.next = NEXT(next_action),
6836 	},
6837 	[ACTION_POL_R] = {
6838 		.name = "r_actions",
6839 		.help = "submit a list of associated actions for red",
6840 		.next = NEXT(next_action),
6841 	},
6842 	[ACTION_QUOTA_CREATE] = {
6843 		.name = "quota_create",
6844 		.help = "create quota action",
6845 		.priv = PRIV_ACTION(QUOTA,
6846 				    sizeof(struct rte_flow_action_quota)),
6847 		.next = NEXT(action_quota_create),
6848 		.call = parse_vc
6849 	},
6850 	[ACTION_QUOTA_CREATE_LIMIT] = {
6851 		.name = "limit",
6852 		.help = "quota limit",
6853 		.next = NEXT(action_quota_create, NEXT_ENTRY(COMMON_UNSIGNED)),
6854 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, quota)),
6855 		.call = parse_vc_conf
6856 	},
6857 	[ACTION_QUOTA_CREATE_MODE] = {
6858 		.name = "mode",
6859 		.help = "quota mode",
6860 		.next = NEXT(action_quota_create,
6861 			     NEXT_ENTRY(ACTION_QUOTA_CREATE_MODE_NAME)),
6862 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, mode)),
6863 		.call = parse_vc_conf
6864 	},
6865 	[ACTION_QUOTA_CREATE_MODE_NAME] = {
6866 		.name = "mode_name",
6867 		.help = "quota mode name",
6868 		.call = parse_quota_mode_name,
6869 		.comp = comp_quota_mode_name
6870 	},
6871 	[ACTION_QUOTA_QU] = {
6872 		.name = "quota_update",
6873 		.help = "update quota action",
6874 		.priv = PRIV_ACTION(QUOTA,
6875 				    sizeof(struct rte_flow_update_quota)),
6876 		.next = NEXT(action_quota_update),
6877 		.call = parse_vc
6878 	},
6879 	[ACTION_QUOTA_QU_LIMIT] = {
6880 		.name = "limit",
6881 		.help = "quota limit",
6882 		.next = NEXT(action_quota_update, NEXT_ENTRY(COMMON_UNSIGNED)),
6883 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, quota)),
6884 		.call = parse_vc_conf
6885 	},
6886 	[ACTION_QUOTA_QU_UPDATE_OP] = {
6887 		.name = "update_op",
6888 		.help = "query update op SET|ADD",
6889 		.next = NEXT(action_quota_update,
6890 			     NEXT_ENTRY(ACTION_QUOTA_QU_UPDATE_OP_NAME)),
6891 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, op)),
6892 		.call = parse_vc_conf
6893 	},
6894 	[ACTION_QUOTA_QU_UPDATE_OP_NAME] = {
6895 		.name = "update_op_name",
6896 		.help = "quota update op name",
6897 		.call = parse_quota_update_name,
6898 		.comp = comp_quota_update_name
6899 	},
6900 
6901 	/* Top-level command. */
6902 	[ADD] = {
6903 		.name = "add",
6904 		.type = "port meter policy {port_id} {arg}",
6905 		.help = "add port meter policy",
6906 		.next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
6907 		.call = parse_init,
6908 	},
6909 	/* Sub-level commands. */
6910 	[ITEM_POL_PORT] = {
6911 		.name = "port",
6912 		.help = "add port meter policy",
6913 		.next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
6914 	},
6915 	[ITEM_POL_METER] = {
6916 		.name = "meter",
6917 		.help = "add port meter policy",
6918 		.next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
6919 	},
6920 	[ITEM_POL_POLICY] = {
6921 		.name = "policy",
6922 		.help = "add port meter policy",
6923 		.next = NEXT(NEXT_ENTRY(ACTION_POL_R),
6924 				NEXT_ENTRY(ACTION_POL_Y),
6925 				NEXT_ENTRY(ACTION_POL_G),
6926 				NEXT_ENTRY(COMMON_POLICY_ID),
6927 				NEXT_ENTRY(COMMON_PORT_ID)),
6928 		.args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
6929 				ARGS_ENTRY(struct buffer, port)),
6930 		.call = parse_mp,
6931 	},
6932 	[ITEM_AGGR_AFFINITY] = {
6933 		.name = "aggr_affinity",
6934 		.help = "match on the aggregated port receiving the packets",
6935 		.priv = PRIV_ITEM(AGGR_AFFINITY,
6936 				  sizeof(struct rte_flow_item_aggr_affinity)),
6937 		.next = NEXT(item_aggr_affinity),
6938 		.call = parse_vc,
6939 	},
6940 	[ITEM_AGGR_AFFINITY_VALUE] = {
6941 		.name = "affinity",
6942 		.help = "aggregated affinity value",
6943 		.next = NEXT(item_aggr_affinity, NEXT_ENTRY(COMMON_UNSIGNED),
6944 			     item_param),
6945 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_aggr_affinity,
6946 					affinity)),
6947 	},
6948 };
6949 
6950 /** Remove and return last entry from argument stack. */
6951 static const struct arg *
6952 pop_args(struct context *ctx)
6953 {
6954 	return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
6955 }
6956 
6957 /** Add entry on top of the argument stack. */
6958 static int
6959 push_args(struct context *ctx, const struct arg *arg)
6960 {
6961 	if (ctx->args_num == CTX_STACK_SIZE)
6962 		return -1;
6963 	ctx->args[ctx->args_num++] = arg;
6964 	return 0;
6965 }
6966 
6967 /** Spread value into buffer according to bit-mask. */
6968 static size_t
6969 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
6970 {
6971 	uint32_t i = arg->size;
6972 	uint32_t end = 0;
6973 	int sub = 1;
6974 	int add = 0;
6975 	size_t len = 0;
6976 
6977 	if (!arg->mask)
6978 		return 0;
6979 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
6980 	if (!arg->hton) {
6981 		i = 0;
6982 		end = arg->size;
6983 		sub = 0;
6984 		add = 1;
6985 	}
6986 #endif
6987 	while (i != end) {
6988 		unsigned int shift = 0;
6989 		uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
6990 
6991 		for (shift = 0; arg->mask[i] >> shift; ++shift) {
6992 			if (!(arg->mask[i] & (1 << shift)))
6993 				continue;
6994 			++len;
6995 			if (!dst)
6996 				continue;
6997 			*buf &= ~(1 << shift);
6998 			*buf |= (val & 1) << shift;
6999 			val >>= 1;
7000 		}
7001 		i += add;
7002 	}
7003 	return len;
7004 }
7005 
7006 /** Compare a string with a partial one of a given length. */
7007 static int
7008 strcmp_partial(const char *full, const char *partial, size_t partial_len)
7009 {
7010 	int r = strncmp(full, partial, partial_len);
7011 
7012 	if (r)
7013 		return r;
7014 	if (strlen(full) <= partial_len)
7015 		return 0;
7016 	return full[partial_len];
7017 }
7018 
7019 /**
7020  * Parse a prefix length and generate a bit-mask.
7021  *
7022  * Last argument (ctx->args) is retrieved to determine mask size, storage
7023  * location and whether the result must use network byte ordering.
7024  */
7025 static int
7026 parse_prefix(struct context *ctx, const struct token *token,
7027 	     const char *str, unsigned int len,
7028 	     void *buf, unsigned int size)
7029 {
7030 	const struct arg *arg = pop_args(ctx);
7031 	static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
7032 	char *end;
7033 	uintmax_t u;
7034 	unsigned int bytes;
7035 	unsigned int extra;
7036 
7037 	(void)token;
7038 	/* Argument is expected. */
7039 	if (!arg)
7040 		return -1;
7041 	errno = 0;
7042 	u = strtoumax(str, &end, 0);
7043 	if (errno || (size_t)(end - str) != len)
7044 		goto error;
7045 	if (arg->mask) {
7046 		uintmax_t v = 0;
7047 
7048 		extra = arg_entry_bf_fill(NULL, 0, arg);
7049 		if (u > extra)
7050 			goto error;
7051 		if (!ctx->object)
7052 			return len;
7053 		extra -= u;
7054 		while (u--)
7055 			(v <<= 1, v |= 1);
7056 		v <<= extra;
7057 		if (!arg_entry_bf_fill(ctx->object, v, arg) ||
7058 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
7059 			goto error;
7060 		return len;
7061 	}
7062 	bytes = u / 8;
7063 	extra = u % 8;
7064 	size = arg->size;
7065 	if (bytes > size || bytes + !!extra > size)
7066 		goto error;
7067 	if (!ctx->object)
7068 		return len;
7069 	buf = (uint8_t *)ctx->object + arg->offset;
7070 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
7071 	if (!arg->hton) {
7072 		memset((uint8_t *)buf + size - bytes, 0xff, bytes);
7073 		memset(buf, 0x00, size - bytes);
7074 		if (extra)
7075 			((uint8_t *)buf)[size - bytes - 1] = conv[extra];
7076 	} else
7077 #endif
7078 	{
7079 		memset(buf, 0xff, bytes);
7080 		memset((uint8_t *)buf + bytes, 0x00, size - bytes);
7081 		if (extra)
7082 			((uint8_t *)buf)[bytes] = conv[extra];
7083 	}
7084 	if (ctx->objmask)
7085 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
7086 	return len;
7087 error:
7088 	push_args(ctx, arg);
7089 	return -1;
7090 }
7091 
7092 /** Default parsing function for token name matching. */
7093 static int
7094 parse_default(struct context *ctx, const struct token *token,
7095 	      const char *str, unsigned int len,
7096 	      void *buf, unsigned int size)
7097 {
7098 	(void)ctx;
7099 	(void)buf;
7100 	(void)size;
7101 	if (strcmp_partial(token->name, str, len))
7102 		return -1;
7103 	return len;
7104 }
7105 
7106 /** Parse flow command, initialize output buffer for subsequent tokens. */
7107 static int
7108 parse_init(struct context *ctx, const struct token *token,
7109 	   const char *str, unsigned int len,
7110 	   void *buf, unsigned int size)
7111 {
7112 	struct buffer *out = buf;
7113 
7114 	/* Token name must match. */
7115 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7116 		return -1;
7117 	/* Nothing else to do if there is no buffer. */
7118 	if (!out)
7119 		return len;
7120 	/* Make sure buffer is large enough. */
7121 	if (size < sizeof(*out))
7122 		return -1;
7123 	/* Initialize buffer. */
7124 	memset(out, 0x00, sizeof(*out));
7125 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
7126 	ctx->objdata = 0;
7127 	ctx->object = out;
7128 	ctx->objmask = NULL;
7129 	return len;
7130 }
7131 
7132 /** Parse tokens for indirect action commands. */
7133 static int
7134 parse_ia(struct context *ctx, const struct token *token,
7135 	 const char *str, unsigned int len,
7136 	 void *buf, unsigned int size)
7137 {
7138 	struct buffer *out = buf;
7139 
7140 	/* Token name must match. */
7141 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7142 		return -1;
7143 	/* Nothing else to do if there is no buffer. */
7144 	if (!out)
7145 		return len;
7146 	if (!out->command) {
7147 		if (ctx->curr != INDIRECT_ACTION)
7148 			return -1;
7149 		if (sizeof(*out) > size)
7150 			return -1;
7151 		out->command = ctx->curr;
7152 		ctx->objdata = 0;
7153 		ctx->object = out;
7154 		ctx->objmask = NULL;
7155 		out->args.vc.data = (uint8_t *)out + size;
7156 		return len;
7157 	}
7158 	switch (ctx->curr) {
7159 	case INDIRECT_ACTION_CREATE:
7160 	case INDIRECT_ACTION_UPDATE:
7161 	case INDIRECT_ACTION_QUERY_UPDATE:
7162 		out->args.vc.actions =
7163 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7164 					       sizeof(double));
7165 		out->args.vc.attr.group = UINT32_MAX;
7166 		/* fallthrough */
7167 	case INDIRECT_ACTION_QUERY:
7168 		out->command = ctx->curr;
7169 		ctx->objdata = 0;
7170 		ctx->object = out;
7171 		ctx->objmask = NULL;
7172 		return len;
7173 	case INDIRECT_ACTION_EGRESS:
7174 		out->args.vc.attr.egress = 1;
7175 		return len;
7176 	case INDIRECT_ACTION_INGRESS:
7177 		out->args.vc.attr.ingress = 1;
7178 		return len;
7179 	case INDIRECT_ACTION_TRANSFER:
7180 		out->args.vc.attr.transfer = 1;
7181 		return len;
7182 	case INDIRECT_ACTION_QU_MODE:
7183 		return len;
7184 	default:
7185 		return -1;
7186 	}
7187 }
7188 
7189 
7190 /** Parse tokens for indirect action destroy command. */
7191 static int
7192 parse_ia_destroy(struct context *ctx, const struct token *token,
7193 		 const char *str, unsigned int len,
7194 		 void *buf, unsigned int size)
7195 {
7196 	struct buffer *out = buf;
7197 	uint32_t *action_id;
7198 
7199 	/* Token name must match. */
7200 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7201 		return -1;
7202 	/* Nothing else to do if there is no buffer. */
7203 	if (!out)
7204 		return len;
7205 	if (!out->command || out->command == INDIRECT_ACTION) {
7206 		if (ctx->curr != INDIRECT_ACTION_DESTROY)
7207 			return -1;
7208 		if (sizeof(*out) > size)
7209 			return -1;
7210 		out->command = ctx->curr;
7211 		ctx->objdata = 0;
7212 		ctx->object = out;
7213 		ctx->objmask = NULL;
7214 		out->args.ia_destroy.action_id =
7215 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7216 					       sizeof(double));
7217 		return len;
7218 	}
7219 	action_id = out->args.ia_destroy.action_id
7220 		    + out->args.ia_destroy.action_id_n++;
7221 	if ((uint8_t *)action_id > (uint8_t *)out + size)
7222 		return -1;
7223 	ctx->objdata = 0;
7224 	ctx->object = action_id;
7225 	ctx->objmask = NULL;
7226 	return len;
7227 }
7228 
7229 /** Parse tokens for indirect action commands. */
7230 static int
7231 parse_qia(struct context *ctx, const struct token *token,
7232 	  const char *str, unsigned int len,
7233 	  void *buf, unsigned int size)
7234 {
7235 	struct buffer *out = buf;
7236 
7237 	/* Token name must match. */
7238 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7239 		return -1;
7240 	/* Nothing else to do if there is no buffer. */
7241 	if (!out)
7242 		return len;
7243 	if (!out->command) {
7244 		if (ctx->curr != QUEUE)
7245 			return -1;
7246 		if (sizeof(*out) > size)
7247 			return -1;
7248 		out->args.vc.data = (uint8_t *)out + size;
7249 		return len;
7250 	}
7251 	switch (ctx->curr) {
7252 	case QUEUE_INDIRECT_ACTION:
7253 		return len;
7254 	case QUEUE_INDIRECT_ACTION_CREATE:
7255 	case QUEUE_INDIRECT_ACTION_UPDATE:
7256 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
7257 		out->args.vc.actions =
7258 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7259 					       sizeof(double));
7260 		out->args.vc.attr.group = UINT32_MAX;
7261 		/* fallthrough */
7262 	case QUEUE_INDIRECT_ACTION_QUERY:
7263 		out->command = ctx->curr;
7264 		ctx->objdata = 0;
7265 		ctx->object = out;
7266 		ctx->objmask = NULL;
7267 		return len;
7268 	case QUEUE_INDIRECT_ACTION_EGRESS:
7269 		out->args.vc.attr.egress = 1;
7270 		return len;
7271 	case QUEUE_INDIRECT_ACTION_INGRESS:
7272 		out->args.vc.attr.ingress = 1;
7273 		return len;
7274 	case QUEUE_INDIRECT_ACTION_TRANSFER:
7275 		out->args.vc.attr.transfer = 1;
7276 		return len;
7277 	case QUEUE_INDIRECT_ACTION_CREATE_POSTPONE:
7278 		return len;
7279 	case QUEUE_INDIRECT_ACTION_QU_MODE:
7280 		return len;
7281 	default:
7282 		return -1;
7283 	}
7284 }
7285 
7286 /** Parse tokens for indirect action destroy command. */
7287 static int
7288 parse_qia_destroy(struct context *ctx, const struct token *token,
7289 		  const char *str, unsigned int len,
7290 		  void *buf, unsigned int size)
7291 {
7292 	struct buffer *out = buf;
7293 	uint32_t *action_id;
7294 
7295 	/* Token name must match. */
7296 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7297 		return -1;
7298 	/* Nothing else to do if there is no buffer. */
7299 	if (!out)
7300 		return len;
7301 	if (!out->command || out->command == QUEUE) {
7302 		if (ctx->curr != QUEUE_INDIRECT_ACTION_DESTROY)
7303 			return -1;
7304 		if (sizeof(*out) > size)
7305 			return -1;
7306 		out->command = ctx->curr;
7307 		ctx->objdata = 0;
7308 		ctx->object = out;
7309 		ctx->objmask = NULL;
7310 		out->args.ia_destroy.action_id =
7311 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7312 					       sizeof(double));
7313 		return len;
7314 	}
7315 	switch (ctx->curr) {
7316 	case QUEUE_INDIRECT_ACTION:
7317 		out->command = ctx->curr;
7318 		ctx->objdata = 0;
7319 		ctx->object = out;
7320 		ctx->objmask = NULL;
7321 		return len;
7322 	case QUEUE_INDIRECT_ACTION_DESTROY_ID:
7323 		action_id = out->args.ia_destroy.action_id
7324 				+ out->args.ia_destroy.action_id_n++;
7325 		if ((uint8_t *)action_id > (uint8_t *)out + size)
7326 			return -1;
7327 		ctx->objdata = 0;
7328 		ctx->object = action_id;
7329 		ctx->objmask = NULL;
7330 		return len;
7331 	case QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE:
7332 		return len;
7333 	default:
7334 		return -1;
7335 	}
7336 }
7337 
7338 /** Parse tokens for meter policy action commands. */
7339 static int
7340 parse_mp(struct context *ctx, const struct token *token,
7341 	const char *str, unsigned int len,
7342 	void *buf, unsigned int size)
7343 {
7344 	struct buffer *out = buf;
7345 
7346 	/* Token name must match. */
7347 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7348 		return -1;
7349 	/* Nothing else to do if there is no buffer. */
7350 	if (!out)
7351 		return len;
7352 	if (!out->command) {
7353 		if (ctx->curr != ITEM_POL_POLICY)
7354 			return -1;
7355 		if (sizeof(*out) > size)
7356 			return -1;
7357 		out->command = ctx->curr;
7358 		ctx->objdata = 0;
7359 		ctx->object = out;
7360 		ctx->objmask = NULL;
7361 		out->args.vc.data = (uint8_t *)out + size;
7362 		return len;
7363 	}
7364 	switch (ctx->curr) {
7365 	case ACTION_POL_G:
7366 		out->args.vc.actions =
7367 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7368 					sizeof(double));
7369 		out->command = ctx->curr;
7370 		ctx->objdata = 0;
7371 		ctx->object = out;
7372 		ctx->objmask = NULL;
7373 		return len;
7374 	default:
7375 		return -1;
7376 	}
7377 }
7378 
7379 /** Parse tokens for validate/create commands. */
7380 static int
7381 parse_vc(struct context *ctx, const struct token *token,
7382 	 const char *str, unsigned int len,
7383 	 void *buf, unsigned int size)
7384 {
7385 	struct buffer *out = buf;
7386 	uint8_t *data;
7387 	uint32_t data_size;
7388 
7389 	/* Token name must match. */
7390 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7391 		return -1;
7392 	/* Nothing else to do if there is no buffer. */
7393 	if (!out)
7394 		return len;
7395 	if (!out->command) {
7396 		if (ctx->curr != VALIDATE && ctx->curr != CREATE &&
7397 		    ctx->curr != PATTERN_TEMPLATE_CREATE &&
7398 		    ctx->curr != ACTIONS_TEMPLATE_CREATE)
7399 			return -1;
7400 		if (sizeof(*out) > size)
7401 			return -1;
7402 		out->command = ctx->curr;
7403 		ctx->objdata = 0;
7404 		ctx->object = out;
7405 		ctx->objmask = NULL;
7406 		out->args.vc.data = (uint8_t *)out + size;
7407 		return len;
7408 	}
7409 	ctx->objdata = 0;
7410 	switch (ctx->curr) {
7411 	default:
7412 		ctx->object = &out->args.vc.attr;
7413 		break;
7414 	case VC_TUNNEL_SET:
7415 	case VC_TUNNEL_MATCH:
7416 		ctx->object = &out->args.vc.tunnel_ops;
7417 		break;
7418 	}
7419 	ctx->objmask = NULL;
7420 	switch (ctx->curr) {
7421 	case VC_GROUP:
7422 	case VC_PRIORITY:
7423 		return len;
7424 	case VC_TUNNEL_SET:
7425 		out->args.vc.tunnel_ops.enabled = 1;
7426 		out->args.vc.tunnel_ops.actions = 1;
7427 		return len;
7428 	case VC_TUNNEL_MATCH:
7429 		out->args.vc.tunnel_ops.enabled = 1;
7430 		out->args.vc.tunnel_ops.items = 1;
7431 		return len;
7432 	case VC_INGRESS:
7433 		out->args.vc.attr.ingress = 1;
7434 		return len;
7435 	case VC_EGRESS:
7436 		out->args.vc.attr.egress = 1;
7437 		return len;
7438 	case VC_TRANSFER:
7439 		out->args.vc.attr.transfer = 1;
7440 		return len;
7441 	case ITEM_PATTERN:
7442 		out->args.vc.pattern =
7443 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7444 					       sizeof(double));
7445 		ctx->object = out->args.vc.pattern;
7446 		ctx->objmask = NULL;
7447 		return len;
7448 	case ITEM_END:
7449 		if ((out->command == VALIDATE || out->command == CREATE) &&
7450 		    ctx->last)
7451 			return -1;
7452 		if (out->command == PATTERN_TEMPLATE_CREATE &&
7453 		    !ctx->last)
7454 			return -1;
7455 		break;
7456 	case ACTIONS:
7457 		out->args.vc.actions =
7458 			(void *)RTE_ALIGN_CEIL((uintptr_t)
7459 					       (out->args.vc.pattern +
7460 						out->args.vc.pattern_n),
7461 					       sizeof(double));
7462 		ctx->object = out->args.vc.actions;
7463 		ctx->objmask = NULL;
7464 		return len;
7465 	default:
7466 		if (!token->priv)
7467 			return -1;
7468 		break;
7469 	}
7470 	if (!out->args.vc.actions) {
7471 		const struct parse_item_priv *priv = token->priv;
7472 		struct rte_flow_item *item =
7473 			out->args.vc.pattern + out->args.vc.pattern_n;
7474 
7475 		data_size = priv->size * 3; /* spec, last, mask */
7476 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
7477 					       (out->args.vc.data - data_size),
7478 					       sizeof(double));
7479 		if ((uint8_t *)item + sizeof(*item) > data)
7480 			return -1;
7481 		*item = (struct rte_flow_item){
7482 			.type = priv->type,
7483 		};
7484 		++out->args.vc.pattern_n;
7485 		ctx->object = item;
7486 		ctx->objmask = NULL;
7487 	} else {
7488 		const struct parse_action_priv *priv = token->priv;
7489 		struct rte_flow_action *action =
7490 			out->args.vc.actions + out->args.vc.actions_n;
7491 
7492 		data_size = priv->size; /* configuration */
7493 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
7494 					       (out->args.vc.data - data_size),
7495 					       sizeof(double));
7496 		if ((uint8_t *)action + sizeof(*action) > data)
7497 			return -1;
7498 		*action = (struct rte_flow_action){
7499 			.type = priv->type,
7500 			.conf = data_size ? data : NULL,
7501 		};
7502 		++out->args.vc.actions_n;
7503 		ctx->object = action;
7504 		ctx->objmask = NULL;
7505 	}
7506 	memset(data, 0, data_size);
7507 	out->args.vc.data = data;
7508 	ctx->objdata = data_size;
7509 	return len;
7510 }
7511 
7512 /** Parse pattern item parameter type. */
7513 static int
7514 parse_vc_spec(struct context *ctx, const struct token *token,
7515 	      const char *str, unsigned int len,
7516 	      void *buf, unsigned int size)
7517 {
7518 	struct buffer *out = buf;
7519 	struct rte_flow_item *item;
7520 	uint32_t data_size;
7521 	int index;
7522 	int objmask = 0;
7523 
7524 	(void)size;
7525 	/* Token name must match. */
7526 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7527 		return -1;
7528 	/* Parse parameter types. */
7529 	switch (ctx->curr) {
7530 		static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
7531 
7532 	case ITEM_PARAM_IS:
7533 		index = 0;
7534 		objmask = 1;
7535 		break;
7536 	case ITEM_PARAM_SPEC:
7537 		index = 0;
7538 		break;
7539 	case ITEM_PARAM_LAST:
7540 		index = 1;
7541 		break;
7542 	case ITEM_PARAM_PREFIX:
7543 		/* Modify next token to expect a prefix. */
7544 		if (ctx->next_num < 2)
7545 			return -1;
7546 		ctx->next[ctx->next_num - 2] = prefix;
7547 		/* Fall through. */
7548 	case ITEM_PARAM_MASK:
7549 		index = 2;
7550 		break;
7551 	default:
7552 		return -1;
7553 	}
7554 	/* Nothing else to do if there is no buffer. */
7555 	if (!out)
7556 		return len;
7557 	if (!out->args.vc.pattern_n)
7558 		return -1;
7559 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
7560 	data_size = ctx->objdata / 3; /* spec, last, mask */
7561 	/* Point to selected object. */
7562 	ctx->object = out->args.vc.data + (data_size * index);
7563 	if (objmask) {
7564 		ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
7565 		item->mask = ctx->objmask;
7566 	} else
7567 		ctx->objmask = NULL;
7568 	/* Update relevant item pointer. */
7569 	*((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
7570 		ctx->object;
7571 	return len;
7572 }
7573 
7574 /** Parse action configuration field. */
7575 static int
7576 parse_vc_conf(struct context *ctx, const struct token *token,
7577 	      const char *str, unsigned int len,
7578 	      void *buf, unsigned int size)
7579 {
7580 	struct buffer *out = buf;
7581 
7582 	(void)size;
7583 	/* Token name must match. */
7584 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7585 		return -1;
7586 	/* Nothing else to do if there is no buffer. */
7587 	if (!out)
7588 		return len;
7589 	/* Point to selected object. */
7590 	ctx->object = out->args.vc.data;
7591 	ctx->objmask = NULL;
7592 	return len;
7593 }
7594 
7595 /** Parse action configuration field. */
7596 static int
7597 parse_vc_conf_timeout(struct context *ctx, const struct token *token,
7598 		      const char *str, unsigned int len,
7599 		      void *buf, unsigned int size)
7600 {
7601 	struct buffer *out = buf;
7602 	struct rte_flow_update_age *update;
7603 
7604 	(void)size;
7605 	if (ctx->curr != ACTION_AGE_UPDATE_TIMEOUT)
7606 		return -1;
7607 	/* Token name must match. */
7608 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7609 		return -1;
7610 	/* Nothing else to do if there is no buffer. */
7611 	if (!out)
7612 		return len;
7613 	/* Point to selected object. */
7614 	ctx->object = out->args.vc.data;
7615 	ctx->objmask = NULL;
7616 	/* Update the timeout is valid. */
7617 	update = (struct rte_flow_update_age *)out->args.vc.data;
7618 	update->timeout_valid = 1;
7619 	return len;
7620 }
7621 
7622 /** Parse eCPRI common header type field. */
7623 static int
7624 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
7625 			 const char *str, unsigned int len,
7626 			 void *buf, unsigned int size)
7627 {
7628 	struct rte_flow_item_ecpri *ecpri;
7629 	struct rte_flow_item_ecpri *ecpri_mask;
7630 	struct rte_flow_item *item;
7631 	uint32_t data_size;
7632 	uint8_t msg_type;
7633 	struct buffer *out = buf;
7634 	const struct arg *arg;
7635 
7636 	(void)size;
7637 	/* Token name must match. */
7638 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7639 		return -1;
7640 	switch (ctx->curr) {
7641 	case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
7642 		msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
7643 		break;
7644 	case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
7645 		msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
7646 		break;
7647 	case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
7648 		msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
7649 		break;
7650 	default:
7651 		return -1;
7652 	}
7653 	if (!ctx->object)
7654 		return len;
7655 	arg = pop_args(ctx);
7656 	if (!arg)
7657 		return -1;
7658 	ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
7659 	ecpri->hdr.common.type = msg_type;
7660 	data_size = ctx->objdata / 3; /* spec, last, mask */
7661 	ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
7662 						    (data_size * 2));
7663 	ecpri_mask->hdr.common.type = 0xFF;
7664 	if (arg->hton) {
7665 		ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
7666 		ecpri_mask->hdr.common.u32 =
7667 				rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
7668 	}
7669 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
7670 	item->spec = ecpri;
7671 	item->mask = ecpri_mask;
7672 	return len;
7673 }
7674 
7675 /** Parse L2TPv2 common header type field. */
7676 static int
7677 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
7678 			 const char *str, unsigned int len,
7679 			 void *buf, unsigned int size)
7680 {
7681 	struct rte_flow_item_l2tpv2 *l2tpv2;
7682 	struct rte_flow_item_l2tpv2 *l2tpv2_mask;
7683 	struct rte_flow_item *item;
7684 	uint32_t data_size;
7685 	uint16_t msg_type = 0;
7686 	struct buffer *out = buf;
7687 	const struct arg *arg;
7688 
7689 	(void)size;
7690 	/* Token name must match. */
7691 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7692 		return -1;
7693 	switch (ctx->curr) {
7694 	case ITEM_L2TPV2_TYPE_DATA:
7695 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
7696 		break;
7697 	case ITEM_L2TPV2_TYPE_DATA_L:
7698 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
7699 		break;
7700 	case ITEM_L2TPV2_TYPE_DATA_S:
7701 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
7702 		break;
7703 	case ITEM_L2TPV2_TYPE_DATA_O:
7704 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
7705 		break;
7706 	case ITEM_L2TPV2_TYPE_DATA_L_S:
7707 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
7708 		break;
7709 	case ITEM_L2TPV2_TYPE_CTRL:
7710 		msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
7711 		break;
7712 	default:
7713 		return -1;
7714 	}
7715 	if (!ctx->object)
7716 		return len;
7717 	arg = pop_args(ctx);
7718 	if (!arg)
7719 		return -1;
7720 	l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
7721 	l2tpv2->hdr.common.flags_version |= msg_type;
7722 	data_size = ctx->objdata / 3; /* spec, last, mask */
7723 	l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
7724 						    (data_size * 2));
7725 	l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
7726 	if (arg->hton) {
7727 		l2tpv2->hdr.common.flags_version =
7728 			rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
7729 		l2tpv2_mask->hdr.common.flags_version =
7730 		    rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
7731 	}
7732 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
7733 	item->spec = l2tpv2;
7734 	item->mask = l2tpv2_mask;
7735 	return len;
7736 }
7737 
7738 /** Parse meter color action type. */
7739 static int
7740 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
7741 				const char *str, unsigned int len,
7742 				void *buf, unsigned int size)
7743 {
7744 	struct rte_flow_action *action_data;
7745 	struct rte_flow_action_meter_color *conf;
7746 	enum rte_color color;
7747 
7748 	(void)buf;
7749 	(void)size;
7750 	/* Token name must match. */
7751 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7752 		return -1;
7753 	switch (ctx->curr) {
7754 	case ACTION_METER_COLOR_GREEN:
7755 		color = RTE_COLOR_GREEN;
7756 	break;
7757 	case ACTION_METER_COLOR_YELLOW:
7758 		color = RTE_COLOR_YELLOW;
7759 	break;
7760 	case ACTION_METER_COLOR_RED:
7761 		color = RTE_COLOR_RED;
7762 	break;
7763 	default:
7764 		return -1;
7765 	}
7766 
7767 	if (!ctx->object)
7768 		return len;
7769 	action_data = ctx->object;
7770 	conf = (struct rte_flow_action_meter_color *)
7771 					(uintptr_t)(action_data->conf);
7772 	conf->color = color;
7773 	return len;
7774 }
7775 
7776 /** Parse RSS action. */
7777 static int
7778 parse_vc_action_rss(struct context *ctx, const struct token *token,
7779 		    const char *str, unsigned int len,
7780 		    void *buf, unsigned int size)
7781 {
7782 	struct buffer *out = buf;
7783 	struct rte_flow_action *action;
7784 	struct action_rss_data *action_rss_data;
7785 	unsigned int i;
7786 	int ret;
7787 
7788 	ret = parse_vc(ctx, token, str, len, buf, size);
7789 	if (ret < 0)
7790 		return ret;
7791 	/* Nothing else to do if there is no buffer. */
7792 	if (!out)
7793 		return ret;
7794 	if (!out->args.vc.actions_n)
7795 		return -1;
7796 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7797 	/* Point to selected object. */
7798 	ctx->object = out->args.vc.data;
7799 	ctx->objmask = NULL;
7800 	/* Set up default configuration. */
7801 	action_rss_data = ctx->object;
7802 	*action_rss_data = (struct action_rss_data){
7803 		.conf = (struct rte_flow_action_rss){
7804 			.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
7805 			.level = 0,
7806 			.types = rss_hf,
7807 			.key_len = 0,
7808 			.queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
7809 			.key = NULL,
7810 			.queue = action_rss_data->queue,
7811 		},
7812 		.queue = { 0 },
7813 	};
7814 	for (i = 0; i < action_rss_data->conf.queue_num; ++i)
7815 		action_rss_data->queue[i] = i;
7816 	action->conf = &action_rss_data->conf;
7817 	return ret;
7818 }
7819 
7820 /**
7821  * Parse func field for RSS action.
7822  *
7823  * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
7824  * ACTION_RSS_FUNC_* index that called this function.
7825  */
7826 static int
7827 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
7828 			 const char *str, unsigned int len,
7829 			 void *buf, unsigned int size)
7830 {
7831 	struct action_rss_data *action_rss_data;
7832 	enum rte_eth_hash_function func;
7833 
7834 	(void)buf;
7835 	(void)size;
7836 	/* Token name must match. */
7837 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7838 		return -1;
7839 	switch (ctx->curr) {
7840 	case ACTION_RSS_FUNC_DEFAULT:
7841 		func = RTE_ETH_HASH_FUNCTION_DEFAULT;
7842 		break;
7843 	case ACTION_RSS_FUNC_TOEPLITZ:
7844 		func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
7845 		break;
7846 	case ACTION_RSS_FUNC_SIMPLE_XOR:
7847 		func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
7848 		break;
7849 	case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
7850 		func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
7851 		break;
7852 	default:
7853 		return -1;
7854 	}
7855 	if (!ctx->object)
7856 		return len;
7857 	action_rss_data = ctx->object;
7858 	action_rss_data->conf.func = func;
7859 	return len;
7860 }
7861 
7862 /**
7863  * Parse type field for RSS action.
7864  *
7865  * Valid tokens are type field names and the "end" token.
7866  */
7867 static int
7868 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
7869 			  const char *str, unsigned int len,
7870 			  void *buf, unsigned int size)
7871 {
7872 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
7873 	struct action_rss_data *action_rss_data;
7874 	unsigned int i;
7875 
7876 	(void)token;
7877 	(void)buf;
7878 	(void)size;
7879 	if (ctx->curr != ACTION_RSS_TYPE)
7880 		return -1;
7881 	if (!(ctx->objdata >> 16) && ctx->object) {
7882 		action_rss_data = ctx->object;
7883 		action_rss_data->conf.types = 0;
7884 	}
7885 	if (!strcmp_partial("end", str, len)) {
7886 		ctx->objdata &= 0xffff;
7887 		return len;
7888 	}
7889 	for (i = 0; rss_type_table[i].str; ++i)
7890 		if (!strcmp_partial(rss_type_table[i].str, str, len))
7891 			break;
7892 	if (!rss_type_table[i].str)
7893 		return -1;
7894 	ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
7895 	/* Repeat token. */
7896 	if (ctx->next_num == RTE_DIM(ctx->next))
7897 		return -1;
7898 	ctx->next[ctx->next_num++] = next;
7899 	if (!ctx->object)
7900 		return len;
7901 	action_rss_data = ctx->object;
7902 	action_rss_data->conf.types |= rss_type_table[i].rss_type;
7903 	return len;
7904 }
7905 
7906 /**
7907  * Parse queue field for RSS action.
7908  *
7909  * Valid tokens are queue indices and the "end" token.
7910  */
7911 static int
7912 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
7913 			  const char *str, unsigned int len,
7914 			  void *buf, unsigned int size)
7915 {
7916 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
7917 	struct action_rss_data *action_rss_data;
7918 	const struct arg *arg;
7919 	int ret;
7920 	int i;
7921 
7922 	(void)token;
7923 	(void)buf;
7924 	(void)size;
7925 	if (ctx->curr != ACTION_RSS_QUEUE)
7926 		return -1;
7927 	i = ctx->objdata >> 16;
7928 	if (!strcmp_partial("end", str, len)) {
7929 		ctx->objdata &= 0xffff;
7930 		goto end;
7931 	}
7932 	if (i >= ACTION_RSS_QUEUE_NUM)
7933 		return -1;
7934 	arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
7935 			     i * sizeof(action_rss_data->queue[i]),
7936 			     sizeof(action_rss_data->queue[i]));
7937 	if (push_args(ctx, arg))
7938 		return -1;
7939 	ret = parse_int(ctx, token, str, len, NULL, 0);
7940 	if (ret < 0) {
7941 		pop_args(ctx);
7942 		return -1;
7943 	}
7944 	++i;
7945 	ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
7946 	/* Repeat token. */
7947 	if (ctx->next_num == RTE_DIM(ctx->next))
7948 		return -1;
7949 	ctx->next[ctx->next_num++] = next;
7950 end:
7951 	if (!ctx->object)
7952 		return len;
7953 	action_rss_data = ctx->object;
7954 	action_rss_data->conf.queue_num = i;
7955 	action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
7956 	return len;
7957 }
7958 
7959 /** Setup VXLAN encap configuration. */
7960 static int
7961 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
7962 {
7963 	/* Set up default configuration. */
7964 	*action_vxlan_encap_data = (struct action_vxlan_encap_data){
7965 		.conf = (struct rte_flow_action_vxlan_encap){
7966 			.definition = action_vxlan_encap_data->items,
7967 		},
7968 		.items = {
7969 			{
7970 				.type = RTE_FLOW_ITEM_TYPE_ETH,
7971 				.spec = &action_vxlan_encap_data->item_eth,
7972 				.mask = &rte_flow_item_eth_mask,
7973 			},
7974 			{
7975 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
7976 				.spec = &action_vxlan_encap_data->item_vlan,
7977 				.mask = &rte_flow_item_vlan_mask,
7978 			},
7979 			{
7980 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
7981 				.spec = &action_vxlan_encap_data->item_ipv4,
7982 				.mask = &rte_flow_item_ipv4_mask,
7983 			},
7984 			{
7985 				.type = RTE_FLOW_ITEM_TYPE_UDP,
7986 				.spec = &action_vxlan_encap_data->item_udp,
7987 				.mask = &rte_flow_item_udp_mask,
7988 			},
7989 			{
7990 				.type = RTE_FLOW_ITEM_TYPE_VXLAN,
7991 				.spec = &action_vxlan_encap_data->item_vxlan,
7992 				.mask = &rte_flow_item_vxlan_mask,
7993 			},
7994 			{
7995 				.type = RTE_FLOW_ITEM_TYPE_END,
7996 			},
7997 		},
7998 		.item_eth.hdr.ether_type = 0,
7999 		.item_vlan = {
8000 			.hdr.vlan_tci = vxlan_encap_conf.vlan_tci,
8001 			.hdr.eth_proto = 0,
8002 		},
8003 		.item_ipv4.hdr = {
8004 			.src_addr = vxlan_encap_conf.ipv4_src,
8005 			.dst_addr = vxlan_encap_conf.ipv4_dst,
8006 		},
8007 		.item_udp.hdr = {
8008 			.src_port = vxlan_encap_conf.udp_src,
8009 			.dst_port = vxlan_encap_conf.udp_dst,
8010 		},
8011 		.item_vxlan.hdr.flags = 0,
8012 	};
8013 	memcpy(action_vxlan_encap_data->item_eth.hdr.dst_addr.addr_bytes,
8014 	       vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
8015 	memcpy(action_vxlan_encap_data->item_eth.hdr.src_addr.addr_bytes,
8016 	       vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
8017 	if (!vxlan_encap_conf.select_ipv4) {
8018 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
8019 		       &vxlan_encap_conf.ipv6_src,
8020 		       sizeof(vxlan_encap_conf.ipv6_src));
8021 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
8022 		       &vxlan_encap_conf.ipv6_dst,
8023 		       sizeof(vxlan_encap_conf.ipv6_dst));
8024 		action_vxlan_encap_data->items[2] = (struct rte_flow_item){
8025 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
8026 			.spec = &action_vxlan_encap_data->item_ipv6,
8027 			.mask = &rte_flow_item_ipv6_mask,
8028 		};
8029 	}
8030 	if (!vxlan_encap_conf.select_vlan)
8031 		action_vxlan_encap_data->items[1].type =
8032 			RTE_FLOW_ITEM_TYPE_VOID;
8033 	if (vxlan_encap_conf.select_tos_ttl) {
8034 		if (vxlan_encap_conf.select_ipv4) {
8035 			static struct rte_flow_item_ipv4 ipv4_mask_tos;
8036 
8037 			memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
8038 			       sizeof(ipv4_mask_tos));
8039 			ipv4_mask_tos.hdr.type_of_service = 0xff;
8040 			ipv4_mask_tos.hdr.time_to_live = 0xff;
8041 			action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
8042 					vxlan_encap_conf.ip_tos;
8043 			action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
8044 					vxlan_encap_conf.ip_ttl;
8045 			action_vxlan_encap_data->items[2].mask =
8046 							&ipv4_mask_tos;
8047 		} else {
8048 			static struct rte_flow_item_ipv6 ipv6_mask_tos;
8049 
8050 			memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
8051 			       sizeof(ipv6_mask_tos));
8052 			ipv6_mask_tos.hdr.vtc_flow |=
8053 				RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
8054 			ipv6_mask_tos.hdr.hop_limits = 0xff;
8055 			action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
8056 				rte_cpu_to_be_32
8057 					((uint32_t)vxlan_encap_conf.ip_tos <<
8058 					 RTE_IPV6_HDR_TC_SHIFT);
8059 			action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
8060 					vxlan_encap_conf.ip_ttl;
8061 			action_vxlan_encap_data->items[2].mask =
8062 							&ipv6_mask_tos;
8063 		}
8064 	}
8065 	memcpy(action_vxlan_encap_data->item_vxlan.hdr.vni, vxlan_encap_conf.vni,
8066 	       RTE_DIM(vxlan_encap_conf.vni));
8067 	return 0;
8068 }
8069 
8070 /** Parse VXLAN encap action. */
8071 static int
8072 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
8073 			    const char *str, unsigned int len,
8074 			    void *buf, unsigned int size)
8075 {
8076 	struct buffer *out = buf;
8077 	struct rte_flow_action *action;
8078 	struct action_vxlan_encap_data *action_vxlan_encap_data;
8079 	int ret;
8080 
8081 	ret = parse_vc(ctx, token, str, len, buf, size);
8082 	if (ret < 0)
8083 		return ret;
8084 	/* Nothing else to do if there is no buffer. */
8085 	if (!out)
8086 		return ret;
8087 	if (!out->args.vc.actions_n)
8088 		return -1;
8089 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8090 	/* Point to selected object. */
8091 	ctx->object = out->args.vc.data;
8092 	ctx->objmask = NULL;
8093 	action_vxlan_encap_data = ctx->object;
8094 	parse_setup_vxlan_encap_data(action_vxlan_encap_data);
8095 	action->conf = &action_vxlan_encap_data->conf;
8096 	return ret;
8097 }
8098 
8099 /** Setup NVGRE encap configuration. */
8100 static int
8101 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
8102 {
8103 	/* Set up default configuration. */
8104 	*action_nvgre_encap_data = (struct action_nvgre_encap_data){
8105 		.conf = (struct rte_flow_action_nvgre_encap){
8106 			.definition = action_nvgre_encap_data->items,
8107 		},
8108 		.items = {
8109 			{
8110 				.type = RTE_FLOW_ITEM_TYPE_ETH,
8111 				.spec = &action_nvgre_encap_data->item_eth,
8112 				.mask = &rte_flow_item_eth_mask,
8113 			},
8114 			{
8115 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
8116 				.spec = &action_nvgre_encap_data->item_vlan,
8117 				.mask = &rte_flow_item_vlan_mask,
8118 			},
8119 			{
8120 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
8121 				.spec = &action_nvgre_encap_data->item_ipv4,
8122 				.mask = &rte_flow_item_ipv4_mask,
8123 			},
8124 			{
8125 				.type = RTE_FLOW_ITEM_TYPE_NVGRE,
8126 				.spec = &action_nvgre_encap_data->item_nvgre,
8127 				.mask = &rte_flow_item_nvgre_mask,
8128 			},
8129 			{
8130 				.type = RTE_FLOW_ITEM_TYPE_END,
8131 			},
8132 		},
8133 		.item_eth.hdr.ether_type = 0,
8134 		.item_vlan = {
8135 			.hdr.vlan_tci = nvgre_encap_conf.vlan_tci,
8136 			.hdr.eth_proto = 0,
8137 		},
8138 		.item_ipv4.hdr = {
8139 		       .src_addr = nvgre_encap_conf.ipv4_src,
8140 		       .dst_addr = nvgre_encap_conf.ipv4_dst,
8141 		},
8142 		.item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
8143 		.item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
8144 		.item_nvgre.flow_id = 0,
8145 	};
8146 	memcpy(action_nvgre_encap_data->item_eth.hdr.dst_addr.addr_bytes,
8147 	       nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
8148 	memcpy(action_nvgre_encap_data->item_eth.hdr.src_addr.addr_bytes,
8149 	       nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
8150 	if (!nvgre_encap_conf.select_ipv4) {
8151 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
8152 		       &nvgre_encap_conf.ipv6_src,
8153 		       sizeof(nvgre_encap_conf.ipv6_src));
8154 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
8155 		       &nvgre_encap_conf.ipv6_dst,
8156 		       sizeof(nvgre_encap_conf.ipv6_dst));
8157 		action_nvgre_encap_data->items[2] = (struct rte_flow_item){
8158 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
8159 			.spec = &action_nvgre_encap_data->item_ipv6,
8160 			.mask = &rte_flow_item_ipv6_mask,
8161 		};
8162 	}
8163 	if (!nvgre_encap_conf.select_vlan)
8164 		action_nvgre_encap_data->items[1].type =
8165 			RTE_FLOW_ITEM_TYPE_VOID;
8166 	memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
8167 	       RTE_DIM(nvgre_encap_conf.tni));
8168 	return 0;
8169 }
8170 
8171 /** Parse NVGRE encap action. */
8172 static int
8173 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
8174 			    const char *str, unsigned int len,
8175 			    void *buf, unsigned int size)
8176 {
8177 	struct buffer *out = buf;
8178 	struct rte_flow_action *action;
8179 	struct action_nvgre_encap_data *action_nvgre_encap_data;
8180 	int ret;
8181 
8182 	ret = parse_vc(ctx, token, str, len, buf, size);
8183 	if (ret < 0)
8184 		return ret;
8185 	/* Nothing else to do if there is no buffer. */
8186 	if (!out)
8187 		return ret;
8188 	if (!out->args.vc.actions_n)
8189 		return -1;
8190 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8191 	/* Point to selected object. */
8192 	ctx->object = out->args.vc.data;
8193 	ctx->objmask = NULL;
8194 	action_nvgre_encap_data = ctx->object;
8195 	parse_setup_nvgre_encap_data(action_nvgre_encap_data);
8196 	action->conf = &action_nvgre_encap_data->conf;
8197 	return ret;
8198 }
8199 
8200 /** Parse l2 encap action. */
8201 static int
8202 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
8203 			 const char *str, unsigned int len,
8204 			 void *buf, unsigned int size)
8205 {
8206 	struct buffer *out = buf;
8207 	struct rte_flow_action *action;
8208 	struct action_raw_encap_data *action_encap_data;
8209 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
8210 	struct rte_flow_item_vlan vlan = {
8211 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
8212 		.hdr.eth_proto = 0,
8213 	};
8214 	uint8_t *header;
8215 	int ret;
8216 
8217 	ret = parse_vc(ctx, token, str, len, buf, size);
8218 	if (ret < 0)
8219 		return ret;
8220 	/* Nothing else to do if there is no buffer. */
8221 	if (!out)
8222 		return ret;
8223 	if (!out->args.vc.actions_n)
8224 		return -1;
8225 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8226 	/* Point to selected object. */
8227 	ctx->object = out->args.vc.data;
8228 	ctx->objmask = NULL;
8229 	/* Copy the headers to the buffer. */
8230 	action_encap_data = ctx->object;
8231 	*action_encap_data = (struct action_raw_encap_data) {
8232 		.conf = (struct rte_flow_action_raw_encap){
8233 			.data = action_encap_data->data,
8234 		},
8235 		.data = {},
8236 	};
8237 	header = action_encap_data->data;
8238 	if (l2_encap_conf.select_vlan)
8239 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
8240 	else if (l2_encap_conf.select_ipv4)
8241 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8242 	else
8243 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8244 	memcpy(eth.hdr.dst_addr.addr_bytes,
8245 	       l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
8246 	memcpy(eth.hdr.src_addr.addr_bytes,
8247 	       l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
8248 	memcpy(header, &eth, sizeof(eth));
8249 	header += sizeof(eth);
8250 	if (l2_encap_conf.select_vlan) {
8251 		if (l2_encap_conf.select_ipv4)
8252 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8253 		else
8254 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8255 		memcpy(header, &vlan, sizeof(vlan));
8256 		header += sizeof(vlan);
8257 	}
8258 	action_encap_data->conf.size = header -
8259 		action_encap_data->data;
8260 	action->conf = &action_encap_data->conf;
8261 	return ret;
8262 }
8263 
8264 /** Parse l2 decap action. */
8265 static int
8266 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
8267 			 const char *str, unsigned int len,
8268 			 void *buf, unsigned int size)
8269 {
8270 	struct buffer *out = buf;
8271 	struct rte_flow_action *action;
8272 	struct action_raw_decap_data *action_decap_data;
8273 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
8274 	struct rte_flow_item_vlan vlan = {
8275 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
8276 		.hdr.eth_proto = 0,
8277 	};
8278 	uint8_t *header;
8279 	int ret;
8280 
8281 	ret = parse_vc(ctx, token, str, len, buf, size);
8282 	if (ret < 0)
8283 		return ret;
8284 	/* Nothing else to do if there is no buffer. */
8285 	if (!out)
8286 		return ret;
8287 	if (!out->args.vc.actions_n)
8288 		return -1;
8289 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8290 	/* Point to selected object. */
8291 	ctx->object = out->args.vc.data;
8292 	ctx->objmask = NULL;
8293 	/* Copy the headers to the buffer. */
8294 	action_decap_data = ctx->object;
8295 	*action_decap_data = (struct action_raw_decap_data) {
8296 		.conf = (struct rte_flow_action_raw_decap){
8297 			.data = action_decap_data->data,
8298 		},
8299 		.data = {},
8300 	};
8301 	header = action_decap_data->data;
8302 	if (l2_decap_conf.select_vlan)
8303 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
8304 	memcpy(header, &eth, sizeof(eth));
8305 	header += sizeof(eth);
8306 	if (l2_decap_conf.select_vlan) {
8307 		memcpy(header, &vlan, sizeof(vlan));
8308 		header += sizeof(vlan);
8309 	}
8310 	action_decap_data->conf.size = header -
8311 		action_decap_data->data;
8312 	action->conf = &action_decap_data->conf;
8313 	return ret;
8314 }
8315 
8316 #define ETHER_TYPE_MPLS_UNICAST 0x8847
8317 
8318 /** Parse MPLSOGRE encap action. */
8319 static int
8320 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
8321 			       const char *str, unsigned int len,
8322 			       void *buf, unsigned int size)
8323 {
8324 	struct buffer *out = buf;
8325 	struct rte_flow_action *action;
8326 	struct action_raw_encap_data *action_encap_data;
8327 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
8328 	struct rte_flow_item_vlan vlan = {
8329 		.hdr.vlan_tci = mplsogre_encap_conf.vlan_tci,
8330 		.hdr.eth_proto = 0,
8331 	};
8332 	struct rte_flow_item_ipv4 ipv4 = {
8333 		.hdr =  {
8334 			.src_addr = mplsogre_encap_conf.ipv4_src,
8335 			.dst_addr = mplsogre_encap_conf.ipv4_dst,
8336 			.next_proto_id = IPPROTO_GRE,
8337 			.version_ihl = RTE_IPV4_VHL_DEF,
8338 			.time_to_live = IPDEFTTL,
8339 		},
8340 	};
8341 	struct rte_flow_item_ipv6 ipv6 = {
8342 		.hdr =  {
8343 			.proto = IPPROTO_GRE,
8344 			.hop_limits = IPDEFTTL,
8345 		},
8346 	};
8347 	struct rte_flow_item_gre gre = {
8348 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
8349 	};
8350 	struct rte_flow_item_mpls mpls = {
8351 		.ttl = 0,
8352 	};
8353 	uint8_t *header;
8354 	int ret;
8355 
8356 	ret = parse_vc(ctx, token, str, len, buf, size);
8357 	if (ret < 0)
8358 		return ret;
8359 	/* Nothing else to do if there is no buffer. */
8360 	if (!out)
8361 		return ret;
8362 	if (!out->args.vc.actions_n)
8363 		return -1;
8364 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8365 	/* Point to selected object. */
8366 	ctx->object = out->args.vc.data;
8367 	ctx->objmask = NULL;
8368 	/* Copy the headers to the buffer. */
8369 	action_encap_data = ctx->object;
8370 	*action_encap_data = (struct action_raw_encap_data) {
8371 		.conf = (struct rte_flow_action_raw_encap){
8372 			.data = action_encap_data->data,
8373 		},
8374 		.data = {},
8375 		.preserve = {},
8376 	};
8377 	header = action_encap_data->data;
8378 	if (mplsogre_encap_conf.select_vlan)
8379 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
8380 	else if (mplsogre_encap_conf.select_ipv4)
8381 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8382 	else
8383 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8384 	memcpy(eth.hdr.dst_addr.addr_bytes,
8385 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
8386 	memcpy(eth.hdr.src_addr.addr_bytes,
8387 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
8388 	memcpy(header, &eth, sizeof(eth));
8389 	header += sizeof(eth);
8390 	if (mplsogre_encap_conf.select_vlan) {
8391 		if (mplsogre_encap_conf.select_ipv4)
8392 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8393 		else
8394 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8395 		memcpy(header, &vlan, sizeof(vlan));
8396 		header += sizeof(vlan);
8397 	}
8398 	if (mplsogre_encap_conf.select_ipv4) {
8399 		memcpy(header, &ipv4, sizeof(ipv4));
8400 		header += sizeof(ipv4);
8401 	} else {
8402 		memcpy(&ipv6.hdr.src_addr,
8403 		       &mplsogre_encap_conf.ipv6_src,
8404 		       sizeof(mplsogre_encap_conf.ipv6_src));
8405 		memcpy(&ipv6.hdr.dst_addr,
8406 		       &mplsogre_encap_conf.ipv6_dst,
8407 		       sizeof(mplsogre_encap_conf.ipv6_dst));
8408 		memcpy(header, &ipv6, sizeof(ipv6));
8409 		header += sizeof(ipv6);
8410 	}
8411 	memcpy(header, &gre, sizeof(gre));
8412 	header += sizeof(gre);
8413 	memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
8414 	       RTE_DIM(mplsogre_encap_conf.label));
8415 	mpls.label_tc_s[2] |= 0x1;
8416 	memcpy(header, &mpls, sizeof(mpls));
8417 	header += sizeof(mpls);
8418 	action_encap_data->conf.size = header -
8419 		action_encap_data->data;
8420 	action->conf = &action_encap_data->conf;
8421 	return ret;
8422 }
8423 
8424 /** Parse MPLSOGRE decap action. */
8425 static int
8426 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
8427 			       const char *str, unsigned int len,
8428 			       void *buf, unsigned int size)
8429 {
8430 	struct buffer *out = buf;
8431 	struct rte_flow_action *action;
8432 	struct action_raw_decap_data *action_decap_data;
8433 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
8434 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
8435 	struct rte_flow_item_ipv4 ipv4 = {
8436 		.hdr =  {
8437 			.next_proto_id = IPPROTO_GRE,
8438 		},
8439 	};
8440 	struct rte_flow_item_ipv6 ipv6 = {
8441 		.hdr =  {
8442 			.proto = IPPROTO_GRE,
8443 		},
8444 	};
8445 	struct rte_flow_item_gre gre = {
8446 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
8447 	};
8448 	struct rte_flow_item_mpls mpls;
8449 	uint8_t *header;
8450 	int ret;
8451 
8452 	ret = parse_vc(ctx, token, str, len, buf, size);
8453 	if (ret < 0)
8454 		return ret;
8455 	/* Nothing else to do if there is no buffer. */
8456 	if (!out)
8457 		return ret;
8458 	if (!out->args.vc.actions_n)
8459 		return -1;
8460 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8461 	/* Point to selected object. */
8462 	ctx->object = out->args.vc.data;
8463 	ctx->objmask = NULL;
8464 	/* Copy the headers to the buffer. */
8465 	action_decap_data = ctx->object;
8466 	*action_decap_data = (struct action_raw_decap_data) {
8467 		.conf = (struct rte_flow_action_raw_decap){
8468 			.data = action_decap_data->data,
8469 		},
8470 		.data = {},
8471 	};
8472 	header = action_decap_data->data;
8473 	if (mplsogre_decap_conf.select_vlan)
8474 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
8475 	else if (mplsogre_encap_conf.select_ipv4)
8476 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8477 	else
8478 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8479 	memcpy(eth.hdr.dst_addr.addr_bytes,
8480 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
8481 	memcpy(eth.hdr.src_addr.addr_bytes,
8482 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
8483 	memcpy(header, &eth, sizeof(eth));
8484 	header += sizeof(eth);
8485 	if (mplsogre_encap_conf.select_vlan) {
8486 		if (mplsogre_encap_conf.select_ipv4)
8487 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8488 		else
8489 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8490 		memcpy(header, &vlan, sizeof(vlan));
8491 		header += sizeof(vlan);
8492 	}
8493 	if (mplsogre_encap_conf.select_ipv4) {
8494 		memcpy(header, &ipv4, sizeof(ipv4));
8495 		header += sizeof(ipv4);
8496 	} else {
8497 		memcpy(header, &ipv6, sizeof(ipv6));
8498 		header += sizeof(ipv6);
8499 	}
8500 	memcpy(header, &gre, sizeof(gre));
8501 	header += sizeof(gre);
8502 	memset(&mpls, 0, sizeof(mpls));
8503 	memcpy(header, &mpls, sizeof(mpls));
8504 	header += sizeof(mpls);
8505 	action_decap_data->conf.size = header -
8506 		action_decap_data->data;
8507 	action->conf = &action_decap_data->conf;
8508 	return ret;
8509 }
8510 
8511 /** Parse MPLSOUDP encap action. */
8512 static int
8513 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
8514 			       const char *str, unsigned int len,
8515 			       void *buf, unsigned int size)
8516 {
8517 	struct buffer *out = buf;
8518 	struct rte_flow_action *action;
8519 	struct action_raw_encap_data *action_encap_data;
8520 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
8521 	struct rte_flow_item_vlan vlan = {
8522 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
8523 		.hdr.eth_proto = 0,
8524 	};
8525 	struct rte_flow_item_ipv4 ipv4 = {
8526 		.hdr =  {
8527 			.src_addr = mplsoudp_encap_conf.ipv4_src,
8528 			.dst_addr = mplsoudp_encap_conf.ipv4_dst,
8529 			.next_proto_id = IPPROTO_UDP,
8530 			.version_ihl = RTE_IPV4_VHL_DEF,
8531 			.time_to_live = IPDEFTTL,
8532 		},
8533 	};
8534 	struct rte_flow_item_ipv6 ipv6 = {
8535 		.hdr =  {
8536 			.proto = IPPROTO_UDP,
8537 			.hop_limits = IPDEFTTL,
8538 		},
8539 	};
8540 	struct rte_flow_item_udp udp = {
8541 		.hdr = {
8542 			.src_port = mplsoudp_encap_conf.udp_src,
8543 			.dst_port = mplsoudp_encap_conf.udp_dst,
8544 		},
8545 	};
8546 	struct rte_flow_item_mpls mpls;
8547 	uint8_t *header;
8548 	int ret;
8549 
8550 	ret = parse_vc(ctx, token, str, len, buf, size);
8551 	if (ret < 0)
8552 		return ret;
8553 	/* Nothing else to do if there is no buffer. */
8554 	if (!out)
8555 		return ret;
8556 	if (!out->args.vc.actions_n)
8557 		return -1;
8558 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8559 	/* Point to selected object. */
8560 	ctx->object = out->args.vc.data;
8561 	ctx->objmask = NULL;
8562 	/* Copy the headers to the buffer. */
8563 	action_encap_data = ctx->object;
8564 	*action_encap_data = (struct action_raw_encap_data) {
8565 		.conf = (struct rte_flow_action_raw_encap){
8566 			.data = action_encap_data->data,
8567 		},
8568 		.data = {},
8569 		.preserve = {},
8570 	};
8571 	header = action_encap_data->data;
8572 	if (mplsoudp_encap_conf.select_vlan)
8573 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
8574 	else if (mplsoudp_encap_conf.select_ipv4)
8575 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8576 	else
8577 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8578 	memcpy(eth.hdr.dst_addr.addr_bytes,
8579 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
8580 	memcpy(eth.hdr.src_addr.addr_bytes,
8581 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
8582 	memcpy(header, &eth, sizeof(eth));
8583 	header += sizeof(eth);
8584 	if (mplsoudp_encap_conf.select_vlan) {
8585 		if (mplsoudp_encap_conf.select_ipv4)
8586 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8587 		else
8588 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8589 		memcpy(header, &vlan, sizeof(vlan));
8590 		header += sizeof(vlan);
8591 	}
8592 	if (mplsoudp_encap_conf.select_ipv4) {
8593 		memcpy(header, &ipv4, sizeof(ipv4));
8594 		header += sizeof(ipv4);
8595 	} else {
8596 		memcpy(&ipv6.hdr.src_addr,
8597 		       &mplsoudp_encap_conf.ipv6_src,
8598 		       sizeof(mplsoudp_encap_conf.ipv6_src));
8599 		memcpy(&ipv6.hdr.dst_addr,
8600 		       &mplsoudp_encap_conf.ipv6_dst,
8601 		       sizeof(mplsoudp_encap_conf.ipv6_dst));
8602 		memcpy(header, &ipv6, sizeof(ipv6));
8603 		header += sizeof(ipv6);
8604 	}
8605 	memcpy(header, &udp, sizeof(udp));
8606 	header += sizeof(udp);
8607 	memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
8608 	       RTE_DIM(mplsoudp_encap_conf.label));
8609 	mpls.label_tc_s[2] |= 0x1;
8610 	memcpy(header, &mpls, sizeof(mpls));
8611 	header += sizeof(mpls);
8612 	action_encap_data->conf.size = header -
8613 		action_encap_data->data;
8614 	action->conf = &action_encap_data->conf;
8615 	return ret;
8616 }
8617 
8618 /** Parse MPLSOUDP decap action. */
8619 static int
8620 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
8621 			       const char *str, unsigned int len,
8622 			       void *buf, unsigned int size)
8623 {
8624 	struct buffer *out = buf;
8625 	struct rte_flow_action *action;
8626 	struct action_raw_decap_data *action_decap_data;
8627 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
8628 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
8629 	struct rte_flow_item_ipv4 ipv4 = {
8630 		.hdr =  {
8631 			.next_proto_id = IPPROTO_UDP,
8632 		},
8633 	};
8634 	struct rte_flow_item_ipv6 ipv6 = {
8635 		.hdr =  {
8636 			.proto = IPPROTO_UDP,
8637 		},
8638 	};
8639 	struct rte_flow_item_udp udp = {
8640 		.hdr = {
8641 			.dst_port = rte_cpu_to_be_16(6635),
8642 		},
8643 	};
8644 	struct rte_flow_item_mpls mpls;
8645 	uint8_t *header;
8646 	int ret;
8647 
8648 	ret = parse_vc(ctx, token, str, len, buf, size);
8649 	if (ret < 0)
8650 		return ret;
8651 	/* Nothing else to do if there is no buffer. */
8652 	if (!out)
8653 		return ret;
8654 	if (!out->args.vc.actions_n)
8655 		return -1;
8656 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8657 	/* Point to selected object. */
8658 	ctx->object = out->args.vc.data;
8659 	ctx->objmask = NULL;
8660 	/* Copy the headers to the buffer. */
8661 	action_decap_data = ctx->object;
8662 	*action_decap_data = (struct action_raw_decap_data) {
8663 		.conf = (struct rte_flow_action_raw_decap){
8664 			.data = action_decap_data->data,
8665 		},
8666 		.data = {},
8667 	};
8668 	header = action_decap_data->data;
8669 	if (mplsoudp_decap_conf.select_vlan)
8670 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
8671 	else if (mplsoudp_encap_conf.select_ipv4)
8672 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8673 	else
8674 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8675 	memcpy(eth.hdr.dst_addr.addr_bytes,
8676 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
8677 	memcpy(eth.hdr.src_addr.addr_bytes,
8678 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
8679 	memcpy(header, &eth, sizeof(eth));
8680 	header += sizeof(eth);
8681 	if (mplsoudp_encap_conf.select_vlan) {
8682 		if (mplsoudp_encap_conf.select_ipv4)
8683 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8684 		else
8685 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8686 		memcpy(header, &vlan, sizeof(vlan));
8687 		header += sizeof(vlan);
8688 	}
8689 	if (mplsoudp_encap_conf.select_ipv4) {
8690 		memcpy(header, &ipv4, sizeof(ipv4));
8691 		header += sizeof(ipv4);
8692 	} else {
8693 		memcpy(header, &ipv6, sizeof(ipv6));
8694 		header += sizeof(ipv6);
8695 	}
8696 	memcpy(header, &udp, sizeof(udp));
8697 	header += sizeof(udp);
8698 	memset(&mpls, 0, sizeof(mpls));
8699 	memcpy(header, &mpls, sizeof(mpls));
8700 	header += sizeof(mpls);
8701 	action_decap_data->conf.size = header -
8702 		action_decap_data->data;
8703 	action->conf = &action_decap_data->conf;
8704 	return ret;
8705 }
8706 
8707 static int
8708 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
8709 				const char *str, unsigned int len, void *buf,
8710 				unsigned int size)
8711 {
8712 	struct action_raw_decap_data *action_raw_decap_data;
8713 	struct rte_flow_action *action;
8714 	const struct arg *arg;
8715 	struct buffer *out = buf;
8716 	int ret;
8717 	uint16_t idx;
8718 
8719 	RTE_SET_USED(token);
8720 	RTE_SET_USED(buf);
8721 	RTE_SET_USED(size);
8722 	arg = ARGS_ENTRY_ARB_BOUNDED
8723 		(offsetof(struct action_raw_decap_data, idx),
8724 		 sizeof(((struct action_raw_decap_data *)0)->idx),
8725 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
8726 	if (push_args(ctx, arg))
8727 		return -1;
8728 	ret = parse_int(ctx, token, str, len, NULL, 0);
8729 	if (ret < 0) {
8730 		pop_args(ctx);
8731 		return -1;
8732 	}
8733 	if (!ctx->object)
8734 		return len;
8735 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8736 	action_raw_decap_data = ctx->object;
8737 	idx = action_raw_decap_data->idx;
8738 	action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
8739 	action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
8740 	action->conf = &action_raw_decap_data->conf;
8741 	return len;
8742 }
8743 
8744 
8745 static int
8746 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
8747 				const char *str, unsigned int len, void *buf,
8748 				unsigned int size)
8749 {
8750 	struct action_raw_encap_data *action_raw_encap_data;
8751 	struct rte_flow_action *action;
8752 	const struct arg *arg;
8753 	struct buffer *out = buf;
8754 	int ret;
8755 	uint16_t idx;
8756 
8757 	RTE_SET_USED(token);
8758 	RTE_SET_USED(buf);
8759 	RTE_SET_USED(size);
8760 	if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
8761 		return -1;
8762 	arg = ARGS_ENTRY_ARB_BOUNDED
8763 		(offsetof(struct action_raw_encap_data, idx),
8764 		 sizeof(((struct action_raw_encap_data *)0)->idx),
8765 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
8766 	if (push_args(ctx, arg))
8767 		return -1;
8768 	ret = parse_int(ctx, token, str, len, NULL, 0);
8769 	if (ret < 0) {
8770 		pop_args(ctx);
8771 		return -1;
8772 	}
8773 	if (!ctx->object)
8774 		return len;
8775 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8776 	action_raw_encap_data = ctx->object;
8777 	idx = action_raw_encap_data->idx;
8778 	action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
8779 	action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
8780 	action_raw_encap_data->conf.preserve = NULL;
8781 	action->conf = &action_raw_encap_data->conf;
8782 	return len;
8783 }
8784 
8785 static int
8786 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
8787 			  const char *str, unsigned int len, void *buf,
8788 			  unsigned int size)
8789 {
8790 	struct buffer *out = buf;
8791 	struct rte_flow_action *action;
8792 	struct action_raw_encap_data *action_raw_encap_data = NULL;
8793 	int ret;
8794 
8795 	ret = parse_vc(ctx, token, str, len, buf, size);
8796 	if (ret < 0)
8797 		return ret;
8798 	/* Nothing else to do if there is no buffer. */
8799 	if (!out)
8800 		return ret;
8801 	if (!out->args.vc.actions_n)
8802 		return -1;
8803 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8804 	/* Point to selected object. */
8805 	ctx->object = out->args.vc.data;
8806 	ctx->objmask = NULL;
8807 	/* Copy the headers to the buffer. */
8808 	action_raw_encap_data = ctx->object;
8809 	action_raw_encap_data->conf.data = raw_encap_confs[0].data;
8810 	action_raw_encap_data->conf.preserve = NULL;
8811 	action_raw_encap_data->conf.size = raw_encap_confs[0].size;
8812 	action->conf = &action_raw_encap_data->conf;
8813 	return ret;
8814 }
8815 
8816 static int
8817 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
8818 			  const char *str, unsigned int len, void *buf,
8819 			  unsigned int size)
8820 {
8821 	struct buffer *out = buf;
8822 	struct rte_flow_action *action;
8823 	struct action_raw_decap_data *action_raw_decap_data = NULL;
8824 	int ret;
8825 
8826 	ret = parse_vc(ctx, token, str, len, buf, size);
8827 	if (ret < 0)
8828 		return ret;
8829 	/* Nothing else to do if there is no buffer. */
8830 	if (!out)
8831 		return ret;
8832 	if (!out->args.vc.actions_n)
8833 		return -1;
8834 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8835 	/* Point to selected object. */
8836 	ctx->object = out->args.vc.data;
8837 	ctx->objmask = NULL;
8838 	/* Copy the headers to the buffer. */
8839 	action_raw_decap_data = ctx->object;
8840 	action_raw_decap_data->conf.data = raw_decap_confs[0].data;
8841 	action_raw_decap_data->conf.size = raw_decap_confs[0].size;
8842 	action->conf = &action_raw_decap_data->conf;
8843 	return ret;
8844 }
8845 
8846 static int
8847 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
8848 			 const char *str, unsigned int len, void *buf,
8849 			 unsigned int size)
8850 {
8851 	int ret;
8852 
8853 	ret = parse_vc(ctx, token, str, len, buf, size);
8854 	if (ret < 0)
8855 		return ret;
8856 	ret = rte_flow_dynf_metadata_register();
8857 	if (ret < 0)
8858 		return -1;
8859 	return len;
8860 }
8861 
8862 static int
8863 parse_vc_action_sample(struct context *ctx, const struct token *token,
8864 			 const char *str, unsigned int len, void *buf,
8865 			 unsigned int size)
8866 {
8867 	struct buffer *out = buf;
8868 	struct rte_flow_action *action;
8869 	struct action_sample_data *action_sample_data = NULL;
8870 	static struct rte_flow_action end_action = {
8871 		RTE_FLOW_ACTION_TYPE_END, 0
8872 	};
8873 	int ret;
8874 
8875 	ret = parse_vc(ctx, token, str, len, buf, size);
8876 	if (ret < 0)
8877 		return ret;
8878 	/* Nothing else to do if there is no buffer. */
8879 	if (!out)
8880 		return ret;
8881 	if (!out->args.vc.actions_n)
8882 		return -1;
8883 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8884 	/* Point to selected object. */
8885 	ctx->object = out->args.vc.data;
8886 	ctx->objmask = NULL;
8887 	/* Copy the headers to the buffer. */
8888 	action_sample_data = ctx->object;
8889 	action_sample_data->conf.actions = &end_action;
8890 	action->conf = &action_sample_data->conf;
8891 	return ret;
8892 }
8893 
8894 static int
8895 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
8896 				const char *str, unsigned int len, void *buf,
8897 				unsigned int size)
8898 {
8899 	struct action_sample_data *action_sample_data;
8900 	struct rte_flow_action *action;
8901 	const struct arg *arg;
8902 	struct buffer *out = buf;
8903 	int ret;
8904 	uint16_t idx;
8905 
8906 	RTE_SET_USED(token);
8907 	RTE_SET_USED(buf);
8908 	RTE_SET_USED(size);
8909 	if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
8910 		return -1;
8911 	arg = ARGS_ENTRY_ARB_BOUNDED
8912 		(offsetof(struct action_sample_data, idx),
8913 		 sizeof(((struct action_sample_data *)0)->idx),
8914 		 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
8915 	if (push_args(ctx, arg))
8916 		return -1;
8917 	ret = parse_int(ctx, token, str, len, NULL, 0);
8918 	if (ret < 0) {
8919 		pop_args(ctx);
8920 		return -1;
8921 	}
8922 	if (!ctx->object)
8923 		return len;
8924 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8925 	action_sample_data = ctx->object;
8926 	idx = action_sample_data->idx;
8927 	action_sample_data->conf.actions = raw_sample_confs[idx].data;
8928 	action->conf = &action_sample_data->conf;
8929 	return len;
8930 }
8931 
8932 /** Parse operation for modify_field command. */
8933 static int
8934 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
8935 			 const char *str, unsigned int len, void *buf,
8936 			 unsigned int size)
8937 {
8938 	struct rte_flow_action_modify_field *action_modify_field;
8939 	unsigned int i;
8940 
8941 	(void)token;
8942 	(void)buf;
8943 	(void)size;
8944 	if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
8945 		return -1;
8946 	for (i = 0; modify_field_ops[i]; ++i)
8947 		if (!strcmp_partial(modify_field_ops[i], str, len))
8948 			break;
8949 	if (!modify_field_ops[i])
8950 		return -1;
8951 	if (!ctx->object)
8952 		return len;
8953 	action_modify_field = ctx->object;
8954 	action_modify_field->operation = (enum rte_flow_modify_op)i;
8955 	return len;
8956 }
8957 
8958 /** Parse id for modify_field command. */
8959 static int
8960 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
8961 			 const char *str, unsigned int len, void *buf,
8962 			 unsigned int size)
8963 {
8964 	struct rte_flow_action_modify_field *action_modify_field;
8965 	unsigned int i;
8966 
8967 	(void)token;
8968 	(void)buf;
8969 	(void)size;
8970 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
8971 		ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
8972 		return -1;
8973 	for (i = 0; modify_field_ids[i]; ++i)
8974 		if (!strcmp_partial(modify_field_ids[i], str, len))
8975 			break;
8976 	if (!modify_field_ids[i])
8977 		return -1;
8978 	if (!ctx->object)
8979 		return len;
8980 	action_modify_field = ctx->object;
8981 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
8982 		action_modify_field->dst.field = (enum rte_flow_field_id)i;
8983 	else
8984 		action_modify_field->src.field = (enum rte_flow_field_id)i;
8985 	return len;
8986 }
8987 
8988 /** Parse level for modify_field command. */
8989 static int
8990 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
8991 			 const char *str, unsigned int len, void *buf,
8992 			 unsigned int size)
8993 {
8994 	struct rte_flow_action_modify_field *action;
8995 	struct flex_item *fp;
8996 	uint32_t val;
8997 	struct buffer *out = buf;
8998 	char *end;
8999 
9000 	(void)token;
9001 	(void)size;
9002 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
9003 		ctx->curr != ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)
9004 		return -1;
9005 	if (!ctx->object)
9006 		return len;
9007 	action = ctx->object;
9008 	errno = 0;
9009 	val = strtoumax(str, &end, 0);
9010 	if (errno || (size_t)(end - str) != len)
9011 		return -1;
9012 	/* No need to validate action template mask value */
9013 	if (out->args.vc.masks) {
9014 		if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)
9015 			action->dst.level = val;
9016 		else
9017 			action->src.level = val;
9018 		return len;
9019 	}
9020 	if ((ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
9021 		action->dst.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
9022 		(ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE &&
9023 		action->src.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
9024 		if (val >= FLEX_MAX_PARSERS_NUM) {
9025 			printf("Bad flex item handle\n");
9026 			return -1;
9027 		}
9028 		fp = flex_items[ctx->port][val];
9029 		if (!fp) {
9030 			printf("Bad flex item handle\n");
9031 			return -1;
9032 		}
9033 	}
9034 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE) {
9035 		if (action->dst.field != RTE_FLOW_FIELD_FLEX_ITEM)
9036 			action->dst.level = val;
9037 		else
9038 			action->dst.flex_handle = fp->flex_handle;
9039 	} else if (ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE) {
9040 		if (action->src.field != RTE_FLOW_FIELD_FLEX_ITEM)
9041 			action->src.level = val;
9042 		else
9043 			action->src.flex_handle = fp->flex_handle;
9044 	}
9045 	return len;
9046 }
9047 
9048 /** Parse the conntrack update, not a rte_flow_action. */
9049 static int
9050 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
9051 			 const char *str, unsigned int len, void *buf,
9052 			 unsigned int size)
9053 {
9054 	struct buffer *out = buf;
9055 	struct rte_flow_modify_conntrack *ct_modify = NULL;
9056 
9057 	(void)size;
9058 	if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
9059 	    ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
9060 		return -1;
9061 	/* Token name must match. */
9062 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9063 		return -1;
9064 	/* Nothing else to do if there is no buffer. */
9065 	if (!out)
9066 		return len;
9067 	ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
9068 	if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
9069 		ct_modify->new_ct.is_original_dir =
9070 				conntrack_context.is_original_dir;
9071 		ct_modify->direction = 1;
9072 	} else {
9073 		uint32_t old_dir;
9074 
9075 		old_dir = ct_modify->new_ct.is_original_dir;
9076 		memcpy(&ct_modify->new_ct, &conntrack_context,
9077 		       sizeof(conntrack_context));
9078 		ct_modify->new_ct.is_original_dir = old_dir;
9079 		ct_modify->state = 1;
9080 	}
9081 	return len;
9082 }
9083 
9084 /** Parse tokens for destroy command. */
9085 static int
9086 parse_destroy(struct context *ctx, const struct token *token,
9087 	      const char *str, unsigned int len,
9088 	      void *buf, unsigned int size)
9089 {
9090 	struct buffer *out = buf;
9091 
9092 	/* Token name must match. */
9093 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9094 		return -1;
9095 	/* Nothing else to do if there is no buffer. */
9096 	if (!out)
9097 		return len;
9098 	if (!out->command) {
9099 		if (ctx->curr != DESTROY)
9100 			return -1;
9101 		if (sizeof(*out) > size)
9102 			return -1;
9103 		out->command = ctx->curr;
9104 		ctx->objdata = 0;
9105 		ctx->object = out;
9106 		ctx->objmask = NULL;
9107 		out->args.destroy.rule =
9108 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9109 					       sizeof(double));
9110 		return len;
9111 	}
9112 	if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
9113 	     sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
9114 		return -1;
9115 	ctx->objdata = 0;
9116 	ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
9117 	ctx->objmask = NULL;
9118 	return len;
9119 }
9120 
9121 /** Parse tokens for flush command. */
9122 static int
9123 parse_flush(struct context *ctx, const struct token *token,
9124 	    const char *str, unsigned int len,
9125 	    void *buf, unsigned int size)
9126 {
9127 	struct buffer *out = buf;
9128 
9129 	/* Token name must match. */
9130 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9131 		return -1;
9132 	/* Nothing else to do if there is no buffer. */
9133 	if (!out)
9134 		return len;
9135 	if (!out->command) {
9136 		if (ctx->curr != FLUSH)
9137 			return -1;
9138 		if (sizeof(*out) > size)
9139 			return -1;
9140 		out->command = ctx->curr;
9141 		ctx->objdata = 0;
9142 		ctx->object = out;
9143 		ctx->objmask = NULL;
9144 	}
9145 	return len;
9146 }
9147 
9148 /** Parse tokens for dump command. */
9149 static int
9150 parse_dump(struct context *ctx, const struct token *token,
9151 	    const char *str, unsigned int len,
9152 	    void *buf, unsigned int size)
9153 {
9154 	struct buffer *out = buf;
9155 
9156 	/* Token name must match. */
9157 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9158 		return -1;
9159 	/* Nothing else to do if there is no buffer. */
9160 	if (!out)
9161 		return len;
9162 	if (!out->command) {
9163 		if (ctx->curr != DUMP)
9164 			return -1;
9165 		if (sizeof(*out) > size)
9166 			return -1;
9167 		out->command = ctx->curr;
9168 		ctx->objdata = 0;
9169 		ctx->object = out;
9170 		ctx->objmask = NULL;
9171 		return len;
9172 	}
9173 	switch (ctx->curr) {
9174 	case DUMP_ALL:
9175 	case DUMP_ONE:
9176 		out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
9177 		out->command = ctx->curr;
9178 		ctx->objdata = 0;
9179 		ctx->object = out;
9180 		ctx->objmask = NULL;
9181 		return len;
9182 	default:
9183 		return -1;
9184 	}
9185 }
9186 
9187 /** Parse tokens for query command. */
9188 static int
9189 parse_query(struct context *ctx, const struct token *token,
9190 	    const char *str, unsigned int len,
9191 	    void *buf, unsigned int size)
9192 {
9193 	struct buffer *out = buf;
9194 
9195 	/* Token name must match. */
9196 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9197 		return -1;
9198 	/* Nothing else to do if there is no buffer. */
9199 	if (!out)
9200 		return len;
9201 	if (!out->command) {
9202 		if (ctx->curr != QUERY)
9203 			return -1;
9204 		if (sizeof(*out) > size)
9205 			return -1;
9206 		out->command = ctx->curr;
9207 		ctx->objdata = 0;
9208 		ctx->object = out;
9209 		ctx->objmask = NULL;
9210 	}
9211 	return len;
9212 }
9213 
9214 /** Parse action names. */
9215 static int
9216 parse_action(struct context *ctx, const struct token *token,
9217 	     const char *str, unsigned int len,
9218 	     void *buf, unsigned int size)
9219 {
9220 	struct buffer *out = buf;
9221 	const struct arg *arg = pop_args(ctx);
9222 	unsigned int i;
9223 
9224 	(void)size;
9225 	/* Argument is expected. */
9226 	if (!arg)
9227 		return -1;
9228 	/* Parse action name. */
9229 	for (i = 0; next_action[i]; ++i) {
9230 		const struct parse_action_priv *priv;
9231 
9232 		token = &token_list[next_action[i]];
9233 		if (strcmp_partial(token->name, str, len))
9234 			continue;
9235 		priv = token->priv;
9236 		if (!priv)
9237 			goto error;
9238 		if (out)
9239 			memcpy((uint8_t *)ctx->object + arg->offset,
9240 			       &priv->type,
9241 			       arg->size);
9242 		return len;
9243 	}
9244 error:
9245 	push_args(ctx, arg);
9246 	return -1;
9247 }
9248 
9249 /** Parse tokens for list command. */
9250 static int
9251 parse_list(struct context *ctx, const struct token *token,
9252 	   const char *str, unsigned int len,
9253 	   void *buf, unsigned int size)
9254 {
9255 	struct buffer *out = buf;
9256 
9257 	/* Token name must match. */
9258 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9259 		return -1;
9260 	/* Nothing else to do if there is no buffer. */
9261 	if (!out)
9262 		return len;
9263 	if (!out->command) {
9264 		if (ctx->curr != LIST)
9265 			return -1;
9266 		if (sizeof(*out) > size)
9267 			return -1;
9268 		out->command = ctx->curr;
9269 		ctx->objdata = 0;
9270 		ctx->object = out;
9271 		ctx->objmask = NULL;
9272 		out->args.list.group =
9273 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9274 					       sizeof(double));
9275 		return len;
9276 	}
9277 	if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
9278 	     sizeof(*out->args.list.group)) > (uint8_t *)out + size)
9279 		return -1;
9280 	ctx->objdata = 0;
9281 	ctx->object = out->args.list.group + out->args.list.group_n++;
9282 	ctx->objmask = NULL;
9283 	return len;
9284 }
9285 
9286 /** Parse tokens for list all aged flows command. */
9287 static int
9288 parse_aged(struct context *ctx, const struct token *token,
9289 	   const char *str, unsigned int len,
9290 	   void *buf, unsigned int size)
9291 {
9292 	struct buffer *out = buf;
9293 
9294 	/* Token name must match. */
9295 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9296 		return -1;
9297 	/* Nothing else to do if there is no buffer. */
9298 	if (!out)
9299 		return len;
9300 	if (!out->command || out->command == QUEUE) {
9301 		if (ctx->curr != AGED && ctx->curr != QUEUE_AGED)
9302 			return -1;
9303 		if (sizeof(*out) > size)
9304 			return -1;
9305 		out->command = ctx->curr;
9306 		ctx->objdata = 0;
9307 		ctx->object = out;
9308 		ctx->objmask = NULL;
9309 	}
9310 	if (ctx->curr == AGED_DESTROY)
9311 		out->args.aged.destroy = 1;
9312 	return len;
9313 }
9314 
9315 /** Parse tokens for isolate command. */
9316 static int
9317 parse_isolate(struct context *ctx, const struct token *token,
9318 	      const char *str, unsigned int len,
9319 	      void *buf, unsigned int size)
9320 {
9321 	struct buffer *out = buf;
9322 
9323 	/* Token name must match. */
9324 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9325 		return -1;
9326 	/* Nothing else to do if there is no buffer. */
9327 	if (!out)
9328 		return len;
9329 	if (!out->command) {
9330 		if (ctx->curr != ISOLATE)
9331 			return -1;
9332 		if (sizeof(*out) > size)
9333 			return -1;
9334 		out->command = ctx->curr;
9335 		ctx->objdata = 0;
9336 		ctx->object = out;
9337 		ctx->objmask = NULL;
9338 	}
9339 	return len;
9340 }
9341 
9342 /** Parse tokens for info/configure command. */
9343 static int
9344 parse_configure(struct context *ctx, const struct token *token,
9345 		const char *str, unsigned int len,
9346 		void *buf, unsigned int size)
9347 {
9348 	struct buffer *out = buf;
9349 
9350 	/* Token name must match. */
9351 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9352 		return -1;
9353 	/* Nothing else to do if there is no buffer. */
9354 	if (!out)
9355 		return len;
9356 	if (!out->command) {
9357 		if (ctx->curr != INFO && ctx->curr != CONFIGURE)
9358 			return -1;
9359 		if (sizeof(*out) > size)
9360 			return -1;
9361 		out->command = ctx->curr;
9362 		ctx->objdata = 0;
9363 		ctx->object = out;
9364 		ctx->objmask = NULL;
9365 	}
9366 	return len;
9367 }
9368 
9369 /** Parse tokens for template create command. */
9370 static int
9371 parse_template(struct context *ctx, const struct token *token,
9372 	       const char *str, unsigned int len,
9373 	       void *buf, unsigned int size)
9374 {
9375 	struct buffer *out = buf;
9376 
9377 	/* Token name must match. */
9378 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9379 		return -1;
9380 	/* Nothing else to do if there is no buffer. */
9381 	if (!out)
9382 		return len;
9383 	if (!out->command) {
9384 		if (ctx->curr != PATTERN_TEMPLATE &&
9385 		    ctx->curr != ACTIONS_TEMPLATE)
9386 			return -1;
9387 		if (sizeof(*out) > size)
9388 			return -1;
9389 		out->command = ctx->curr;
9390 		ctx->objdata = 0;
9391 		ctx->object = out;
9392 		ctx->objmask = NULL;
9393 		out->args.vc.data = (uint8_t *)out + size;
9394 		return len;
9395 	}
9396 	switch (ctx->curr) {
9397 	case PATTERN_TEMPLATE_CREATE:
9398 		out->args.vc.pattern =
9399 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9400 					       sizeof(double));
9401 		out->args.vc.pat_templ_id = UINT32_MAX;
9402 		out->command = ctx->curr;
9403 		ctx->objdata = 0;
9404 		ctx->object = out;
9405 		ctx->objmask = NULL;
9406 		return len;
9407 	case PATTERN_TEMPLATE_EGRESS:
9408 		out->args.vc.attr.egress = 1;
9409 		return len;
9410 	case PATTERN_TEMPLATE_INGRESS:
9411 		out->args.vc.attr.ingress = 1;
9412 		return len;
9413 	case PATTERN_TEMPLATE_TRANSFER:
9414 		out->args.vc.attr.transfer = 1;
9415 		return len;
9416 	case ACTIONS_TEMPLATE_CREATE:
9417 		out->args.vc.act_templ_id = UINT32_MAX;
9418 		out->command = ctx->curr;
9419 		ctx->objdata = 0;
9420 		ctx->object = out;
9421 		ctx->objmask = NULL;
9422 		return len;
9423 	case ACTIONS_TEMPLATE_SPEC:
9424 		out->args.vc.actions =
9425 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9426 					       sizeof(double));
9427 		ctx->object = out->args.vc.actions;
9428 		ctx->objmask = NULL;
9429 		return len;
9430 	case ACTIONS_TEMPLATE_MASK:
9431 		out->args.vc.masks =
9432 			(void *)RTE_ALIGN_CEIL((uintptr_t)
9433 					       (out->args.vc.actions +
9434 						out->args.vc.actions_n),
9435 					       sizeof(double));
9436 		ctx->object = out->args.vc.masks;
9437 		ctx->objmask = NULL;
9438 		return len;
9439 	case ACTIONS_TEMPLATE_EGRESS:
9440 		out->args.vc.attr.egress = 1;
9441 		return len;
9442 	case ACTIONS_TEMPLATE_INGRESS:
9443 		out->args.vc.attr.ingress = 1;
9444 		return len;
9445 	case ACTIONS_TEMPLATE_TRANSFER:
9446 		out->args.vc.attr.transfer = 1;
9447 		return len;
9448 	default:
9449 		return -1;
9450 	}
9451 }
9452 
9453 /** Parse tokens for template destroy command. */
9454 static int
9455 parse_template_destroy(struct context *ctx, const struct token *token,
9456 		       const char *str, unsigned int len,
9457 		       void *buf, unsigned int size)
9458 {
9459 	struct buffer *out = buf;
9460 	uint32_t *template_id;
9461 
9462 	/* Token name must match. */
9463 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9464 		return -1;
9465 	/* Nothing else to do if there is no buffer. */
9466 	if (!out)
9467 		return len;
9468 	if (!out->command ||
9469 		out->command == PATTERN_TEMPLATE ||
9470 		out->command == ACTIONS_TEMPLATE) {
9471 		if (ctx->curr != PATTERN_TEMPLATE_DESTROY &&
9472 			ctx->curr != ACTIONS_TEMPLATE_DESTROY)
9473 			return -1;
9474 		if (sizeof(*out) > size)
9475 			return -1;
9476 		out->command = ctx->curr;
9477 		ctx->objdata = 0;
9478 		ctx->object = out;
9479 		ctx->objmask = NULL;
9480 		out->args.templ_destroy.template_id =
9481 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9482 					       sizeof(double));
9483 		return len;
9484 	}
9485 	template_id = out->args.templ_destroy.template_id
9486 		    + out->args.templ_destroy.template_id_n++;
9487 	if ((uint8_t *)template_id > (uint8_t *)out + size)
9488 		return -1;
9489 	ctx->objdata = 0;
9490 	ctx->object = template_id;
9491 	ctx->objmask = NULL;
9492 	return len;
9493 }
9494 
9495 /** Parse tokens for table create command. */
9496 static int
9497 parse_table(struct context *ctx, const struct token *token,
9498 	    const char *str, unsigned int len,
9499 	    void *buf, unsigned int size)
9500 {
9501 	struct buffer *out = buf;
9502 	uint32_t *template_id;
9503 
9504 	/* Token name must match. */
9505 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9506 		return -1;
9507 	/* Nothing else to do if there is no buffer. */
9508 	if (!out)
9509 		return len;
9510 	if (!out->command) {
9511 		if (ctx->curr != TABLE)
9512 			return -1;
9513 		if (sizeof(*out) > size)
9514 			return -1;
9515 		out->command = ctx->curr;
9516 		ctx->objdata = 0;
9517 		ctx->object = out;
9518 		ctx->objmask = NULL;
9519 		return len;
9520 	}
9521 	switch (ctx->curr) {
9522 	case TABLE_CREATE:
9523 		out->command = ctx->curr;
9524 		ctx->objdata = 0;
9525 		ctx->object = out;
9526 		ctx->objmask = NULL;
9527 		out->args.table.id = UINT32_MAX;
9528 		return len;
9529 	case TABLE_PATTERN_TEMPLATE:
9530 		out->args.table.pat_templ_id =
9531 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9532 					       sizeof(double));
9533 		template_id = out->args.table.pat_templ_id
9534 				+ out->args.table.pat_templ_id_n++;
9535 		if ((uint8_t *)template_id > (uint8_t *)out + size)
9536 			return -1;
9537 		ctx->objdata = 0;
9538 		ctx->object = template_id;
9539 		ctx->objmask = NULL;
9540 		return len;
9541 	case TABLE_ACTIONS_TEMPLATE:
9542 		out->args.table.act_templ_id =
9543 			(void *)RTE_ALIGN_CEIL((uintptr_t)
9544 					       (out->args.table.pat_templ_id +
9545 						out->args.table.pat_templ_id_n),
9546 					       sizeof(double));
9547 		template_id = out->args.table.act_templ_id
9548 				+ out->args.table.act_templ_id_n++;
9549 		if ((uint8_t *)template_id > (uint8_t *)out + size)
9550 			return -1;
9551 		ctx->objdata = 0;
9552 		ctx->object = template_id;
9553 		ctx->objmask = NULL;
9554 		return len;
9555 	case TABLE_INGRESS:
9556 		out->args.table.attr.flow_attr.ingress = 1;
9557 		return len;
9558 	case TABLE_EGRESS:
9559 		out->args.table.attr.flow_attr.egress = 1;
9560 		return len;
9561 	case TABLE_TRANSFER:
9562 		out->args.table.attr.flow_attr.transfer = 1;
9563 		return len;
9564 	case TABLE_TRANSFER_WIRE_ORIG:
9565 		if (!out->args.table.attr.flow_attr.transfer)
9566 			return -1;
9567 		out->args.table.attr.specialize = RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_WIRE_ORIG;
9568 		return len;
9569 	case TABLE_TRANSFER_VPORT_ORIG:
9570 		if (!out->args.table.attr.flow_attr.transfer)
9571 			return -1;
9572 		out->args.table.attr.specialize = RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_VPORT_ORIG;
9573 		return len;
9574 	default:
9575 		return -1;
9576 	}
9577 }
9578 
9579 /** Parse tokens for table destroy command. */
9580 static int
9581 parse_table_destroy(struct context *ctx, const struct token *token,
9582 		    const char *str, unsigned int len,
9583 		    void *buf, unsigned int size)
9584 {
9585 	struct buffer *out = buf;
9586 	uint32_t *table_id;
9587 
9588 	/* Token name must match. */
9589 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9590 		return -1;
9591 	/* Nothing else to do if there is no buffer. */
9592 	if (!out)
9593 		return len;
9594 	if (!out->command || out->command == TABLE) {
9595 		if (ctx->curr != TABLE_DESTROY)
9596 			return -1;
9597 		if (sizeof(*out) > size)
9598 			return -1;
9599 		out->command = ctx->curr;
9600 		ctx->objdata = 0;
9601 		ctx->object = out;
9602 		ctx->objmask = NULL;
9603 		out->args.table_destroy.table_id =
9604 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9605 					       sizeof(double));
9606 		return len;
9607 	}
9608 	table_id = out->args.table_destroy.table_id
9609 		    + out->args.table_destroy.table_id_n++;
9610 	if ((uint8_t *)table_id > (uint8_t *)out + size)
9611 		return -1;
9612 	ctx->objdata = 0;
9613 	ctx->object = table_id;
9614 	ctx->objmask = NULL;
9615 	return len;
9616 }
9617 
9618 /** Parse tokens for queue create commands. */
9619 static int
9620 parse_qo(struct context *ctx, const struct token *token,
9621 	 const char *str, unsigned int len,
9622 	 void *buf, unsigned int size)
9623 {
9624 	struct buffer *out = buf;
9625 
9626 	/* Token name must match. */
9627 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9628 		return -1;
9629 	/* Nothing else to do if there is no buffer. */
9630 	if (!out)
9631 		return len;
9632 	if (!out->command) {
9633 		if (ctx->curr != QUEUE)
9634 			return -1;
9635 		if (sizeof(*out) > size)
9636 			return -1;
9637 		out->command = ctx->curr;
9638 		ctx->objdata = 0;
9639 		ctx->object = out;
9640 		ctx->objmask = NULL;
9641 		out->args.vc.data = (uint8_t *)out + size;
9642 		return len;
9643 	}
9644 	switch (ctx->curr) {
9645 	case QUEUE_CREATE:
9646 		out->command = ctx->curr;
9647 		ctx->objdata = 0;
9648 		ctx->object = out;
9649 		ctx->objmask = NULL;
9650 		out->args.vc.rule_id = UINT32_MAX;
9651 		return len;
9652 	case QUEUE_TEMPLATE_TABLE:
9653 	case QUEUE_PATTERN_TEMPLATE:
9654 	case QUEUE_ACTIONS_TEMPLATE:
9655 	case QUEUE_CREATE_POSTPONE:
9656 	case QUEUE_RULE_ID:
9657 		return len;
9658 	case ITEM_PATTERN:
9659 		out->args.vc.pattern =
9660 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9661 					       sizeof(double));
9662 		ctx->object = out->args.vc.pattern;
9663 		ctx->objmask = NULL;
9664 		return len;
9665 	case ACTIONS:
9666 		out->args.vc.actions =
9667 			(void *)RTE_ALIGN_CEIL((uintptr_t)
9668 					       (out->args.vc.pattern +
9669 						out->args.vc.pattern_n),
9670 					       sizeof(double));
9671 		ctx->object = out->args.vc.actions;
9672 		ctx->objmask = NULL;
9673 		return len;
9674 	default:
9675 		return -1;
9676 	}
9677 }
9678 
9679 /** Parse tokens for queue destroy command. */
9680 static int
9681 parse_qo_destroy(struct context *ctx, const struct token *token,
9682 		 const char *str, unsigned int len,
9683 		 void *buf, unsigned int size)
9684 {
9685 	struct buffer *out = buf;
9686 	uint32_t *flow_id;
9687 
9688 	/* Token name must match. */
9689 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9690 		return -1;
9691 	/* Nothing else to do if there is no buffer. */
9692 	if (!out)
9693 		return len;
9694 	if (!out->command || out->command == QUEUE) {
9695 		if (ctx->curr != QUEUE_DESTROY)
9696 			return -1;
9697 		if (sizeof(*out) > size)
9698 			return -1;
9699 		out->command = ctx->curr;
9700 		ctx->objdata = 0;
9701 		ctx->object = out;
9702 		ctx->objmask = NULL;
9703 		out->args.destroy.rule =
9704 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9705 					       sizeof(double));
9706 		return len;
9707 	}
9708 	switch (ctx->curr) {
9709 	case QUEUE_DESTROY_ID:
9710 		flow_id = out->args.destroy.rule
9711 				+ out->args.destroy.rule_n++;
9712 		if ((uint8_t *)flow_id > (uint8_t *)out + size)
9713 			return -1;
9714 		ctx->objdata = 0;
9715 		ctx->object = flow_id;
9716 		ctx->objmask = NULL;
9717 		return len;
9718 	case QUEUE_DESTROY_POSTPONE:
9719 		return len;
9720 	default:
9721 		return -1;
9722 	}
9723 }
9724 
9725 /** Parse tokens for push queue command. */
9726 static int
9727 parse_push(struct context *ctx, const struct token *token,
9728 	   const char *str, unsigned int len,
9729 	   void *buf, unsigned int size)
9730 {
9731 	struct buffer *out = buf;
9732 
9733 	/* Token name must match. */
9734 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9735 		return -1;
9736 	/* Nothing else to do if there is no buffer. */
9737 	if (!out)
9738 		return len;
9739 	if (!out->command) {
9740 		if (ctx->curr != PUSH)
9741 			return -1;
9742 		if (sizeof(*out) > size)
9743 			return -1;
9744 		out->command = ctx->curr;
9745 		ctx->objdata = 0;
9746 		ctx->object = out;
9747 		ctx->objmask = NULL;
9748 		out->args.vc.data = (uint8_t *)out + size;
9749 	}
9750 	return len;
9751 }
9752 
9753 /** Parse tokens for pull command. */
9754 static int
9755 parse_pull(struct context *ctx, const struct token *token,
9756 	   const char *str, unsigned int len,
9757 	   void *buf, unsigned int size)
9758 {
9759 	struct buffer *out = buf;
9760 
9761 	/* Token name must match. */
9762 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9763 		return -1;
9764 	/* Nothing else to do if there is no buffer. */
9765 	if (!out)
9766 		return len;
9767 	if (!out->command) {
9768 		if (ctx->curr != PULL)
9769 			return -1;
9770 		if (sizeof(*out) > size)
9771 			return -1;
9772 		out->command = ctx->curr;
9773 		ctx->objdata = 0;
9774 		ctx->object = out;
9775 		ctx->objmask = NULL;
9776 		out->args.vc.data = (uint8_t *)out + size;
9777 	}
9778 	return len;
9779 }
9780 
9781 static int
9782 parse_flex(struct context *ctx, const struct token *token,
9783 	     const char *str, unsigned int len,
9784 	     void *buf, unsigned int size)
9785 {
9786 	struct buffer *out = buf;
9787 
9788 	/* Token name must match. */
9789 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9790 		return -1;
9791 	/* Nothing else to do if there is no buffer. */
9792 	if (!out)
9793 		return len;
9794 	if (out->command == ZERO) {
9795 		if (ctx->curr != FLEX)
9796 			return -1;
9797 		if (sizeof(*out) > size)
9798 			return -1;
9799 		out->command = ctx->curr;
9800 		ctx->objdata = 0;
9801 		ctx->object = out;
9802 		ctx->objmask = NULL;
9803 	} else {
9804 		switch (ctx->curr) {
9805 		default:
9806 			break;
9807 		case FLEX_ITEM_INIT:
9808 		case FLEX_ITEM_CREATE:
9809 		case FLEX_ITEM_DESTROY:
9810 			out->command = ctx->curr;
9811 			break;
9812 		}
9813 	}
9814 
9815 	return len;
9816 }
9817 
9818 static int
9819 parse_tunnel(struct context *ctx, const struct token *token,
9820 	     const char *str, unsigned int len,
9821 	     void *buf, unsigned int size)
9822 {
9823 	struct buffer *out = buf;
9824 
9825 	/* Token name must match. */
9826 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9827 		return -1;
9828 	/* Nothing else to do if there is no buffer. */
9829 	if (!out)
9830 		return len;
9831 	if (!out->command) {
9832 		if (ctx->curr != TUNNEL)
9833 			return -1;
9834 		if (sizeof(*out) > size)
9835 			return -1;
9836 		out->command = ctx->curr;
9837 		ctx->objdata = 0;
9838 		ctx->object = out;
9839 		ctx->objmask = NULL;
9840 	} else {
9841 		switch (ctx->curr) {
9842 		default:
9843 			break;
9844 		case TUNNEL_CREATE:
9845 		case TUNNEL_DESTROY:
9846 		case TUNNEL_LIST:
9847 			out->command = ctx->curr;
9848 			break;
9849 		case TUNNEL_CREATE_TYPE:
9850 		case TUNNEL_DESTROY_ID:
9851 			ctx->object = &out->args.vc.tunnel_ops;
9852 			break;
9853 		}
9854 	}
9855 
9856 	return len;
9857 }
9858 
9859 /**
9860  * Parse signed/unsigned integers 8 to 64-bit long.
9861  *
9862  * Last argument (ctx->args) is retrieved to determine integer type and
9863  * storage location.
9864  */
9865 static int
9866 parse_int(struct context *ctx, const struct token *token,
9867 	  const char *str, unsigned int len,
9868 	  void *buf, unsigned int size)
9869 {
9870 	const struct arg *arg = pop_args(ctx);
9871 	uintmax_t u;
9872 	char *end;
9873 
9874 	(void)token;
9875 	/* Argument is expected. */
9876 	if (!arg)
9877 		return -1;
9878 	errno = 0;
9879 	u = arg->sign ?
9880 		(uintmax_t)strtoimax(str, &end, 0) :
9881 		strtoumax(str, &end, 0);
9882 	if (errno || (size_t)(end - str) != len)
9883 		goto error;
9884 	if (arg->bounded &&
9885 	    ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
9886 			    (intmax_t)u > (intmax_t)arg->max)) ||
9887 	     (!arg->sign && (u < arg->min || u > arg->max))))
9888 		goto error;
9889 	if (!ctx->object)
9890 		return len;
9891 	if (arg->mask) {
9892 		if (!arg_entry_bf_fill(ctx->object, u, arg) ||
9893 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
9894 			goto error;
9895 		return len;
9896 	}
9897 	buf = (uint8_t *)ctx->object + arg->offset;
9898 	size = arg->size;
9899 	if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
9900 		return -1;
9901 objmask:
9902 	switch (size) {
9903 	case sizeof(uint8_t):
9904 		*(uint8_t *)buf = u;
9905 		break;
9906 	case sizeof(uint16_t):
9907 		*(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
9908 		break;
9909 	case sizeof(uint8_t [3]):
9910 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
9911 		if (!arg->hton) {
9912 			((uint8_t *)buf)[0] = u;
9913 			((uint8_t *)buf)[1] = u >> 8;
9914 			((uint8_t *)buf)[2] = u >> 16;
9915 			break;
9916 		}
9917 #endif
9918 		((uint8_t *)buf)[0] = u >> 16;
9919 		((uint8_t *)buf)[1] = u >> 8;
9920 		((uint8_t *)buf)[2] = u;
9921 		break;
9922 	case sizeof(uint32_t):
9923 		*(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
9924 		break;
9925 	case sizeof(uint64_t):
9926 		*(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
9927 		break;
9928 	default:
9929 		goto error;
9930 	}
9931 	if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
9932 		u = -1;
9933 		buf = (uint8_t *)ctx->objmask + arg->offset;
9934 		goto objmask;
9935 	}
9936 	return len;
9937 error:
9938 	push_args(ctx, arg);
9939 	return -1;
9940 }
9941 
9942 /**
9943  * Parse a string.
9944  *
9945  * Three arguments (ctx->args) are retrieved from the stack to store data,
9946  * its actual length and address (in that order).
9947  */
9948 static int
9949 parse_string(struct context *ctx, const struct token *token,
9950 	     const char *str, unsigned int len,
9951 	     void *buf, unsigned int size)
9952 {
9953 	const struct arg *arg_data = pop_args(ctx);
9954 	const struct arg *arg_len = pop_args(ctx);
9955 	const struct arg *arg_addr = pop_args(ctx);
9956 	char tmp[16]; /* Ought to be enough. */
9957 	int ret;
9958 
9959 	/* Arguments are expected. */
9960 	if (!arg_data)
9961 		return -1;
9962 	if (!arg_len) {
9963 		push_args(ctx, arg_data);
9964 		return -1;
9965 	}
9966 	if (!arg_addr) {
9967 		push_args(ctx, arg_len);
9968 		push_args(ctx, arg_data);
9969 		return -1;
9970 	}
9971 	size = arg_data->size;
9972 	/* Bit-mask fill is not supported. */
9973 	if (arg_data->mask || size < len)
9974 		goto error;
9975 	if (!ctx->object)
9976 		return len;
9977 	/* Let parse_int() fill length information first. */
9978 	ret = snprintf(tmp, sizeof(tmp), "%u", len);
9979 	if (ret < 0)
9980 		goto error;
9981 	push_args(ctx, arg_len);
9982 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
9983 	if (ret < 0) {
9984 		pop_args(ctx);
9985 		goto error;
9986 	}
9987 	buf = (uint8_t *)ctx->object + arg_data->offset;
9988 	/* Output buffer is not necessarily NUL-terminated. */
9989 	memcpy(buf, str, len);
9990 	memset((uint8_t *)buf + len, 0x00, size - len);
9991 	if (ctx->objmask)
9992 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
9993 	/* Save address if requested. */
9994 	if (arg_addr->size) {
9995 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
9996 		       (void *[]){
9997 			(uint8_t *)ctx->object + arg_data->offset
9998 		       },
9999 		       arg_addr->size);
10000 		if (ctx->objmask)
10001 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
10002 			       (void *[]){
10003 				(uint8_t *)ctx->objmask + arg_data->offset
10004 			       },
10005 			       arg_addr->size);
10006 	}
10007 	return len;
10008 error:
10009 	push_args(ctx, arg_addr);
10010 	push_args(ctx, arg_len);
10011 	push_args(ctx, arg_data);
10012 	return -1;
10013 }
10014 
10015 static int
10016 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
10017 {
10018 	const uint8_t *head = dst;
10019 	uint32_t left;
10020 
10021 	if (*size == 0)
10022 		return -1;
10023 
10024 	left = *size;
10025 
10026 	/* Convert chars to bytes */
10027 	while (left) {
10028 		char tmp[3], *end = tmp;
10029 		uint32_t read_lim = left & 1 ? 1 : 2;
10030 
10031 		snprintf(tmp, read_lim + 1, "%s", src);
10032 		*dst = strtoul(tmp, &end, 16);
10033 		if (*end) {
10034 			*dst = 0;
10035 			*size = (uint32_t)(dst - head);
10036 			return -1;
10037 		}
10038 		left -= read_lim;
10039 		src += read_lim;
10040 		dst++;
10041 	}
10042 	*dst = 0;
10043 	*size = (uint32_t)(dst - head);
10044 	return 0;
10045 }
10046 
10047 static int
10048 parse_hex(struct context *ctx, const struct token *token,
10049 		const char *str, unsigned int len,
10050 		void *buf, unsigned int size)
10051 {
10052 	const struct arg *arg_data = pop_args(ctx);
10053 	const struct arg *arg_len = pop_args(ctx);
10054 	const struct arg *arg_addr = pop_args(ctx);
10055 	char tmp[16]; /* Ought to be enough. */
10056 	int ret;
10057 	unsigned int hexlen = len;
10058 	unsigned int length = 256;
10059 	uint8_t hex_tmp[length];
10060 
10061 	/* Arguments are expected. */
10062 	if (!arg_data)
10063 		return -1;
10064 	if (!arg_len) {
10065 		push_args(ctx, arg_data);
10066 		return -1;
10067 	}
10068 	if (!arg_addr) {
10069 		push_args(ctx, arg_len);
10070 		push_args(ctx, arg_data);
10071 		return -1;
10072 	}
10073 	size = arg_data->size;
10074 	/* Bit-mask fill is not supported. */
10075 	if (arg_data->mask)
10076 		goto error;
10077 	if (!ctx->object)
10078 		return len;
10079 
10080 	/* translate bytes string to array. */
10081 	if (str[0] == '0' && ((str[1] == 'x') ||
10082 			(str[1] == 'X'))) {
10083 		str += 2;
10084 		hexlen -= 2;
10085 	}
10086 	if (hexlen > length)
10087 		goto error;
10088 	ret = parse_hex_string(str, hex_tmp, &hexlen);
10089 	if (ret < 0)
10090 		goto error;
10091 	/* Check the converted binary fits into data buffer. */
10092 	if (hexlen > size)
10093 		goto error;
10094 	/* Let parse_int() fill length information first. */
10095 	ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
10096 	if (ret < 0)
10097 		goto error;
10098 	/* Save length if requested. */
10099 	if (arg_len->size) {
10100 		push_args(ctx, arg_len);
10101 		ret = parse_int(ctx, token, tmp, ret, NULL, 0);
10102 		if (ret < 0) {
10103 			pop_args(ctx);
10104 			goto error;
10105 		}
10106 	}
10107 	buf = (uint8_t *)ctx->object + arg_data->offset;
10108 	/* Output buffer is not necessarily NUL-terminated. */
10109 	memcpy(buf, hex_tmp, hexlen);
10110 	memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
10111 	if (ctx->objmask)
10112 		memset((uint8_t *)ctx->objmask + arg_data->offset,
10113 					0xff, hexlen);
10114 	/* Save address if requested. */
10115 	if (arg_addr->size) {
10116 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
10117 		       (void *[]){
10118 			(uint8_t *)ctx->object + arg_data->offset
10119 		       },
10120 		       arg_addr->size);
10121 		if (ctx->objmask)
10122 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
10123 			       (void *[]){
10124 				(uint8_t *)ctx->objmask + arg_data->offset
10125 			       },
10126 			       arg_addr->size);
10127 	}
10128 	return len;
10129 error:
10130 	push_args(ctx, arg_addr);
10131 	push_args(ctx, arg_len);
10132 	push_args(ctx, arg_data);
10133 	return -1;
10134 
10135 }
10136 
10137 /**
10138  * Parse a zero-ended string.
10139  */
10140 static int
10141 parse_string0(struct context *ctx, const struct token *token __rte_unused,
10142 	     const char *str, unsigned int len,
10143 	     void *buf, unsigned int size)
10144 {
10145 	const struct arg *arg_data = pop_args(ctx);
10146 
10147 	/* Arguments are expected. */
10148 	if (!arg_data)
10149 		return -1;
10150 	size = arg_data->size;
10151 	/* Bit-mask fill is not supported. */
10152 	if (arg_data->mask || size < len + 1)
10153 		goto error;
10154 	if (!ctx->object)
10155 		return len;
10156 	buf = (uint8_t *)ctx->object + arg_data->offset;
10157 	strncpy(buf, str, len);
10158 	if (ctx->objmask)
10159 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
10160 	return len;
10161 error:
10162 	push_args(ctx, arg_data);
10163 	return -1;
10164 }
10165 
10166 /**
10167  * Parse a MAC address.
10168  *
10169  * Last argument (ctx->args) is retrieved to determine storage size and
10170  * location.
10171  */
10172 static int
10173 parse_mac_addr(struct context *ctx, const struct token *token,
10174 	       const char *str, unsigned int len,
10175 	       void *buf, unsigned int size)
10176 {
10177 	const struct arg *arg = pop_args(ctx);
10178 	struct rte_ether_addr tmp;
10179 	int ret;
10180 
10181 	(void)token;
10182 	/* Argument is expected. */
10183 	if (!arg)
10184 		return -1;
10185 	size = arg->size;
10186 	/* Bit-mask fill is not supported. */
10187 	if (arg->mask || size != sizeof(tmp))
10188 		goto error;
10189 	/* Only network endian is supported. */
10190 	if (!arg->hton)
10191 		goto error;
10192 	ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
10193 	if (ret < 0 || (unsigned int)ret != len)
10194 		goto error;
10195 	if (!ctx->object)
10196 		return len;
10197 	buf = (uint8_t *)ctx->object + arg->offset;
10198 	memcpy(buf, &tmp, size);
10199 	if (ctx->objmask)
10200 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
10201 	return len;
10202 error:
10203 	push_args(ctx, arg);
10204 	return -1;
10205 }
10206 
10207 /**
10208  * Parse an IPv4 address.
10209  *
10210  * Last argument (ctx->args) is retrieved to determine storage size and
10211  * location.
10212  */
10213 static int
10214 parse_ipv4_addr(struct context *ctx, const struct token *token,
10215 		const char *str, unsigned int len,
10216 		void *buf, unsigned int size)
10217 {
10218 	const struct arg *arg = pop_args(ctx);
10219 	char str2[len + 1];
10220 	struct in_addr tmp;
10221 	int ret;
10222 
10223 	/* Argument is expected. */
10224 	if (!arg)
10225 		return -1;
10226 	size = arg->size;
10227 	/* Bit-mask fill is not supported. */
10228 	if (arg->mask || size != sizeof(tmp))
10229 		goto error;
10230 	/* Only network endian is supported. */
10231 	if (!arg->hton)
10232 		goto error;
10233 	memcpy(str2, str, len);
10234 	str2[len] = '\0';
10235 	ret = inet_pton(AF_INET, str2, &tmp);
10236 	if (ret != 1) {
10237 		/* Attempt integer parsing. */
10238 		push_args(ctx, arg);
10239 		return parse_int(ctx, token, str, len, buf, size);
10240 	}
10241 	if (!ctx->object)
10242 		return len;
10243 	buf = (uint8_t *)ctx->object + arg->offset;
10244 	memcpy(buf, &tmp, size);
10245 	if (ctx->objmask)
10246 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
10247 	return len;
10248 error:
10249 	push_args(ctx, arg);
10250 	return -1;
10251 }
10252 
10253 /**
10254  * Parse an IPv6 address.
10255  *
10256  * Last argument (ctx->args) is retrieved to determine storage size and
10257  * location.
10258  */
10259 static int
10260 parse_ipv6_addr(struct context *ctx, const struct token *token,
10261 		const char *str, unsigned int len,
10262 		void *buf, unsigned int size)
10263 {
10264 	const struct arg *arg = pop_args(ctx);
10265 	char str2[len + 1];
10266 	struct in6_addr tmp;
10267 	int ret;
10268 
10269 	(void)token;
10270 	/* Argument is expected. */
10271 	if (!arg)
10272 		return -1;
10273 	size = arg->size;
10274 	/* Bit-mask fill is not supported. */
10275 	if (arg->mask || size != sizeof(tmp))
10276 		goto error;
10277 	/* Only network endian is supported. */
10278 	if (!arg->hton)
10279 		goto error;
10280 	memcpy(str2, str, len);
10281 	str2[len] = '\0';
10282 	ret = inet_pton(AF_INET6, str2, &tmp);
10283 	if (ret != 1)
10284 		goto error;
10285 	if (!ctx->object)
10286 		return len;
10287 	buf = (uint8_t *)ctx->object + arg->offset;
10288 	memcpy(buf, &tmp, size);
10289 	if (ctx->objmask)
10290 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
10291 	return len;
10292 error:
10293 	push_args(ctx, arg);
10294 	return -1;
10295 }
10296 
10297 /** Boolean values (even indices stand for false). */
10298 static const char *const boolean_name[] = {
10299 	"0", "1",
10300 	"false", "true",
10301 	"no", "yes",
10302 	"N", "Y",
10303 	"off", "on",
10304 	NULL,
10305 };
10306 
10307 /**
10308  * Parse a boolean value.
10309  *
10310  * Last argument (ctx->args) is retrieved to determine storage size and
10311  * location.
10312  */
10313 static int
10314 parse_boolean(struct context *ctx, const struct token *token,
10315 	      const char *str, unsigned int len,
10316 	      void *buf, unsigned int size)
10317 {
10318 	const struct arg *arg = pop_args(ctx);
10319 	unsigned int i;
10320 	int ret;
10321 
10322 	/* Argument is expected. */
10323 	if (!arg)
10324 		return -1;
10325 	for (i = 0; boolean_name[i]; ++i)
10326 		if (!strcmp_partial(boolean_name[i], str, len))
10327 			break;
10328 	/* Process token as integer. */
10329 	if (boolean_name[i])
10330 		str = i & 1 ? "1" : "0";
10331 	push_args(ctx, arg);
10332 	ret = parse_int(ctx, token, str, strlen(str), buf, size);
10333 	return ret > 0 ? (int)len : ret;
10334 }
10335 
10336 /** Parse port and update context. */
10337 static int
10338 parse_port(struct context *ctx, const struct token *token,
10339 	   const char *str, unsigned int len,
10340 	   void *buf, unsigned int size)
10341 {
10342 	struct buffer *out = &(struct buffer){ .port = 0 };
10343 	int ret;
10344 
10345 	if (buf)
10346 		out = buf;
10347 	else {
10348 		ctx->objdata = 0;
10349 		ctx->object = out;
10350 		ctx->objmask = NULL;
10351 		size = sizeof(*out);
10352 	}
10353 	ret = parse_int(ctx, token, str, len, out, size);
10354 	if (ret >= 0)
10355 		ctx->port = out->port;
10356 	if (!buf)
10357 		ctx->object = NULL;
10358 	return ret;
10359 }
10360 
10361 /** Parse tokens for shared indirect actions. */
10362 static int
10363 parse_ia_port(struct context *ctx, const struct token *token,
10364 	      const char *str, unsigned int len,
10365 	      void *buf, unsigned int size)
10366 {
10367 	struct rte_flow_action *action = ctx->object;
10368 	uint32_t id;
10369 	int ret;
10370 
10371 	(void)buf;
10372 	(void)size;
10373 	ctx->objdata = 0;
10374 	ctx->object = &id;
10375 	ctx->objmask = NULL;
10376 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
10377 	ctx->object = action;
10378 	if (ret != (int)len)
10379 		return ret;
10380 	/* set indirect action */
10381 	if (action)
10382 		action->conf = (void *)(uintptr_t)id;
10383 	return ret;
10384 }
10385 
10386 static int
10387 parse_ia_id2ptr(struct context *ctx, const struct token *token,
10388 		const char *str, unsigned int len,
10389 		void *buf, unsigned int size)
10390 {
10391 	struct rte_flow_action *action = ctx->object;
10392 	uint32_t id;
10393 	int ret;
10394 
10395 	(void)buf;
10396 	(void)size;
10397 	ctx->objdata = 0;
10398 	ctx->object = &id;
10399 	ctx->objmask = NULL;
10400 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
10401 	ctx->object = action;
10402 	if (ret != (int)len)
10403 		return ret;
10404 	/* set indirect action */
10405 	if (action) {
10406 		portid_t port_id = ctx->port;
10407 		if (ctx->prev == INDIRECT_ACTION_PORT)
10408 			port_id = (portid_t)(uintptr_t)action->conf;
10409 		action->conf = port_action_handle_get_by_id(port_id, id);
10410 		ret = (action->conf) ? ret : -1;
10411 	}
10412 	return ret;
10413 }
10414 
10415 static int
10416 parse_meter_profile_id2ptr(struct context *ctx, const struct token *token,
10417 		const char *str, unsigned int len,
10418 		void *buf, unsigned int size)
10419 {
10420 	struct rte_flow_action *action = ctx->object;
10421 	struct rte_flow_action_meter_mark *meter;
10422 	struct rte_flow_meter_profile *profile = NULL;
10423 	uint32_t id = 0;
10424 	int ret;
10425 
10426 	(void)buf;
10427 	(void)size;
10428 	ctx->objdata = 0;
10429 	ctx->object = &id;
10430 	ctx->objmask = NULL;
10431 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
10432 	ctx->object = action;
10433 	if (ret != (int)len)
10434 		return ret;
10435 	/* set meter profile */
10436 	if (action) {
10437 		meter = (struct rte_flow_action_meter_mark *)
10438 			(uintptr_t)(action->conf);
10439 		profile = port_meter_profile_get_by_id(ctx->port, id);
10440 		meter->profile = profile;
10441 		ret = (profile) ? ret : -1;
10442 	}
10443 	return ret;
10444 }
10445 
10446 static int
10447 parse_meter_policy_id2ptr(struct context *ctx, const struct token *token,
10448 		const char *str, unsigned int len,
10449 		void *buf, unsigned int size)
10450 {
10451 	struct rte_flow_action *action = ctx->object;
10452 	struct rte_flow_action_meter_mark *meter;
10453 	struct rte_flow_meter_policy *policy = NULL;
10454 	uint32_t id = 0;
10455 	int ret;
10456 
10457 	(void)buf;
10458 	(void)size;
10459 	ctx->objdata = 0;
10460 	ctx->object = &id;
10461 	ctx->objmask = NULL;
10462 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
10463 	ctx->object = action;
10464 	if (ret != (int)len)
10465 		return ret;
10466 	/* set meter policy */
10467 	if (action) {
10468 		meter = (struct rte_flow_action_meter_mark *)
10469 			(uintptr_t)(action->conf);
10470 		policy = port_meter_policy_get_by_id(ctx->port, id);
10471 		meter->policy = policy;
10472 		ret = (policy) ? ret : -1;
10473 	}
10474 	return ret;
10475 }
10476 
10477 /** Parse set command, initialize output buffer for subsequent tokens. */
10478 static int
10479 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
10480 			  const char *str, unsigned int len,
10481 			  void *buf, unsigned int size)
10482 {
10483 	struct buffer *out = buf;
10484 
10485 	/* Token name must match. */
10486 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10487 		return -1;
10488 	/* Nothing else to do if there is no buffer. */
10489 	if (!out)
10490 		return len;
10491 	/* Make sure buffer is large enough. */
10492 	if (size < sizeof(*out))
10493 		return -1;
10494 	ctx->objdata = 0;
10495 	ctx->objmask = NULL;
10496 	ctx->object = out;
10497 	if (!out->command)
10498 		return -1;
10499 	out->command = ctx->curr;
10500 	/* For encap/decap we need is pattern */
10501 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10502 						       sizeof(double));
10503 	return len;
10504 }
10505 
10506 /** Parse set command, initialize output buffer for subsequent tokens. */
10507 static int
10508 parse_set_sample_action(struct context *ctx, const struct token *token,
10509 			  const char *str, unsigned int len,
10510 			  void *buf, unsigned int size)
10511 {
10512 	struct buffer *out = buf;
10513 
10514 	/* Token name must match. */
10515 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10516 		return -1;
10517 	/* Nothing else to do if there is no buffer. */
10518 	if (!out)
10519 		return len;
10520 	/* Make sure buffer is large enough. */
10521 	if (size < sizeof(*out))
10522 		return -1;
10523 	ctx->objdata = 0;
10524 	ctx->objmask = NULL;
10525 	ctx->object = out;
10526 	if (!out->command)
10527 		return -1;
10528 	out->command = ctx->curr;
10529 	/* For sampler we need is actions */
10530 	out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10531 						       sizeof(double));
10532 	return len;
10533 }
10534 
10535 /**
10536  * Parse set raw_encap/raw_decap command,
10537  * initialize output buffer for subsequent tokens.
10538  */
10539 static int
10540 parse_set_init(struct context *ctx, const struct token *token,
10541 	       const char *str, unsigned int len,
10542 	       void *buf, unsigned int size)
10543 {
10544 	struct buffer *out = buf;
10545 
10546 	/* Token name must match. */
10547 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10548 		return -1;
10549 	/* Nothing else to do if there is no buffer. */
10550 	if (!out)
10551 		return len;
10552 	/* Make sure buffer is large enough. */
10553 	if (size < sizeof(*out))
10554 		return -1;
10555 	/* Initialize buffer. */
10556 	memset(out, 0x00, sizeof(*out));
10557 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
10558 	ctx->objdata = 0;
10559 	ctx->object = out;
10560 	ctx->objmask = NULL;
10561 	if (!out->command) {
10562 		if (ctx->curr != SET)
10563 			return -1;
10564 		if (sizeof(*out) > size)
10565 			return -1;
10566 		out->command = ctx->curr;
10567 		out->args.vc.data = (uint8_t *)out + size;
10568 		ctx->object  = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10569 						       sizeof(double));
10570 	}
10571 	return len;
10572 }
10573 
10574 /*
10575  * Replace testpmd handles in a flex flow item with real values.
10576  */
10577 static int
10578 parse_flex_handle(struct context *ctx, const struct token *token,
10579 		  const char *str, unsigned int len,
10580 		  void *buf, unsigned int size)
10581 {
10582 	struct rte_flow_item_flex *spec, *mask;
10583 	const struct rte_flow_item_flex *src_spec, *src_mask;
10584 	const struct arg *arg = pop_args(ctx);
10585 	uint32_t offset;
10586 	uint16_t handle;
10587 	int ret;
10588 
10589 	if (!arg) {
10590 		printf("Bad environment\n");
10591 		return -1;
10592 	}
10593 	offset = arg->offset;
10594 	push_args(ctx, arg);
10595 	ret = parse_int(ctx, token, str, len, buf, size);
10596 	if (ret <= 0 || !ctx->object)
10597 		return ret;
10598 	if (ctx->port >= RTE_MAX_ETHPORTS) {
10599 		printf("Bad port\n");
10600 		return -1;
10601 	}
10602 	if (offset == offsetof(struct rte_flow_item_flex, handle)) {
10603 		const struct flex_item *fp;
10604 		spec = ctx->object;
10605 		handle = (uint16_t)(uintptr_t)spec->handle;
10606 		if (handle >= FLEX_MAX_PARSERS_NUM) {
10607 			printf("Bad flex item handle\n");
10608 			return -1;
10609 		}
10610 		fp = flex_items[ctx->port][handle];
10611 		if (!fp) {
10612 			printf("Bad flex item handle\n");
10613 			return -1;
10614 		}
10615 		spec->handle = fp->flex_handle;
10616 		mask = spec + 2; /* spec, last, mask */
10617 		mask->handle = fp->flex_handle;
10618 	} else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
10619 		handle = (uint16_t)(uintptr_t)
10620 			((struct rte_flow_item_flex *)ctx->object)->pattern;
10621 		if (handle >= FLEX_MAX_PATTERNS_NUM) {
10622 			printf("Bad pattern handle\n");
10623 			return -1;
10624 		}
10625 		src_spec = &flex_patterns[handle].spec;
10626 		src_mask = &flex_patterns[handle].mask;
10627 		spec = ctx->object;
10628 		mask = spec + 2; /* spec, last, mask */
10629 		/* fill flow rule spec and mask parameters */
10630 		spec->length = src_spec->length;
10631 		spec->pattern = src_spec->pattern;
10632 		mask->length = src_mask->length;
10633 		mask->pattern = src_mask->pattern;
10634 	} else {
10635 		printf("Bad arguments - unknown flex item offset\n");
10636 		return -1;
10637 	}
10638 	return ret;
10639 }
10640 
10641 /** Parse Meter color name */
10642 static int
10643 parse_meter_color(struct context *ctx, const struct token *token,
10644 		  const char *str, unsigned int len, void *buf,
10645 		  unsigned int size)
10646 {
10647 	struct rte_flow_item_meter_color *meter_color;
10648 	unsigned int i;
10649 
10650 	(void)token;
10651 	(void)buf;
10652 	(void)size;
10653 	for (i = 0; meter_colors[i]; ++i)
10654 		if (!strcmp_partial(meter_colors[i], str, len))
10655 			break;
10656 	if (!meter_colors[i])
10657 		return -1;
10658 	if (!ctx->object)
10659 		return len;
10660 	meter_color = ctx->object;
10661 	meter_color->color = (enum rte_color)i;
10662 	return len;
10663 }
10664 
10665 /** Parse Insertion Table Type name */
10666 static int
10667 parse_insertion_table_type(struct context *ctx, const struct token *token,
10668 			   const char *str, unsigned int len, void *buf,
10669 			   unsigned int size)
10670 {
10671 	const struct arg *arg = pop_args(ctx);
10672 	unsigned int i;
10673 	char tmp[2];
10674 	int ret;
10675 
10676 	(void)size;
10677 	/* Argument is expected. */
10678 	if (!arg)
10679 		return -1;
10680 	for (i = 0; table_insertion_types[i]; ++i)
10681 		if (!strcmp_partial(table_insertion_types[i], str, len))
10682 			break;
10683 	if (!table_insertion_types[i])
10684 		return -1;
10685 	push_args(ctx, arg);
10686 	snprintf(tmp, sizeof(tmp), "%u", i);
10687 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
10688 	return ret > 0 ? (int)len : ret;
10689 }
10690 
10691 /** Parse Hash Calculation Table Type name */
10692 static int
10693 parse_hash_table_type(struct context *ctx, const struct token *token,
10694 		      const char *str, unsigned int len, void *buf,
10695 		      unsigned int size)
10696 {
10697 	const struct arg *arg = pop_args(ctx);
10698 	unsigned int i;
10699 	char tmp[2];
10700 	int ret;
10701 
10702 	(void)size;
10703 	/* Argument is expected. */
10704 	if (!arg)
10705 		return -1;
10706 	for (i = 0; table_hash_funcs[i]; ++i)
10707 		if (!strcmp_partial(table_hash_funcs[i], str, len))
10708 			break;
10709 	if (!table_hash_funcs[i])
10710 		return -1;
10711 	push_args(ctx, arg);
10712 	snprintf(tmp, sizeof(tmp), "%u", i);
10713 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
10714 	return ret > 0 ? (int)len : ret;
10715 }
10716 
10717 static int
10718 parse_name_to_index(struct context *ctx, const struct token *token,
10719 		    const char *str, unsigned int len, void *buf,
10720 		    unsigned int size,
10721 		    const char *const names[], size_t names_size, uint32_t *dst)
10722 {
10723 	int ret;
10724 	uint32_t i;
10725 
10726 	RTE_SET_USED(token);
10727 	RTE_SET_USED(buf);
10728 	RTE_SET_USED(size);
10729 	if (!ctx->object)
10730 		return len;
10731 	for (i = 0; i < names_size; i++) {
10732 		if (!names[i])
10733 			continue;
10734 		ret = strcmp_partial(names[i], str,
10735 				     RTE_MIN(len, strlen(names[i])));
10736 		if (!ret) {
10737 			*dst = i;
10738 			return len;
10739 		}
10740 	}
10741 	return -1;
10742 }
10743 
10744 static const char *const quota_mode_names[] = {
10745 	NULL,
10746 	[RTE_FLOW_QUOTA_MODE_PACKET] = "packet",
10747 	[RTE_FLOW_QUOTA_MODE_L2] = "l2",
10748 	[RTE_FLOW_QUOTA_MODE_L3] = "l3"
10749 };
10750 
10751 static const char *const quota_state_names[] = {
10752 	[RTE_FLOW_QUOTA_STATE_PASS] = "pass",
10753 	[RTE_FLOW_QUOTA_STATE_BLOCK] = "block"
10754 };
10755 
10756 static const char *const quota_update_names[] = {
10757 	[RTE_FLOW_UPDATE_QUOTA_SET] = "set",
10758 	[RTE_FLOW_UPDATE_QUOTA_ADD] = "add"
10759 };
10760 
10761 static const char *const query_update_mode_names[] = {
10762 	[RTE_FLOW_QU_QUERY_FIRST] = "query_first",
10763 	[RTE_FLOW_QU_UPDATE_FIRST] = "update_first"
10764 };
10765 
10766 static int
10767 parse_quota_state_name(struct context *ctx, const struct token *token,
10768 		       const char *str, unsigned int len, void *buf,
10769 		       unsigned int size)
10770 {
10771 	struct rte_flow_item_quota *quota = ctx->object;
10772 
10773 	return parse_name_to_index(ctx, token, str, len, buf, size,
10774 				   quota_state_names,
10775 				   RTE_DIM(quota_state_names),
10776 				   (uint32_t *)&quota->state);
10777 }
10778 
10779 static int
10780 parse_quota_mode_name(struct context *ctx, const struct token *token,
10781 		      const char *str, unsigned int len, void *buf,
10782 		      unsigned int size)
10783 {
10784 	struct rte_flow_action_quota *quota = ctx->object;
10785 
10786 	return parse_name_to_index(ctx, token, str, len, buf, size,
10787 				   quota_mode_names,
10788 				   RTE_DIM(quota_mode_names),
10789 				   (uint32_t *)&quota->mode);
10790 }
10791 
10792 static int
10793 parse_quota_update_name(struct context *ctx, const struct token *token,
10794 			const char *str, unsigned int len, void *buf,
10795 			unsigned int size)
10796 {
10797 	struct rte_flow_update_quota *update = ctx->object;
10798 
10799 	return parse_name_to_index(ctx, token, str, len, buf, size,
10800 				   quota_update_names,
10801 				   RTE_DIM(quota_update_names),
10802 				   (uint32_t *)&update->op);
10803 }
10804 
10805 static int
10806 parse_qu_mode_name(struct context *ctx, const struct token *token,
10807 		   const char *str, unsigned int len, void *buf,
10808 		   unsigned int size)
10809 {
10810 	struct buffer *out = ctx->object;
10811 
10812 	return parse_name_to_index(ctx, token, str, len, buf, size,
10813 				   query_update_mode_names,
10814 				   RTE_DIM(query_update_mode_names),
10815 				   (uint32_t *)&out->args.ia.qu_mode);
10816 }
10817 
10818 /** No completion. */
10819 static int
10820 comp_none(struct context *ctx, const struct token *token,
10821 	  unsigned int ent, char *buf, unsigned int size)
10822 {
10823 	(void)ctx;
10824 	(void)token;
10825 	(void)ent;
10826 	(void)buf;
10827 	(void)size;
10828 	return 0;
10829 }
10830 
10831 /** Complete boolean values. */
10832 static int
10833 comp_boolean(struct context *ctx, const struct token *token,
10834 	     unsigned int ent, char *buf, unsigned int size)
10835 {
10836 	unsigned int i;
10837 
10838 	(void)ctx;
10839 	(void)token;
10840 	for (i = 0; boolean_name[i]; ++i)
10841 		if (buf && i == ent)
10842 			return strlcpy(buf, boolean_name[i], size);
10843 	if (buf)
10844 		return -1;
10845 	return i;
10846 }
10847 
10848 /** Complete action names. */
10849 static int
10850 comp_action(struct context *ctx, const struct token *token,
10851 	    unsigned int ent, char *buf, unsigned int size)
10852 {
10853 	unsigned int i;
10854 
10855 	(void)ctx;
10856 	(void)token;
10857 	for (i = 0; next_action[i]; ++i)
10858 		if (buf && i == ent)
10859 			return strlcpy(buf, token_list[next_action[i]].name,
10860 				       size);
10861 	if (buf)
10862 		return -1;
10863 	return i;
10864 }
10865 
10866 /** Complete available ports. */
10867 static int
10868 comp_port(struct context *ctx, const struct token *token,
10869 	  unsigned int ent, char *buf, unsigned int size)
10870 {
10871 	unsigned int i = 0;
10872 	portid_t p;
10873 
10874 	(void)ctx;
10875 	(void)token;
10876 	RTE_ETH_FOREACH_DEV(p) {
10877 		if (buf && i == ent)
10878 			return snprintf(buf, size, "%u", p);
10879 		++i;
10880 	}
10881 	if (buf)
10882 		return -1;
10883 	return i;
10884 }
10885 
10886 /** Complete available rule IDs. */
10887 static int
10888 comp_rule_id(struct context *ctx, const struct token *token,
10889 	     unsigned int ent, char *buf, unsigned int size)
10890 {
10891 	unsigned int i = 0;
10892 	struct rte_port *port;
10893 	struct port_flow *pf;
10894 
10895 	(void)token;
10896 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
10897 	    ctx->port == (portid_t)RTE_PORT_ALL)
10898 		return -1;
10899 	port = &ports[ctx->port];
10900 	for (pf = port->flow_list; pf != NULL; pf = pf->next) {
10901 		if (buf && i == ent)
10902 			return snprintf(buf, size, "%u", pf->id);
10903 		++i;
10904 	}
10905 	if (buf)
10906 		return -1;
10907 	return i;
10908 }
10909 
10910 /** Complete type field for RSS action. */
10911 static int
10912 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
10913 			unsigned int ent, char *buf, unsigned int size)
10914 {
10915 	unsigned int i;
10916 
10917 	(void)ctx;
10918 	(void)token;
10919 	for (i = 0; rss_type_table[i].str; ++i)
10920 		;
10921 	if (!buf)
10922 		return i + 1;
10923 	if (ent < i)
10924 		return strlcpy(buf, rss_type_table[ent].str, size);
10925 	if (ent == i)
10926 		return snprintf(buf, size, "end");
10927 	return -1;
10928 }
10929 
10930 /** Complete queue field for RSS action. */
10931 static int
10932 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
10933 			 unsigned int ent, char *buf, unsigned int size)
10934 {
10935 	(void)ctx;
10936 	(void)token;
10937 	if (!buf)
10938 		return nb_rxq + 1;
10939 	if (ent < nb_rxq)
10940 		return snprintf(buf, size, "%u", ent);
10941 	if (ent == nb_rxq)
10942 		return snprintf(buf, size, "end");
10943 	return -1;
10944 }
10945 
10946 /** Complete index number for set raw_encap/raw_decap commands. */
10947 static int
10948 comp_set_raw_index(struct context *ctx, const struct token *token,
10949 		   unsigned int ent, char *buf, unsigned int size)
10950 {
10951 	uint16_t idx = 0;
10952 	uint16_t nb = 0;
10953 
10954 	RTE_SET_USED(ctx);
10955 	RTE_SET_USED(token);
10956 	for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
10957 		if (buf && idx == ent)
10958 			return snprintf(buf, size, "%u", idx);
10959 		++nb;
10960 	}
10961 	return nb;
10962 }
10963 
10964 /** Complete index number for set raw_encap/raw_decap commands. */
10965 static int
10966 comp_set_sample_index(struct context *ctx, const struct token *token,
10967 		   unsigned int ent, char *buf, unsigned int size)
10968 {
10969 	uint16_t idx = 0;
10970 	uint16_t nb = 0;
10971 
10972 	RTE_SET_USED(ctx);
10973 	RTE_SET_USED(token);
10974 	for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
10975 		if (buf && idx == ent)
10976 			return snprintf(buf, size, "%u", idx);
10977 		++nb;
10978 	}
10979 	return nb;
10980 }
10981 
10982 /** Complete operation for modify_field command. */
10983 static int
10984 comp_set_modify_field_op(struct context *ctx, const struct token *token,
10985 		   unsigned int ent, char *buf, unsigned int size)
10986 {
10987 	RTE_SET_USED(ctx);
10988 	RTE_SET_USED(token);
10989 	if (!buf)
10990 		return RTE_DIM(modify_field_ops);
10991 	if (ent < RTE_DIM(modify_field_ops) - 1)
10992 		return strlcpy(buf, modify_field_ops[ent], size);
10993 	return -1;
10994 }
10995 
10996 /** Complete field id for modify_field command. */
10997 static int
10998 comp_set_modify_field_id(struct context *ctx, const struct token *token,
10999 		   unsigned int ent, char *buf, unsigned int size)
11000 {
11001 	const char *name;
11002 
11003 	RTE_SET_USED(token);
11004 	if (!buf)
11005 		return RTE_DIM(modify_field_ids);
11006 	if (ent >= RTE_DIM(modify_field_ids) - 1)
11007 		return -1;
11008 	name = modify_field_ids[ent];
11009 	if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
11010 	    (strcmp(name, "pointer") && strcmp(name, "value")))
11011 		return strlcpy(buf, name, size);
11012 	return -1;
11013 }
11014 
11015 /** Complete available pattern template IDs. */
11016 static int
11017 comp_pattern_template_id(struct context *ctx, const struct token *token,
11018 			 unsigned int ent, char *buf, unsigned int size)
11019 {
11020 	unsigned int i = 0;
11021 	struct rte_port *port;
11022 	struct port_template *pt;
11023 
11024 	(void)token;
11025 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
11026 	    ctx->port == (portid_t)RTE_PORT_ALL)
11027 		return -1;
11028 	port = &ports[ctx->port];
11029 	for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) {
11030 		if (buf && i == ent)
11031 			return snprintf(buf, size, "%u", pt->id);
11032 		++i;
11033 	}
11034 	if (buf)
11035 		return -1;
11036 	return i;
11037 }
11038 
11039 /** Complete available actions template IDs. */
11040 static int
11041 comp_actions_template_id(struct context *ctx, const struct token *token,
11042 			 unsigned int ent, char *buf, unsigned int size)
11043 {
11044 	unsigned int i = 0;
11045 	struct rte_port *port;
11046 	struct port_template *pt;
11047 
11048 	(void)token;
11049 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
11050 	    ctx->port == (portid_t)RTE_PORT_ALL)
11051 		return -1;
11052 	port = &ports[ctx->port];
11053 	for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) {
11054 		if (buf && i == ent)
11055 			return snprintf(buf, size, "%u", pt->id);
11056 		++i;
11057 	}
11058 	if (buf)
11059 		return -1;
11060 	return i;
11061 }
11062 
11063 /** Complete available table IDs. */
11064 static int
11065 comp_table_id(struct context *ctx, const struct token *token,
11066 	      unsigned int ent, char *buf, unsigned int size)
11067 {
11068 	unsigned int i = 0;
11069 	struct rte_port *port;
11070 	struct port_table *pt;
11071 
11072 	(void)token;
11073 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
11074 	    ctx->port == (portid_t)RTE_PORT_ALL)
11075 		return -1;
11076 	port = &ports[ctx->port];
11077 	for (pt = port->table_list; pt != NULL; pt = pt->next) {
11078 		if (buf && i == ent)
11079 			return snprintf(buf, size, "%u", pt->id);
11080 		++i;
11081 	}
11082 	if (buf)
11083 		return -1;
11084 	return i;
11085 }
11086 
11087 /** Complete available queue IDs. */
11088 static int
11089 comp_queue_id(struct context *ctx, const struct token *token,
11090 	      unsigned int ent, char *buf, unsigned int size)
11091 {
11092 	unsigned int i = 0;
11093 	struct rte_port *port;
11094 
11095 	(void)token;
11096 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
11097 	    ctx->port == (portid_t)RTE_PORT_ALL)
11098 		return -1;
11099 	port = &ports[ctx->port];
11100 	for (i = 0; i < port->queue_nb; i++) {
11101 		if (buf && i == ent)
11102 			return snprintf(buf, size, "%u", i);
11103 	}
11104 	if (buf)
11105 		return -1;
11106 	return i;
11107 }
11108 
11109 static int
11110 comp_names_to_index(struct context *ctx, const struct token *token,
11111 		    unsigned int ent, char *buf, unsigned int size,
11112 		    const char *const names[], size_t names_size)
11113 {
11114 	RTE_SET_USED(ctx);
11115 	RTE_SET_USED(token);
11116 	if (!buf)
11117 		return names_size;
11118 	if (names[ent] && ent < names_size)
11119 		return rte_strscpy(buf, names[ent], size);
11120 	return -1;
11121 
11122 }
11123 
11124 /** Complete available Meter colors. */
11125 static int
11126 comp_meter_color(struct context *ctx, const struct token *token,
11127 		 unsigned int ent, char *buf, unsigned int size)
11128 {
11129 	RTE_SET_USED(ctx);
11130 	RTE_SET_USED(token);
11131 	if (!buf)
11132 		return RTE_DIM(meter_colors);
11133 	if (ent < RTE_DIM(meter_colors) - 1)
11134 		return strlcpy(buf, meter_colors[ent], size);
11135 	return -1;
11136 }
11137 
11138 /** Complete available Insertion Table types. */
11139 static int
11140 comp_insertion_table_type(struct context *ctx, const struct token *token,
11141 			  unsigned int ent, char *buf, unsigned int size)
11142 {
11143 	RTE_SET_USED(ctx);
11144 	RTE_SET_USED(token);
11145 	if (!buf)
11146 		return RTE_DIM(table_insertion_types);
11147 	if (ent < RTE_DIM(table_insertion_types) - 1)
11148 		return rte_strscpy(buf, table_insertion_types[ent], size);
11149 	return -1;
11150 }
11151 
11152 /** Complete available Hash Calculation Table types. */
11153 static int
11154 comp_hash_table_type(struct context *ctx, const struct token *token,
11155 		     unsigned int ent, char *buf, unsigned int size)
11156 {
11157 	RTE_SET_USED(ctx);
11158 	RTE_SET_USED(token);
11159 	if (!buf)
11160 		return RTE_DIM(table_hash_funcs);
11161 	if (ent < RTE_DIM(table_hash_funcs) - 1)
11162 		return rte_strscpy(buf, table_hash_funcs[ent], size);
11163 	return -1;
11164 }
11165 
11166 static int
11167 comp_quota_state_name(struct context *ctx, const struct token *token,
11168 		      unsigned int ent, char *buf, unsigned int size)
11169 {
11170 	return comp_names_to_index(ctx, token, ent, buf, size,
11171 				   quota_state_names,
11172 				   RTE_DIM(quota_state_names));
11173 }
11174 
11175 static int
11176 comp_quota_mode_name(struct context *ctx, const struct token *token,
11177 		     unsigned int ent, char *buf, unsigned int size)
11178 {
11179 	return comp_names_to_index(ctx, token, ent, buf, size,
11180 				   quota_mode_names,
11181 				   RTE_DIM(quota_mode_names));
11182 }
11183 
11184 static int
11185 comp_quota_update_name(struct context *ctx, const struct token *token,
11186 		       unsigned int ent, char *buf, unsigned int size)
11187 {
11188 	return comp_names_to_index(ctx, token, ent, buf, size,
11189 				   quota_update_names,
11190 				   RTE_DIM(quota_update_names));
11191 }
11192 
11193 static int
11194 comp_qu_mode_name(struct context *ctx, const struct token *token,
11195 		  unsigned int ent, char *buf, unsigned int size)
11196 {
11197 	return comp_names_to_index(ctx, token, ent, buf, size,
11198 				   query_update_mode_names,
11199 				   RTE_DIM(query_update_mode_names));
11200 }
11201 
11202 /** Internal context. */
11203 static struct context cmd_flow_context;
11204 
11205 /** Global parser instance (cmdline API). */
11206 cmdline_parse_inst_t cmd_flow;
11207 cmdline_parse_inst_t cmd_set_raw;
11208 
11209 /** Initialize context. */
11210 static void
11211 cmd_flow_context_init(struct context *ctx)
11212 {
11213 	/* A full memset() is not necessary. */
11214 	ctx->curr = ZERO;
11215 	ctx->prev = ZERO;
11216 	ctx->next_num = 0;
11217 	ctx->args_num = 0;
11218 	ctx->eol = 0;
11219 	ctx->last = 0;
11220 	ctx->port = 0;
11221 	ctx->objdata = 0;
11222 	ctx->object = NULL;
11223 	ctx->objmask = NULL;
11224 }
11225 
11226 /** Parse a token (cmdline API). */
11227 static int
11228 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
11229 	       unsigned int size)
11230 {
11231 	struct context *ctx = &cmd_flow_context;
11232 	const struct token *token;
11233 	const enum index *list;
11234 	int len;
11235 	int i;
11236 
11237 	(void)hdr;
11238 	token = &token_list[ctx->curr];
11239 	/* Check argument length. */
11240 	ctx->eol = 0;
11241 	ctx->last = 1;
11242 	for (len = 0; src[len]; ++len)
11243 		if (src[len] == '#' || isspace(src[len]))
11244 			break;
11245 	if (!len)
11246 		return -1;
11247 	/* Last argument and EOL detection. */
11248 	for (i = len; src[i]; ++i)
11249 		if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
11250 			break;
11251 		else if (!isspace(src[i])) {
11252 			ctx->last = 0;
11253 			break;
11254 		}
11255 	for (; src[i]; ++i)
11256 		if (src[i] == '\r' || src[i] == '\n') {
11257 			ctx->eol = 1;
11258 			break;
11259 		}
11260 	/* Initialize context if necessary. */
11261 	if (!ctx->next_num) {
11262 		if (!token->next)
11263 			return 0;
11264 		ctx->next[ctx->next_num++] = token->next[0];
11265 	}
11266 	/* Process argument through candidates. */
11267 	ctx->prev = ctx->curr;
11268 	list = ctx->next[ctx->next_num - 1];
11269 	for (i = 0; list[i]; ++i) {
11270 		const struct token *next = &token_list[list[i]];
11271 		int tmp;
11272 
11273 		ctx->curr = list[i];
11274 		if (next->call)
11275 			tmp = next->call(ctx, next, src, len, result, size);
11276 		else
11277 			tmp = parse_default(ctx, next, src, len, result, size);
11278 		if (tmp == -1 || tmp != len)
11279 			continue;
11280 		token = next;
11281 		break;
11282 	}
11283 	if (!list[i])
11284 		return -1;
11285 	--ctx->next_num;
11286 	/* Push subsequent tokens if any. */
11287 	if (token->next)
11288 		for (i = 0; token->next[i]; ++i) {
11289 			if (ctx->next_num == RTE_DIM(ctx->next))
11290 				return -1;
11291 			ctx->next[ctx->next_num++] = token->next[i];
11292 		}
11293 	/* Push arguments if any. */
11294 	if (token->args)
11295 		for (i = 0; token->args[i]; ++i) {
11296 			if (ctx->args_num == RTE_DIM(ctx->args))
11297 				return -1;
11298 			ctx->args[ctx->args_num++] = token->args[i];
11299 		}
11300 	return len;
11301 }
11302 
11303 int
11304 flow_parse(const char *src, void *result, unsigned int size,
11305 	   struct rte_flow_attr **attr,
11306 	   struct rte_flow_item **pattern, struct rte_flow_action **actions)
11307 {
11308 	int ret;
11309 	struct context saved_flow_ctx = cmd_flow_context;
11310 
11311 	cmd_flow_context_init(&cmd_flow_context);
11312 	do {
11313 		ret = cmd_flow_parse(NULL, src, result, size);
11314 		if (ret > 0) {
11315 			src += ret;
11316 			while (isspace(*src))
11317 				src++;
11318 		}
11319 	} while (ret > 0 && strlen(src));
11320 	cmd_flow_context = saved_flow_ctx;
11321 	*attr = &((struct buffer *)result)->args.vc.attr;
11322 	*pattern = ((struct buffer *)result)->args.vc.pattern;
11323 	*actions = ((struct buffer *)result)->args.vc.actions;
11324 	return (ret >= 0 && !strlen(src)) ? 0 : -1;
11325 }
11326 
11327 /** Return number of completion entries (cmdline API). */
11328 static int
11329 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
11330 {
11331 	struct context *ctx = &cmd_flow_context;
11332 	const struct token *token = &token_list[ctx->curr];
11333 	const enum index *list;
11334 	int i;
11335 
11336 	(void)hdr;
11337 	/* Count number of tokens in current list. */
11338 	if (ctx->next_num)
11339 		list = ctx->next[ctx->next_num - 1];
11340 	else
11341 		list = token->next[0];
11342 	for (i = 0; list[i]; ++i)
11343 		;
11344 	if (!i)
11345 		return 0;
11346 	/*
11347 	 * If there is a single token, use its completion callback, otherwise
11348 	 * return the number of entries.
11349 	 */
11350 	token = &token_list[list[0]];
11351 	if (i == 1 && token->comp) {
11352 		/* Save index for cmd_flow_get_help(). */
11353 		ctx->prev = list[0];
11354 		return token->comp(ctx, token, 0, NULL, 0);
11355 	}
11356 	return i;
11357 }
11358 
11359 /** Return a completion entry (cmdline API). */
11360 static int
11361 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
11362 			  char *dst, unsigned int size)
11363 {
11364 	struct context *ctx = &cmd_flow_context;
11365 	const struct token *token = &token_list[ctx->curr];
11366 	const enum index *list;
11367 	int i;
11368 
11369 	(void)hdr;
11370 	/* Count number of tokens in current list. */
11371 	if (ctx->next_num)
11372 		list = ctx->next[ctx->next_num - 1];
11373 	else
11374 		list = token->next[0];
11375 	for (i = 0; list[i]; ++i)
11376 		;
11377 	if (!i)
11378 		return -1;
11379 	/* If there is a single token, use its completion callback. */
11380 	token = &token_list[list[0]];
11381 	if (i == 1 && token->comp) {
11382 		/* Save index for cmd_flow_get_help(). */
11383 		ctx->prev = list[0];
11384 		return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
11385 	}
11386 	/* Otherwise make sure the index is valid and use defaults. */
11387 	if (index >= i)
11388 		return -1;
11389 	token = &token_list[list[index]];
11390 	strlcpy(dst, token->name, size);
11391 	/* Save index for cmd_flow_get_help(). */
11392 	ctx->prev = list[index];
11393 	return 0;
11394 }
11395 
11396 /** Populate help strings for current token (cmdline API). */
11397 static int
11398 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
11399 {
11400 	struct context *ctx = &cmd_flow_context;
11401 	const struct token *token = &token_list[ctx->prev];
11402 
11403 	(void)hdr;
11404 	if (!size)
11405 		return -1;
11406 	/* Set token type and update global help with details. */
11407 	strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
11408 	if (token->help)
11409 		cmd_flow.help_str = token->help;
11410 	else
11411 		cmd_flow.help_str = token->name;
11412 	return 0;
11413 }
11414 
11415 /** Token definition template (cmdline API). */
11416 static struct cmdline_token_hdr cmd_flow_token_hdr = {
11417 	.ops = &(struct cmdline_token_ops){
11418 		.parse = cmd_flow_parse,
11419 		.complete_get_nb = cmd_flow_complete_get_nb,
11420 		.complete_get_elt = cmd_flow_complete_get_elt,
11421 		.get_help = cmd_flow_get_help,
11422 	},
11423 	.offset = 0,
11424 };
11425 
11426 /** Populate the next dynamic token. */
11427 static void
11428 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
11429 	     cmdline_parse_token_hdr_t **hdr_inst)
11430 {
11431 	struct context *ctx = &cmd_flow_context;
11432 
11433 	/* Always reinitialize context before requesting the first token. */
11434 	if (!(hdr_inst - cmd_flow.tokens))
11435 		cmd_flow_context_init(ctx);
11436 	/* Return NULL when no more tokens are expected. */
11437 	if (!ctx->next_num && ctx->curr) {
11438 		*hdr = NULL;
11439 		return;
11440 	}
11441 	/* Determine if command should end here. */
11442 	if (ctx->eol && ctx->last && ctx->next_num) {
11443 		const enum index *list = ctx->next[ctx->next_num - 1];
11444 		int i;
11445 
11446 		for (i = 0; list[i]; ++i) {
11447 			if (list[i] != END)
11448 				continue;
11449 			*hdr = NULL;
11450 			return;
11451 		}
11452 	}
11453 	*hdr = &cmd_flow_token_hdr;
11454 }
11455 
11456 /** Dispatch parsed buffer to function calls. */
11457 static void
11458 cmd_flow_parsed(const struct buffer *in)
11459 {
11460 	switch (in->command) {
11461 	case INFO:
11462 		port_flow_get_info(in->port);
11463 		break;
11464 	case CONFIGURE:
11465 		port_flow_configure(in->port,
11466 				    &in->args.configure.port_attr,
11467 				    in->args.configure.nb_queue,
11468 				    &in->args.configure.queue_attr);
11469 		break;
11470 	case PATTERN_TEMPLATE_CREATE:
11471 		port_flow_pattern_template_create(in->port,
11472 				in->args.vc.pat_templ_id,
11473 				&((const struct rte_flow_pattern_template_attr) {
11474 					.relaxed_matching = in->args.vc.attr.reserved,
11475 					.ingress = in->args.vc.attr.ingress,
11476 					.egress = in->args.vc.attr.egress,
11477 					.transfer = in->args.vc.attr.transfer,
11478 				}),
11479 				in->args.vc.pattern);
11480 		break;
11481 	case PATTERN_TEMPLATE_DESTROY:
11482 		port_flow_pattern_template_destroy(in->port,
11483 				in->args.templ_destroy.template_id_n,
11484 				in->args.templ_destroy.template_id);
11485 		break;
11486 	case ACTIONS_TEMPLATE_CREATE:
11487 		port_flow_actions_template_create(in->port,
11488 				in->args.vc.act_templ_id,
11489 				&((const struct rte_flow_actions_template_attr) {
11490 					.ingress = in->args.vc.attr.ingress,
11491 					.egress = in->args.vc.attr.egress,
11492 					.transfer = in->args.vc.attr.transfer,
11493 				}),
11494 				in->args.vc.actions,
11495 				in->args.vc.masks);
11496 		break;
11497 	case ACTIONS_TEMPLATE_DESTROY:
11498 		port_flow_actions_template_destroy(in->port,
11499 				in->args.templ_destroy.template_id_n,
11500 				in->args.templ_destroy.template_id);
11501 		break;
11502 	case TABLE_CREATE:
11503 		port_flow_template_table_create(in->port, in->args.table.id,
11504 			&in->args.table.attr, in->args.table.pat_templ_id_n,
11505 			in->args.table.pat_templ_id, in->args.table.act_templ_id_n,
11506 			in->args.table.act_templ_id);
11507 		break;
11508 	case TABLE_DESTROY:
11509 		port_flow_template_table_destroy(in->port,
11510 					in->args.table_destroy.table_id_n,
11511 					in->args.table_destroy.table_id);
11512 		break;
11513 	case QUEUE_CREATE:
11514 		port_queue_flow_create(in->port, in->queue, in->postpone,
11515 			in->args.vc.table_id, in->args.vc.rule_id,
11516 			in->args.vc.pat_templ_id, in->args.vc.act_templ_id,
11517 			in->args.vc.pattern, in->args.vc.actions);
11518 		break;
11519 	case QUEUE_DESTROY:
11520 		port_queue_flow_destroy(in->port, in->queue, in->postpone,
11521 					in->args.destroy.rule_n,
11522 					in->args.destroy.rule);
11523 		break;
11524 	case PUSH:
11525 		port_queue_flow_push(in->port, in->queue);
11526 		break;
11527 	case PULL:
11528 		port_queue_flow_pull(in->port, in->queue);
11529 		break;
11530 	case QUEUE_AGED:
11531 		port_queue_flow_aged(in->port, in->queue,
11532 				     in->args.aged.destroy);
11533 		break;
11534 	case QUEUE_INDIRECT_ACTION_CREATE:
11535 		port_queue_action_handle_create(
11536 				in->port, in->queue, in->postpone,
11537 				in->args.vc.attr.group,
11538 				&((const struct rte_flow_indir_action_conf) {
11539 					.ingress = in->args.vc.attr.ingress,
11540 					.egress = in->args.vc.attr.egress,
11541 					.transfer = in->args.vc.attr.transfer,
11542 				}),
11543 				in->args.vc.actions);
11544 		break;
11545 	case QUEUE_INDIRECT_ACTION_DESTROY:
11546 		port_queue_action_handle_destroy(in->port,
11547 					   in->queue, in->postpone,
11548 					   in->args.ia_destroy.action_id_n,
11549 					   in->args.ia_destroy.action_id);
11550 		break;
11551 	case QUEUE_INDIRECT_ACTION_UPDATE:
11552 		port_queue_action_handle_update(in->port,
11553 						in->queue, in->postpone,
11554 						in->args.vc.attr.group,
11555 						in->args.vc.actions);
11556 		break;
11557 	case QUEUE_INDIRECT_ACTION_QUERY:
11558 		port_queue_action_handle_query(in->port,
11559 					       in->queue, in->postpone,
11560 					       in->args.ia.action_id);
11561 		break;
11562 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
11563 		port_queue_action_handle_query_update(in->port, in->queue,
11564 						      in->postpone,
11565 						      in->args.ia.action_id,
11566 						      in->args.ia.qu_mode,
11567 						      in->args.vc.actions);
11568 		break;
11569 	case INDIRECT_ACTION_CREATE:
11570 		port_action_handle_create(
11571 				in->port, in->args.vc.attr.group,
11572 				&((const struct rte_flow_indir_action_conf) {
11573 					.ingress = in->args.vc.attr.ingress,
11574 					.egress = in->args.vc.attr.egress,
11575 					.transfer = in->args.vc.attr.transfer,
11576 				}),
11577 				in->args.vc.actions);
11578 		break;
11579 	case INDIRECT_ACTION_DESTROY:
11580 		port_action_handle_destroy(in->port,
11581 					   in->args.ia_destroy.action_id_n,
11582 					   in->args.ia_destroy.action_id);
11583 		break;
11584 	case INDIRECT_ACTION_UPDATE:
11585 		port_action_handle_update(in->port, in->args.vc.attr.group,
11586 					  in->args.vc.actions);
11587 		break;
11588 	case INDIRECT_ACTION_QUERY:
11589 		port_action_handle_query(in->port, in->args.ia.action_id);
11590 		break;
11591 	case INDIRECT_ACTION_QUERY_UPDATE:
11592 		port_action_handle_query_update(in->port,
11593 						in->args.ia.action_id,
11594 						in->args.ia.qu_mode,
11595 						in->args.vc.actions);
11596 		break;
11597 	case VALIDATE:
11598 		port_flow_validate(in->port, &in->args.vc.attr,
11599 				   in->args.vc.pattern, in->args.vc.actions,
11600 				   &in->args.vc.tunnel_ops);
11601 		break;
11602 	case CREATE:
11603 		port_flow_create(in->port, &in->args.vc.attr,
11604 				 in->args.vc.pattern, in->args.vc.actions,
11605 				 &in->args.vc.tunnel_ops);
11606 		break;
11607 	case DESTROY:
11608 		port_flow_destroy(in->port, in->args.destroy.rule_n,
11609 				  in->args.destroy.rule);
11610 		break;
11611 	case FLUSH:
11612 		port_flow_flush(in->port);
11613 		break;
11614 	case DUMP_ONE:
11615 	case DUMP_ALL:
11616 		port_flow_dump(in->port, in->args.dump.mode,
11617 				in->args.dump.rule, in->args.dump.file);
11618 		break;
11619 	case QUERY:
11620 		port_flow_query(in->port, in->args.query.rule,
11621 				&in->args.query.action);
11622 		break;
11623 	case LIST:
11624 		port_flow_list(in->port, in->args.list.group_n,
11625 			       in->args.list.group);
11626 		break;
11627 	case ISOLATE:
11628 		port_flow_isolate(in->port, in->args.isolate.set);
11629 		break;
11630 	case AGED:
11631 		port_flow_aged(in->port, in->args.aged.destroy);
11632 		break;
11633 	case TUNNEL_CREATE:
11634 		port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
11635 		break;
11636 	case TUNNEL_DESTROY:
11637 		port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
11638 		break;
11639 	case TUNNEL_LIST:
11640 		port_flow_tunnel_list(in->port);
11641 		break;
11642 	case ACTION_POL_G:
11643 		port_meter_policy_add(in->port, in->args.policy.policy_id,
11644 					in->args.vc.actions);
11645 		break;
11646 	case FLEX_ITEM_CREATE:
11647 		flex_item_create(in->port, in->args.flex.token,
11648 				 in->args.flex.filename);
11649 		break;
11650 	case FLEX_ITEM_DESTROY:
11651 		flex_item_destroy(in->port, in->args.flex.token);
11652 		break;
11653 	default:
11654 		break;
11655 	}
11656 }
11657 
11658 /** Token generator and output processing callback (cmdline API). */
11659 static void
11660 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
11661 {
11662 	if (cl == NULL)
11663 		cmd_flow_tok(arg0, arg2);
11664 	else
11665 		cmd_flow_parsed(arg0);
11666 }
11667 
11668 /** Global parser instance (cmdline API). */
11669 cmdline_parse_inst_t cmd_flow = {
11670 	.f = cmd_flow_cb,
11671 	.data = NULL, /**< Unused. */
11672 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
11673 	.tokens = {
11674 		NULL,
11675 	}, /**< Tokens are returned by cmd_flow_tok(). */
11676 };
11677 
11678 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
11679 
11680 static void
11681 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
11682 {
11683 	struct rte_ipv4_hdr *ipv4;
11684 	struct rte_ether_hdr *eth;
11685 	struct rte_ipv6_hdr *ipv6;
11686 	struct rte_vxlan_hdr *vxlan;
11687 	struct rte_vxlan_gpe_hdr *gpe;
11688 	struct rte_flow_item_nvgre *nvgre;
11689 	uint32_t ipv6_vtc_flow;
11690 
11691 	switch (item->type) {
11692 	case RTE_FLOW_ITEM_TYPE_ETH:
11693 		eth = (struct rte_ether_hdr *)buf;
11694 		if (next_proto)
11695 			eth->ether_type = rte_cpu_to_be_16(next_proto);
11696 		break;
11697 	case RTE_FLOW_ITEM_TYPE_IPV4:
11698 		ipv4 = (struct rte_ipv4_hdr *)buf;
11699 		if (!ipv4->version_ihl)
11700 			ipv4->version_ihl = RTE_IPV4_VHL_DEF;
11701 		if (next_proto && ipv4->next_proto_id == 0)
11702 			ipv4->next_proto_id = (uint8_t)next_proto;
11703 		break;
11704 	case RTE_FLOW_ITEM_TYPE_IPV6:
11705 		ipv6 = (struct rte_ipv6_hdr *)buf;
11706 		if (next_proto && ipv6->proto == 0)
11707 			ipv6->proto = (uint8_t)next_proto;
11708 		ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
11709 		ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
11710 		ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
11711 		ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
11712 		break;
11713 	case RTE_FLOW_ITEM_TYPE_VXLAN:
11714 		vxlan = (struct rte_vxlan_hdr *)buf;
11715 		vxlan->vx_flags = 0x08;
11716 		break;
11717 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
11718 		gpe = (struct rte_vxlan_gpe_hdr *)buf;
11719 		gpe->vx_flags = 0x0C;
11720 		break;
11721 	case RTE_FLOW_ITEM_TYPE_NVGRE:
11722 		nvgre = (struct rte_flow_item_nvgre *)buf;
11723 		nvgre->protocol = rte_cpu_to_be_16(0x6558);
11724 		nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
11725 		break;
11726 	default:
11727 		break;
11728 	}
11729 }
11730 
11731 /** Helper of get item's default mask. */
11732 static const void *
11733 flow_item_default_mask(const struct rte_flow_item *item)
11734 {
11735 	const void *mask = NULL;
11736 	static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
11737 	static struct rte_flow_item_ipv6_routing_ext ipv6_routing_ext_default_mask = {
11738 		.hdr = {
11739 			.next_hdr = 0xff,
11740 			.type = 0xff,
11741 			.segments_left = 0xff,
11742 		},
11743 	};
11744 
11745 	switch (item->type) {
11746 	case RTE_FLOW_ITEM_TYPE_ANY:
11747 		mask = &rte_flow_item_any_mask;
11748 		break;
11749 	case RTE_FLOW_ITEM_TYPE_PORT_ID:
11750 		mask = &rte_flow_item_port_id_mask;
11751 		break;
11752 	case RTE_FLOW_ITEM_TYPE_RAW:
11753 		mask = &rte_flow_item_raw_mask;
11754 		break;
11755 	case RTE_FLOW_ITEM_TYPE_ETH:
11756 		mask = &rte_flow_item_eth_mask;
11757 		break;
11758 	case RTE_FLOW_ITEM_TYPE_VLAN:
11759 		mask = &rte_flow_item_vlan_mask;
11760 		break;
11761 	case RTE_FLOW_ITEM_TYPE_IPV4:
11762 		mask = &rte_flow_item_ipv4_mask;
11763 		break;
11764 	case RTE_FLOW_ITEM_TYPE_IPV6:
11765 		mask = &rte_flow_item_ipv6_mask;
11766 		break;
11767 	case RTE_FLOW_ITEM_TYPE_ICMP:
11768 		mask = &rte_flow_item_icmp_mask;
11769 		break;
11770 	case RTE_FLOW_ITEM_TYPE_UDP:
11771 		mask = &rte_flow_item_udp_mask;
11772 		break;
11773 	case RTE_FLOW_ITEM_TYPE_TCP:
11774 		mask = &rte_flow_item_tcp_mask;
11775 		break;
11776 	case RTE_FLOW_ITEM_TYPE_SCTP:
11777 		mask = &rte_flow_item_sctp_mask;
11778 		break;
11779 	case RTE_FLOW_ITEM_TYPE_VXLAN:
11780 		mask = &rte_flow_item_vxlan_mask;
11781 		break;
11782 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
11783 		mask = &rte_flow_item_vxlan_gpe_mask;
11784 		break;
11785 	case RTE_FLOW_ITEM_TYPE_E_TAG:
11786 		mask = &rte_flow_item_e_tag_mask;
11787 		break;
11788 	case RTE_FLOW_ITEM_TYPE_NVGRE:
11789 		mask = &rte_flow_item_nvgre_mask;
11790 		break;
11791 	case RTE_FLOW_ITEM_TYPE_MPLS:
11792 		mask = &rte_flow_item_mpls_mask;
11793 		break;
11794 	case RTE_FLOW_ITEM_TYPE_GRE:
11795 		mask = &rte_flow_item_gre_mask;
11796 		break;
11797 	case RTE_FLOW_ITEM_TYPE_GRE_KEY:
11798 		mask = &gre_key_default_mask;
11799 		break;
11800 	case RTE_FLOW_ITEM_TYPE_META:
11801 		mask = &rte_flow_item_meta_mask;
11802 		break;
11803 	case RTE_FLOW_ITEM_TYPE_FUZZY:
11804 		mask = &rte_flow_item_fuzzy_mask;
11805 		break;
11806 	case RTE_FLOW_ITEM_TYPE_GTP:
11807 		mask = &rte_flow_item_gtp_mask;
11808 		break;
11809 	case RTE_FLOW_ITEM_TYPE_GTP_PSC:
11810 		mask = &rte_flow_item_gtp_psc_mask;
11811 		break;
11812 	case RTE_FLOW_ITEM_TYPE_GENEVE:
11813 		mask = &rte_flow_item_geneve_mask;
11814 		break;
11815 	case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
11816 		mask = &rte_flow_item_geneve_opt_mask;
11817 		break;
11818 	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
11819 		mask = &rte_flow_item_pppoe_proto_id_mask;
11820 		break;
11821 	case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
11822 		mask = &rte_flow_item_l2tpv3oip_mask;
11823 		break;
11824 	case RTE_FLOW_ITEM_TYPE_ESP:
11825 		mask = &rte_flow_item_esp_mask;
11826 		break;
11827 	case RTE_FLOW_ITEM_TYPE_AH:
11828 		mask = &rte_flow_item_ah_mask;
11829 		break;
11830 	case RTE_FLOW_ITEM_TYPE_PFCP:
11831 		mask = &rte_flow_item_pfcp_mask;
11832 		break;
11833 	case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
11834 	case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
11835 		mask = &rte_flow_item_ethdev_mask;
11836 		break;
11837 	case RTE_FLOW_ITEM_TYPE_L2TPV2:
11838 		mask = &rte_flow_item_l2tpv2_mask;
11839 		break;
11840 	case RTE_FLOW_ITEM_TYPE_PPP:
11841 		mask = &rte_flow_item_ppp_mask;
11842 		break;
11843 	case RTE_FLOW_ITEM_TYPE_METER_COLOR:
11844 		mask = &rte_flow_item_meter_color_mask;
11845 		break;
11846 	case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
11847 		mask = &ipv6_routing_ext_default_mask;
11848 		break;
11849 	case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
11850 		mask = &rte_flow_item_aggr_affinity_mask;
11851 		break;
11852 	default:
11853 		break;
11854 	}
11855 	return mask;
11856 }
11857 
11858 /** Dispatch parsed buffer to function calls. */
11859 static void
11860 cmd_set_raw_parsed_sample(const struct buffer *in)
11861 {
11862 	uint32_t n = in->args.vc.actions_n;
11863 	uint32_t i = 0;
11864 	struct rte_flow_action *action = NULL;
11865 	struct rte_flow_action *data = NULL;
11866 	const struct rte_flow_action_rss *rss = NULL;
11867 	size_t size = 0;
11868 	uint16_t idx = in->port; /* We borrow port field as index */
11869 	uint32_t max_size = sizeof(struct rte_flow_action) *
11870 						ACTION_SAMPLE_ACTIONS_NUM;
11871 
11872 	RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
11873 	data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
11874 	memset(data, 0x00, max_size);
11875 	for (; i <= n - 1; i++) {
11876 		action = in->args.vc.actions + i;
11877 		if (action->type == RTE_FLOW_ACTION_TYPE_END)
11878 			break;
11879 		switch (action->type) {
11880 		case RTE_FLOW_ACTION_TYPE_MARK:
11881 			size = sizeof(struct rte_flow_action_mark);
11882 			rte_memcpy(&sample_mark[idx],
11883 				(const void *)action->conf, size);
11884 			action->conf = &sample_mark[idx];
11885 			break;
11886 		case RTE_FLOW_ACTION_TYPE_COUNT:
11887 			size = sizeof(struct rte_flow_action_count);
11888 			rte_memcpy(&sample_count[idx],
11889 				(const void *)action->conf, size);
11890 			action->conf = &sample_count[idx];
11891 			break;
11892 		case RTE_FLOW_ACTION_TYPE_QUEUE:
11893 			size = sizeof(struct rte_flow_action_queue);
11894 			rte_memcpy(&sample_queue[idx],
11895 				(const void *)action->conf, size);
11896 			action->conf = &sample_queue[idx];
11897 			break;
11898 		case RTE_FLOW_ACTION_TYPE_RSS:
11899 			size = sizeof(struct rte_flow_action_rss);
11900 			rss = action->conf;
11901 			rte_memcpy(&sample_rss_data[idx].conf,
11902 				   (const void *)rss, size);
11903 			if (rss->key_len && rss->key) {
11904 				sample_rss_data[idx].conf.key =
11905 						sample_rss_data[idx].key;
11906 				rte_memcpy((void *)((uintptr_t)
11907 					   sample_rss_data[idx].conf.key),
11908 					   (const void *)rss->key,
11909 					   sizeof(uint8_t) * rss->key_len);
11910 			}
11911 			if (rss->queue_num && rss->queue) {
11912 				sample_rss_data[idx].conf.queue =
11913 						sample_rss_data[idx].queue;
11914 				rte_memcpy((void *)((uintptr_t)
11915 					   sample_rss_data[idx].conf.queue),
11916 					   (const void *)rss->queue,
11917 					   sizeof(uint16_t) * rss->queue_num);
11918 			}
11919 			action->conf = &sample_rss_data[idx].conf;
11920 			break;
11921 		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
11922 			size = sizeof(struct rte_flow_action_raw_encap);
11923 			rte_memcpy(&sample_encap[idx],
11924 				(const void *)action->conf, size);
11925 			action->conf = &sample_encap[idx];
11926 			break;
11927 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
11928 			size = sizeof(struct rte_flow_action_port_id);
11929 			rte_memcpy(&sample_port_id[idx],
11930 				(const void *)action->conf, size);
11931 			action->conf = &sample_port_id[idx];
11932 			break;
11933 		case RTE_FLOW_ACTION_TYPE_PF:
11934 			break;
11935 		case RTE_FLOW_ACTION_TYPE_VF:
11936 			size = sizeof(struct rte_flow_action_vf);
11937 			rte_memcpy(&sample_vf[idx],
11938 					(const void *)action->conf, size);
11939 			action->conf = &sample_vf[idx];
11940 			break;
11941 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
11942 			size = sizeof(struct rte_flow_action_vxlan_encap);
11943 			parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
11944 			action->conf = &sample_vxlan_encap[idx].conf;
11945 			break;
11946 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
11947 			size = sizeof(struct rte_flow_action_nvgre_encap);
11948 			parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
11949 			action->conf = &sample_nvgre_encap[idx];
11950 			break;
11951 		case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
11952 			size = sizeof(struct rte_flow_action_ethdev);
11953 			rte_memcpy(&sample_port_representor[idx],
11954 					(const void *)action->conf, size);
11955 			action->conf = &sample_port_representor[idx];
11956 			break;
11957 		case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
11958 			size = sizeof(struct rte_flow_action_ethdev);
11959 			rte_memcpy(&sample_represented_port[idx],
11960 					(const void *)action->conf, size);
11961 			action->conf = &sample_represented_port[idx];
11962 			break;
11963 		default:
11964 			fprintf(stderr, "Error - Not supported action\n");
11965 			return;
11966 		}
11967 		rte_memcpy(data, action, sizeof(struct rte_flow_action));
11968 		data++;
11969 	}
11970 }
11971 
11972 /** Dispatch parsed buffer to function calls. */
11973 static void
11974 cmd_set_raw_parsed(const struct buffer *in)
11975 {
11976 	uint32_t n = in->args.vc.pattern_n;
11977 	int i = 0;
11978 	struct rte_flow_item *item = NULL;
11979 	size_t size = 0;
11980 	uint8_t *data = NULL;
11981 	uint8_t *data_tail = NULL;
11982 	size_t *total_size = NULL;
11983 	uint16_t upper_layer = 0;
11984 	uint16_t proto = 0;
11985 	uint16_t idx = in->port; /* We borrow port field as index */
11986 	int gtp_psc = -1; /* GTP PSC option index. */
11987 	const void *src_spec;
11988 
11989 	if (in->command == SET_SAMPLE_ACTIONS)
11990 		return cmd_set_raw_parsed_sample(in);
11991 	RTE_ASSERT(in->command == SET_RAW_ENCAP ||
11992 		   in->command == SET_RAW_DECAP);
11993 	if (in->command == SET_RAW_ENCAP) {
11994 		total_size = &raw_encap_confs[idx].size;
11995 		data = (uint8_t *)&raw_encap_confs[idx].data;
11996 	} else {
11997 		total_size = &raw_decap_confs[idx].size;
11998 		data = (uint8_t *)&raw_decap_confs[idx].data;
11999 	}
12000 	*total_size = 0;
12001 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
12002 	/* process hdr from upper layer to low layer (L3/L4 -> L2). */
12003 	data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
12004 	for (i = n - 1 ; i >= 0; --i) {
12005 		const struct rte_flow_item_gtp *gtp;
12006 		const struct rte_flow_item_geneve_opt *opt;
12007 		struct rte_flow_item_ipv6_routing_ext *ext;
12008 
12009 		item = in->args.vc.pattern + i;
12010 		if (item->spec == NULL)
12011 			item->spec = flow_item_default_mask(item);
12012 		src_spec = item->spec;
12013 		switch (item->type) {
12014 		case RTE_FLOW_ITEM_TYPE_ETH:
12015 			size = sizeof(struct rte_ether_hdr);
12016 			break;
12017 		case RTE_FLOW_ITEM_TYPE_VLAN:
12018 			size = sizeof(struct rte_vlan_hdr);
12019 			proto = RTE_ETHER_TYPE_VLAN;
12020 			break;
12021 		case RTE_FLOW_ITEM_TYPE_IPV4:
12022 			size = sizeof(struct rte_ipv4_hdr);
12023 			proto = RTE_ETHER_TYPE_IPV4;
12024 			break;
12025 		case RTE_FLOW_ITEM_TYPE_IPV6:
12026 			size = sizeof(struct rte_ipv6_hdr);
12027 			proto = RTE_ETHER_TYPE_IPV6;
12028 			break;
12029 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
12030 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
12031 			if (!ext->hdr.hdr_len) {
12032 				size = sizeof(struct rte_ipv6_routing_ext) +
12033 					(ext->hdr.segments_left << 4);
12034 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
12035 			} else {
12036 				size = sizeof(struct rte_ipv6_routing_ext) +
12037 					(ext->hdr.hdr_len << 3);
12038 			}
12039 			proto = IPPROTO_ROUTING;
12040 			break;
12041 		case RTE_FLOW_ITEM_TYPE_UDP:
12042 			size = sizeof(struct rte_udp_hdr);
12043 			proto = 0x11;
12044 			break;
12045 		case RTE_FLOW_ITEM_TYPE_TCP:
12046 			size = sizeof(struct rte_tcp_hdr);
12047 			proto = 0x06;
12048 			break;
12049 		case RTE_FLOW_ITEM_TYPE_VXLAN:
12050 			size = sizeof(struct rte_vxlan_hdr);
12051 			break;
12052 		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
12053 			size = sizeof(struct rte_vxlan_gpe_hdr);
12054 			break;
12055 		case RTE_FLOW_ITEM_TYPE_GRE:
12056 			size = sizeof(struct rte_gre_hdr);
12057 			proto = 0x2F;
12058 			break;
12059 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
12060 			size = sizeof(rte_be32_t);
12061 			proto = 0x0;
12062 			break;
12063 		case RTE_FLOW_ITEM_TYPE_MPLS:
12064 			size = sizeof(struct rte_mpls_hdr);
12065 			proto = 0x0;
12066 			break;
12067 		case RTE_FLOW_ITEM_TYPE_NVGRE:
12068 			size = sizeof(struct rte_flow_item_nvgre);
12069 			proto = 0x2F;
12070 			break;
12071 		case RTE_FLOW_ITEM_TYPE_GENEVE:
12072 			size = sizeof(struct rte_geneve_hdr);
12073 			break;
12074 		case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
12075 			opt = (const struct rte_flow_item_geneve_opt *)
12076 								item->spec;
12077 			size = offsetof(struct rte_flow_item_geneve_opt,
12078 					option_len) + sizeof(uint8_t);
12079 			if (opt->option_len && opt->data) {
12080 				*total_size += opt->option_len *
12081 					       sizeof(uint32_t);
12082 				rte_memcpy(data_tail - (*total_size),
12083 					   opt->data,
12084 					   opt->option_len * sizeof(uint32_t));
12085 			}
12086 			break;
12087 		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
12088 			size = sizeof(rte_be32_t);
12089 			proto = 0x73;
12090 			break;
12091 		case RTE_FLOW_ITEM_TYPE_ESP:
12092 			size = sizeof(struct rte_esp_hdr);
12093 			proto = 0x32;
12094 			break;
12095 		case RTE_FLOW_ITEM_TYPE_AH:
12096 			size = sizeof(struct rte_flow_item_ah);
12097 			proto = 0x33;
12098 			break;
12099 		case RTE_FLOW_ITEM_TYPE_GTP:
12100 			if (gtp_psc < 0) {
12101 				size = sizeof(struct rte_gtp_hdr);
12102 				break;
12103 			}
12104 			if (gtp_psc != i + 1) {
12105 				fprintf(stderr,
12106 					"Error - GTP PSC does not follow GTP\n");
12107 				goto error;
12108 			}
12109 			gtp = item->spec;
12110 			if (gtp->hdr.s == 1 || gtp->hdr.pn == 1) {
12111 				/* Only E flag should be set. */
12112 				fprintf(stderr,
12113 					"Error - GTP unsupported flags\n");
12114 				goto error;
12115 			} else {
12116 				struct rte_gtp_hdr_ext_word ext_word = {
12117 					.next_ext = 0x85
12118 				};
12119 
12120 				/* We have to add GTP header extra word. */
12121 				*total_size += sizeof(ext_word);
12122 				rte_memcpy(data_tail - (*total_size),
12123 					   &ext_word, sizeof(ext_word));
12124 			}
12125 			size = sizeof(struct rte_gtp_hdr);
12126 			break;
12127 		case RTE_FLOW_ITEM_TYPE_GTP_PSC:
12128 			if (gtp_psc >= 0) {
12129 				fprintf(stderr,
12130 					"Error - Multiple GTP PSC items\n");
12131 				goto error;
12132 			} else {
12133 				const struct rte_flow_item_gtp_psc
12134 					*opt = item->spec;
12135 				struct rte_gtp_psc_generic_hdr *hdr;
12136 				size_t hdr_size = RTE_ALIGN(sizeof(*hdr),
12137 							 sizeof(int32_t));
12138 
12139 				*total_size += hdr_size;
12140 				hdr = (typeof(hdr))(data_tail - (*total_size));
12141 				memset(hdr, 0, hdr_size);
12142 				*hdr = opt->hdr;
12143 				hdr->ext_hdr_len = 1;
12144 				gtp_psc = i;
12145 				size = 0;
12146 			}
12147 			break;
12148 		case RTE_FLOW_ITEM_TYPE_PFCP:
12149 			size = sizeof(struct rte_flow_item_pfcp);
12150 			break;
12151 		case RTE_FLOW_ITEM_TYPE_FLEX:
12152 			if (item->spec != NULL) {
12153 				size = ((const struct rte_flow_item_flex *)item->spec)->length;
12154 				src_spec = ((const struct rte_flow_item_flex *)item->spec)->pattern;
12155 			} else {
12156 				size = 0;
12157 				src_spec = NULL;
12158 			}
12159 			break;
12160 		case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
12161 			size = 0;
12162 			if (item->spec) {
12163 				const struct rte_flow_item_gre_opt
12164 					*opt = item->spec;
12165 				if (opt->checksum_rsvd.checksum) {
12166 					*total_size +=
12167 						sizeof(opt->checksum_rsvd);
12168 					rte_memcpy(data_tail - (*total_size),
12169 						   &opt->checksum_rsvd,
12170 						   sizeof(opt->checksum_rsvd));
12171 				}
12172 				if (opt->key.key) {
12173 					*total_size += sizeof(opt->key.key);
12174 					rte_memcpy(data_tail - (*total_size),
12175 						   &opt->key.key,
12176 						   sizeof(opt->key.key));
12177 				}
12178 				if (opt->sequence.sequence) {
12179 					*total_size += sizeof(opt->sequence.sequence);
12180 					rte_memcpy(data_tail - (*total_size),
12181 						   &opt->sequence.sequence,
12182 						   sizeof(opt->sequence.sequence));
12183 				}
12184 			}
12185 			proto = 0x2F;
12186 			break;
12187 		default:
12188 			fprintf(stderr, "Error - Not supported item\n");
12189 			goto error;
12190 		}
12191 		if (size) {
12192 			*total_size += size;
12193 			rte_memcpy(data_tail - (*total_size), src_spec, size);
12194 			/* update some fields which cannot be set by cmdline */
12195 			update_fields((data_tail - (*total_size)), item,
12196 				      upper_layer);
12197 			upper_layer = proto;
12198 		}
12199 	}
12200 	if (verbose_level & 0x1)
12201 		printf("total data size is %zu\n", (*total_size));
12202 	RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
12203 	memmove(data, (data_tail - (*total_size)), *total_size);
12204 	return;
12205 
12206 error:
12207 	*total_size = 0;
12208 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
12209 }
12210 
12211 /** Populate help strings for current token (cmdline API). */
12212 static int
12213 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
12214 		     unsigned int size)
12215 {
12216 	struct context *ctx = &cmd_flow_context;
12217 	const struct token *token = &token_list[ctx->prev];
12218 
12219 	(void)hdr;
12220 	if (!size)
12221 		return -1;
12222 	/* Set token type and update global help with details. */
12223 	snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
12224 	if (token->help)
12225 		cmd_set_raw.help_str = token->help;
12226 	else
12227 		cmd_set_raw.help_str = token->name;
12228 	return 0;
12229 }
12230 
12231 /** Token definition template (cmdline API). */
12232 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
12233 	.ops = &(struct cmdline_token_ops){
12234 		.parse = cmd_flow_parse,
12235 		.complete_get_nb = cmd_flow_complete_get_nb,
12236 		.complete_get_elt = cmd_flow_complete_get_elt,
12237 		.get_help = cmd_set_raw_get_help,
12238 	},
12239 	.offset = 0,
12240 };
12241 
12242 /** Populate the next dynamic token. */
12243 static void
12244 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
12245 	     cmdline_parse_token_hdr_t **hdr_inst)
12246 {
12247 	struct context *ctx = &cmd_flow_context;
12248 
12249 	/* Always reinitialize context before requesting the first token. */
12250 	if (!(hdr_inst - cmd_set_raw.tokens)) {
12251 		cmd_flow_context_init(ctx);
12252 		ctx->curr = START_SET;
12253 	}
12254 	/* Return NULL when no more tokens are expected. */
12255 	if (!ctx->next_num && (ctx->curr != START_SET)) {
12256 		*hdr = NULL;
12257 		return;
12258 	}
12259 	/* Determine if command should end here. */
12260 	if (ctx->eol && ctx->last && ctx->next_num) {
12261 		const enum index *list = ctx->next[ctx->next_num - 1];
12262 		int i;
12263 
12264 		for (i = 0; list[i]; ++i) {
12265 			if (list[i] != END)
12266 				continue;
12267 			*hdr = NULL;
12268 			return;
12269 		}
12270 	}
12271 	*hdr = &cmd_set_raw_token_hdr;
12272 }
12273 
12274 /** Token generator and output processing callback (cmdline API). */
12275 static void
12276 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
12277 {
12278 	if (cl == NULL)
12279 		cmd_set_raw_tok(arg0, arg2);
12280 	else
12281 		cmd_set_raw_parsed(arg0);
12282 }
12283 
12284 /** Global parser instance (cmdline API). */
12285 cmdline_parse_inst_t cmd_set_raw = {
12286 	.f = cmd_set_raw_cb,
12287 	.data = NULL, /**< Unused. */
12288 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
12289 	.tokens = {
12290 		NULL,
12291 	}, /**< Tokens are returned by cmd_flow_tok(). */
12292 };
12293 
12294 /* *** display raw_encap/raw_decap buf */
12295 struct cmd_show_set_raw_result {
12296 	cmdline_fixed_string_t cmd_show;
12297 	cmdline_fixed_string_t cmd_what;
12298 	cmdline_fixed_string_t cmd_all;
12299 	uint16_t cmd_index;
12300 };
12301 
12302 static void
12303 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
12304 {
12305 	struct cmd_show_set_raw_result *res = parsed_result;
12306 	uint16_t index = res->cmd_index;
12307 	uint8_t all = 0;
12308 	uint8_t *raw_data = NULL;
12309 	size_t raw_size = 0;
12310 	char title[16] = {0};
12311 
12312 	RTE_SET_USED(cl);
12313 	RTE_SET_USED(data);
12314 	if (!strcmp(res->cmd_all, "all")) {
12315 		all = 1;
12316 		index = 0;
12317 	} else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
12318 		fprintf(stderr, "index should be 0-%u\n",
12319 			RAW_ENCAP_CONFS_MAX_NUM - 1);
12320 		return;
12321 	}
12322 	do {
12323 		if (!strcmp(res->cmd_what, "raw_encap")) {
12324 			raw_data = (uint8_t *)&raw_encap_confs[index].data;
12325 			raw_size = raw_encap_confs[index].size;
12326 			snprintf(title, 16, "\nindex: %u", index);
12327 			rte_hexdump(stdout, title, raw_data, raw_size);
12328 		} else {
12329 			raw_data = (uint8_t *)&raw_decap_confs[index].data;
12330 			raw_size = raw_decap_confs[index].size;
12331 			snprintf(title, 16, "\nindex: %u", index);
12332 			rte_hexdump(stdout, title, raw_data, raw_size);
12333 		}
12334 	} while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
12335 }
12336 
12337 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
12338 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
12339 			cmd_show, "show");
12340 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
12341 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
12342 			cmd_what, "raw_encap#raw_decap");
12343 static cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
12344 	TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
12345 			cmd_index, RTE_UINT16);
12346 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
12347 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
12348 			cmd_all, "all");
12349 cmdline_parse_inst_t cmd_show_set_raw = {
12350 	.f = cmd_show_set_raw_parsed,
12351 	.data = NULL,
12352 	.help_str = "show <raw_encap|raw_decap> <index>",
12353 	.tokens = {
12354 		(void *)&cmd_show_set_raw_cmd_show,
12355 		(void *)&cmd_show_set_raw_cmd_what,
12356 		(void *)&cmd_show_set_raw_cmd_index,
12357 		NULL,
12358 	},
12359 };
12360 cmdline_parse_inst_t cmd_show_set_raw_all = {
12361 	.f = cmd_show_set_raw_parsed,
12362 	.data = NULL,
12363 	.help_str = "show <raw_encap|raw_decap> all",
12364 	.tokens = {
12365 		(void *)&cmd_show_set_raw_cmd_show,
12366 		(void *)&cmd_show_set_raw_cmd_what,
12367 		(void *)&cmd_show_set_raw_cmd_all,
12368 		NULL,
12369 	},
12370 };
12371