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