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