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