xref: /dpdk/app/test-pmd/cmdline_flow.c (revision 9733f0995e1cfc16ee2e13b4dfb620e600e1a6ec)
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 	HASH_CALC_ENCAP,
223 	HASH_CALC_DEST,
224 	ENCAP_HASH_FIELD_SRC_PORT,
225 	ENCAP_HASH_FIELD_GRE_FLOW_ID,
226 
227 	/* Tunnel arguments. */
228 	TUNNEL_CREATE,
229 	TUNNEL_CREATE_TYPE,
230 	TUNNEL_LIST,
231 	TUNNEL_DESTROY,
232 	TUNNEL_DESTROY_ID,
233 
234 	/* Destroy arguments. */
235 	DESTROY_RULE,
236 	DESTROY_IS_USER_ID,
237 
238 	/* Query arguments. */
239 	QUERY_ACTION,
240 	QUERY_IS_USER_ID,
241 
242 	/* List arguments. */
243 	LIST_GROUP,
244 
245 	/* Destroy aged flow arguments. */
246 	AGED_DESTROY,
247 
248 	/* Validate/create arguments. */
249 	VC_GROUP,
250 	VC_PRIORITY,
251 	VC_INGRESS,
252 	VC_EGRESS,
253 	VC_TRANSFER,
254 	VC_TUNNEL_SET,
255 	VC_TUNNEL_MATCH,
256 	VC_USER_ID,
257 
258 	/* Dump arguments */
259 	DUMP_ALL,
260 	DUMP_ONE,
261 	DUMP_IS_USER_ID,
262 
263 	/* Configure arguments */
264 	CONFIG_QUEUES_NUMBER,
265 	CONFIG_QUEUES_SIZE,
266 	CONFIG_COUNTERS_NUMBER,
267 	CONFIG_AGING_OBJECTS_NUMBER,
268 	CONFIG_METERS_NUMBER,
269 	CONFIG_CONN_TRACK_NUMBER,
270 	CONFIG_QUOTAS_NUMBER,
271 	CONFIG_FLAGS,
272 	CONFIG_HOST_PORT,
273 
274 	/* Indirect action arguments */
275 	INDIRECT_ACTION_CREATE,
276 	INDIRECT_ACTION_LIST_CREATE,
277 	INDIRECT_ACTION_FLOW_CONF_CREATE,
278 	INDIRECT_ACTION_UPDATE,
279 	INDIRECT_ACTION_DESTROY,
280 	INDIRECT_ACTION_QUERY,
281 	INDIRECT_ACTION_QUERY_UPDATE,
282 
283 	/* Indirect action create arguments */
284 	INDIRECT_ACTION_CREATE_ID,
285 	INDIRECT_ACTION_INGRESS,
286 	INDIRECT_ACTION_EGRESS,
287 	INDIRECT_ACTION_TRANSFER,
288 	INDIRECT_ACTION_SPEC,
289 	INDIRECT_ACTION_LIST,
290 	INDIRECT_ACTION_FLOW_CONF,
291 
292 	/* Indirect action destroy arguments */
293 	INDIRECT_ACTION_DESTROY_ID,
294 
295 	/* Indirect action query-and-update arguments */
296 	INDIRECT_ACTION_QU_MODE,
297 	INDIRECT_ACTION_QU_MODE_NAME,
298 
299 	/* Validate/create pattern. */
300 	ITEM_PATTERN,
301 	ITEM_PARAM_IS,
302 	ITEM_PARAM_SPEC,
303 	ITEM_PARAM_LAST,
304 	ITEM_PARAM_MASK,
305 	ITEM_PARAM_PREFIX,
306 	ITEM_NEXT,
307 	ITEM_END,
308 	ITEM_VOID,
309 	ITEM_INVERT,
310 	ITEM_ANY,
311 	ITEM_ANY_NUM,
312 	ITEM_PORT_ID,
313 	ITEM_PORT_ID_ID,
314 	ITEM_MARK,
315 	ITEM_MARK_ID,
316 	ITEM_RAW,
317 	ITEM_RAW_RELATIVE,
318 	ITEM_RAW_SEARCH,
319 	ITEM_RAW_OFFSET,
320 	ITEM_RAW_LIMIT,
321 	ITEM_RAW_PATTERN,
322 	ITEM_RAW_PATTERN_HEX,
323 	ITEM_ETH,
324 	ITEM_ETH_DST,
325 	ITEM_ETH_SRC,
326 	ITEM_ETH_TYPE,
327 	ITEM_ETH_HAS_VLAN,
328 	ITEM_VLAN,
329 	ITEM_VLAN_TCI,
330 	ITEM_VLAN_PCP,
331 	ITEM_VLAN_DEI,
332 	ITEM_VLAN_VID,
333 	ITEM_VLAN_INNER_TYPE,
334 	ITEM_VLAN_HAS_MORE_VLAN,
335 	ITEM_IPV4,
336 	ITEM_IPV4_VER_IHL,
337 	ITEM_IPV4_TOS,
338 	ITEM_IPV4_LENGTH,
339 	ITEM_IPV4_ID,
340 	ITEM_IPV4_FRAGMENT_OFFSET,
341 	ITEM_IPV4_TTL,
342 	ITEM_IPV4_PROTO,
343 	ITEM_IPV4_SRC,
344 	ITEM_IPV4_DST,
345 	ITEM_IPV6,
346 	ITEM_IPV6_TC,
347 	ITEM_IPV6_FLOW,
348 	ITEM_IPV6_LEN,
349 	ITEM_IPV6_PROTO,
350 	ITEM_IPV6_HOP,
351 	ITEM_IPV6_SRC,
352 	ITEM_IPV6_DST,
353 	ITEM_IPV6_HAS_FRAG_EXT,
354 	ITEM_IPV6_ROUTING_EXT,
355 	ITEM_IPV6_ROUTING_EXT_TYPE,
356 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
357 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
358 	ITEM_ICMP,
359 	ITEM_ICMP_TYPE,
360 	ITEM_ICMP_CODE,
361 	ITEM_ICMP_IDENT,
362 	ITEM_ICMP_SEQ,
363 	ITEM_UDP,
364 	ITEM_UDP_SRC,
365 	ITEM_UDP_DST,
366 	ITEM_TCP,
367 	ITEM_TCP_SRC,
368 	ITEM_TCP_DST,
369 	ITEM_TCP_FLAGS,
370 	ITEM_SCTP,
371 	ITEM_SCTP_SRC,
372 	ITEM_SCTP_DST,
373 	ITEM_SCTP_TAG,
374 	ITEM_SCTP_CKSUM,
375 	ITEM_VXLAN,
376 	ITEM_VXLAN_VNI,
377 	ITEM_VXLAN_LAST_RSVD,
378 	ITEM_E_TAG,
379 	ITEM_E_TAG_GRP_ECID_B,
380 	ITEM_NVGRE,
381 	ITEM_NVGRE_TNI,
382 	ITEM_MPLS,
383 	ITEM_MPLS_LABEL,
384 	ITEM_MPLS_TC,
385 	ITEM_MPLS_S,
386 	ITEM_MPLS_TTL,
387 	ITEM_GRE,
388 	ITEM_GRE_PROTO,
389 	ITEM_GRE_C_RSVD0_VER,
390 	ITEM_GRE_C_BIT,
391 	ITEM_GRE_K_BIT,
392 	ITEM_GRE_S_BIT,
393 	ITEM_FUZZY,
394 	ITEM_FUZZY_THRESH,
395 	ITEM_GTP,
396 	ITEM_GTP_FLAGS,
397 	ITEM_GTP_MSG_TYPE,
398 	ITEM_GTP_TEID,
399 	ITEM_GTPC,
400 	ITEM_GTPU,
401 	ITEM_GENEVE,
402 	ITEM_GENEVE_VNI,
403 	ITEM_GENEVE_PROTO,
404 	ITEM_GENEVE_OPTLEN,
405 	ITEM_VXLAN_GPE,
406 	ITEM_VXLAN_GPE_VNI,
407 	ITEM_VXLAN_GPE_PROTO,
408 	ITEM_ARP_ETH_IPV4,
409 	ITEM_ARP_ETH_IPV4_SHA,
410 	ITEM_ARP_ETH_IPV4_SPA,
411 	ITEM_ARP_ETH_IPV4_THA,
412 	ITEM_ARP_ETH_IPV4_TPA,
413 	ITEM_IPV6_EXT,
414 	ITEM_IPV6_EXT_NEXT_HDR,
415 	ITEM_IPV6_FRAG_EXT,
416 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
417 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
418 	ITEM_IPV6_FRAG_EXT_ID,
419 	ITEM_ICMP6,
420 	ITEM_ICMP6_TYPE,
421 	ITEM_ICMP6_CODE,
422 	ITEM_ICMP6_ECHO_REQUEST,
423 	ITEM_ICMP6_ECHO_REQUEST_ID,
424 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
425 	ITEM_ICMP6_ECHO_REPLY,
426 	ITEM_ICMP6_ECHO_REPLY_ID,
427 	ITEM_ICMP6_ECHO_REPLY_SEQ,
428 	ITEM_ICMP6_ND_NS,
429 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
430 	ITEM_ICMP6_ND_NA,
431 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
432 	ITEM_ICMP6_ND_OPT,
433 	ITEM_ICMP6_ND_OPT_TYPE,
434 	ITEM_ICMP6_ND_OPT_SLA_ETH,
435 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
436 	ITEM_ICMP6_ND_OPT_TLA_ETH,
437 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
438 	ITEM_META,
439 	ITEM_META_DATA,
440 	ITEM_RANDOM,
441 	ITEM_RANDOM_VALUE,
442 	ITEM_GRE_KEY,
443 	ITEM_GRE_KEY_VALUE,
444 	ITEM_GRE_OPTION,
445 	ITEM_GRE_OPTION_CHECKSUM,
446 	ITEM_GRE_OPTION_KEY,
447 	ITEM_GRE_OPTION_SEQUENCE,
448 	ITEM_GTP_PSC,
449 	ITEM_GTP_PSC_QFI,
450 	ITEM_GTP_PSC_PDU_T,
451 	ITEM_PPPOES,
452 	ITEM_PPPOED,
453 	ITEM_PPPOE_SEID,
454 	ITEM_PPPOE_PROTO_ID,
455 	ITEM_HIGIG2,
456 	ITEM_HIGIG2_CLASSIFICATION,
457 	ITEM_HIGIG2_VID,
458 	ITEM_TAG,
459 	ITEM_TAG_DATA,
460 	ITEM_TAG_INDEX,
461 	ITEM_L2TPV3OIP,
462 	ITEM_L2TPV3OIP_SESSION_ID,
463 	ITEM_ESP,
464 	ITEM_ESP_SPI,
465 	ITEM_AH,
466 	ITEM_AH_SPI,
467 	ITEM_PFCP,
468 	ITEM_PFCP_S_FIELD,
469 	ITEM_PFCP_SEID,
470 	ITEM_ECPRI,
471 	ITEM_ECPRI_COMMON,
472 	ITEM_ECPRI_COMMON_TYPE,
473 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
474 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
475 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
476 	ITEM_ECPRI_MSG_IQ_DATA_PCID,
477 	ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
478 	ITEM_ECPRI_MSG_DLY_MSR_MSRID,
479 	ITEM_GENEVE_OPT,
480 	ITEM_GENEVE_OPT_CLASS,
481 	ITEM_GENEVE_OPT_TYPE,
482 	ITEM_GENEVE_OPT_LENGTH,
483 	ITEM_GENEVE_OPT_DATA,
484 	ITEM_INTEGRITY,
485 	ITEM_INTEGRITY_LEVEL,
486 	ITEM_INTEGRITY_VALUE,
487 	ITEM_CONNTRACK,
488 	ITEM_POL_PORT,
489 	ITEM_POL_METER,
490 	ITEM_POL_POLICY,
491 	ITEM_PORT_REPRESENTOR,
492 	ITEM_PORT_REPRESENTOR_PORT_ID,
493 	ITEM_REPRESENTED_PORT,
494 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
495 	ITEM_FLEX,
496 	ITEM_FLEX_ITEM_HANDLE,
497 	ITEM_FLEX_PATTERN_HANDLE,
498 	ITEM_L2TPV2,
499 	ITEM_L2TPV2_TYPE,
500 	ITEM_L2TPV2_TYPE_DATA,
501 	ITEM_L2TPV2_TYPE_DATA_L,
502 	ITEM_L2TPV2_TYPE_DATA_S,
503 	ITEM_L2TPV2_TYPE_DATA_O,
504 	ITEM_L2TPV2_TYPE_DATA_L_S,
505 	ITEM_L2TPV2_TYPE_CTRL,
506 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
507 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
508 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
509 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
510 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
511 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
512 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
513 	ITEM_L2TPV2_MSG_DATA_S_NS,
514 	ITEM_L2TPV2_MSG_DATA_S_NR,
515 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
516 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
517 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
518 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
519 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
520 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
521 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
522 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
523 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
524 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
525 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
526 	ITEM_L2TPV2_MSG_CTRL_NS,
527 	ITEM_L2TPV2_MSG_CTRL_NR,
528 	ITEM_PPP,
529 	ITEM_PPP_ADDR,
530 	ITEM_PPP_CTRL,
531 	ITEM_PPP_PROTO_ID,
532 	ITEM_METER,
533 	ITEM_METER_COLOR,
534 	ITEM_METER_COLOR_NAME,
535 	ITEM_QUOTA,
536 	ITEM_QUOTA_STATE,
537 	ITEM_QUOTA_STATE_NAME,
538 	ITEM_AGGR_AFFINITY,
539 	ITEM_AGGR_AFFINITY_VALUE,
540 	ITEM_TX_QUEUE,
541 	ITEM_TX_QUEUE_VALUE,
542 	ITEM_IB_BTH,
543 	ITEM_IB_BTH_OPCODE,
544 	ITEM_IB_BTH_PKEY,
545 	ITEM_IB_BTH_DST_QPN,
546 	ITEM_IB_BTH_PSN,
547 	ITEM_IPV6_PUSH_REMOVE_EXT,
548 	ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
549 	ITEM_PTYPE,
550 	ITEM_PTYPE_VALUE,
551 	ITEM_NSH,
552 	ITEM_COMPARE,
553 	ITEM_COMPARE_OP,
554 	ITEM_COMPARE_OP_VALUE,
555 	ITEM_COMPARE_FIELD_A_TYPE,
556 	ITEM_COMPARE_FIELD_A_TYPE_VALUE,
557 	ITEM_COMPARE_FIELD_A_LEVEL,
558 	ITEM_COMPARE_FIELD_A_LEVEL_VALUE,
559 	ITEM_COMPARE_FIELD_A_TAG_INDEX,
560 	ITEM_COMPARE_FIELD_A_TYPE_ID,
561 	ITEM_COMPARE_FIELD_A_CLASS_ID,
562 	ITEM_COMPARE_FIELD_A_OFFSET,
563 	ITEM_COMPARE_FIELD_B_TYPE,
564 	ITEM_COMPARE_FIELD_B_TYPE_VALUE,
565 	ITEM_COMPARE_FIELD_B_LEVEL,
566 	ITEM_COMPARE_FIELD_B_LEVEL_VALUE,
567 	ITEM_COMPARE_FIELD_B_TAG_INDEX,
568 	ITEM_COMPARE_FIELD_B_TYPE_ID,
569 	ITEM_COMPARE_FIELD_B_CLASS_ID,
570 	ITEM_COMPARE_FIELD_B_OFFSET,
571 	ITEM_COMPARE_FIELD_B_VALUE,
572 	ITEM_COMPARE_FIELD_B_POINTER,
573 	ITEM_COMPARE_FIELD_WIDTH,
574 
575 	/* Validate/create actions. */
576 	ACTIONS,
577 	ACTION_NEXT,
578 	ACTION_END,
579 	ACTION_VOID,
580 	ACTION_PASSTHRU,
581 	ACTION_SKIP_CMAN,
582 	ACTION_JUMP,
583 	ACTION_JUMP_GROUP,
584 	ACTION_MARK,
585 	ACTION_MARK_ID,
586 	ACTION_FLAG,
587 	ACTION_QUEUE,
588 	ACTION_QUEUE_INDEX,
589 	ACTION_DROP,
590 	ACTION_COUNT,
591 	ACTION_COUNT_ID,
592 	ACTION_RSS,
593 	ACTION_RSS_FUNC,
594 	ACTION_RSS_LEVEL,
595 	ACTION_RSS_FUNC_DEFAULT,
596 	ACTION_RSS_FUNC_TOEPLITZ,
597 	ACTION_RSS_FUNC_SIMPLE_XOR,
598 	ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
599 	ACTION_RSS_TYPES,
600 	ACTION_RSS_TYPE,
601 	ACTION_RSS_KEY,
602 	ACTION_RSS_KEY_LEN,
603 	ACTION_RSS_QUEUES,
604 	ACTION_RSS_QUEUE,
605 	ACTION_PF,
606 	ACTION_VF,
607 	ACTION_VF_ORIGINAL,
608 	ACTION_VF_ID,
609 	ACTION_PORT_ID,
610 	ACTION_PORT_ID_ORIGINAL,
611 	ACTION_PORT_ID_ID,
612 	ACTION_METER,
613 	ACTION_METER_COLOR,
614 	ACTION_METER_COLOR_TYPE,
615 	ACTION_METER_COLOR_GREEN,
616 	ACTION_METER_COLOR_YELLOW,
617 	ACTION_METER_COLOR_RED,
618 	ACTION_METER_ID,
619 	ACTION_METER_MARK,
620 	ACTION_METER_PROFILE,
621 	ACTION_METER_PROFILE_ID2PTR,
622 	ACTION_METER_POLICY,
623 	ACTION_METER_POLICY_ID2PTR,
624 	ACTION_METER_COLOR_MODE,
625 	ACTION_METER_STATE,
626 	ACTION_OF_DEC_NW_TTL,
627 	ACTION_OF_POP_VLAN,
628 	ACTION_OF_PUSH_VLAN,
629 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
630 	ACTION_OF_SET_VLAN_VID,
631 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
632 	ACTION_OF_SET_VLAN_PCP,
633 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
634 	ACTION_OF_POP_MPLS,
635 	ACTION_OF_POP_MPLS_ETHERTYPE,
636 	ACTION_OF_PUSH_MPLS,
637 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
638 	ACTION_VXLAN_ENCAP,
639 	ACTION_VXLAN_DECAP,
640 	ACTION_NVGRE_ENCAP,
641 	ACTION_NVGRE_DECAP,
642 	ACTION_L2_ENCAP,
643 	ACTION_L2_DECAP,
644 	ACTION_MPLSOGRE_ENCAP,
645 	ACTION_MPLSOGRE_DECAP,
646 	ACTION_MPLSOUDP_ENCAP,
647 	ACTION_MPLSOUDP_DECAP,
648 	ACTION_SET_IPV4_SRC,
649 	ACTION_SET_IPV4_SRC_IPV4_SRC,
650 	ACTION_SET_IPV4_DST,
651 	ACTION_SET_IPV4_DST_IPV4_DST,
652 	ACTION_SET_IPV6_SRC,
653 	ACTION_SET_IPV6_SRC_IPV6_SRC,
654 	ACTION_SET_IPV6_DST,
655 	ACTION_SET_IPV6_DST_IPV6_DST,
656 	ACTION_SET_TP_SRC,
657 	ACTION_SET_TP_SRC_TP_SRC,
658 	ACTION_SET_TP_DST,
659 	ACTION_SET_TP_DST_TP_DST,
660 	ACTION_MAC_SWAP,
661 	ACTION_DEC_TTL,
662 	ACTION_SET_TTL,
663 	ACTION_SET_TTL_TTL,
664 	ACTION_SET_MAC_SRC,
665 	ACTION_SET_MAC_SRC_MAC_SRC,
666 	ACTION_SET_MAC_DST,
667 	ACTION_SET_MAC_DST_MAC_DST,
668 	ACTION_INC_TCP_SEQ,
669 	ACTION_INC_TCP_SEQ_VALUE,
670 	ACTION_DEC_TCP_SEQ,
671 	ACTION_DEC_TCP_SEQ_VALUE,
672 	ACTION_INC_TCP_ACK,
673 	ACTION_INC_TCP_ACK_VALUE,
674 	ACTION_DEC_TCP_ACK,
675 	ACTION_DEC_TCP_ACK_VALUE,
676 	ACTION_RAW_ENCAP,
677 	ACTION_RAW_DECAP,
678 	ACTION_RAW_ENCAP_SIZE,
679 	ACTION_RAW_ENCAP_INDEX,
680 	ACTION_RAW_ENCAP_INDEX_VALUE,
681 	ACTION_RAW_DECAP_INDEX,
682 	ACTION_RAW_DECAP_INDEX_VALUE,
683 	ACTION_SET_TAG,
684 	ACTION_SET_TAG_DATA,
685 	ACTION_SET_TAG_INDEX,
686 	ACTION_SET_TAG_MASK,
687 	ACTION_SET_META,
688 	ACTION_SET_META_DATA,
689 	ACTION_SET_META_MASK,
690 	ACTION_SET_IPV4_DSCP,
691 	ACTION_SET_IPV4_DSCP_VALUE,
692 	ACTION_SET_IPV6_DSCP,
693 	ACTION_SET_IPV6_DSCP_VALUE,
694 	ACTION_AGE,
695 	ACTION_AGE_TIMEOUT,
696 	ACTION_AGE_UPDATE,
697 	ACTION_AGE_UPDATE_TIMEOUT,
698 	ACTION_AGE_UPDATE_TOUCH,
699 	ACTION_SAMPLE,
700 	ACTION_SAMPLE_RATIO,
701 	ACTION_SAMPLE_INDEX,
702 	ACTION_SAMPLE_INDEX_VALUE,
703 	ACTION_INDIRECT,
704 	ACTION_INDIRECT_LIST,
705 	ACTION_INDIRECT_LIST_HANDLE,
706 	ACTION_INDIRECT_LIST_CONF,
707 	INDIRECT_LIST_ACTION_ID2PTR_HANDLE,
708 	INDIRECT_LIST_ACTION_ID2PTR_CONF,
709 	ACTION_SHARED_INDIRECT,
710 	INDIRECT_ACTION_PORT,
711 	INDIRECT_ACTION_ID2PTR,
712 	ACTION_MODIFY_FIELD,
713 	ACTION_MODIFY_FIELD_OP,
714 	ACTION_MODIFY_FIELD_OP_VALUE,
715 	ACTION_MODIFY_FIELD_DST_TYPE,
716 	ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
717 	ACTION_MODIFY_FIELD_DST_LEVEL,
718 	ACTION_MODIFY_FIELD_DST_LEVEL_VALUE,
719 	ACTION_MODIFY_FIELD_DST_TAG_INDEX,
720 	ACTION_MODIFY_FIELD_DST_TYPE_ID,
721 	ACTION_MODIFY_FIELD_DST_CLASS_ID,
722 	ACTION_MODIFY_FIELD_DST_OFFSET,
723 	ACTION_MODIFY_FIELD_SRC_TYPE,
724 	ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
725 	ACTION_MODIFY_FIELD_SRC_LEVEL,
726 	ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE,
727 	ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
728 	ACTION_MODIFY_FIELD_SRC_TYPE_ID,
729 	ACTION_MODIFY_FIELD_SRC_CLASS_ID,
730 	ACTION_MODIFY_FIELD_SRC_OFFSET,
731 	ACTION_MODIFY_FIELD_SRC_VALUE,
732 	ACTION_MODIFY_FIELD_SRC_POINTER,
733 	ACTION_MODIFY_FIELD_WIDTH,
734 	ACTION_CONNTRACK,
735 	ACTION_CONNTRACK_UPDATE,
736 	ACTION_CONNTRACK_UPDATE_DIR,
737 	ACTION_CONNTRACK_UPDATE_CTX,
738 	ACTION_POL_G,
739 	ACTION_POL_Y,
740 	ACTION_POL_R,
741 	ACTION_PORT_REPRESENTOR,
742 	ACTION_PORT_REPRESENTOR_PORT_ID,
743 	ACTION_REPRESENTED_PORT,
744 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
745 	ACTION_SEND_TO_KERNEL,
746 	ACTION_QUOTA_CREATE,
747 	ACTION_QUOTA_CREATE_LIMIT,
748 	ACTION_QUOTA_CREATE_MODE,
749 	ACTION_QUOTA_CREATE_MODE_NAME,
750 	ACTION_QUOTA_QU,
751 	ACTION_QUOTA_QU_LIMIT,
752 	ACTION_QUOTA_QU_UPDATE_OP,
753 	ACTION_QUOTA_QU_UPDATE_OP_NAME,
754 	ACTION_IPV6_EXT_REMOVE,
755 	ACTION_IPV6_EXT_REMOVE_INDEX,
756 	ACTION_IPV6_EXT_REMOVE_INDEX_VALUE,
757 	ACTION_IPV6_EXT_PUSH,
758 	ACTION_IPV6_EXT_PUSH_INDEX,
759 	ACTION_IPV6_EXT_PUSH_INDEX_VALUE,
760 	ACTION_NAT64,
761 	ACTION_NAT64_MODE,
762 };
763 
764 /** Maximum size for pattern in struct rte_flow_item_raw. */
765 #define ITEM_RAW_PATTERN_SIZE 512
766 
767 /** Maximum size for GENEVE option data pattern in bytes. */
768 #define ITEM_GENEVE_OPT_DATA_SIZE 124
769 
770 /** Storage size for struct rte_flow_item_raw including pattern. */
771 #define ITEM_RAW_SIZE \
772 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
773 
774 static const char *const compare_ops[] = {
775 	"eq", "ne", "lt", "le", "gt", "ge", NULL
776 };
777 
778 /** Maximum size for external pattern in struct rte_flow_field_data. */
779 #define FLOW_FIELD_PATTERN_SIZE 32
780 
781 /** Storage size for struct rte_flow_action_modify_field including pattern. */
782 #define ACTION_MODIFY_SIZE \
783 	(sizeof(struct rte_flow_action_modify_field) + \
784 	FLOW_FIELD_PATTERN_SIZE)
785 
786 /** Maximum number of queue indices in struct rte_flow_action_rss. */
787 #define ACTION_RSS_QUEUE_NUM 128
788 
789 /** Storage for struct rte_flow_action_rss including external data. */
790 struct action_rss_data {
791 	struct rte_flow_action_rss conf;
792 	uint8_t key[RSS_HASH_KEY_LENGTH];
793 	uint16_t queue[ACTION_RSS_QUEUE_NUM];
794 };
795 
796 /** Maximum data size in struct rte_flow_action_raw_encap. */
797 #define ACTION_RAW_ENCAP_MAX_DATA 512
798 #define RAW_ENCAP_CONFS_MAX_NUM 8
799 
800 /** Storage for struct rte_flow_action_raw_encap. */
801 struct raw_encap_conf {
802 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
803 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
804 	size_t size;
805 };
806 
807 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
808 
809 /** Storage for struct rte_flow_action_raw_encap including external data. */
810 struct action_raw_encap_data {
811 	struct rte_flow_action_raw_encap conf;
812 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
813 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
814 	uint16_t idx;
815 };
816 
817 /** Storage for struct rte_flow_action_raw_decap. */
818 struct raw_decap_conf {
819 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
820 	size_t size;
821 };
822 
823 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
824 
825 /** Storage for struct rte_flow_action_raw_decap including external data. */
826 struct action_raw_decap_data {
827 	struct rte_flow_action_raw_decap conf;
828 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
829 	uint16_t idx;
830 };
831 
832 /** Maximum data size in struct rte_flow_action_ipv6_ext_push. */
833 #define ACTION_IPV6_EXT_PUSH_MAX_DATA 512
834 #define IPV6_EXT_PUSH_CONFS_MAX_NUM 8
835 
836 /** Storage for struct rte_flow_action_ipv6_ext_push. */
837 struct ipv6_ext_push_conf {
838 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
839 	size_t size;
840 	uint8_t type;
841 };
842 
843 struct ipv6_ext_push_conf ipv6_ext_push_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
844 
845 /** Storage for struct rte_flow_action_ipv6_ext_push including external data. */
846 struct action_ipv6_ext_push_data {
847 	struct rte_flow_action_ipv6_ext_push conf;
848 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
849 	uint8_t type;
850 	uint16_t idx;
851 };
852 
853 /** Storage for struct rte_flow_action_ipv6_ext_remove. */
854 struct ipv6_ext_remove_conf {
855 	struct rte_flow_action_ipv6_ext_remove conf;
856 	uint8_t type;
857 };
858 
859 struct ipv6_ext_remove_conf ipv6_ext_remove_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
860 
861 /** Storage for struct rte_flow_action_ipv6_ext_remove including external data. */
862 struct action_ipv6_ext_remove_data {
863 	struct rte_flow_action_ipv6_ext_remove conf;
864 	uint8_t type;
865 	uint16_t idx;
866 };
867 
868 struct vxlan_encap_conf vxlan_encap_conf = {
869 	.select_ipv4 = 1,
870 	.select_vlan = 0,
871 	.select_tos_ttl = 0,
872 	.vni = "\x00\x00\x00",
873 	.udp_src = 0,
874 	.udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
875 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
876 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
877 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
878 		"\x00\x00\x00\x00\x00\x00\x00\x01",
879 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
880 		"\x00\x00\x00\x00\x00\x00\x11\x11",
881 	.vlan_tci = 0,
882 	.ip_tos = 0,
883 	.ip_ttl = 255,
884 	.eth_src = "\x00\x00\x00\x00\x00\x00",
885 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
886 };
887 
888 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
889 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
890 
891 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
892 struct action_vxlan_encap_data {
893 	struct rte_flow_action_vxlan_encap conf;
894 	struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
895 	struct rte_flow_item_eth item_eth;
896 	struct rte_flow_item_vlan item_vlan;
897 	union {
898 		struct rte_flow_item_ipv4 item_ipv4;
899 		struct rte_flow_item_ipv6 item_ipv6;
900 	};
901 	struct rte_flow_item_udp item_udp;
902 	struct rte_flow_item_vxlan item_vxlan;
903 };
904 
905 struct nvgre_encap_conf nvgre_encap_conf = {
906 	.select_ipv4 = 1,
907 	.select_vlan = 0,
908 	.tni = "\x00\x00\x00",
909 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
910 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
911 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
912 		"\x00\x00\x00\x00\x00\x00\x00\x01",
913 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
914 		"\x00\x00\x00\x00\x00\x00\x11\x11",
915 	.vlan_tci = 0,
916 	.eth_src = "\x00\x00\x00\x00\x00\x00",
917 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
918 };
919 
920 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
921 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
922 
923 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
924 struct action_nvgre_encap_data {
925 	struct rte_flow_action_nvgre_encap conf;
926 	struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
927 	struct rte_flow_item_eth item_eth;
928 	struct rte_flow_item_vlan item_vlan;
929 	union {
930 		struct rte_flow_item_ipv4 item_ipv4;
931 		struct rte_flow_item_ipv6 item_ipv6;
932 	};
933 	struct rte_flow_item_nvgre item_nvgre;
934 };
935 
936 struct l2_encap_conf l2_encap_conf;
937 
938 struct l2_decap_conf l2_decap_conf;
939 
940 struct mplsogre_encap_conf mplsogre_encap_conf;
941 
942 struct mplsogre_decap_conf mplsogre_decap_conf;
943 
944 struct mplsoudp_encap_conf mplsoudp_encap_conf;
945 
946 struct mplsoudp_decap_conf mplsoudp_decap_conf;
947 
948 struct rte_flow_action_conntrack conntrack_context;
949 
950 #define ACTION_SAMPLE_ACTIONS_NUM 10
951 #define RAW_SAMPLE_CONFS_MAX_NUM 8
952 /** Storage for struct rte_flow_action_sample including external data. */
953 struct action_sample_data {
954 	struct rte_flow_action_sample conf;
955 	uint32_t idx;
956 };
957 /** Storage for struct rte_flow_action_sample. */
958 struct raw_sample_conf {
959 	struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
960 };
961 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
962 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
963 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
964 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
965 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
966 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
967 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
968 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
969 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
970 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
971 struct rte_flow_action_ethdev sample_port_representor[RAW_SAMPLE_CONFS_MAX_NUM];
972 struct rte_flow_action_ethdev sample_represented_port[RAW_SAMPLE_CONFS_MAX_NUM];
973 
974 static const char *const modify_field_ops[] = {
975 	"set", "add", "sub", NULL
976 };
977 
978 static const char *const flow_field_ids[] = {
979 	"start", "mac_dst", "mac_src",
980 	"vlan_type", "vlan_id", "mac_type",
981 	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
982 	"ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
983 	"tcp_port_src", "tcp_port_dst",
984 	"tcp_seq_num", "tcp_ack_num", "tcp_flags",
985 	"udp_port_src", "udp_port_dst",
986 	"vxlan_vni", "geneve_vni", "gtp_teid",
987 	"tag", "mark", "meta", "pointer", "value",
988 	"ipv4_ecn", "ipv6_ecn", "gtp_psc_qfi", "meter_color",
989 	"ipv6_proto",
990 	"flex_item",
991 	"hash_result",
992 	"geneve_opt_type", "geneve_opt_class", "geneve_opt_data", "mpls",
993 	"tcp_data_off", "ipv4_ihl", "ipv4_total_len", "ipv6_payload_len",
994 	"random",
995 	NULL
996 };
997 
998 static const char *const meter_colors[] = {
999 	"green", "yellow", "red", "all", NULL
1000 };
1001 
1002 static const char *const table_insertion_types[] = {
1003 	"pattern", "index", NULL
1004 };
1005 
1006 static const char *const table_hash_funcs[] = {
1007 	"default", "linear", "crc32", "crc16", NULL
1008 };
1009 
1010 #define RAW_IPSEC_CONFS_MAX_NUM 8
1011 
1012 /** Maximum number of subsequent tokens and arguments on the stack. */
1013 #define CTX_STACK_SIZE 16
1014 
1015 /** Parser context. */
1016 struct context {
1017 	/** Stack of subsequent token lists to process. */
1018 	const enum index *next[CTX_STACK_SIZE];
1019 	/** Arguments for stacked tokens. */
1020 	const void *args[CTX_STACK_SIZE];
1021 	enum index curr; /**< Current token index. */
1022 	enum index prev; /**< Index of the last token seen. */
1023 	int next_num; /**< Number of entries in next[]. */
1024 	int args_num; /**< Number of entries in args[]. */
1025 	uint32_t eol:1; /**< EOL has been detected. */
1026 	uint32_t last:1; /**< No more arguments. */
1027 	portid_t port; /**< Current port ID (for completions). */
1028 	uint32_t objdata; /**< Object-specific data. */
1029 	void *object; /**< Address of current object for relative offsets. */
1030 	void *objmask; /**< Object a full mask must be written to. */
1031 };
1032 
1033 /** Token argument. */
1034 struct arg {
1035 	uint32_t hton:1; /**< Use network byte ordering. */
1036 	uint32_t sign:1; /**< Value is signed. */
1037 	uint32_t bounded:1; /**< Value is bounded. */
1038 	uintmax_t min; /**< Minimum value if bounded. */
1039 	uintmax_t max; /**< Maximum value if bounded. */
1040 	uint32_t offset; /**< Relative offset from ctx->object. */
1041 	uint32_t size; /**< Field size. */
1042 	const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
1043 };
1044 
1045 /** Parser token definition. */
1046 struct token {
1047 	/** Type displayed during completion (defaults to "TOKEN"). */
1048 	const char *type;
1049 	/** Help displayed during completion (defaults to token name). */
1050 	const char *help;
1051 	/** Private data used by parser functions. */
1052 	const void *priv;
1053 	/**
1054 	 * Lists of subsequent tokens to push on the stack. Each call to the
1055 	 * parser consumes the last entry of that stack.
1056 	 */
1057 	const enum index *const *next;
1058 	/** Arguments stack for subsequent tokens that need them. */
1059 	const struct arg *const *args;
1060 	/**
1061 	 * Token-processing callback, returns -1 in case of error, the
1062 	 * length of the matched string otherwise. If NULL, attempts to
1063 	 * match the token name.
1064 	 *
1065 	 * If buf is not NULL, the result should be stored in it according
1066 	 * to context. An error is returned if not large enough.
1067 	 */
1068 	int (*call)(struct context *ctx, const struct token *token,
1069 		    const char *str, unsigned int len,
1070 		    void *buf, unsigned int size);
1071 	/**
1072 	 * Callback that provides possible values for this token, used for
1073 	 * completion. Returns -1 in case of error, the number of possible
1074 	 * values otherwise. If NULL, the token name is used.
1075 	 *
1076 	 * If buf is not NULL, entry index ent is written to buf and the
1077 	 * full length of the entry is returned (same behavior as
1078 	 * snprintf()).
1079 	 */
1080 	int (*comp)(struct context *ctx, const struct token *token,
1081 		    unsigned int ent, char *buf, unsigned int size);
1082 	/** Mandatory token name, no default value. */
1083 	const char *name;
1084 };
1085 
1086 /** Static initializer for the next field. */
1087 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
1088 
1089 /** Static initializer for a NEXT() entry. */
1090 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
1091 
1092 /** Static initializer for the args field. */
1093 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
1094 
1095 /** Static initializer for ARGS() to target a field. */
1096 #define ARGS_ENTRY(s, f) \
1097 	(&(const struct arg){ \
1098 		.offset = offsetof(s, f), \
1099 		.size = sizeof(((s *)0)->f), \
1100 	})
1101 
1102 /** Static initializer for ARGS() to target a bit-field. */
1103 #define ARGS_ENTRY_BF(s, f, b) \
1104 	(&(const struct arg){ \
1105 		.size = sizeof(s), \
1106 		.mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
1107 	})
1108 
1109 /** Static initializer for ARGS() to target a field with limits. */
1110 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
1111 	(&(const struct arg){ \
1112 		.bounded = 1, \
1113 		.min = (i), \
1114 		.max = (a), \
1115 		.offset = offsetof(s, f), \
1116 		.size = sizeof(((s *)0)->f), \
1117 	})
1118 
1119 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
1120 #define ARGS_ENTRY_MASK(s, f, m) \
1121 	(&(const struct arg){ \
1122 		.offset = offsetof(s, f), \
1123 		.size = sizeof(((s *)0)->f), \
1124 		.mask = (const void *)(m), \
1125 	})
1126 
1127 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
1128 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
1129 	(&(const struct arg){ \
1130 		.hton = 1, \
1131 		.offset = offsetof(s, f), \
1132 		.size = sizeof(((s *)0)->f), \
1133 		.mask = (const void *)(m), \
1134 	})
1135 
1136 /** Static initializer for ARGS() to target a pointer. */
1137 #define ARGS_ENTRY_PTR(s, f) \
1138 	(&(const struct arg){ \
1139 		.size = sizeof(*((s *)0)->f), \
1140 	})
1141 
1142 /** Static initializer for ARGS() with arbitrary offset and size. */
1143 #define ARGS_ENTRY_ARB(o, s) \
1144 	(&(const struct arg){ \
1145 		.offset = (o), \
1146 		.size = (s), \
1147 	})
1148 
1149 /** Same as ARGS_ENTRY_ARB() with bounded values. */
1150 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
1151 	(&(const struct arg){ \
1152 		.bounded = 1, \
1153 		.min = (i), \
1154 		.max = (a), \
1155 		.offset = (o), \
1156 		.size = (s), \
1157 	})
1158 
1159 /** Same as ARGS_ENTRY() using network byte ordering. */
1160 #define ARGS_ENTRY_HTON(s, f) \
1161 	(&(const struct arg){ \
1162 		.hton = 1, \
1163 		.offset = offsetof(s, f), \
1164 		.size = sizeof(((s *)0)->f), \
1165 	})
1166 
1167 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
1168 #define ARG_ENTRY_HTON(s) \
1169 	(&(const struct arg){ \
1170 		.hton = 1, \
1171 		.offset = 0, \
1172 		.size = sizeof(s), \
1173 	})
1174 
1175 /** Parser output buffer layout expected by cmd_flow_parsed(). */
1176 struct buffer {
1177 	enum index command; /**< Flow command. */
1178 	portid_t port; /**< Affected port ID. */
1179 	queueid_t queue; /** Async queue ID. */
1180 	bool postpone; /** Postpone async operation */
1181 	union {
1182 		struct {
1183 			struct rte_flow_port_attr port_attr;
1184 			uint32_t nb_queue;
1185 			struct rte_flow_queue_attr queue_attr;
1186 		} configure; /**< Configuration arguments. */
1187 		struct {
1188 			uint32_t *template_id;
1189 			uint32_t template_id_n;
1190 		} templ_destroy; /**< Template destroy arguments. */
1191 		struct {
1192 			uint32_t id;
1193 			struct rte_flow_template_table_attr attr;
1194 			uint32_t *pat_templ_id;
1195 			uint32_t pat_templ_id_n;
1196 			uint32_t *act_templ_id;
1197 			uint32_t act_templ_id_n;
1198 		} table; /**< Table arguments. */
1199 		struct {
1200 			uint32_t *table_id;
1201 			uint32_t table_id_n;
1202 		} table_destroy; /**< Template destroy arguments. */
1203 		struct {
1204 			uint32_t *action_id;
1205 			uint32_t action_id_n;
1206 		} ia_destroy; /**< Indirect action destroy arguments. */
1207 		struct {
1208 			uint32_t action_id;
1209 			enum rte_flow_query_update_mode qu_mode;
1210 		} ia; /* Indirect action query arguments */
1211 		struct {
1212 			uint32_t table_id;
1213 			uint32_t pat_templ_id;
1214 			uint32_t rule_id;
1215 			uint32_t act_templ_id;
1216 			struct rte_flow_attr attr;
1217 			struct tunnel_ops tunnel_ops;
1218 			uintptr_t user_id;
1219 			struct rte_flow_item *pattern;
1220 			struct rte_flow_action *actions;
1221 			struct rte_flow_action *masks;
1222 			uint32_t pattern_n;
1223 			uint32_t actions_n;
1224 			uint8_t *data;
1225 			enum rte_flow_encap_hash_field field;
1226 			uint8_t encap_hash;
1227 		} vc; /**< Validate/create arguments. */
1228 		struct {
1229 			uint64_t *rule;
1230 			uint64_t rule_n;
1231 			bool is_user_id;
1232 		} destroy; /**< Destroy arguments. */
1233 		struct {
1234 			char file[128];
1235 			bool mode;
1236 			uint64_t rule;
1237 			bool is_user_id;
1238 		} dump; /**< Dump arguments. */
1239 		struct {
1240 			uint64_t rule;
1241 			struct rte_flow_action action;
1242 			bool is_user_id;
1243 		} query; /**< Query arguments. */
1244 		struct {
1245 			uint32_t *group;
1246 			uint32_t group_n;
1247 		} list; /**< List arguments. */
1248 		struct {
1249 			int set;
1250 		} isolate; /**< Isolated mode arguments. */
1251 		struct {
1252 			int destroy;
1253 		} aged; /**< Aged arguments. */
1254 		struct {
1255 			uint32_t policy_id;
1256 		} policy;/**< Policy arguments. */
1257 		struct {
1258 			uint16_t token;
1259 			uintptr_t uintptr;
1260 			char filename[128];
1261 		} flex; /**< Flex arguments*/
1262 	} args; /**< Command arguments. */
1263 };
1264 
1265 /** Private data for pattern items. */
1266 struct parse_item_priv {
1267 	enum rte_flow_item_type type; /**< Item type. */
1268 	uint32_t size; /**< Size of item specification structure. */
1269 };
1270 
1271 #define PRIV_ITEM(t, s) \
1272 	(&(const struct parse_item_priv){ \
1273 		.type = RTE_FLOW_ITEM_TYPE_ ## t, \
1274 		.size = s, \
1275 	})
1276 
1277 /** Private data for actions. */
1278 struct parse_action_priv {
1279 	enum rte_flow_action_type type; /**< Action type. */
1280 	uint32_t size; /**< Size of action configuration structure. */
1281 };
1282 
1283 #define PRIV_ACTION(t, s) \
1284 	(&(const struct parse_action_priv){ \
1285 		.type = RTE_FLOW_ACTION_TYPE_ ## t, \
1286 		.size = s, \
1287 	})
1288 
1289 static const enum index next_flex_item[] = {
1290 	FLEX_ITEM_INIT,
1291 	FLEX_ITEM_CREATE,
1292 	FLEX_ITEM_DESTROY,
1293 	ZERO,
1294 };
1295 
1296 static const enum index next_config_attr[] = {
1297 	CONFIG_QUEUES_NUMBER,
1298 	CONFIG_QUEUES_SIZE,
1299 	CONFIG_COUNTERS_NUMBER,
1300 	CONFIG_AGING_OBJECTS_NUMBER,
1301 	CONFIG_METERS_NUMBER,
1302 	CONFIG_CONN_TRACK_NUMBER,
1303 	CONFIG_QUOTAS_NUMBER,
1304 	CONFIG_FLAGS,
1305 	CONFIG_HOST_PORT,
1306 	END,
1307 	ZERO,
1308 };
1309 
1310 static const enum index next_pt_subcmd[] = {
1311 	PATTERN_TEMPLATE_CREATE,
1312 	PATTERN_TEMPLATE_DESTROY,
1313 	ZERO,
1314 };
1315 
1316 static const enum index next_pt_attr[] = {
1317 	PATTERN_TEMPLATE_CREATE_ID,
1318 	PATTERN_TEMPLATE_RELAXED_MATCHING,
1319 	PATTERN_TEMPLATE_INGRESS,
1320 	PATTERN_TEMPLATE_EGRESS,
1321 	PATTERN_TEMPLATE_TRANSFER,
1322 	PATTERN_TEMPLATE_SPEC,
1323 	ZERO,
1324 };
1325 
1326 static const enum index next_pt_destroy_attr[] = {
1327 	PATTERN_TEMPLATE_DESTROY_ID,
1328 	END,
1329 	ZERO,
1330 };
1331 
1332 static const enum index next_at_subcmd[] = {
1333 	ACTIONS_TEMPLATE_CREATE,
1334 	ACTIONS_TEMPLATE_DESTROY,
1335 	ZERO,
1336 };
1337 
1338 static const enum index next_at_attr[] = {
1339 	ACTIONS_TEMPLATE_CREATE_ID,
1340 	ACTIONS_TEMPLATE_INGRESS,
1341 	ACTIONS_TEMPLATE_EGRESS,
1342 	ACTIONS_TEMPLATE_TRANSFER,
1343 	ACTIONS_TEMPLATE_SPEC,
1344 	ZERO,
1345 };
1346 
1347 static const enum index next_at_destroy_attr[] = {
1348 	ACTIONS_TEMPLATE_DESTROY_ID,
1349 	END,
1350 	ZERO,
1351 };
1352 
1353 static const enum index next_group_attr[] = {
1354 	GROUP_INGRESS,
1355 	GROUP_EGRESS,
1356 	GROUP_TRANSFER,
1357 	GROUP_SET_MISS_ACTIONS,
1358 	ZERO,
1359 };
1360 
1361 static const enum index next_table_subcmd[] = {
1362 	TABLE_CREATE,
1363 	TABLE_DESTROY,
1364 	ZERO,
1365 };
1366 
1367 static const enum index next_table_attr[] = {
1368 	TABLE_CREATE_ID,
1369 	TABLE_GROUP,
1370 	TABLE_INSERTION_TYPE,
1371 	TABLE_HASH_FUNC,
1372 	TABLE_PRIORITY,
1373 	TABLE_INGRESS,
1374 	TABLE_EGRESS,
1375 	TABLE_TRANSFER,
1376 	TABLE_TRANSFER_WIRE_ORIG,
1377 	TABLE_TRANSFER_VPORT_ORIG,
1378 	TABLE_RULES_NUMBER,
1379 	TABLE_PATTERN_TEMPLATE,
1380 	TABLE_ACTIONS_TEMPLATE,
1381 	END,
1382 	ZERO,
1383 };
1384 
1385 static const enum index next_table_destroy_attr[] = {
1386 	TABLE_DESTROY_ID,
1387 	END,
1388 	ZERO,
1389 };
1390 
1391 static const enum index next_queue_subcmd[] = {
1392 	QUEUE_CREATE,
1393 	QUEUE_DESTROY,
1394 	QUEUE_UPDATE,
1395 	QUEUE_AGED,
1396 	QUEUE_INDIRECT_ACTION,
1397 	ZERO,
1398 };
1399 
1400 static const enum index next_queue_destroy_attr[] = {
1401 	QUEUE_DESTROY_ID,
1402 	END,
1403 	ZERO,
1404 };
1405 
1406 static const enum index next_qia_subcmd[] = {
1407 	QUEUE_INDIRECT_ACTION_CREATE,
1408 	QUEUE_INDIRECT_ACTION_UPDATE,
1409 	QUEUE_INDIRECT_ACTION_DESTROY,
1410 	QUEUE_INDIRECT_ACTION_QUERY,
1411 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
1412 	ZERO,
1413 };
1414 
1415 static const enum index next_qia_create_attr[] = {
1416 	QUEUE_INDIRECT_ACTION_CREATE_ID,
1417 	QUEUE_INDIRECT_ACTION_INGRESS,
1418 	QUEUE_INDIRECT_ACTION_EGRESS,
1419 	QUEUE_INDIRECT_ACTION_TRANSFER,
1420 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
1421 	QUEUE_INDIRECT_ACTION_SPEC,
1422 	QUEUE_INDIRECT_ACTION_LIST,
1423 	ZERO,
1424 };
1425 
1426 static const enum index next_qia_update_attr[] = {
1427 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1428 	QUEUE_INDIRECT_ACTION_SPEC,
1429 	ZERO,
1430 };
1431 
1432 static const enum index next_qia_destroy_attr[] = {
1433 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
1434 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
1435 	END,
1436 	ZERO,
1437 };
1438 
1439 static const enum index next_qia_query_attr[] = {
1440 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
1441 	END,
1442 	ZERO,
1443 };
1444 
1445 static const enum index next_ia_create_attr[] = {
1446 	INDIRECT_ACTION_CREATE_ID,
1447 	INDIRECT_ACTION_INGRESS,
1448 	INDIRECT_ACTION_EGRESS,
1449 	INDIRECT_ACTION_TRANSFER,
1450 	INDIRECT_ACTION_SPEC,
1451 	INDIRECT_ACTION_LIST,
1452 	INDIRECT_ACTION_FLOW_CONF,
1453 	ZERO,
1454 };
1455 
1456 static const enum index next_ia[] = {
1457 	INDIRECT_ACTION_ID2PTR,
1458 	ACTION_NEXT,
1459 	ZERO
1460 };
1461 
1462 static const enum index next_ial[] = {
1463 	ACTION_INDIRECT_LIST_HANDLE,
1464 	ACTION_INDIRECT_LIST_CONF,
1465 	ACTION_NEXT,
1466 	ZERO
1467 };
1468 
1469 static const enum index next_qia_qu_attr[] = {
1470 	QUEUE_INDIRECT_ACTION_QU_MODE,
1471 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1472 	INDIRECT_ACTION_SPEC,
1473 	ZERO
1474 };
1475 
1476 static const enum index next_ia_qu_attr[] = {
1477 	INDIRECT_ACTION_QU_MODE,
1478 	INDIRECT_ACTION_SPEC,
1479 	ZERO
1480 };
1481 
1482 static const enum index next_dump_subcmd[] = {
1483 	DUMP_ALL,
1484 	DUMP_ONE,
1485 	DUMP_IS_USER_ID,
1486 	ZERO,
1487 };
1488 
1489 static const enum index next_ia_subcmd[] = {
1490 	INDIRECT_ACTION_CREATE,
1491 	INDIRECT_ACTION_UPDATE,
1492 	INDIRECT_ACTION_DESTROY,
1493 	INDIRECT_ACTION_QUERY,
1494 	INDIRECT_ACTION_QUERY_UPDATE,
1495 	ZERO,
1496 };
1497 
1498 static const enum index next_vc_attr[] = {
1499 	VC_GROUP,
1500 	VC_PRIORITY,
1501 	VC_INGRESS,
1502 	VC_EGRESS,
1503 	VC_TRANSFER,
1504 	VC_TUNNEL_SET,
1505 	VC_TUNNEL_MATCH,
1506 	VC_USER_ID,
1507 	ITEM_PATTERN,
1508 	ZERO,
1509 };
1510 
1511 static const enum index next_destroy_attr[] = {
1512 	DESTROY_RULE,
1513 	DESTROY_IS_USER_ID,
1514 	END,
1515 	ZERO,
1516 };
1517 
1518 static const enum index next_dump_attr[] = {
1519 	COMMON_FILE_PATH,
1520 	END,
1521 	ZERO,
1522 };
1523 
1524 static const enum index next_query_attr[] = {
1525 	QUERY_IS_USER_ID,
1526 	END,
1527 	ZERO,
1528 };
1529 
1530 static const enum index next_list_attr[] = {
1531 	LIST_GROUP,
1532 	END,
1533 	ZERO,
1534 };
1535 
1536 static const enum index next_aged_attr[] = {
1537 	AGED_DESTROY,
1538 	END,
1539 	ZERO,
1540 };
1541 
1542 static const enum index next_ia_destroy_attr[] = {
1543 	INDIRECT_ACTION_DESTROY_ID,
1544 	END,
1545 	ZERO,
1546 };
1547 
1548 static const enum index next_async_insert_subcmd[] = {
1549 	QUEUE_PATTERN_TEMPLATE,
1550 	QUEUE_RULE_ID,
1551 	ZERO,
1552 };
1553 
1554 static const enum index item_param[] = {
1555 	ITEM_PARAM_IS,
1556 	ITEM_PARAM_SPEC,
1557 	ITEM_PARAM_LAST,
1558 	ITEM_PARAM_MASK,
1559 	ITEM_PARAM_PREFIX,
1560 	ZERO,
1561 };
1562 
1563 static const enum index next_item[] = {
1564 	ITEM_END,
1565 	ITEM_VOID,
1566 	ITEM_INVERT,
1567 	ITEM_ANY,
1568 	ITEM_PORT_ID,
1569 	ITEM_MARK,
1570 	ITEM_RAW,
1571 	ITEM_ETH,
1572 	ITEM_VLAN,
1573 	ITEM_IPV4,
1574 	ITEM_IPV6,
1575 	ITEM_ICMP,
1576 	ITEM_UDP,
1577 	ITEM_TCP,
1578 	ITEM_SCTP,
1579 	ITEM_VXLAN,
1580 	ITEM_E_TAG,
1581 	ITEM_NVGRE,
1582 	ITEM_MPLS,
1583 	ITEM_GRE,
1584 	ITEM_FUZZY,
1585 	ITEM_GTP,
1586 	ITEM_GTPC,
1587 	ITEM_GTPU,
1588 	ITEM_GENEVE,
1589 	ITEM_VXLAN_GPE,
1590 	ITEM_ARP_ETH_IPV4,
1591 	ITEM_IPV6_EXT,
1592 	ITEM_IPV6_FRAG_EXT,
1593 	ITEM_IPV6_ROUTING_EXT,
1594 	ITEM_ICMP6,
1595 	ITEM_ICMP6_ECHO_REQUEST,
1596 	ITEM_ICMP6_ECHO_REPLY,
1597 	ITEM_ICMP6_ND_NS,
1598 	ITEM_ICMP6_ND_NA,
1599 	ITEM_ICMP6_ND_OPT,
1600 	ITEM_ICMP6_ND_OPT_SLA_ETH,
1601 	ITEM_ICMP6_ND_OPT_TLA_ETH,
1602 	ITEM_META,
1603 	ITEM_RANDOM,
1604 	ITEM_GRE_KEY,
1605 	ITEM_GRE_OPTION,
1606 	ITEM_GTP_PSC,
1607 	ITEM_PPPOES,
1608 	ITEM_PPPOED,
1609 	ITEM_PPPOE_PROTO_ID,
1610 	ITEM_HIGIG2,
1611 	ITEM_TAG,
1612 	ITEM_L2TPV3OIP,
1613 	ITEM_ESP,
1614 	ITEM_AH,
1615 	ITEM_PFCP,
1616 	ITEM_ECPRI,
1617 	ITEM_GENEVE_OPT,
1618 	ITEM_INTEGRITY,
1619 	ITEM_CONNTRACK,
1620 	ITEM_PORT_REPRESENTOR,
1621 	ITEM_REPRESENTED_PORT,
1622 	ITEM_FLEX,
1623 	ITEM_L2TPV2,
1624 	ITEM_PPP,
1625 	ITEM_METER,
1626 	ITEM_QUOTA,
1627 	ITEM_AGGR_AFFINITY,
1628 	ITEM_TX_QUEUE,
1629 	ITEM_IB_BTH,
1630 	ITEM_PTYPE,
1631 	ITEM_NSH,
1632 	ITEM_COMPARE,
1633 	END_SET,
1634 	ZERO,
1635 };
1636 
1637 static const enum index item_fuzzy[] = {
1638 	ITEM_FUZZY_THRESH,
1639 	ITEM_NEXT,
1640 	ZERO,
1641 };
1642 
1643 static const enum index item_any[] = {
1644 	ITEM_ANY_NUM,
1645 	ITEM_NEXT,
1646 	ZERO,
1647 };
1648 
1649 static const enum index item_port_id[] = {
1650 	ITEM_PORT_ID_ID,
1651 	ITEM_NEXT,
1652 	ZERO,
1653 };
1654 
1655 static const enum index item_mark[] = {
1656 	ITEM_MARK_ID,
1657 	ITEM_NEXT,
1658 	ZERO,
1659 };
1660 
1661 static const enum index item_raw[] = {
1662 	ITEM_RAW_RELATIVE,
1663 	ITEM_RAW_SEARCH,
1664 	ITEM_RAW_OFFSET,
1665 	ITEM_RAW_LIMIT,
1666 	ITEM_RAW_PATTERN,
1667 	ITEM_RAW_PATTERN_HEX,
1668 	ITEM_NEXT,
1669 	ZERO,
1670 };
1671 
1672 static const enum index item_eth[] = {
1673 	ITEM_ETH_DST,
1674 	ITEM_ETH_SRC,
1675 	ITEM_ETH_TYPE,
1676 	ITEM_ETH_HAS_VLAN,
1677 	ITEM_NEXT,
1678 	ZERO,
1679 };
1680 
1681 static const enum index item_vlan[] = {
1682 	ITEM_VLAN_TCI,
1683 	ITEM_VLAN_PCP,
1684 	ITEM_VLAN_DEI,
1685 	ITEM_VLAN_VID,
1686 	ITEM_VLAN_INNER_TYPE,
1687 	ITEM_VLAN_HAS_MORE_VLAN,
1688 	ITEM_NEXT,
1689 	ZERO,
1690 };
1691 
1692 static const enum index item_ipv4[] = {
1693 	ITEM_IPV4_VER_IHL,
1694 	ITEM_IPV4_TOS,
1695 	ITEM_IPV4_LENGTH,
1696 	ITEM_IPV4_ID,
1697 	ITEM_IPV4_FRAGMENT_OFFSET,
1698 	ITEM_IPV4_TTL,
1699 	ITEM_IPV4_PROTO,
1700 	ITEM_IPV4_SRC,
1701 	ITEM_IPV4_DST,
1702 	ITEM_NEXT,
1703 	ZERO,
1704 };
1705 
1706 static const enum index item_ipv6[] = {
1707 	ITEM_IPV6_TC,
1708 	ITEM_IPV6_FLOW,
1709 	ITEM_IPV6_LEN,
1710 	ITEM_IPV6_PROTO,
1711 	ITEM_IPV6_HOP,
1712 	ITEM_IPV6_SRC,
1713 	ITEM_IPV6_DST,
1714 	ITEM_IPV6_HAS_FRAG_EXT,
1715 	ITEM_IPV6_ROUTING_EXT,
1716 	ITEM_NEXT,
1717 	ZERO,
1718 };
1719 
1720 static const enum index item_ipv6_routing_ext[] = {
1721 	ITEM_IPV6_ROUTING_EXT_TYPE,
1722 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
1723 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
1724 	ITEM_NEXT,
1725 	ZERO,
1726 };
1727 
1728 static const enum index item_icmp[] = {
1729 	ITEM_ICMP_TYPE,
1730 	ITEM_ICMP_CODE,
1731 	ITEM_ICMP_IDENT,
1732 	ITEM_ICMP_SEQ,
1733 	ITEM_NEXT,
1734 	ZERO,
1735 };
1736 
1737 static const enum index item_udp[] = {
1738 	ITEM_UDP_SRC,
1739 	ITEM_UDP_DST,
1740 	ITEM_NEXT,
1741 	ZERO,
1742 };
1743 
1744 static const enum index item_tcp[] = {
1745 	ITEM_TCP_SRC,
1746 	ITEM_TCP_DST,
1747 	ITEM_TCP_FLAGS,
1748 	ITEM_NEXT,
1749 	ZERO,
1750 };
1751 
1752 static const enum index item_sctp[] = {
1753 	ITEM_SCTP_SRC,
1754 	ITEM_SCTP_DST,
1755 	ITEM_SCTP_TAG,
1756 	ITEM_SCTP_CKSUM,
1757 	ITEM_NEXT,
1758 	ZERO,
1759 };
1760 
1761 static const enum index item_vxlan[] = {
1762 	ITEM_VXLAN_VNI,
1763 	ITEM_VXLAN_LAST_RSVD,
1764 	ITEM_NEXT,
1765 	ZERO,
1766 };
1767 
1768 static const enum index item_e_tag[] = {
1769 	ITEM_E_TAG_GRP_ECID_B,
1770 	ITEM_NEXT,
1771 	ZERO,
1772 };
1773 
1774 static const enum index item_nvgre[] = {
1775 	ITEM_NVGRE_TNI,
1776 	ITEM_NEXT,
1777 	ZERO,
1778 };
1779 
1780 static const enum index item_mpls[] = {
1781 	ITEM_MPLS_LABEL,
1782 	ITEM_MPLS_TC,
1783 	ITEM_MPLS_S,
1784 	ITEM_MPLS_TTL,
1785 	ITEM_NEXT,
1786 	ZERO,
1787 };
1788 
1789 static const enum index item_gre[] = {
1790 	ITEM_GRE_PROTO,
1791 	ITEM_GRE_C_RSVD0_VER,
1792 	ITEM_GRE_C_BIT,
1793 	ITEM_GRE_K_BIT,
1794 	ITEM_GRE_S_BIT,
1795 	ITEM_NEXT,
1796 	ZERO,
1797 };
1798 
1799 static const enum index item_gre_key[] = {
1800 	ITEM_GRE_KEY_VALUE,
1801 	ITEM_NEXT,
1802 	ZERO,
1803 };
1804 
1805 static const enum index item_gre_option[] = {
1806 	ITEM_GRE_OPTION_CHECKSUM,
1807 	ITEM_GRE_OPTION_KEY,
1808 	ITEM_GRE_OPTION_SEQUENCE,
1809 	ITEM_NEXT,
1810 	ZERO,
1811 };
1812 
1813 static const enum index item_gtp[] = {
1814 	ITEM_GTP_FLAGS,
1815 	ITEM_GTP_MSG_TYPE,
1816 	ITEM_GTP_TEID,
1817 	ITEM_NEXT,
1818 	ZERO,
1819 };
1820 
1821 static const enum index item_geneve[] = {
1822 	ITEM_GENEVE_VNI,
1823 	ITEM_GENEVE_PROTO,
1824 	ITEM_GENEVE_OPTLEN,
1825 	ITEM_NEXT,
1826 	ZERO,
1827 };
1828 
1829 static const enum index item_vxlan_gpe[] = {
1830 	ITEM_VXLAN_GPE_VNI,
1831 	ITEM_VXLAN_GPE_PROTO,
1832 	ITEM_NEXT,
1833 	ZERO,
1834 };
1835 
1836 static const enum index item_arp_eth_ipv4[] = {
1837 	ITEM_ARP_ETH_IPV4_SHA,
1838 	ITEM_ARP_ETH_IPV4_SPA,
1839 	ITEM_ARP_ETH_IPV4_THA,
1840 	ITEM_ARP_ETH_IPV4_TPA,
1841 	ITEM_NEXT,
1842 	ZERO,
1843 };
1844 
1845 static const enum index item_ipv6_ext[] = {
1846 	ITEM_IPV6_EXT_NEXT_HDR,
1847 	ITEM_NEXT,
1848 	ZERO,
1849 };
1850 
1851 static const enum index item_ipv6_frag_ext[] = {
1852 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1853 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1854 	ITEM_IPV6_FRAG_EXT_ID,
1855 	ITEM_NEXT,
1856 	ZERO,
1857 };
1858 
1859 static const enum index item_icmp6[] = {
1860 	ITEM_ICMP6_TYPE,
1861 	ITEM_ICMP6_CODE,
1862 	ITEM_NEXT,
1863 	ZERO,
1864 };
1865 
1866 static const enum index item_icmp6_echo_request[] = {
1867 	ITEM_ICMP6_ECHO_REQUEST_ID,
1868 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
1869 	ITEM_NEXT,
1870 	ZERO,
1871 };
1872 
1873 static const enum index item_icmp6_echo_reply[] = {
1874 	ITEM_ICMP6_ECHO_REPLY_ID,
1875 	ITEM_ICMP6_ECHO_REPLY_SEQ,
1876 	ITEM_NEXT,
1877 	ZERO,
1878 };
1879 
1880 static const enum index item_icmp6_nd_ns[] = {
1881 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
1882 	ITEM_NEXT,
1883 	ZERO,
1884 };
1885 
1886 static const enum index item_icmp6_nd_na[] = {
1887 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
1888 	ITEM_NEXT,
1889 	ZERO,
1890 };
1891 
1892 static const enum index item_icmp6_nd_opt[] = {
1893 	ITEM_ICMP6_ND_OPT_TYPE,
1894 	ITEM_NEXT,
1895 	ZERO,
1896 };
1897 
1898 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1899 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1900 	ITEM_NEXT,
1901 	ZERO,
1902 };
1903 
1904 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1905 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1906 	ITEM_NEXT,
1907 	ZERO,
1908 };
1909 
1910 static const enum index item_meta[] = {
1911 	ITEM_META_DATA,
1912 	ITEM_NEXT,
1913 	ZERO,
1914 };
1915 
1916 static const enum index item_random[] = {
1917 	ITEM_RANDOM_VALUE,
1918 	ITEM_NEXT,
1919 	ZERO,
1920 };
1921 
1922 static const enum index item_gtp_psc[] = {
1923 	ITEM_GTP_PSC_QFI,
1924 	ITEM_GTP_PSC_PDU_T,
1925 	ITEM_NEXT,
1926 	ZERO,
1927 };
1928 
1929 static const enum index item_pppoed[] = {
1930 	ITEM_PPPOE_SEID,
1931 	ITEM_NEXT,
1932 	ZERO,
1933 };
1934 
1935 static const enum index item_pppoes[] = {
1936 	ITEM_PPPOE_SEID,
1937 	ITEM_NEXT,
1938 	ZERO,
1939 };
1940 
1941 static const enum index item_pppoe_proto_id[] = {
1942 	ITEM_NEXT,
1943 	ZERO,
1944 };
1945 
1946 static const enum index item_higig2[] = {
1947 	ITEM_HIGIG2_CLASSIFICATION,
1948 	ITEM_HIGIG2_VID,
1949 	ITEM_NEXT,
1950 	ZERO,
1951 };
1952 
1953 static const enum index item_esp[] = {
1954 	ITEM_ESP_SPI,
1955 	ITEM_NEXT,
1956 	ZERO,
1957 };
1958 
1959 static const enum index item_ah[] = {
1960 	ITEM_AH_SPI,
1961 	ITEM_NEXT,
1962 	ZERO,
1963 };
1964 
1965 static const enum index item_pfcp[] = {
1966 	ITEM_PFCP_S_FIELD,
1967 	ITEM_PFCP_SEID,
1968 	ITEM_NEXT,
1969 	ZERO,
1970 };
1971 
1972 static const enum index next_set_raw[] = {
1973 	SET_RAW_INDEX,
1974 	ITEM_ETH,
1975 	ZERO,
1976 };
1977 
1978 static const enum index item_tag[] = {
1979 	ITEM_TAG_DATA,
1980 	ITEM_TAG_INDEX,
1981 	ITEM_NEXT,
1982 	ZERO,
1983 };
1984 
1985 static const enum index item_l2tpv3oip[] = {
1986 	ITEM_L2TPV3OIP_SESSION_ID,
1987 	ITEM_NEXT,
1988 	ZERO,
1989 };
1990 
1991 static const enum index item_ecpri[] = {
1992 	ITEM_ECPRI_COMMON,
1993 	ITEM_NEXT,
1994 	ZERO,
1995 };
1996 
1997 static const enum index item_ecpri_common[] = {
1998 	ITEM_ECPRI_COMMON_TYPE,
1999 	ZERO,
2000 };
2001 
2002 static const enum index item_ecpri_common_type[] = {
2003 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
2004 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
2005 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
2006 	ZERO,
2007 };
2008 
2009 static const enum index item_geneve_opt[] = {
2010 	ITEM_GENEVE_OPT_CLASS,
2011 	ITEM_GENEVE_OPT_TYPE,
2012 	ITEM_GENEVE_OPT_LENGTH,
2013 	ITEM_GENEVE_OPT_DATA,
2014 	ITEM_NEXT,
2015 	ZERO,
2016 };
2017 
2018 static const enum index item_integrity[] = {
2019 	ITEM_INTEGRITY_LEVEL,
2020 	ITEM_INTEGRITY_VALUE,
2021 	ZERO,
2022 };
2023 
2024 static const enum index item_integrity_lv[] = {
2025 	ITEM_INTEGRITY_LEVEL,
2026 	ITEM_INTEGRITY_VALUE,
2027 	ITEM_NEXT,
2028 	ZERO,
2029 };
2030 
2031 static const enum index item_port_representor[] = {
2032 	ITEM_PORT_REPRESENTOR_PORT_ID,
2033 	ITEM_NEXT,
2034 	ZERO,
2035 };
2036 
2037 static const enum index item_represented_port[] = {
2038 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
2039 	ITEM_NEXT,
2040 	ZERO,
2041 };
2042 
2043 static const enum index item_flex[] = {
2044 	ITEM_FLEX_PATTERN_HANDLE,
2045 	ITEM_FLEX_ITEM_HANDLE,
2046 	ITEM_NEXT,
2047 	ZERO,
2048 };
2049 
2050 static const enum index item_l2tpv2[] = {
2051 	ITEM_L2TPV2_TYPE,
2052 	ITEM_NEXT,
2053 	ZERO,
2054 };
2055 
2056 static const enum index item_l2tpv2_type[] = {
2057 	ITEM_L2TPV2_TYPE_DATA,
2058 	ITEM_L2TPV2_TYPE_DATA_L,
2059 	ITEM_L2TPV2_TYPE_DATA_S,
2060 	ITEM_L2TPV2_TYPE_DATA_O,
2061 	ITEM_L2TPV2_TYPE_DATA_L_S,
2062 	ITEM_L2TPV2_TYPE_CTRL,
2063 	ZERO,
2064 };
2065 
2066 static const enum index item_l2tpv2_type_data[] = {
2067 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
2068 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
2069 	ITEM_NEXT,
2070 	ZERO,
2071 };
2072 
2073 static const enum index item_l2tpv2_type_data_l[] = {
2074 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
2075 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
2076 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
2077 	ITEM_NEXT,
2078 	ZERO,
2079 };
2080 
2081 static const enum index item_l2tpv2_type_data_s[] = {
2082 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
2083 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
2084 	ITEM_L2TPV2_MSG_DATA_S_NS,
2085 	ITEM_L2TPV2_MSG_DATA_S_NR,
2086 	ITEM_NEXT,
2087 	ZERO,
2088 };
2089 
2090 static const enum index item_l2tpv2_type_data_o[] = {
2091 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
2092 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
2093 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
2094 	ITEM_NEXT,
2095 	ZERO,
2096 };
2097 
2098 static const enum index item_l2tpv2_type_data_l_s[] = {
2099 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
2100 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
2101 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
2102 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
2103 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
2104 	ITEM_NEXT,
2105 	ZERO,
2106 };
2107 
2108 static const enum index item_l2tpv2_type_ctrl[] = {
2109 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
2110 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
2111 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
2112 	ITEM_L2TPV2_MSG_CTRL_NS,
2113 	ITEM_L2TPV2_MSG_CTRL_NR,
2114 	ITEM_NEXT,
2115 	ZERO,
2116 };
2117 
2118 static const enum index item_ppp[] = {
2119 	ITEM_PPP_ADDR,
2120 	ITEM_PPP_CTRL,
2121 	ITEM_PPP_PROTO_ID,
2122 	ITEM_NEXT,
2123 	ZERO,
2124 };
2125 
2126 static const enum index item_meter[] = {
2127 	ITEM_METER_COLOR,
2128 	ITEM_NEXT,
2129 	ZERO,
2130 };
2131 
2132 static const enum index item_quota[] = {
2133 	ITEM_QUOTA_STATE,
2134 	ITEM_NEXT,
2135 	ZERO,
2136 };
2137 
2138 static const enum index item_aggr_affinity[] = {
2139 	ITEM_AGGR_AFFINITY_VALUE,
2140 	ITEM_NEXT,
2141 	ZERO,
2142 };
2143 
2144 static const enum index item_tx_queue[] = {
2145 	ITEM_TX_QUEUE_VALUE,
2146 	ITEM_NEXT,
2147 	ZERO,
2148 };
2149 
2150 static const enum index item_ib_bth[] = {
2151 	ITEM_IB_BTH_OPCODE,
2152 	ITEM_IB_BTH_PKEY,
2153 	ITEM_IB_BTH_DST_QPN,
2154 	ITEM_IB_BTH_PSN,
2155 	ITEM_NEXT,
2156 	ZERO,
2157 };
2158 
2159 static const enum index item_ptype[] = {
2160 	ITEM_PTYPE_VALUE,
2161 	ITEM_NEXT,
2162 	ZERO,
2163 };
2164 
2165 static const enum index item_nsh[] = {
2166 	ITEM_NEXT,
2167 	ZERO,
2168 };
2169 
2170 static const enum index item_compare_field[] = {
2171 	ITEM_COMPARE_OP,
2172 	ITEM_COMPARE_FIELD_A_TYPE,
2173 	ITEM_COMPARE_FIELD_B_TYPE,
2174 	ITEM_NEXT,
2175 	ZERO,
2176 };
2177 
2178 static const enum index compare_field_a[] = {
2179 	ITEM_COMPARE_FIELD_A_TYPE,
2180 	ITEM_COMPARE_FIELD_A_LEVEL,
2181 	ITEM_COMPARE_FIELD_A_TAG_INDEX,
2182 	ITEM_COMPARE_FIELD_A_TYPE_ID,
2183 	ITEM_COMPARE_FIELD_A_CLASS_ID,
2184 	ITEM_COMPARE_FIELD_A_OFFSET,
2185 	ITEM_COMPARE_FIELD_B_TYPE,
2186 	ZERO,
2187 };
2188 
2189 static const enum index compare_field_b[] = {
2190 	ITEM_COMPARE_FIELD_B_TYPE,
2191 	ITEM_COMPARE_FIELD_B_LEVEL,
2192 	ITEM_COMPARE_FIELD_B_TAG_INDEX,
2193 	ITEM_COMPARE_FIELD_B_TYPE_ID,
2194 	ITEM_COMPARE_FIELD_B_CLASS_ID,
2195 	ITEM_COMPARE_FIELD_B_OFFSET,
2196 	ITEM_COMPARE_FIELD_B_VALUE,
2197 	ITEM_COMPARE_FIELD_B_POINTER,
2198 	ITEM_COMPARE_FIELD_WIDTH,
2199 	ZERO,
2200 };
2201 
2202 static const enum index next_action[] = {
2203 	ACTION_END,
2204 	ACTION_VOID,
2205 	ACTION_PASSTHRU,
2206 	ACTION_SKIP_CMAN,
2207 	ACTION_JUMP,
2208 	ACTION_MARK,
2209 	ACTION_FLAG,
2210 	ACTION_QUEUE,
2211 	ACTION_DROP,
2212 	ACTION_COUNT,
2213 	ACTION_RSS,
2214 	ACTION_PF,
2215 	ACTION_VF,
2216 	ACTION_PORT_ID,
2217 	ACTION_METER,
2218 	ACTION_METER_COLOR,
2219 	ACTION_METER_MARK,
2220 	ACTION_OF_DEC_NW_TTL,
2221 	ACTION_OF_POP_VLAN,
2222 	ACTION_OF_PUSH_VLAN,
2223 	ACTION_OF_SET_VLAN_VID,
2224 	ACTION_OF_SET_VLAN_PCP,
2225 	ACTION_OF_POP_MPLS,
2226 	ACTION_OF_PUSH_MPLS,
2227 	ACTION_VXLAN_ENCAP,
2228 	ACTION_VXLAN_DECAP,
2229 	ACTION_NVGRE_ENCAP,
2230 	ACTION_NVGRE_DECAP,
2231 	ACTION_L2_ENCAP,
2232 	ACTION_L2_DECAP,
2233 	ACTION_MPLSOGRE_ENCAP,
2234 	ACTION_MPLSOGRE_DECAP,
2235 	ACTION_MPLSOUDP_ENCAP,
2236 	ACTION_MPLSOUDP_DECAP,
2237 	ACTION_SET_IPV4_SRC,
2238 	ACTION_SET_IPV4_DST,
2239 	ACTION_SET_IPV6_SRC,
2240 	ACTION_SET_IPV6_DST,
2241 	ACTION_SET_TP_SRC,
2242 	ACTION_SET_TP_DST,
2243 	ACTION_MAC_SWAP,
2244 	ACTION_DEC_TTL,
2245 	ACTION_SET_TTL,
2246 	ACTION_SET_MAC_SRC,
2247 	ACTION_SET_MAC_DST,
2248 	ACTION_INC_TCP_SEQ,
2249 	ACTION_DEC_TCP_SEQ,
2250 	ACTION_INC_TCP_ACK,
2251 	ACTION_DEC_TCP_ACK,
2252 	ACTION_RAW_ENCAP,
2253 	ACTION_RAW_DECAP,
2254 	ACTION_SET_TAG,
2255 	ACTION_SET_META,
2256 	ACTION_SET_IPV4_DSCP,
2257 	ACTION_SET_IPV6_DSCP,
2258 	ACTION_AGE,
2259 	ACTION_AGE_UPDATE,
2260 	ACTION_SAMPLE,
2261 	ACTION_INDIRECT,
2262 	ACTION_INDIRECT_LIST,
2263 	ACTION_SHARED_INDIRECT,
2264 	ACTION_MODIFY_FIELD,
2265 	ACTION_CONNTRACK,
2266 	ACTION_CONNTRACK_UPDATE,
2267 	ACTION_PORT_REPRESENTOR,
2268 	ACTION_REPRESENTED_PORT,
2269 	ACTION_SEND_TO_KERNEL,
2270 	ACTION_QUOTA_CREATE,
2271 	ACTION_QUOTA_QU,
2272 	ACTION_IPV6_EXT_REMOVE,
2273 	ACTION_IPV6_EXT_PUSH,
2274 	ACTION_NAT64,
2275 	ZERO,
2276 };
2277 
2278 static const enum index action_quota_create[] = {
2279 	ACTION_QUOTA_CREATE_LIMIT,
2280 	ACTION_QUOTA_CREATE_MODE,
2281 	ACTION_NEXT,
2282 	ZERO
2283 };
2284 
2285 static const enum index action_quota_update[] = {
2286 	ACTION_QUOTA_QU_LIMIT,
2287 	ACTION_QUOTA_QU_UPDATE_OP,
2288 	ACTION_NEXT,
2289 	ZERO
2290 };
2291 
2292 static const enum index action_mark[] = {
2293 	ACTION_MARK_ID,
2294 	ACTION_NEXT,
2295 	ZERO,
2296 };
2297 
2298 static const enum index action_queue[] = {
2299 	ACTION_QUEUE_INDEX,
2300 	ACTION_NEXT,
2301 	ZERO,
2302 };
2303 
2304 static const enum index action_count[] = {
2305 	ACTION_COUNT_ID,
2306 	ACTION_NEXT,
2307 	ZERO,
2308 };
2309 
2310 static const enum index action_rss[] = {
2311 	ACTION_RSS_FUNC,
2312 	ACTION_RSS_LEVEL,
2313 	ACTION_RSS_TYPES,
2314 	ACTION_RSS_KEY,
2315 	ACTION_RSS_KEY_LEN,
2316 	ACTION_RSS_QUEUES,
2317 	ACTION_NEXT,
2318 	ZERO,
2319 };
2320 
2321 static const enum index action_vf[] = {
2322 	ACTION_VF_ORIGINAL,
2323 	ACTION_VF_ID,
2324 	ACTION_NEXT,
2325 	ZERO,
2326 };
2327 
2328 static const enum index action_port_id[] = {
2329 	ACTION_PORT_ID_ORIGINAL,
2330 	ACTION_PORT_ID_ID,
2331 	ACTION_NEXT,
2332 	ZERO,
2333 };
2334 
2335 static const enum index action_meter[] = {
2336 	ACTION_METER_ID,
2337 	ACTION_NEXT,
2338 	ZERO,
2339 };
2340 
2341 static const enum index action_meter_color[] = {
2342 	ACTION_METER_COLOR_TYPE,
2343 	ACTION_NEXT,
2344 	ZERO,
2345 };
2346 
2347 static const enum index action_meter_mark[] = {
2348 	ACTION_METER_PROFILE,
2349 	ACTION_METER_POLICY,
2350 	ACTION_METER_COLOR_MODE,
2351 	ACTION_METER_STATE,
2352 	ACTION_NEXT,
2353 	ZERO,
2354 };
2355 
2356 static const enum index action_of_push_vlan[] = {
2357 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
2358 	ACTION_NEXT,
2359 	ZERO,
2360 };
2361 
2362 static const enum index action_of_set_vlan_vid[] = {
2363 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
2364 	ACTION_NEXT,
2365 	ZERO,
2366 };
2367 
2368 static const enum index action_of_set_vlan_pcp[] = {
2369 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
2370 	ACTION_NEXT,
2371 	ZERO,
2372 };
2373 
2374 static const enum index action_of_pop_mpls[] = {
2375 	ACTION_OF_POP_MPLS_ETHERTYPE,
2376 	ACTION_NEXT,
2377 	ZERO,
2378 };
2379 
2380 static const enum index action_of_push_mpls[] = {
2381 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
2382 	ACTION_NEXT,
2383 	ZERO,
2384 };
2385 
2386 static const enum index action_set_ipv4_src[] = {
2387 	ACTION_SET_IPV4_SRC_IPV4_SRC,
2388 	ACTION_NEXT,
2389 	ZERO,
2390 };
2391 
2392 static const enum index action_set_mac_src[] = {
2393 	ACTION_SET_MAC_SRC_MAC_SRC,
2394 	ACTION_NEXT,
2395 	ZERO,
2396 };
2397 
2398 static const enum index action_set_ipv4_dst[] = {
2399 	ACTION_SET_IPV4_DST_IPV4_DST,
2400 	ACTION_NEXT,
2401 	ZERO,
2402 };
2403 
2404 static const enum index action_set_ipv6_src[] = {
2405 	ACTION_SET_IPV6_SRC_IPV6_SRC,
2406 	ACTION_NEXT,
2407 	ZERO,
2408 };
2409 
2410 static const enum index action_set_ipv6_dst[] = {
2411 	ACTION_SET_IPV6_DST_IPV6_DST,
2412 	ACTION_NEXT,
2413 	ZERO,
2414 };
2415 
2416 static const enum index action_set_tp_src[] = {
2417 	ACTION_SET_TP_SRC_TP_SRC,
2418 	ACTION_NEXT,
2419 	ZERO,
2420 };
2421 
2422 static const enum index action_set_tp_dst[] = {
2423 	ACTION_SET_TP_DST_TP_DST,
2424 	ACTION_NEXT,
2425 	ZERO,
2426 };
2427 
2428 static const enum index action_set_ttl[] = {
2429 	ACTION_SET_TTL_TTL,
2430 	ACTION_NEXT,
2431 	ZERO,
2432 };
2433 
2434 static const enum index action_jump[] = {
2435 	ACTION_JUMP_GROUP,
2436 	ACTION_NEXT,
2437 	ZERO,
2438 };
2439 
2440 static const enum index action_set_mac_dst[] = {
2441 	ACTION_SET_MAC_DST_MAC_DST,
2442 	ACTION_NEXT,
2443 	ZERO,
2444 };
2445 
2446 static const enum index action_inc_tcp_seq[] = {
2447 	ACTION_INC_TCP_SEQ_VALUE,
2448 	ACTION_NEXT,
2449 	ZERO,
2450 };
2451 
2452 static const enum index action_dec_tcp_seq[] = {
2453 	ACTION_DEC_TCP_SEQ_VALUE,
2454 	ACTION_NEXT,
2455 	ZERO,
2456 };
2457 
2458 static const enum index action_inc_tcp_ack[] = {
2459 	ACTION_INC_TCP_ACK_VALUE,
2460 	ACTION_NEXT,
2461 	ZERO,
2462 };
2463 
2464 static const enum index action_dec_tcp_ack[] = {
2465 	ACTION_DEC_TCP_ACK_VALUE,
2466 	ACTION_NEXT,
2467 	ZERO,
2468 };
2469 
2470 static const enum index action_raw_encap[] = {
2471 	ACTION_RAW_ENCAP_SIZE,
2472 	ACTION_RAW_ENCAP_INDEX,
2473 	ACTION_NEXT,
2474 	ZERO,
2475 };
2476 
2477 static const enum index action_raw_decap[] = {
2478 	ACTION_RAW_DECAP_INDEX,
2479 	ACTION_NEXT,
2480 	ZERO,
2481 };
2482 
2483 static const enum index action_ipv6_ext_remove[] = {
2484 	ACTION_IPV6_EXT_REMOVE_INDEX,
2485 	ACTION_NEXT,
2486 	ZERO,
2487 };
2488 
2489 static const enum index action_ipv6_ext_push[] = {
2490 	ACTION_IPV6_EXT_PUSH_INDEX,
2491 	ACTION_NEXT,
2492 	ZERO,
2493 };
2494 
2495 static const enum index action_set_tag[] = {
2496 	ACTION_SET_TAG_DATA,
2497 	ACTION_SET_TAG_INDEX,
2498 	ACTION_SET_TAG_MASK,
2499 	ACTION_NEXT,
2500 	ZERO,
2501 };
2502 
2503 static const enum index action_set_meta[] = {
2504 	ACTION_SET_META_DATA,
2505 	ACTION_SET_META_MASK,
2506 	ACTION_NEXT,
2507 	ZERO,
2508 };
2509 
2510 static const enum index action_set_ipv4_dscp[] = {
2511 	ACTION_SET_IPV4_DSCP_VALUE,
2512 	ACTION_NEXT,
2513 	ZERO,
2514 };
2515 
2516 static const enum index action_set_ipv6_dscp[] = {
2517 	ACTION_SET_IPV6_DSCP_VALUE,
2518 	ACTION_NEXT,
2519 	ZERO,
2520 };
2521 
2522 static const enum index action_age[] = {
2523 	ACTION_AGE,
2524 	ACTION_AGE_TIMEOUT,
2525 	ACTION_NEXT,
2526 	ZERO,
2527 };
2528 
2529 static const enum index action_age_update[] = {
2530 	ACTION_AGE_UPDATE,
2531 	ACTION_AGE_UPDATE_TIMEOUT,
2532 	ACTION_AGE_UPDATE_TOUCH,
2533 	ACTION_NEXT,
2534 	ZERO,
2535 };
2536 
2537 static const enum index action_sample[] = {
2538 	ACTION_SAMPLE,
2539 	ACTION_SAMPLE_RATIO,
2540 	ACTION_SAMPLE_INDEX,
2541 	ACTION_NEXT,
2542 	ZERO,
2543 };
2544 
2545 static const enum index next_action_sample[] = {
2546 	ACTION_QUEUE,
2547 	ACTION_RSS,
2548 	ACTION_MARK,
2549 	ACTION_COUNT,
2550 	ACTION_PORT_ID,
2551 	ACTION_RAW_ENCAP,
2552 	ACTION_VXLAN_ENCAP,
2553 	ACTION_NVGRE_ENCAP,
2554 	ACTION_REPRESENTED_PORT,
2555 	ACTION_PORT_REPRESENTOR,
2556 	ACTION_NEXT,
2557 	ZERO,
2558 };
2559 
2560 static const enum index item_ipv6_push_ext[] = {
2561 	ITEM_IPV6_PUSH_REMOVE_EXT,
2562 	ZERO,
2563 };
2564 
2565 static const enum index item_ipv6_push_ext_type[] = {
2566 	ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
2567 	ZERO,
2568 };
2569 
2570 static const enum index item_ipv6_push_ext_header[] = {
2571 	ITEM_IPV6_ROUTING_EXT,
2572 	ITEM_NEXT,
2573 	ZERO,
2574 };
2575 
2576 static const enum index action_modify_field_dst[] = {
2577 	ACTION_MODIFY_FIELD_DST_LEVEL,
2578 	ACTION_MODIFY_FIELD_DST_TAG_INDEX,
2579 	ACTION_MODIFY_FIELD_DST_TYPE_ID,
2580 	ACTION_MODIFY_FIELD_DST_CLASS_ID,
2581 	ACTION_MODIFY_FIELD_DST_OFFSET,
2582 	ACTION_MODIFY_FIELD_SRC_TYPE,
2583 	ZERO,
2584 };
2585 
2586 static const enum index action_modify_field_src[] = {
2587 	ACTION_MODIFY_FIELD_SRC_LEVEL,
2588 	ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
2589 	ACTION_MODIFY_FIELD_SRC_TYPE_ID,
2590 	ACTION_MODIFY_FIELD_SRC_CLASS_ID,
2591 	ACTION_MODIFY_FIELD_SRC_OFFSET,
2592 	ACTION_MODIFY_FIELD_SRC_VALUE,
2593 	ACTION_MODIFY_FIELD_SRC_POINTER,
2594 	ACTION_MODIFY_FIELD_WIDTH,
2595 	ZERO,
2596 };
2597 
2598 static const enum index action_update_conntrack[] = {
2599 	ACTION_CONNTRACK_UPDATE_DIR,
2600 	ACTION_CONNTRACK_UPDATE_CTX,
2601 	ACTION_NEXT,
2602 	ZERO,
2603 };
2604 
2605 static const enum index action_port_representor[] = {
2606 	ACTION_PORT_REPRESENTOR_PORT_ID,
2607 	ACTION_NEXT,
2608 	ZERO,
2609 };
2610 
2611 static const enum index action_represented_port[] = {
2612 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
2613 	ACTION_NEXT,
2614 	ZERO,
2615 };
2616 
2617 static const enum index action_nat64[] = {
2618 	ACTION_NAT64_MODE,
2619 	ACTION_NEXT,
2620 	ZERO,
2621 };
2622 
2623 static const enum index next_hash_subcmd[] = {
2624 	HASH_CALC_TABLE,
2625 	HASH_CALC_ENCAP,
2626 	ZERO,
2627 };
2628 
2629 static const enum index next_hash_encap_dest_subcmd[] = {
2630 	ENCAP_HASH_FIELD_SRC_PORT,
2631 	ENCAP_HASH_FIELD_GRE_FLOW_ID,
2632 	ZERO,
2633 };
2634 
2635 static int parse_set_raw_encap_decap(struct context *, const struct token *,
2636 				     const char *, unsigned int,
2637 				     void *, unsigned int);
2638 static int parse_set_sample_action(struct context *, const struct token *,
2639 				   const char *, unsigned int,
2640 				   void *, unsigned int);
2641 static int parse_set_ipv6_ext_action(struct context *, const struct token *,
2642 				     const char *, unsigned int,
2643 				     void *, unsigned int);
2644 static int parse_set_init(struct context *, const struct token *,
2645 			  const char *, unsigned int,
2646 			  void *, unsigned int);
2647 static int
2648 parse_flex_handle(struct context *, const struct token *,
2649 		  const char *, unsigned int, void *, unsigned int);
2650 static int parse_init(struct context *, const struct token *,
2651 		      const char *, unsigned int,
2652 		      void *, unsigned int);
2653 static int parse_vc(struct context *, const struct token *,
2654 		    const char *, unsigned int,
2655 		    void *, unsigned int);
2656 static int parse_vc_spec(struct context *, const struct token *,
2657 			 const char *, unsigned int, void *, unsigned int);
2658 static int parse_vc_conf(struct context *, const struct token *,
2659 			 const char *, unsigned int, void *, unsigned int);
2660 static int parse_vc_conf_timeout(struct context *, const struct token *,
2661 				 const char *, unsigned int, void *,
2662 				 unsigned int);
2663 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
2664 				    const char *, unsigned int,
2665 				    void *, unsigned int);
2666 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *,
2667 				    const char *, unsigned int,
2668 				    void *, unsigned int);
2669 static int parse_vc_action_meter_color_type(struct context *,
2670 					const struct token *,
2671 					const char *, unsigned int, void *,
2672 					unsigned int);
2673 static int parse_vc_action_rss(struct context *, const struct token *,
2674 			       const char *, unsigned int, void *,
2675 			       unsigned int);
2676 static int parse_vc_action_rss_func(struct context *, const struct token *,
2677 				    const char *, unsigned int, void *,
2678 				    unsigned int);
2679 static int parse_vc_action_rss_type(struct context *, const struct token *,
2680 				    const char *, unsigned int, void *,
2681 				    unsigned int);
2682 static int parse_vc_action_rss_queue(struct context *, const struct token *,
2683 				     const char *, unsigned int, void *,
2684 				     unsigned int);
2685 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
2686 				       const char *, unsigned int, void *,
2687 				       unsigned int);
2688 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
2689 				       const char *, unsigned int, void *,
2690 				       unsigned int);
2691 static int parse_vc_action_l2_encap(struct context *, const struct token *,
2692 				    const char *, unsigned int, void *,
2693 				    unsigned int);
2694 static int parse_vc_action_l2_decap(struct context *, const struct token *,
2695 				    const char *, unsigned int, void *,
2696 				    unsigned int);
2697 static int parse_vc_action_mplsogre_encap(struct context *,
2698 					  const struct token *, const char *,
2699 					  unsigned int, void *, unsigned int);
2700 static int parse_vc_action_mplsogre_decap(struct context *,
2701 					  const struct token *, const char *,
2702 					  unsigned int, void *, unsigned int);
2703 static int parse_vc_action_mplsoudp_encap(struct context *,
2704 					  const struct token *, const char *,
2705 					  unsigned int, void *, unsigned int);
2706 static int parse_vc_action_mplsoudp_decap(struct context *,
2707 					  const struct token *, const char *,
2708 					  unsigned int, void *, unsigned int);
2709 static int parse_vc_action_raw_encap(struct context *,
2710 				     const struct token *, const char *,
2711 				     unsigned int, void *, unsigned int);
2712 static int parse_vc_action_raw_decap(struct context *,
2713 				     const struct token *, const char *,
2714 				     unsigned int, void *, unsigned int);
2715 static int parse_vc_action_raw_encap_index(struct context *,
2716 					   const struct token *, const char *,
2717 					   unsigned int, void *, unsigned int);
2718 static int parse_vc_action_raw_decap_index(struct context *,
2719 					   const struct token *, const char *,
2720 					   unsigned int, void *, unsigned int);
2721 static int parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
2722 					   const char *str, unsigned int len, void *buf,
2723 					   unsigned int size);
2724 static int parse_vc_action_ipv6_ext_remove_index(struct context *ctx,
2725 						 const struct token *token,
2726 						 const char *str, unsigned int len,
2727 						 void *buf,
2728 						 unsigned int size);
2729 static int parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
2730 					 const char *str, unsigned int len, void *buf,
2731 					 unsigned int size);
2732 static int parse_vc_action_ipv6_ext_push_index(struct context *ctx,
2733 					       const struct token *token,
2734 					       const char *str, unsigned int len,
2735 					       void *buf,
2736 					       unsigned int size);
2737 static int parse_vc_action_set_meta(struct context *ctx,
2738 				    const struct token *token, const char *str,
2739 				    unsigned int len, void *buf,
2740 					unsigned int size);
2741 static int parse_vc_action_sample(struct context *ctx,
2742 				    const struct token *token, const char *str,
2743 				    unsigned int len, void *buf,
2744 				    unsigned int size);
2745 static int
2746 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
2747 				const char *str, unsigned int len, void *buf,
2748 				unsigned int size);
2749 static int
2750 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
2751 				const char *str, unsigned int len, void *buf,
2752 				unsigned int size);
2753 static int
2754 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
2755 				const char *str, unsigned int len, void *buf,
2756 				unsigned int size);
2757 static int
2758 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
2759 				const char *str, unsigned int len, void *buf,
2760 				unsigned int size);
2761 static int
2762 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
2763 			 const char *str, unsigned int len, void *buf,
2764 			 unsigned int size);
2765 static int parse_destroy(struct context *, const struct token *,
2766 			 const char *, unsigned int,
2767 			 void *, unsigned int);
2768 static int parse_flush(struct context *, const struct token *,
2769 		       const char *, unsigned int,
2770 		       void *, unsigned int);
2771 static int parse_dump(struct context *, const struct token *,
2772 		      const char *, unsigned int,
2773 		      void *, unsigned int);
2774 static int parse_query(struct context *, const struct token *,
2775 		       const char *, unsigned int,
2776 		       void *, unsigned int);
2777 static int parse_action(struct context *, const struct token *,
2778 			const char *, unsigned int,
2779 			void *, unsigned int);
2780 static int parse_list(struct context *, const struct token *,
2781 		      const char *, unsigned int,
2782 		      void *, unsigned int);
2783 static int parse_aged(struct context *, const struct token *,
2784 		      const char *, unsigned int,
2785 		      void *, unsigned int);
2786 static int parse_isolate(struct context *, const struct token *,
2787 			 const char *, unsigned int,
2788 			 void *, unsigned int);
2789 static int parse_configure(struct context *, const struct token *,
2790 			   const char *, unsigned int,
2791 			   void *, unsigned int);
2792 static int parse_template(struct context *, const struct token *,
2793 			  const char *, unsigned int,
2794 			  void *, unsigned int);
2795 static int parse_template_destroy(struct context *, const struct token *,
2796 				  const char *, unsigned int,
2797 				  void *, unsigned int);
2798 static int parse_table(struct context *, const struct token *,
2799 		       const char *, unsigned int, void *, unsigned int);
2800 static int parse_table_destroy(struct context *, const struct token *,
2801 			       const char *, unsigned int,
2802 			       void *, unsigned int);
2803 static int parse_qo(struct context *, const struct token *,
2804 		    const char *, unsigned int,
2805 		    void *, unsigned int);
2806 static int parse_qo_destroy(struct context *, const struct token *,
2807 			    const char *, unsigned int,
2808 			    void *, unsigned int);
2809 static int parse_qia(struct context *, const struct token *,
2810 		     const char *, unsigned int,
2811 		     void *, unsigned int);
2812 static int parse_qia_destroy(struct context *, const struct token *,
2813 			     const char *, unsigned int,
2814 			     void *, unsigned int);
2815 static int parse_push(struct context *, const struct token *,
2816 		      const char *, unsigned int,
2817 		      void *, unsigned int);
2818 static int parse_pull(struct context *, const struct token *,
2819 		      const char *, unsigned int,
2820 		      void *, unsigned int);
2821 static int parse_group(struct context *, const struct token *,
2822 		       const char *, unsigned int,
2823 		       void *, unsigned int);
2824 static int parse_hash(struct context *, const struct token *,
2825 		      const char *, unsigned int,
2826 		      void *, unsigned int);
2827 static int parse_tunnel(struct context *, const struct token *,
2828 			const char *, unsigned int,
2829 			void *, unsigned int);
2830 static int parse_flex(struct context *, const struct token *,
2831 		      const char *, unsigned int, void *, unsigned int);
2832 static int parse_int(struct context *, const struct token *,
2833 		     const char *, unsigned int,
2834 		     void *, unsigned int);
2835 static int parse_prefix(struct context *, const struct token *,
2836 			const char *, unsigned int,
2837 			void *, unsigned int);
2838 static int parse_boolean(struct context *, const struct token *,
2839 			 const char *, unsigned int,
2840 			 void *, unsigned int);
2841 static int parse_string(struct context *, const struct token *,
2842 			const char *, unsigned int,
2843 			void *, unsigned int);
2844 static int parse_hex(struct context *ctx, const struct token *token,
2845 			const char *str, unsigned int len,
2846 			void *buf, unsigned int size);
2847 static int parse_string0(struct context *, const struct token *,
2848 			const char *, unsigned int,
2849 			void *, unsigned int);
2850 static int parse_mac_addr(struct context *, const struct token *,
2851 			  const char *, unsigned int,
2852 			  void *, unsigned int);
2853 static int parse_ipv4_addr(struct context *, const struct token *,
2854 			   const char *, unsigned int,
2855 			   void *, unsigned int);
2856 static int parse_ipv6_addr(struct context *, const struct token *,
2857 			   const char *, unsigned int,
2858 			   void *, unsigned int);
2859 static int parse_port(struct context *, const struct token *,
2860 		      const char *, unsigned int,
2861 		      void *, unsigned int);
2862 static int parse_ia(struct context *, const struct token *,
2863 		    const char *, unsigned int,
2864 		    void *, unsigned int);
2865 static int parse_ia_destroy(struct context *ctx, const struct token *token,
2866 			    const char *str, unsigned int len,
2867 			    void *buf, unsigned int size);
2868 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
2869 			   const char *str, unsigned int len, void *buf,
2870 			   unsigned int size);
2871 
2872 static int parse_indlst_id2ptr(struct context *ctx, const struct token *token,
2873 			       const char *str, unsigned int len, void *buf,
2874 			       unsigned int size);
2875 static int parse_ia_port(struct context *ctx, const struct token *token,
2876 			 const char *str, unsigned int len, void *buf,
2877 			 unsigned int size);
2878 static int parse_mp(struct context *, const struct token *,
2879 		    const char *, unsigned int,
2880 		    void *, unsigned int);
2881 static int parse_meter_profile_id2ptr(struct context *ctx,
2882 				      const struct token *token,
2883 				      const char *str, unsigned int len,
2884 				      void *buf, unsigned int size);
2885 static int parse_meter_policy_id2ptr(struct context *ctx,
2886 				     const struct token *token,
2887 				     const char *str, unsigned int len,
2888 				     void *buf, unsigned int size);
2889 static int parse_meter_color(struct context *ctx, const struct token *token,
2890 			     const char *str, unsigned int len, void *buf,
2891 			     unsigned int size);
2892 static int parse_insertion_table_type(struct context *ctx, const struct token *token,
2893 				      const char *str, unsigned int len, void *buf,
2894 				      unsigned int size);
2895 static int parse_hash_table_type(struct context *ctx, const struct token *token,
2896 				 const char *str, unsigned int len, void *buf,
2897 				 unsigned int size);
2898 static int
2899 parse_quota_state_name(struct context *ctx, const struct token *token,
2900 		       const char *str, unsigned int len, void *buf,
2901 		       unsigned int size);
2902 static int
2903 parse_quota_mode_name(struct context *ctx, const struct token *token,
2904 		      const char *str, unsigned int len, void *buf,
2905 		      unsigned int size);
2906 static int
2907 parse_quota_update_name(struct context *ctx, const struct token *token,
2908 			const char *str, unsigned int len, void *buf,
2909 			unsigned int size);
2910 static int
2911 parse_qu_mode_name(struct context *ctx, const struct token *token,
2912 		   const char *str, unsigned int len, void *buf,
2913 		   unsigned int size);
2914 static int comp_none(struct context *, const struct token *,
2915 		     unsigned int, char *, unsigned int);
2916 static int comp_boolean(struct context *, const struct token *,
2917 			unsigned int, char *, unsigned int);
2918 static int comp_action(struct context *, const struct token *,
2919 		       unsigned int, char *, unsigned int);
2920 static int comp_port(struct context *, const struct token *,
2921 		     unsigned int, char *, unsigned int);
2922 static int comp_rule_id(struct context *, const struct token *,
2923 			unsigned int, char *, unsigned int);
2924 static int comp_vc_action_rss_type(struct context *, const struct token *,
2925 				   unsigned int, char *, unsigned int);
2926 static int comp_vc_action_rss_queue(struct context *, const struct token *,
2927 				    unsigned int, char *, unsigned int);
2928 static int comp_set_raw_index(struct context *, const struct token *,
2929 			      unsigned int, char *, unsigned int);
2930 static int comp_set_sample_index(struct context *, const struct token *,
2931 			      unsigned int, char *, unsigned int);
2932 static int comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
2933 				   unsigned int ent, char *buf, unsigned int size);
2934 static int comp_set_modify_field_op(struct context *, const struct token *,
2935 			      unsigned int, char *, unsigned int);
2936 static int comp_set_modify_field_id(struct context *, const struct token *,
2937 			      unsigned int, char *, unsigned int);
2938 static int comp_pattern_template_id(struct context *, const struct token *,
2939 				    unsigned int, char *, unsigned int);
2940 static int comp_actions_template_id(struct context *, const struct token *,
2941 				    unsigned int, char *, unsigned int);
2942 static int comp_table_id(struct context *, const struct token *,
2943 			 unsigned int, char *, unsigned int);
2944 static int comp_queue_id(struct context *, const struct token *,
2945 			 unsigned int, char *, unsigned int);
2946 static int comp_meter_color(struct context *, const struct token *,
2947 			    unsigned int, char *, unsigned int);
2948 static int comp_insertion_table_type(struct context *, const struct token *,
2949 				     unsigned int, char *, unsigned int);
2950 static int comp_hash_table_type(struct context *, const struct token *,
2951 				unsigned int, char *, unsigned int);
2952 static int
2953 comp_quota_state_name(struct context *ctx, const struct token *token,
2954 		      unsigned int ent, char *buf, unsigned int size);
2955 static int
2956 comp_quota_mode_name(struct context *ctx, const struct token *token,
2957 		     unsigned int ent, char *buf, unsigned int size);
2958 static int
2959 comp_quota_update_name(struct context *ctx, const struct token *token,
2960 		       unsigned int ent, char *buf, unsigned int size);
2961 static int
2962 comp_qu_mode_name(struct context *ctx, const struct token *token,
2963 		  unsigned int ent, char *buf, unsigned int size);
2964 static int
2965 comp_set_compare_field_id(struct context *ctx, const struct token *token,
2966 			  unsigned int ent, char *buf, unsigned int size);
2967 static int
2968 comp_set_compare_op(struct context *ctx, const struct token *token,
2969 		    unsigned int ent, char *buf, unsigned int size);
2970 static int
2971 parse_vc_compare_op(struct context *ctx, const struct token *token,
2972 			 const char *str, unsigned int len, void *buf,
2973 			 unsigned int size);
2974 static int
2975 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
2976 			  const char *str, unsigned int len, void *buf,
2977 			  unsigned int size);
2978 static int
2979 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
2980 			     const char *str, unsigned int len, void *buf,
2981 			     unsigned int size);
2982 
2983 struct indlst_conf {
2984 	uint32_t id;
2985 	uint32_t conf_num;
2986 	struct rte_flow_action *actions;
2987 	const void **conf;
2988 	SLIST_ENTRY(indlst_conf) next;
2989 };
2990 
2991 static const struct indlst_conf *indirect_action_list_conf_get(uint32_t conf_id);
2992 
2993 /** Token definitions. */
2994 static const struct token token_list[] = {
2995 	/* Special tokens. */
2996 	[ZERO] = {
2997 		.name = "ZERO",
2998 		.help = "null entry, abused as the entry point",
2999 		.next = NEXT(NEXT_ENTRY(FLOW, ADD)),
3000 	},
3001 	[END] = {
3002 		.name = "",
3003 		.type = "RETURN",
3004 		.help = "command may end here",
3005 	},
3006 	[START_SET] = {
3007 		.name = "START_SET",
3008 		.help = "null entry, abused as the entry point for set",
3009 		.next = NEXT(NEXT_ENTRY(SET)),
3010 	},
3011 	[END_SET] = {
3012 		.name = "end_set",
3013 		.type = "RETURN",
3014 		.help = "set command may end here",
3015 	},
3016 	/* Common tokens. */
3017 	[COMMON_INTEGER] = {
3018 		.name = "{int}",
3019 		.type = "INTEGER",
3020 		.help = "integer value",
3021 		.call = parse_int,
3022 		.comp = comp_none,
3023 	},
3024 	[COMMON_UNSIGNED] = {
3025 		.name = "{unsigned}",
3026 		.type = "UNSIGNED",
3027 		.help = "unsigned integer value",
3028 		.call = parse_int,
3029 		.comp = comp_none,
3030 	},
3031 	[COMMON_PREFIX] = {
3032 		.name = "{prefix}",
3033 		.type = "PREFIX",
3034 		.help = "prefix length for bit-mask",
3035 		.call = parse_prefix,
3036 		.comp = comp_none,
3037 	},
3038 	[COMMON_BOOLEAN] = {
3039 		.name = "{boolean}",
3040 		.type = "BOOLEAN",
3041 		.help = "any boolean value",
3042 		.call = parse_boolean,
3043 		.comp = comp_boolean,
3044 	},
3045 	[COMMON_STRING] = {
3046 		.name = "{string}",
3047 		.type = "STRING",
3048 		.help = "fixed string",
3049 		.call = parse_string,
3050 		.comp = comp_none,
3051 	},
3052 	[COMMON_HEX] = {
3053 		.name = "{hex}",
3054 		.type = "HEX",
3055 		.help = "fixed string",
3056 		.call = parse_hex,
3057 	},
3058 	[COMMON_FILE_PATH] = {
3059 		.name = "{file path}",
3060 		.type = "STRING",
3061 		.help = "file path",
3062 		.call = parse_string0,
3063 		.comp = comp_none,
3064 	},
3065 	[COMMON_MAC_ADDR] = {
3066 		.name = "{MAC address}",
3067 		.type = "MAC-48",
3068 		.help = "standard MAC address notation",
3069 		.call = parse_mac_addr,
3070 		.comp = comp_none,
3071 	},
3072 	[COMMON_IPV4_ADDR] = {
3073 		.name = "{IPv4 address}",
3074 		.type = "IPV4 ADDRESS",
3075 		.help = "standard IPv4 address notation",
3076 		.call = parse_ipv4_addr,
3077 		.comp = comp_none,
3078 	},
3079 	[COMMON_IPV6_ADDR] = {
3080 		.name = "{IPv6 address}",
3081 		.type = "IPV6 ADDRESS",
3082 		.help = "standard IPv6 address notation",
3083 		.call = parse_ipv6_addr,
3084 		.comp = comp_none,
3085 	},
3086 	[COMMON_RULE_ID] = {
3087 		.name = "{rule id}",
3088 		.type = "RULE ID",
3089 		.help = "rule identifier",
3090 		.call = parse_int,
3091 		.comp = comp_rule_id,
3092 	},
3093 	[COMMON_PORT_ID] = {
3094 		.name = "{port_id}",
3095 		.type = "PORT ID",
3096 		.help = "port identifier",
3097 		.call = parse_port,
3098 		.comp = comp_port,
3099 	},
3100 	[COMMON_GROUP_ID] = {
3101 		.name = "{group_id}",
3102 		.type = "GROUP ID",
3103 		.help = "group identifier",
3104 		.call = parse_int,
3105 		.comp = comp_none,
3106 	},
3107 	[COMMON_PRIORITY_LEVEL] = {
3108 		.name = "{level}",
3109 		.type = "PRIORITY",
3110 		.help = "priority level",
3111 		.call = parse_int,
3112 		.comp = comp_none,
3113 	},
3114 	[COMMON_INDIRECT_ACTION_ID] = {
3115 		.name = "{indirect_action_id}",
3116 		.type = "INDIRECT_ACTION_ID",
3117 		.help = "indirect action id",
3118 		.call = parse_int,
3119 		.comp = comp_none,
3120 	},
3121 	[COMMON_PROFILE_ID] = {
3122 		.name = "{profile_id}",
3123 		.type = "PROFILE_ID",
3124 		.help = "profile id",
3125 		.call = parse_int,
3126 		.comp = comp_none,
3127 	},
3128 	[COMMON_POLICY_ID] = {
3129 		.name = "{policy_id}",
3130 		.type = "POLICY_ID",
3131 		.help = "policy id",
3132 		.call = parse_int,
3133 		.comp = comp_none,
3134 	},
3135 	[COMMON_FLEX_TOKEN] = {
3136 		.name = "{flex token}",
3137 		.type = "flex token",
3138 		.help = "flex token",
3139 		.call = parse_int,
3140 		.comp = comp_none,
3141 	},
3142 	[COMMON_FLEX_HANDLE] = {
3143 		.name = "{flex handle}",
3144 		.type = "FLEX HANDLE",
3145 		.help = "fill flex item data",
3146 		.call = parse_flex_handle,
3147 		.comp = comp_none,
3148 	},
3149 	[COMMON_PATTERN_TEMPLATE_ID] = {
3150 		.name = "{pattern_template_id}",
3151 		.type = "PATTERN_TEMPLATE_ID",
3152 		.help = "pattern template id",
3153 		.call = parse_int,
3154 		.comp = comp_pattern_template_id,
3155 	},
3156 	[COMMON_ACTIONS_TEMPLATE_ID] = {
3157 		.name = "{actions_template_id}",
3158 		.type = "ACTIONS_TEMPLATE_ID",
3159 		.help = "actions template id",
3160 		.call = parse_int,
3161 		.comp = comp_actions_template_id,
3162 	},
3163 	[COMMON_TABLE_ID] = {
3164 		.name = "{table_id}",
3165 		.type = "TABLE_ID",
3166 		.help = "table id",
3167 		.call = parse_int,
3168 		.comp = comp_table_id,
3169 	},
3170 	[COMMON_QUEUE_ID] = {
3171 		.name = "{queue_id}",
3172 		.type = "QUEUE_ID",
3173 		.help = "queue id",
3174 		.call = parse_int,
3175 		.comp = comp_queue_id,
3176 	},
3177 	/* Top-level command. */
3178 	[FLOW] = {
3179 		.name = "flow",
3180 		.type = "{command} {port_id} [{arg} [...]]",
3181 		.help = "manage ingress/egress flow rules",
3182 		.next = NEXT(NEXT_ENTRY
3183 			     (INFO,
3184 			      CONFIGURE,
3185 			      PATTERN_TEMPLATE,
3186 			      ACTIONS_TEMPLATE,
3187 			      TABLE,
3188 			      FLOW_GROUP,
3189 			      INDIRECT_ACTION,
3190 			      VALIDATE,
3191 			      CREATE,
3192 			      DESTROY,
3193 			      FLUSH,
3194 			      DUMP,
3195 			      LIST,
3196 			      AGED,
3197 			      QUERY,
3198 			      ISOLATE,
3199 			      TUNNEL,
3200 			      FLEX,
3201 			      QUEUE,
3202 			      PUSH,
3203 			      PULL,
3204 			      HASH)),
3205 		.call = parse_init,
3206 	},
3207 	/* Top-level command. */
3208 	[INFO] = {
3209 		.name = "info",
3210 		.help = "get information about flow engine",
3211 		.next = NEXT(NEXT_ENTRY(END),
3212 			     NEXT_ENTRY(COMMON_PORT_ID)),
3213 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3214 		.call = parse_configure,
3215 	},
3216 	/* Top-level command. */
3217 	[CONFIGURE] = {
3218 		.name = "configure",
3219 		.help = "configure flow engine",
3220 		.next = NEXT(next_config_attr,
3221 			     NEXT_ENTRY(COMMON_PORT_ID)),
3222 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3223 		.call = parse_configure,
3224 	},
3225 	/* Configure arguments. */
3226 	[CONFIG_QUEUES_NUMBER] = {
3227 		.name = "queues_number",
3228 		.help = "number of queues",
3229 		.next = NEXT(next_config_attr,
3230 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3231 		.args = ARGS(ARGS_ENTRY(struct buffer,
3232 					args.configure.nb_queue)),
3233 	},
3234 	[CONFIG_QUEUES_SIZE] = {
3235 		.name = "queues_size",
3236 		.help = "number of elements in queues",
3237 		.next = NEXT(next_config_attr,
3238 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3239 		.args = ARGS(ARGS_ENTRY(struct buffer,
3240 					args.configure.queue_attr.size)),
3241 	},
3242 	[CONFIG_COUNTERS_NUMBER] = {
3243 		.name = "counters_number",
3244 		.help = "number of counters",
3245 		.next = NEXT(next_config_attr,
3246 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3247 		.args = ARGS(ARGS_ENTRY(struct buffer,
3248 					args.configure.port_attr.nb_counters)),
3249 	},
3250 	[CONFIG_AGING_OBJECTS_NUMBER] = {
3251 		.name = "aging_counters_number",
3252 		.help = "number of aging objects",
3253 		.next = NEXT(next_config_attr,
3254 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3255 		.args = ARGS(ARGS_ENTRY(struct buffer,
3256 					args.configure.port_attr.nb_aging_objects)),
3257 	},
3258 	[CONFIG_QUOTAS_NUMBER] = {
3259 		.name = "quotas_number",
3260 		.help = "number of quotas",
3261 		.next = NEXT(next_config_attr,
3262 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3263 		.args = ARGS(ARGS_ENTRY(struct buffer,
3264 				     args.configure.port_attr.nb_quotas)),
3265 	},
3266 	[CONFIG_METERS_NUMBER] = {
3267 		.name = "meters_number",
3268 		.help = "number of meters",
3269 		.next = NEXT(next_config_attr,
3270 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3271 		.args = ARGS(ARGS_ENTRY(struct buffer,
3272 					args.configure.port_attr.nb_meters)),
3273 	},
3274 	[CONFIG_CONN_TRACK_NUMBER] = {
3275 		.name = "conn_tracks_number",
3276 		.help = "number of connection trackings",
3277 		.next = NEXT(next_config_attr,
3278 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3279 		.args = ARGS(ARGS_ENTRY(struct buffer,
3280 					args.configure.port_attr.nb_conn_tracks)),
3281 	},
3282 	[CONFIG_FLAGS] = {
3283 		.name = "flags",
3284 		.help = "configuration flags",
3285 		.next = NEXT(next_config_attr,
3286 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3287 		.args = ARGS(ARGS_ENTRY(struct buffer,
3288 					args.configure.port_attr.flags)),
3289 	},
3290 	[CONFIG_HOST_PORT] = {
3291 		.name = "host_port",
3292 		.help = "host port for shared objects",
3293 		.next = NEXT(next_config_attr,
3294 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3295 		.args = ARGS(ARGS_ENTRY(struct buffer,
3296 					args.configure.port_attr.host_port_id)),
3297 	},
3298 	/* Top-level command. */
3299 	[PATTERN_TEMPLATE] = {
3300 		.name = "pattern_template",
3301 		.type = "{command} {port_id} [{arg} [...]]",
3302 		.help = "manage pattern templates",
3303 		.next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3304 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3305 		.call = parse_template,
3306 	},
3307 	/* Sub-level commands. */
3308 	[PATTERN_TEMPLATE_CREATE] = {
3309 		.name = "create",
3310 		.help = "create pattern template",
3311 		.next = NEXT(next_pt_attr),
3312 		.call = parse_template,
3313 	},
3314 	[PATTERN_TEMPLATE_DESTROY] = {
3315 		.name = "destroy",
3316 		.help = "destroy pattern template",
3317 		.next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)),
3318 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3319 		.call = parse_template_destroy,
3320 	},
3321 	/* Pattern template arguments. */
3322 	[PATTERN_TEMPLATE_CREATE_ID] = {
3323 		.name = "pattern_template_id",
3324 		.help = "specify a pattern template id to create",
3325 		.next = NEXT(next_pt_attr,
3326 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3327 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)),
3328 	},
3329 	[PATTERN_TEMPLATE_DESTROY_ID] = {
3330 		.name = "pattern_template",
3331 		.help = "specify a pattern template id to destroy",
3332 		.next = NEXT(next_pt_destroy_attr,
3333 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3334 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3335 					    args.templ_destroy.template_id)),
3336 		.call = parse_template_destroy,
3337 	},
3338 	[PATTERN_TEMPLATE_RELAXED_MATCHING] = {
3339 		.name = "relaxed",
3340 		.help = "is matching relaxed",
3341 		.next = NEXT(next_pt_attr,
3342 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3343 		.args = ARGS(ARGS_ENTRY_BF(struct buffer,
3344 			     args.vc.attr.reserved, 1)),
3345 	},
3346 	[PATTERN_TEMPLATE_INGRESS] = {
3347 		.name = "ingress",
3348 		.help = "attribute pattern to ingress",
3349 		.next = NEXT(next_pt_attr),
3350 		.call = parse_template,
3351 	},
3352 	[PATTERN_TEMPLATE_EGRESS] = {
3353 		.name = "egress",
3354 		.help = "attribute pattern to egress",
3355 		.next = NEXT(next_pt_attr),
3356 		.call = parse_template,
3357 	},
3358 	[PATTERN_TEMPLATE_TRANSFER] = {
3359 		.name = "transfer",
3360 		.help = "attribute pattern to transfer",
3361 		.next = NEXT(next_pt_attr),
3362 		.call = parse_template,
3363 	},
3364 	[PATTERN_TEMPLATE_SPEC] = {
3365 		.name = "template",
3366 		.help = "specify item to create pattern template",
3367 		.next = NEXT(next_item),
3368 	},
3369 	/* Top-level command. */
3370 	[ACTIONS_TEMPLATE] = {
3371 		.name = "actions_template",
3372 		.type = "{command} {port_id} [{arg} [...]]",
3373 		.help = "manage actions templates",
3374 		.next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3375 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3376 		.call = parse_template,
3377 	},
3378 	/* Sub-level commands. */
3379 	[ACTIONS_TEMPLATE_CREATE] = {
3380 		.name = "create",
3381 		.help = "create actions template",
3382 		.next = NEXT(next_at_attr),
3383 		.call = parse_template,
3384 	},
3385 	[ACTIONS_TEMPLATE_DESTROY] = {
3386 		.name = "destroy",
3387 		.help = "destroy actions template",
3388 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)),
3389 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3390 		.call = parse_template_destroy,
3391 	},
3392 	/* Actions template arguments. */
3393 	[ACTIONS_TEMPLATE_CREATE_ID] = {
3394 		.name = "actions_template_id",
3395 		.help = "specify an actions template id to create",
3396 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK),
3397 			     NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC),
3398 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3399 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)),
3400 	},
3401 	[ACTIONS_TEMPLATE_DESTROY_ID] = {
3402 		.name = "actions_template",
3403 		.help = "specify an actions template id to destroy",
3404 		.next = NEXT(next_at_destroy_attr,
3405 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3406 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3407 					    args.templ_destroy.template_id)),
3408 		.call = parse_template_destroy,
3409 	},
3410 	[ACTIONS_TEMPLATE_INGRESS] = {
3411 		.name = "ingress",
3412 		.help = "attribute actions to ingress",
3413 		.next = NEXT(next_at_attr),
3414 		.call = parse_template,
3415 	},
3416 	[ACTIONS_TEMPLATE_EGRESS] = {
3417 		.name = "egress",
3418 		.help = "attribute actions to egress",
3419 		.next = NEXT(next_at_attr),
3420 		.call = parse_template,
3421 	},
3422 	[ACTIONS_TEMPLATE_TRANSFER] = {
3423 		.name = "transfer",
3424 		.help = "attribute actions to transfer",
3425 		.next = NEXT(next_at_attr),
3426 		.call = parse_template,
3427 	},
3428 	[ACTIONS_TEMPLATE_SPEC] = {
3429 		.name = "template",
3430 		.help = "specify action to create actions template",
3431 		.next = NEXT(next_action),
3432 		.call = parse_template,
3433 	},
3434 	[ACTIONS_TEMPLATE_MASK] = {
3435 		.name = "mask",
3436 		.help = "specify action mask to create actions template",
3437 		.next = NEXT(next_action),
3438 		.call = parse_template,
3439 	},
3440 	/* Top-level command. */
3441 	[TABLE] = {
3442 		.name = "template_table",
3443 		.type = "{command} {port_id} [{arg} [...]]",
3444 		.help = "manage template tables",
3445 		.next = NEXT(next_table_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3446 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3447 		.call = parse_table,
3448 	},
3449 	/* Sub-level commands. */
3450 	[TABLE_CREATE] = {
3451 		.name = "create",
3452 		.help = "create template table",
3453 		.next = NEXT(next_table_attr),
3454 		.call = parse_table,
3455 	},
3456 	[TABLE_DESTROY] = {
3457 		.name = "destroy",
3458 		.help = "destroy template table",
3459 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3460 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3461 		.call = parse_table_destroy,
3462 	},
3463 	/* Table  arguments. */
3464 	[TABLE_CREATE_ID] = {
3465 		.name = "table_id",
3466 		.help = "specify table id to create",
3467 		.next = NEXT(next_table_attr,
3468 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3469 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3470 	},
3471 	[TABLE_DESTROY_ID] = {
3472 		.name = "table",
3473 		.help = "specify table id to destroy",
3474 		.next = NEXT(next_table_destroy_attr,
3475 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3476 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3477 					    args.table_destroy.table_id)),
3478 		.call = parse_table_destroy,
3479 	},
3480 	[TABLE_INSERTION_TYPE] = {
3481 		.name = "insertion_type",
3482 		.help = "specify insertion type",
3483 		.next = NEXT(next_table_attr,
3484 			     NEXT_ENTRY(TABLE_INSERTION_TYPE_NAME)),
3485 		.args = ARGS(ARGS_ENTRY(struct buffer,
3486 					args.table.attr.insertion_type)),
3487 	},
3488 	[TABLE_INSERTION_TYPE_NAME] = {
3489 		.name = "insertion_type_name",
3490 		.help = "insertion type name",
3491 		.call = parse_insertion_table_type,
3492 		.comp = comp_insertion_table_type,
3493 	},
3494 	[TABLE_HASH_FUNC] = {
3495 		.name = "hash_func",
3496 		.help = "specify hash calculation function",
3497 		.next = NEXT(next_table_attr,
3498 			     NEXT_ENTRY(TABLE_HASH_FUNC_NAME)),
3499 		.args = ARGS(ARGS_ENTRY(struct buffer,
3500 					args.table.attr.hash_func)),
3501 	},
3502 	[TABLE_HASH_FUNC_NAME] = {
3503 		.name = "hash_func_name",
3504 		.help = "hash calculation function name",
3505 		.call = parse_hash_table_type,
3506 		.comp = comp_hash_table_type,
3507 	},
3508 	[TABLE_GROUP] = {
3509 		.name = "group",
3510 		.help = "specify a group",
3511 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3512 		.args = ARGS(ARGS_ENTRY(struct buffer,
3513 					args.table.attr.flow_attr.group)),
3514 	},
3515 	[TABLE_PRIORITY] = {
3516 		.name = "priority",
3517 		.help = "specify a priority level",
3518 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
3519 		.args = ARGS(ARGS_ENTRY(struct buffer,
3520 					args.table.attr.flow_attr.priority)),
3521 	},
3522 	[TABLE_EGRESS] = {
3523 		.name = "egress",
3524 		.help = "affect rule to egress",
3525 		.next = NEXT(next_table_attr),
3526 		.call = parse_table,
3527 	},
3528 	[TABLE_INGRESS] = {
3529 		.name = "ingress",
3530 		.help = "affect rule to ingress",
3531 		.next = NEXT(next_table_attr),
3532 		.call = parse_table,
3533 	},
3534 	[TABLE_TRANSFER] = {
3535 		.name = "transfer",
3536 		.help = "affect rule to transfer",
3537 		.next = NEXT(next_table_attr),
3538 		.call = parse_table,
3539 	},
3540 	[TABLE_TRANSFER_WIRE_ORIG] = {
3541 		.name = "wire_orig",
3542 		.help = "affect rule direction to transfer",
3543 		.next = NEXT(next_table_attr),
3544 		.call = parse_table,
3545 	},
3546 	[TABLE_TRANSFER_VPORT_ORIG] = {
3547 		.name = "vport_orig",
3548 		.help = "affect rule direction to transfer",
3549 		.next = NEXT(next_table_attr),
3550 		.call = parse_table,
3551 	},
3552 	[TABLE_RULES_NUMBER] = {
3553 		.name = "rules_number",
3554 		.help = "number of rules in table",
3555 		.next = NEXT(next_table_attr,
3556 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3557 		.args = ARGS(ARGS_ENTRY(struct buffer,
3558 					args.table.attr.nb_flows)),
3559 		.call = parse_table,
3560 	},
3561 	[TABLE_PATTERN_TEMPLATE] = {
3562 		.name = "pattern_template",
3563 		.help = "specify pattern template id",
3564 		.next = NEXT(next_table_attr,
3565 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3566 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3567 					    args.table.pat_templ_id)),
3568 		.call = parse_table,
3569 	},
3570 	[TABLE_ACTIONS_TEMPLATE] = {
3571 		.name = "actions_template",
3572 		.help = "specify actions template id",
3573 		.next = NEXT(next_table_attr,
3574 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3575 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3576 					    args.table.act_templ_id)),
3577 		.call = parse_table,
3578 	},
3579 	/* Top-level command. */
3580 	[FLOW_GROUP] = {
3581 		.name = "group",
3582 		.help = "manage flow groups",
3583 		.next = NEXT(NEXT_ENTRY(GROUP_ID), NEXT_ENTRY(COMMON_PORT_ID)),
3584 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3585 		.call = parse_group,
3586 	},
3587 	/* Sub-level commands. */
3588 	[GROUP_SET_MISS_ACTIONS] = {
3589 		.name = "set_miss_actions",
3590 		.help = "set group miss actions",
3591 		.next = NEXT(next_action),
3592 		.call = parse_group,
3593 	},
3594 	/* Group arguments */
3595 	[GROUP_ID]	= {
3596 		.name = "group_id",
3597 		.help = "group id",
3598 		.next = NEXT(next_group_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3599 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3600 	},
3601 	[GROUP_INGRESS] = {
3602 		.name = "ingress",
3603 		.help = "group ingress attr",
3604 		.next = NEXT(next_group_attr),
3605 		.call = parse_group,
3606 	},
3607 	[GROUP_EGRESS] = {
3608 		.name = "egress",
3609 		.help = "group egress attr",
3610 		.next = NEXT(next_group_attr),
3611 		.call = parse_group,
3612 	},
3613 	[GROUP_TRANSFER] = {
3614 		.name = "transfer",
3615 		.help = "group transfer attr",
3616 		.next = NEXT(next_group_attr),
3617 		.call = parse_group,
3618 	},
3619 	/* Top-level command. */
3620 	[QUEUE] = {
3621 		.name = "queue",
3622 		.help = "queue a flow rule operation",
3623 		.next = NEXT(next_queue_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3624 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3625 		.call = parse_qo,
3626 	},
3627 	/* Sub-level commands. */
3628 	[QUEUE_CREATE] = {
3629 		.name = "create",
3630 		.help = "create a flow rule",
3631 		.next = NEXT(NEXT_ENTRY(QUEUE_TEMPLATE_TABLE),
3632 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3633 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3634 		.call = parse_qo,
3635 	},
3636 	[QUEUE_DESTROY] = {
3637 		.name = "destroy",
3638 		.help = "destroy a flow rule",
3639 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3640 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3641 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3642 		.call = parse_qo_destroy,
3643 	},
3644 	[QUEUE_UPDATE] = {
3645 		.name = "update",
3646 		.help = "update a flow rule",
3647 		.next = NEXT(NEXT_ENTRY(QUEUE_UPDATE_ID),
3648 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3649 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3650 		.call = parse_qo,
3651 	},
3652 	[QUEUE_AGED] = {
3653 		.name = "aged",
3654 		.help = "list and destroy aged flows",
3655 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_QUEUE_ID)),
3656 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3657 		.call = parse_aged,
3658 	},
3659 	[QUEUE_INDIRECT_ACTION] = {
3660 		.name = "indirect_action",
3661 		.help = "queue indirect actions",
3662 		.next = NEXT(next_qia_subcmd, NEXT_ENTRY(COMMON_QUEUE_ID)),
3663 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3664 		.call = parse_qia,
3665 	},
3666 	/* Queue  arguments. */
3667 	[QUEUE_TEMPLATE_TABLE] = {
3668 		.name = "template_table",
3669 		.help = "specify table id",
3670 		.next = NEXT(next_async_insert_subcmd,
3671 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3672 		.args = ARGS(ARGS_ENTRY(struct buffer,
3673 					args.vc.table_id)),
3674 		.call = parse_qo,
3675 	},
3676 	[QUEUE_PATTERN_TEMPLATE] = {
3677 		.name = "pattern_template",
3678 		.help = "specify pattern template index",
3679 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3680 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3681 		.args = ARGS(ARGS_ENTRY(struct buffer,
3682 					args.vc.pat_templ_id)),
3683 		.call = parse_qo,
3684 	},
3685 	[QUEUE_ACTIONS_TEMPLATE] = {
3686 		.name = "actions_template",
3687 		.help = "specify actions template index",
3688 		.next = NEXT(NEXT_ENTRY(QUEUE_CREATE_POSTPONE),
3689 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3690 		.args = ARGS(ARGS_ENTRY(struct buffer,
3691 					args.vc.act_templ_id)),
3692 		.call = parse_qo,
3693 	},
3694 	[QUEUE_RULE_ID] = {
3695 		.name = "rule_index",
3696 		.help = "specify flow rule index",
3697 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3698 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3699 		.args = ARGS(ARGS_ENTRY(struct buffer,
3700 					args.vc.rule_id)),
3701 		.call = parse_qo,
3702 	},
3703 	[QUEUE_CREATE_POSTPONE] = {
3704 		.name = "postpone",
3705 		.help = "postpone create operation",
3706 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
3707 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3708 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3709 		.call = parse_qo,
3710 	},
3711 	[QUEUE_DESTROY_POSTPONE] = {
3712 		.name = "postpone",
3713 		.help = "postpone destroy operation",
3714 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3715 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3716 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3717 		.call = parse_qo_destroy,
3718 	},
3719 	[QUEUE_DESTROY_ID] = {
3720 		.name = "rule",
3721 		.help = "specify rule id to destroy",
3722 		.next = NEXT(next_queue_destroy_attr,
3723 			NEXT_ENTRY(COMMON_UNSIGNED)),
3724 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3725 					    args.destroy.rule)),
3726 		.call = parse_qo_destroy,
3727 	},
3728 	[QUEUE_UPDATE_ID] = {
3729 		.name = "rule",
3730 		.help = "specify rule id to update",
3731 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3732 			NEXT_ENTRY(COMMON_UNSIGNED)),
3733 		.args = ARGS(ARGS_ENTRY(struct buffer,
3734 				     args.vc.rule_id)),
3735 		.call = parse_qo,
3736 	},
3737 	/* Queue indirect action arguments */
3738 	[QUEUE_INDIRECT_ACTION_CREATE] = {
3739 		.name = "create",
3740 		.help = "create indirect action",
3741 		.next = NEXT(next_qia_create_attr),
3742 		.call = parse_qia,
3743 	},
3744 	[QUEUE_INDIRECT_ACTION_UPDATE] = {
3745 		.name = "update",
3746 		.help = "update indirect action",
3747 		.next = NEXT(next_qia_update_attr,
3748 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3749 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3750 		.call = parse_qia,
3751 	},
3752 	[QUEUE_INDIRECT_ACTION_DESTROY] = {
3753 		.name = "destroy",
3754 		.help = "destroy indirect action",
3755 		.next = NEXT(next_qia_destroy_attr),
3756 		.call = parse_qia_destroy,
3757 	},
3758 	[QUEUE_INDIRECT_ACTION_QUERY] = {
3759 		.name = "query",
3760 		.help = "query indirect action",
3761 		.next = NEXT(next_qia_query_attr,
3762 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3763 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3764 		.call = parse_qia,
3765 	},
3766 	/* Indirect action destroy arguments. */
3767 	[QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE] = {
3768 		.name = "postpone",
3769 		.help = "postpone destroy operation",
3770 		.next = NEXT(next_qia_destroy_attr,
3771 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3772 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3773 	},
3774 	[QUEUE_INDIRECT_ACTION_DESTROY_ID] = {
3775 		.name = "action_id",
3776 		.help = "specify a indirect action id to destroy",
3777 		.next = NEXT(next_qia_destroy_attr,
3778 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3779 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3780 					    args.ia_destroy.action_id)),
3781 		.call = parse_qia_destroy,
3782 	},
3783 	[QUEUE_INDIRECT_ACTION_QUERY_UPDATE] = {
3784 		.name = "query_update",
3785 		.help = "indirect query [and|or] update action",
3786 		.next = NEXT(next_qia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3787 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3788 		.call = parse_qia
3789 	},
3790 	[QUEUE_INDIRECT_ACTION_QU_MODE] = {
3791 		.name = "mode",
3792 		.help = "indirect query [and|or] update action",
3793 		.next = NEXT(next_qia_qu_attr,
3794 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
3795 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
3796 		.call = parse_qia
3797 	},
3798 	/* Indirect action update arguments. */
3799 	[QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE] = {
3800 		.name = "postpone",
3801 		.help = "postpone update operation",
3802 		.next = NEXT(next_qia_update_attr,
3803 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3804 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3805 	},
3806 	/* Indirect action update arguments. */
3807 	[QUEUE_INDIRECT_ACTION_QUERY_POSTPONE] = {
3808 		.name = "postpone",
3809 		.help = "postpone query operation",
3810 		.next = NEXT(next_qia_query_attr,
3811 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3812 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3813 	},
3814 	/* Indirect action create arguments. */
3815 	[QUEUE_INDIRECT_ACTION_CREATE_ID] = {
3816 		.name = "action_id",
3817 		.help = "specify a indirect action id to create",
3818 		.next = NEXT(next_qia_create_attr,
3819 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3820 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3821 	},
3822 	[QUEUE_INDIRECT_ACTION_INGRESS] = {
3823 		.name = "ingress",
3824 		.help = "affect rule to ingress",
3825 		.next = NEXT(next_qia_create_attr),
3826 		.call = parse_qia,
3827 	},
3828 	[QUEUE_INDIRECT_ACTION_EGRESS] = {
3829 		.name = "egress",
3830 		.help = "affect rule to egress",
3831 		.next = NEXT(next_qia_create_attr),
3832 		.call = parse_qia,
3833 	},
3834 	[QUEUE_INDIRECT_ACTION_TRANSFER] = {
3835 		.name = "transfer",
3836 		.help = "affect rule to transfer",
3837 		.next = NEXT(next_qia_create_attr),
3838 		.call = parse_qia,
3839 	},
3840 	[QUEUE_INDIRECT_ACTION_CREATE_POSTPONE] = {
3841 		.name = "postpone",
3842 		.help = "postpone create operation",
3843 		.next = NEXT(next_qia_create_attr,
3844 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3845 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3846 	},
3847 	[QUEUE_INDIRECT_ACTION_SPEC] = {
3848 		.name = "action",
3849 		.help = "specify action to create indirect handle",
3850 		.next = NEXT(next_action),
3851 	},
3852 	[QUEUE_INDIRECT_ACTION_LIST] = {
3853 		.name = "list",
3854 		.help = "specify actions for indirect handle list",
3855 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
3856 		.call = parse_qia,
3857 	},
3858 	/* Top-level command. */
3859 	[PUSH] = {
3860 		.name = "push",
3861 		.help = "push enqueued operations",
3862 		.next = NEXT(NEXT_ENTRY(PUSH_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3863 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3864 		.call = parse_push,
3865 	},
3866 	/* Sub-level commands. */
3867 	[PUSH_QUEUE] = {
3868 		.name = "queue",
3869 		.help = "specify queue id",
3870 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3871 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3872 	},
3873 	/* Top-level command. */
3874 	[PULL] = {
3875 		.name = "pull",
3876 		.help = "pull flow operations results",
3877 		.next = NEXT(NEXT_ENTRY(PULL_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3878 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3879 		.call = parse_pull,
3880 	},
3881 	/* Sub-level commands. */
3882 	[PULL_QUEUE] = {
3883 		.name = "queue",
3884 		.help = "specify queue id",
3885 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3886 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3887 	},
3888 	/* Top-level command. */
3889 	[HASH] = {
3890 		.name = "hash",
3891 		.help = "calculate hash for a given pattern in a given template table",
3892 		.next = NEXT(next_hash_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3893 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3894 		.call = parse_hash,
3895 	},
3896 	/* Sub-level commands. */
3897 	[HASH_CALC_TABLE] = {
3898 		.name = "template_table",
3899 		.help = "specify table id",
3900 		.next = NEXT(NEXT_ENTRY(HASH_CALC_PATTERN_INDEX),
3901 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3902 		.args = ARGS(ARGS_ENTRY(struct buffer,
3903 					args.vc.table_id)),
3904 		.call = parse_hash,
3905 	},
3906 	[HASH_CALC_ENCAP] = {
3907 		.name = "encap",
3908 		.help = "calculates encap hash",
3909 		.next = NEXT(next_hash_encap_dest_subcmd),
3910 		.call = parse_hash,
3911 	},
3912 	[HASH_CALC_PATTERN_INDEX] = {
3913 		.name = "pattern_template",
3914 		.help = "specify pattern template id",
3915 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
3916 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3917 		.args = ARGS(ARGS_ENTRY(struct buffer,
3918 					args.vc.pat_templ_id)),
3919 		.call = parse_hash,
3920 	},
3921 	[ENCAP_HASH_FIELD_SRC_PORT] = {
3922 		.name = "hash_field_sport",
3923 		.help = "the encap hash field is src port",
3924 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
3925 		.call = parse_hash,
3926 	},
3927 	[ENCAP_HASH_FIELD_GRE_FLOW_ID] = {
3928 		.name = "hash_field_flow_id",
3929 		.help = "the encap hash field is NVGRE flow id",
3930 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
3931 		.call = parse_hash,
3932 	},
3933 	/* Top-level command. */
3934 	[INDIRECT_ACTION] = {
3935 		.name = "indirect_action",
3936 		.type = "{command} {port_id} [{arg} [...]]",
3937 		.help = "manage indirect actions",
3938 		.next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3939 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3940 		.call = parse_ia,
3941 	},
3942 	/* Sub-level commands. */
3943 	[INDIRECT_ACTION_CREATE] = {
3944 		.name = "create",
3945 		.help = "create indirect action",
3946 		.next = NEXT(next_ia_create_attr),
3947 		.call = parse_ia,
3948 	},
3949 	[INDIRECT_ACTION_UPDATE] = {
3950 		.name = "update",
3951 		.help = "update indirect action",
3952 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
3953 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3954 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3955 		.call = parse_ia,
3956 	},
3957 	[INDIRECT_ACTION_DESTROY] = {
3958 		.name = "destroy",
3959 		.help = "destroy indirect action",
3960 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
3961 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3962 		.call = parse_ia_destroy,
3963 	},
3964 	[INDIRECT_ACTION_QUERY] = {
3965 		.name = "query",
3966 		.help = "query indirect action",
3967 		.next = NEXT(NEXT_ENTRY(END),
3968 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3969 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3970 		.call = parse_ia,
3971 	},
3972 	[INDIRECT_ACTION_QUERY_UPDATE] = {
3973 		.name = "query_update",
3974 		.help = "query [and|or] update",
3975 		.next = NEXT(next_ia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3976 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3977 		.call = parse_ia
3978 	},
3979 	[INDIRECT_ACTION_QU_MODE] = {
3980 		.name = "mode",
3981 		.help = "query_update mode",
3982 		.next = NEXT(next_ia_qu_attr,
3983 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
3984 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
3985 		.call = parse_ia,
3986 	},
3987 	[INDIRECT_ACTION_QU_MODE_NAME] = {
3988 		.name = "mode_name",
3989 		.help = "query-update mode name",
3990 		.call = parse_qu_mode_name,
3991 		.comp = comp_qu_mode_name,
3992 	},
3993 	[VALIDATE] = {
3994 		.name = "validate",
3995 		.help = "check whether a flow rule can be created",
3996 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
3997 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3998 		.call = parse_vc,
3999 	},
4000 	[CREATE] = {
4001 		.name = "create",
4002 		.help = "create a flow rule",
4003 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4004 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4005 		.call = parse_vc,
4006 	},
4007 	[DESTROY] = {
4008 		.name = "destroy",
4009 		.help = "destroy specific flow rules",
4010 		.next = NEXT(next_destroy_attr,
4011 			     NEXT_ENTRY(COMMON_PORT_ID)),
4012 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4013 		.call = parse_destroy,
4014 	},
4015 	[FLUSH] = {
4016 		.name = "flush",
4017 		.help = "destroy all flow rules",
4018 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4019 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4020 		.call = parse_flush,
4021 	},
4022 	[DUMP] = {
4023 		.name = "dump",
4024 		.help = "dump single/all flow rules to file",
4025 		.next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
4026 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4027 		.call = parse_dump,
4028 	},
4029 	[QUERY] = {
4030 		.name = "query",
4031 		.help = "query an existing flow rule",
4032 		.next = NEXT(next_query_attr, NEXT_ENTRY(QUERY_ACTION),
4033 			     NEXT_ENTRY(COMMON_RULE_ID),
4034 			     NEXT_ENTRY(COMMON_PORT_ID)),
4035 		.args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
4036 			     ARGS_ENTRY(struct buffer, args.query.rule),
4037 			     ARGS_ENTRY(struct buffer, port)),
4038 		.call = parse_query,
4039 	},
4040 	[LIST] = {
4041 		.name = "list",
4042 		.help = "list existing flow rules",
4043 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4044 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4045 		.call = parse_list,
4046 	},
4047 	[AGED] = {
4048 		.name = "aged",
4049 		.help = "list and destroy aged flows",
4050 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4051 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4052 		.call = parse_aged,
4053 	},
4054 	[ISOLATE] = {
4055 		.name = "isolate",
4056 		.help = "restrict ingress traffic to the defined flow rules",
4057 		.next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
4058 			     NEXT_ENTRY(COMMON_PORT_ID)),
4059 		.args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
4060 			     ARGS_ENTRY(struct buffer, port)),
4061 		.call = parse_isolate,
4062 	},
4063 	[FLEX] = {
4064 		.name = "flex_item",
4065 		.help = "flex item API",
4066 		.next = NEXT(next_flex_item),
4067 		.call = parse_flex,
4068 	},
4069 	[FLEX_ITEM_INIT] = {
4070 		.name = "init",
4071 		.help = "flex item init",
4072 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
4073 			     ARGS_ENTRY(struct buffer, port)),
4074 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
4075 			     NEXT_ENTRY(COMMON_PORT_ID)),
4076 		.call = parse_flex
4077 	},
4078 	[FLEX_ITEM_CREATE] = {
4079 		.name = "create",
4080 		.help = "flex item create",
4081 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename),
4082 			     ARGS_ENTRY(struct buffer, args.flex.token),
4083 			     ARGS_ENTRY(struct buffer, port)),
4084 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH),
4085 			     NEXT_ENTRY(COMMON_FLEX_TOKEN),
4086 			     NEXT_ENTRY(COMMON_PORT_ID)),
4087 		.call = parse_flex
4088 	},
4089 	[FLEX_ITEM_DESTROY] = {
4090 		.name = "destroy",
4091 		.help = "flex item destroy",
4092 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
4093 			     ARGS_ENTRY(struct buffer, port)),
4094 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
4095 			     NEXT_ENTRY(COMMON_PORT_ID)),
4096 		.call = parse_flex
4097 	},
4098 	[TUNNEL] = {
4099 		.name = "tunnel",
4100 		.help = "new tunnel API",
4101 		.next = NEXT(NEXT_ENTRY
4102 			     (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
4103 		.call = parse_tunnel,
4104 	},
4105 	/* Tunnel arguments. */
4106 	[TUNNEL_CREATE] = {
4107 		.name = "create",
4108 		.help = "create new tunnel object",
4109 		.next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
4110 			     NEXT_ENTRY(COMMON_PORT_ID)),
4111 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4112 		.call = parse_tunnel,
4113 	},
4114 	[TUNNEL_CREATE_TYPE] = {
4115 		.name = "type",
4116 		.help = "create new tunnel",
4117 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
4118 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
4119 		.call = parse_tunnel,
4120 	},
4121 	[TUNNEL_DESTROY] = {
4122 		.name = "destroy",
4123 		.help = "destroy tunnel",
4124 		.next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
4125 			     NEXT_ENTRY(COMMON_PORT_ID)),
4126 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4127 		.call = parse_tunnel,
4128 	},
4129 	[TUNNEL_DESTROY_ID] = {
4130 		.name = "id",
4131 		.help = "tunnel identifier to destroy",
4132 		.next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
4133 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4134 		.call = parse_tunnel,
4135 	},
4136 	[TUNNEL_LIST] = {
4137 		.name = "list",
4138 		.help = "list existing tunnels",
4139 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4140 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4141 		.call = parse_tunnel,
4142 	},
4143 	/* Destroy arguments. */
4144 	[DESTROY_RULE] = {
4145 		.name = "rule",
4146 		.help = "specify a rule identifier",
4147 		.next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4148 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
4149 		.call = parse_destroy,
4150 	},
4151 	[DESTROY_IS_USER_ID] = {
4152 		.name = "user_id",
4153 		.help = "rule identifier is user-id",
4154 		.next = NEXT(next_destroy_attr),
4155 		.call = parse_destroy,
4156 	},
4157 	/* Dump arguments. */
4158 	[DUMP_ALL] = {
4159 		.name = "all",
4160 		.help = "dump all",
4161 		.next = NEXT(next_dump_attr),
4162 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
4163 		.call = parse_dump,
4164 	},
4165 	[DUMP_ONE] = {
4166 		.name = "rule",
4167 		.help = "dump one rule",
4168 		.next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4169 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
4170 				ARGS_ENTRY(struct buffer, args.dump.rule)),
4171 		.call = parse_dump,
4172 	},
4173 	[DUMP_IS_USER_ID] = {
4174 		.name = "user_id",
4175 		.help = "rule identifier is user-id",
4176 		.next = NEXT(next_dump_subcmd),
4177 		.call = parse_dump,
4178 	},
4179 	/* Query arguments. */
4180 	[QUERY_ACTION] = {
4181 		.name = "{action}",
4182 		.type = "ACTION",
4183 		.help = "action to query, must be part of the rule",
4184 		.call = parse_action,
4185 		.comp = comp_action,
4186 	},
4187 	[QUERY_IS_USER_ID] = {
4188 		.name = "user_id",
4189 		.help = "rule identifier is user-id",
4190 		.next = NEXT(next_query_attr),
4191 		.call = parse_query,
4192 	},
4193 	/* List arguments. */
4194 	[LIST_GROUP] = {
4195 		.name = "group",
4196 		.help = "specify a group",
4197 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4198 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
4199 		.call = parse_list,
4200 	},
4201 	[AGED_DESTROY] = {
4202 		.name = "destroy",
4203 		.help = "specify aged flows need be destroyed",
4204 		.call = parse_aged,
4205 		.comp = comp_none,
4206 	},
4207 	/* Validate/create attributes. */
4208 	[VC_GROUP] = {
4209 		.name = "group",
4210 		.help = "specify a group",
4211 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4212 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
4213 		.call = parse_vc,
4214 	},
4215 	[VC_PRIORITY] = {
4216 		.name = "priority",
4217 		.help = "specify a priority level",
4218 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
4219 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
4220 		.call = parse_vc,
4221 	},
4222 	[VC_INGRESS] = {
4223 		.name = "ingress",
4224 		.help = "affect rule to ingress",
4225 		.next = NEXT(next_vc_attr),
4226 		.call = parse_vc,
4227 	},
4228 	[VC_EGRESS] = {
4229 		.name = "egress",
4230 		.help = "affect rule to egress",
4231 		.next = NEXT(next_vc_attr),
4232 		.call = parse_vc,
4233 	},
4234 	[VC_TRANSFER] = {
4235 		.name = "transfer",
4236 		.help = "apply rule directly to endpoints found in pattern",
4237 		.next = NEXT(next_vc_attr),
4238 		.call = parse_vc,
4239 	},
4240 	[VC_TUNNEL_SET] = {
4241 		.name = "tunnel_set",
4242 		.help = "tunnel steer rule",
4243 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4244 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4245 		.call = parse_vc,
4246 	},
4247 	[VC_TUNNEL_MATCH] = {
4248 		.name = "tunnel_match",
4249 		.help = "tunnel match rule",
4250 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4251 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4252 		.call = parse_vc,
4253 	},
4254 	[VC_USER_ID] = {
4255 		.name = "user_id",
4256 		.help = "specify a user id to create",
4257 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4258 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.user_id)),
4259 		.call = parse_vc,
4260 	},
4261 	/* Validate/create pattern. */
4262 	[ITEM_PATTERN] = {
4263 		.name = "pattern",
4264 		.help = "submit a list of pattern items",
4265 		.next = NEXT(next_item),
4266 		.call = parse_vc,
4267 	},
4268 	[ITEM_PARAM_IS] = {
4269 		.name = "is",
4270 		.help = "match value perfectly (with full bit-mask)",
4271 		.call = parse_vc_spec,
4272 	},
4273 	[ITEM_PARAM_SPEC] = {
4274 		.name = "spec",
4275 		.help = "match value according to configured bit-mask",
4276 		.call = parse_vc_spec,
4277 	},
4278 	[ITEM_PARAM_LAST] = {
4279 		.name = "last",
4280 		.help = "specify upper bound to establish a range",
4281 		.call = parse_vc_spec,
4282 	},
4283 	[ITEM_PARAM_MASK] = {
4284 		.name = "mask",
4285 		.help = "specify bit-mask with relevant bits set to one",
4286 		.call = parse_vc_spec,
4287 	},
4288 	[ITEM_PARAM_PREFIX] = {
4289 		.name = "prefix",
4290 		.help = "generate bit-mask from a prefix length",
4291 		.call = parse_vc_spec,
4292 	},
4293 	[ITEM_NEXT] = {
4294 		.name = "/",
4295 		.help = "specify next pattern item",
4296 		.next = NEXT(next_item),
4297 	},
4298 	[ITEM_END] = {
4299 		.name = "end",
4300 		.help = "end list of pattern items",
4301 		.priv = PRIV_ITEM(END, 0),
4302 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
4303 		.call = parse_vc,
4304 	},
4305 	[ITEM_VOID] = {
4306 		.name = "void",
4307 		.help = "no-op pattern item",
4308 		.priv = PRIV_ITEM(VOID, 0),
4309 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4310 		.call = parse_vc,
4311 	},
4312 	[ITEM_INVERT] = {
4313 		.name = "invert",
4314 		.help = "perform actions when pattern does not match",
4315 		.priv = PRIV_ITEM(INVERT, 0),
4316 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4317 		.call = parse_vc,
4318 	},
4319 	[ITEM_ANY] = {
4320 		.name = "any",
4321 		.help = "match any protocol for the current layer",
4322 		.priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
4323 		.next = NEXT(item_any),
4324 		.call = parse_vc,
4325 	},
4326 	[ITEM_ANY_NUM] = {
4327 		.name = "num",
4328 		.help = "number of layers covered",
4329 		.next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4330 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
4331 	},
4332 	[ITEM_PORT_ID] = {
4333 		.name = "port_id",
4334 		.help = "match traffic from/to a given DPDK port ID",
4335 		.priv = PRIV_ITEM(PORT_ID,
4336 				  sizeof(struct rte_flow_item_port_id)),
4337 		.next = NEXT(item_port_id),
4338 		.call = parse_vc,
4339 	},
4340 	[ITEM_PORT_ID_ID] = {
4341 		.name = "id",
4342 		.help = "DPDK port ID",
4343 		.next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
4344 			     item_param),
4345 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
4346 	},
4347 	[ITEM_MARK] = {
4348 		.name = "mark",
4349 		.help = "match traffic against value set in previously matched rule",
4350 		.priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
4351 		.next = NEXT(item_mark),
4352 		.call = parse_vc,
4353 	},
4354 	[ITEM_MARK_ID] = {
4355 		.name = "id",
4356 		.help = "Integer value to match against",
4357 		.next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
4358 			     item_param),
4359 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
4360 	},
4361 	[ITEM_RAW] = {
4362 		.name = "raw",
4363 		.help = "match an arbitrary byte string",
4364 		.priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
4365 		.next = NEXT(item_raw),
4366 		.call = parse_vc,
4367 	},
4368 	[ITEM_RAW_RELATIVE] = {
4369 		.name = "relative",
4370 		.help = "look for pattern after the previous item",
4371 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4372 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4373 					   relative, 1)),
4374 	},
4375 	[ITEM_RAW_SEARCH] = {
4376 		.name = "search",
4377 		.help = "search pattern from offset (see also limit)",
4378 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4379 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4380 					   search, 1)),
4381 	},
4382 	[ITEM_RAW_OFFSET] = {
4383 		.name = "offset",
4384 		.help = "absolute or relative offset for pattern",
4385 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
4386 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
4387 	},
4388 	[ITEM_RAW_LIMIT] = {
4389 		.name = "limit",
4390 		.help = "search area limit for start of pattern",
4391 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4392 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
4393 	},
4394 	[ITEM_RAW_PATTERN] = {
4395 		.name = "pattern",
4396 		.help = "byte string to look for",
4397 		.next = NEXT(item_raw,
4398 			     NEXT_ENTRY(COMMON_STRING),
4399 			     NEXT_ENTRY(ITEM_PARAM_IS,
4400 					ITEM_PARAM_SPEC,
4401 					ITEM_PARAM_MASK)),
4402 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4403 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4404 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4405 					    ITEM_RAW_PATTERN_SIZE)),
4406 	},
4407 	[ITEM_RAW_PATTERN_HEX] = {
4408 		.name = "pattern_hex",
4409 		.help = "hex string to look for",
4410 		.next = NEXT(item_raw,
4411 			     NEXT_ENTRY(COMMON_HEX),
4412 			     NEXT_ENTRY(ITEM_PARAM_IS,
4413 					ITEM_PARAM_SPEC,
4414 					ITEM_PARAM_MASK)),
4415 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4416 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4417 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4418 					    ITEM_RAW_PATTERN_SIZE)),
4419 	},
4420 	[ITEM_ETH] = {
4421 		.name = "eth",
4422 		.help = "match Ethernet header",
4423 		.priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
4424 		.next = NEXT(item_eth),
4425 		.call = parse_vc,
4426 	},
4427 	[ITEM_ETH_DST] = {
4428 		.name = "dst",
4429 		.help = "destination MAC",
4430 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4431 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.dst_addr)),
4432 	},
4433 	[ITEM_ETH_SRC] = {
4434 		.name = "src",
4435 		.help = "source MAC",
4436 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4437 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.src_addr)),
4438 	},
4439 	[ITEM_ETH_TYPE] = {
4440 		.name = "type",
4441 		.help = "EtherType",
4442 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4443 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.ether_type)),
4444 	},
4445 	[ITEM_ETH_HAS_VLAN] = {
4446 		.name = "has_vlan",
4447 		.help = "packet header contains VLAN",
4448 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4449 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
4450 					   has_vlan, 1)),
4451 	},
4452 	[ITEM_VLAN] = {
4453 		.name = "vlan",
4454 		.help = "match 802.1Q/ad VLAN tag",
4455 		.priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
4456 		.next = NEXT(item_vlan),
4457 		.call = parse_vc,
4458 	},
4459 	[ITEM_VLAN_TCI] = {
4460 		.name = "tci",
4461 		.help = "tag control information",
4462 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4463 			     item_param),
4464 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, hdr.vlan_tci)),
4465 	},
4466 	[ITEM_VLAN_PCP] = {
4467 		.name = "pcp",
4468 		.help = "priority code point",
4469 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4470 			     item_param),
4471 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4472 						  hdr.vlan_tci, "\xe0\x00")),
4473 	},
4474 	[ITEM_VLAN_DEI] = {
4475 		.name = "dei",
4476 		.help = "drop eligible indicator",
4477 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4478 			     item_param),
4479 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4480 						  hdr.vlan_tci, "\x10\x00")),
4481 	},
4482 	[ITEM_VLAN_VID] = {
4483 		.name = "vid",
4484 		.help = "VLAN identifier",
4485 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4486 			     item_param),
4487 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4488 						  hdr.vlan_tci, "\x0f\xff")),
4489 	},
4490 	[ITEM_VLAN_INNER_TYPE] = {
4491 		.name = "inner_type",
4492 		.help = "inner EtherType",
4493 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4494 			     item_param),
4495 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
4496 					     hdr.eth_proto)),
4497 	},
4498 	[ITEM_VLAN_HAS_MORE_VLAN] = {
4499 		.name = "has_more_vlan",
4500 		.help = "packet header contains another VLAN",
4501 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4502 			     item_param),
4503 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
4504 					   has_more_vlan, 1)),
4505 	},
4506 	[ITEM_IPV4] = {
4507 		.name = "ipv4",
4508 		.help = "match IPv4 header",
4509 		.priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
4510 		.next = NEXT(item_ipv4),
4511 		.call = parse_vc,
4512 	},
4513 	[ITEM_IPV4_VER_IHL] = {
4514 		.name = "version_ihl",
4515 		.help = "match header length",
4516 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4517 			     item_param),
4518 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
4519 				     hdr.version_ihl)),
4520 	},
4521 	[ITEM_IPV4_TOS] = {
4522 		.name = "tos",
4523 		.help = "type of service",
4524 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4525 			     item_param),
4526 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4527 					     hdr.type_of_service)),
4528 	},
4529 	[ITEM_IPV4_LENGTH] = {
4530 		.name = "length",
4531 		.help = "total length",
4532 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4533 			     item_param),
4534 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4535 					     hdr.total_length)),
4536 	},
4537 	[ITEM_IPV4_ID] = {
4538 		.name = "packet_id",
4539 		.help = "fragment packet id",
4540 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4541 			     item_param),
4542 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4543 					     hdr.packet_id)),
4544 	},
4545 	[ITEM_IPV4_FRAGMENT_OFFSET] = {
4546 		.name = "fragment_offset",
4547 		.help = "fragmentation flags and fragment offset",
4548 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4549 			     item_param),
4550 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4551 					     hdr.fragment_offset)),
4552 	},
4553 	[ITEM_IPV4_TTL] = {
4554 		.name = "ttl",
4555 		.help = "time to live",
4556 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4557 			     item_param),
4558 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4559 					     hdr.time_to_live)),
4560 	},
4561 	[ITEM_IPV4_PROTO] = {
4562 		.name = "proto",
4563 		.help = "next protocol ID",
4564 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4565 			     item_param),
4566 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4567 					     hdr.next_proto_id)),
4568 	},
4569 	[ITEM_IPV4_SRC] = {
4570 		.name = "src",
4571 		.help = "source address",
4572 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4573 			     item_param),
4574 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4575 					     hdr.src_addr)),
4576 	},
4577 	[ITEM_IPV4_DST] = {
4578 		.name = "dst",
4579 		.help = "destination address",
4580 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4581 			     item_param),
4582 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4583 					     hdr.dst_addr)),
4584 	},
4585 	[ITEM_IPV6] = {
4586 		.name = "ipv6",
4587 		.help = "match IPv6 header",
4588 		.priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
4589 		.next = NEXT(item_ipv6),
4590 		.call = parse_vc,
4591 	},
4592 	[ITEM_IPV6_TC] = {
4593 		.name = "tc",
4594 		.help = "traffic class",
4595 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4596 			     item_param),
4597 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4598 						  hdr.vtc_flow,
4599 						  "\x0f\xf0\x00\x00")),
4600 	},
4601 	[ITEM_IPV6_FLOW] = {
4602 		.name = "flow",
4603 		.help = "flow label",
4604 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4605 			     item_param),
4606 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4607 						  hdr.vtc_flow,
4608 						  "\x00\x0f\xff\xff")),
4609 	},
4610 	[ITEM_IPV6_LEN] = {
4611 		.name = "length",
4612 		.help = "payload length",
4613 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4614 			     item_param),
4615 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4616 					     hdr.payload_len)),
4617 	},
4618 	[ITEM_IPV6_PROTO] = {
4619 		.name = "proto",
4620 		.help = "protocol (next header)",
4621 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4622 			     item_param),
4623 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4624 					     hdr.proto)),
4625 	},
4626 	[ITEM_IPV6_HOP] = {
4627 		.name = "hop",
4628 		.help = "hop limit",
4629 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4630 			     item_param),
4631 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4632 					     hdr.hop_limits)),
4633 	},
4634 	[ITEM_IPV6_SRC] = {
4635 		.name = "src",
4636 		.help = "source address",
4637 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4638 			     item_param),
4639 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4640 					     hdr.src_addr)),
4641 	},
4642 	[ITEM_IPV6_DST] = {
4643 		.name = "dst",
4644 		.help = "destination address",
4645 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4646 			     item_param),
4647 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4648 					     hdr.dst_addr)),
4649 	},
4650 	[ITEM_IPV6_HAS_FRAG_EXT] = {
4651 		.name = "has_frag_ext",
4652 		.help = "fragment packet attribute",
4653 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4654 			     item_param),
4655 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
4656 					   has_frag_ext, 1)),
4657 	},
4658 	[ITEM_IPV6_ROUTING_EXT] = {
4659 		.name = "ipv6_routing_ext",
4660 		.help = "match IPv6 routing extension header",
4661 		.priv = PRIV_ITEM(IPV6_ROUTING_EXT,
4662 				  sizeof(struct rte_flow_item_ipv6_routing_ext)),
4663 		.next = NEXT(item_ipv6_routing_ext),
4664 		.call = parse_vc,
4665 	},
4666 	[ITEM_IPV6_ROUTING_EXT_TYPE] = {
4667 		.name = "ext_type",
4668 		.help = "match IPv6 routing extension header type",
4669 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4670 			     item_param),
4671 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4672 					     hdr.type)),
4673 	},
4674 	[ITEM_IPV6_ROUTING_EXT_NEXT_HDR] = {
4675 		.name = "ext_next_hdr",
4676 		.help = "match IPv6 routing extension header next header type",
4677 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4678 			     item_param),
4679 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4680 					     hdr.next_hdr)),
4681 	},
4682 	[ITEM_IPV6_ROUTING_EXT_SEG_LEFT] = {
4683 		.name = "ext_seg_left",
4684 		.help = "match IPv6 routing extension header segment left",
4685 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4686 			     item_param),
4687 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4688 					     hdr.segments_left)),
4689 	},
4690 	[ITEM_ICMP] = {
4691 		.name = "icmp",
4692 		.help = "match ICMP header",
4693 		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
4694 		.next = NEXT(item_icmp),
4695 		.call = parse_vc,
4696 	},
4697 	[ITEM_ICMP_TYPE] = {
4698 		.name = "type",
4699 		.help = "ICMP packet type",
4700 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4701 			     item_param),
4702 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4703 					     hdr.icmp_type)),
4704 	},
4705 	[ITEM_ICMP_CODE] = {
4706 		.name = "code",
4707 		.help = "ICMP packet code",
4708 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4709 			     item_param),
4710 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4711 					     hdr.icmp_code)),
4712 	},
4713 	[ITEM_ICMP_IDENT] = {
4714 		.name = "ident",
4715 		.help = "ICMP packet identifier",
4716 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4717 			     item_param),
4718 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4719 					     hdr.icmp_ident)),
4720 	},
4721 	[ITEM_ICMP_SEQ] = {
4722 		.name = "seq",
4723 		.help = "ICMP packet sequence number",
4724 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4725 			     item_param),
4726 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4727 					     hdr.icmp_seq_nb)),
4728 	},
4729 	[ITEM_UDP] = {
4730 		.name = "udp",
4731 		.help = "match UDP header",
4732 		.priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
4733 		.next = NEXT(item_udp),
4734 		.call = parse_vc,
4735 	},
4736 	[ITEM_UDP_SRC] = {
4737 		.name = "src",
4738 		.help = "UDP source port",
4739 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
4740 			     item_param),
4741 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4742 					     hdr.src_port)),
4743 	},
4744 	[ITEM_UDP_DST] = {
4745 		.name = "dst",
4746 		.help = "UDP destination port",
4747 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4748 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4749 					     hdr.dst_port)),
4750 	},
4751 	[ITEM_TCP] = {
4752 		.name = "tcp",
4753 		.help = "match TCP header",
4754 		.priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
4755 		.next = NEXT(item_tcp),
4756 		.call = parse_vc,
4757 	},
4758 	[ITEM_TCP_SRC] = {
4759 		.name = "src",
4760 		.help = "TCP source port",
4761 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4762 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4763 					     hdr.src_port)),
4764 	},
4765 	[ITEM_TCP_DST] = {
4766 		.name = "dst",
4767 		.help = "TCP destination port",
4768 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4769 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4770 					     hdr.dst_port)),
4771 	},
4772 	[ITEM_TCP_FLAGS] = {
4773 		.name = "flags",
4774 		.help = "TCP flags",
4775 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4776 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4777 					     hdr.tcp_flags)),
4778 	},
4779 	[ITEM_SCTP] = {
4780 		.name = "sctp",
4781 		.help = "match SCTP header",
4782 		.priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
4783 		.next = NEXT(item_sctp),
4784 		.call = parse_vc,
4785 	},
4786 	[ITEM_SCTP_SRC] = {
4787 		.name = "src",
4788 		.help = "SCTP source port",
4789 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4790 			     item_param),
4791 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4792 					     hdr.src_port)),
4793 	},
4794 	[ITEM_SCTP_DST] = {
4795 		.name = "dst",
4796 		.help = "SCTP destination port",
4797 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4798 			     item_param),
4799 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4800 					     hdr.dst_port)),
4801 	},
4802 	[ITEM_SCTP_TAG] = {
4803 		.name = "tag",
4804 		.help = "validation tag",
4805 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4806 			     item_param),
4807 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4808 					     hdr.tag)),
4809 	},
4810 	[ITEM_SCTP_CKSUM] = {
4811 		.name = "cksum",
4812 		.help = "checksum",
4813 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4814 			     item_param),
4815 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4816 					     hdr.cksum)),
4817 	},
4818 	[ITEM_VXLAN] = {
4819 		.name = "vxlan",
4820 		.help = "match VXLAN header",
4821 		.priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
4822 		.next = NEXT(item_vxlan),
4823 		.call = parse_vc,
4824 	},
4825 	[ITEM_VXLAN_VNI] = {
4826 		.name = "vni",
4827 		.help = "VXLAN identifier",
4828 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4829 			     item_param),
4830 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, hdr.vni)),
4831 	},
4832 	[ITEM_VXLAN_LAST_RSVD] = {
4833 		.name = "last_rsvd",
4834 		.help = "VXLAN last reserved bits",
4835 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4836 			     item_param),
4837 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
4838 					     hdr.rsvd1)),
4839 	},
4840 	[ITEM_E_TAG] = {
4841 		.name = "e_tag",
4842 		.help = "match E-Tag header",
4843 		.priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
4844 		.next = NEXT(item_e_tag),
4845 		.call = parse_vc,
4846 	},
4847 	[ITEM_E_TAG_GRP_ECID_B] = {
4848 		.name = "grp_ecid_b",
4849 		.help = "GRP and E-CID base",
4850 		.next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
4851 			     item_param),
4852 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
4853 						  rsvd_grp_ecid_b,
4854 						  "\x3f\xff")),
4855 	},
4856 	[ITEM_NVGRE] = {
4857 		.name = "nvgre",
4858 		.help = "match NVGRE header",
4859 		.priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
4860 		.next = NEXT(item_nvgre),
4861 		.call = parse_vc,
4862 	},
4863 	[ITEM_NVGRE_TNI] = {
4864 		.name = "tni",
4865 		.help = "virtual subnet ID",
4866 		.next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
4867 			     item_param),
4868 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
4869 	},
4870 	[ITEM_MPLS] = {
4871 		.name = "mpls",
4872 		.help = "match MPLS header",
4873 		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
4874 		.next = NEXT(item_mpls),
4875 		.call = parse_vc,
4876 	},
4877 	[ITEM_MPLS_LABEL] = {
4878 		.name = "label",
4879 		.help = "MPLS label",
4880 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4881 			     item_param),
4882 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4883 						  label_tc_s,
4884 						  "\xff\xff\xf0")),
4885 	},
4886 	[ITEM_MPLS_TC] = {
4887 		.name = "tc",
4888 		.help = "MPLS Traffic Class",
4889 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4890 			     item_param),
4891 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4892 						  label_tc_s,
4893 						  "\x00\x00\x0e")),
4894 	},
4895 	[ITEM_MPLS_S] = {
4896 		.name = "s",
4897 		.help = "MPLS Bottom-of-Stack",
4898 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4899 			     item_param),
4900 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4901 						  label_tc_s,
4902 						  "\x00\x00\x01")),
4903 	},
4904 	[ITEM_MPLS_TTL] = {
4905 		.name = "ttl",
4906 		.help = "MPLS Time-to-Live",
4907 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4908 			     item_param),
4909 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_mpls, ttl)),
4910 	},
4911 	[ITEM_GRE] = {
4912 		.name = "gre",
4913 		.help = "match GRE header",
4914 		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
4915 		.next = NEXT(item_gre),
4916 		.call = parse_vc,
4917 	},
4918 	[ITEM_GRE_PROTO] = {
4919 		.name = "protocol",
4920 		.help = "GRE protocol type",
4921 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
4922 			     item_param),
4923 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
4924 					     protocol)),
4925 	},
4926 	[ITEM_GRE_C_RSVD0_VER] = {
4927 		.name = "c_rsvd0_ver",
4928 		.help =
4929 			"checksum (1b), undefined (1b), key bit (1b),"
4930 			" sequence number (1b), reserved 0 (9b),"
4931 			" version (3b)",
4932 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
4933 			     item_param),
4934 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
4935 					     c_rsvd0_ver)),
4936 	},
4937 	[ITEM_GRE_C_BIT] = {
4938 		.name = "c_bit",
4939 		.help = "checksum bit (C)",
4940 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
4941 			     item_param),
4942 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
4943 						  c_rsvd0_ver,
4944 						  "\x80\x00\x00\x00")),
4945 	},
4946 	[ITEM_GRE_S_BIT] = {
4947 		.name = "s_bit",
4948 		.help = "sequence number bit (S)",
4949 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4950 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
4951 						  c_rsvd0_ver,
4952 						  "\x10\x00\x00\x00")),
4953 	},
4954 	[ITEM_GRE_K_BIT] = {
4955 		.name = "k_bit",
4956 		.help = "key bit (K)",
4957 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4958 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
4959 						  c_rsvd0_ver,
4960 						  "\x20\x00\x00\x00")),
4961 	},
4962 	[ITEM_FUZZY] = {
4963 		.name = "fuzzy",
4964 		.help = "fuzzy pattern match, expect faster than default",
4965 		.priv = PRIV_ITEM(FUZZY,
4966 				sizeof(struct rte_flow_item_fuzzy)),
4967 		.next = NEXT(item_fuzzy),
4968 		.call = parse_vc,
4969 	},
4970 	[ITEM_FUZZY_THRESH] = {
4971 		.name = "thresh",
4972 		.help = "match accuracy threshold",
4973 		.next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
4974 			     item_param),
4975 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
4976 					thresh)),
4977 	},
4978 	[ITEM_GTP] = {
4979 		.name = "gtp",
4980 		.help = "match GTP header",
4981 		.priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
4982 		.next = NEXT(item_gtp),
4983 		.call = parse_vc,
4984 	},
4985 	[ITEM_GTP_FLAGS] = {
4986 		.name = "v_pt_rsv_flags",
4987 		.help = "GTP flags",
4988 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4989 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
4990 					hdr.gtp_hdr_info)),
4991 	},
4992 	[ITEM_GTP_MSG_TYPE] = {
4993 		.name = "msg_type",
4994 		.help = "GTP message type",
4995 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4996 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, hdr.msg_type)),
4997 	},
4998 	[ITEM_GTP_TEID] = {
4999 		.name = "teid",
5000 		.help = "tunnel endpoint identifier",
5001 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5002 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, hdr.teid)),
5003 	},
5004 	[ITEM_GTPC] = {
5005 		.name = "gtpc",
5006 		.help = "match GTP header",
5007 		.priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
5008 		.next = NEXT(item_gtp),
5009 		.call = parse_vc,
5010 	},
5011 	[ITEM_GTPU] = {
5012 		.name = "gtpu",
5013 		.help = "match GTP header",
5014 		.priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
5015 		.next = NEXT(item_gtp),
5016 		.call = parse_vc,
5017 	},
5018 	[ITEM_GENEVE] = {
5019 		.name = "geneve",
5020 		.help = "match GENEVE header",
5021 		.priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
5022 		.next = NEXT(item_geneve),
5023 		.call = parse_vc,
5024 	},
5025 	[ITEM_GENEVE_VNI] = {
5026 		.name = "vni",
5027 		.help = "virtual network identifier",
5028 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5029 			     item_param),
5030 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
5031 	},
5032 	[ITEM_GENEVE_PROTO] = {
5033 		.name = "protocol",
5034 		.help = "GENEVE protocol type",
5035 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5036 			     item_param),
5037 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
5038 					     protocol)),
5039 	},
5040 	[ITEM_GENEVE_OPTLEN] = {
5041 		.name = "optlen",
5042 		.help = "GENEVE options length in dwords",
5043 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5044 			     item_param),
5045 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
5046 						  ver_opt_len_o_c_rsvd0,
5047 						  "\x3f\x00")),
5048 	},
5049 	[ITEM_VXLAN_GPE] = {
5050 		.name = "vxlan-gpe",
5051 		.help = "match VXLAN-GPE header",
5052 		.priv = PRIV_ITEM(VXLAN_GPE,
5053 				  sizeof(struct rte_flow_item_vxlan_gpe)),
5054 		.next = NEXT(item_vxlan_gpe),
5055 		.call = parse_vc,
5056 	},
5057 	[ITEM_VXLAN_GPE_VNI] = {
5058 		.name = "vni",
5059 		.help = "VXLAN-GPE identifier",
5060 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5061 			     item_param),
5062 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5063 					     hdr.vni)),
5064 	},
5065 	[ITEM_VXLAN_GPE_PROTO] = {
5066 		.name = "protocol",
5067 		.help = "VXLAN-GPE next protocol",
5068 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5069 			     item_param),
5070 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5071 					     protocol)),
5072 	},
5073 	[ITEM_ARP_ETH_IPV4] = {
5074 		.name = "arp_eth_ipv4",
5075 		.help = "match ARP header for Ethernet/IPv4",
5076 		.priv = PRIV_ITEM(ARP_ETH_IPV4,
5077 				  sizeof(struct rte_flow_item_arp_eth_ipv4)),
5078 		.next = NEXT(item_arp_eth_ipv4),
5079 		.call = parse_vc,
5080 	},
5081 	[ITEM_ARP_ETH_IPV4_SHA] = {
5082 		.name = "sha",
5083 		.help = "sender hardware address",
5084 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5085 			     item_param),
5086 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5087 					     hdr.arp_data.arp_sha)),
5088 	},
5089 	[ITEM_ARP_ETH_IPV4_SPA] = {
5090 		.name = "spa",
5091 		.help = "sender IPv4 address",
5092 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5093 			     item_param),
5094 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5095 					     hdr.arp_data.arp_sip)),
5096 	},
5097 	[ITEM_ARP_ETH_IPV4_THA] = {
5098 		.name = "tha",
5099 		.help = "target hardware address",
5100 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5101 			     item_param),
5102 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5103 					     hdr.arp_data.arp_tha)),
5104 	},
5105 	[ITEM_ARP_ETH_IPV4_TPA] = {
5106 		.name = "tpa",
5107 		.help = "target IPv4 address",
5108 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5109 			     item_param),
5110 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5111 					     hdr.arp_data.arp_tip)),
5112 	},
5113 	[ITEM_IPV6_EXT] = {
5114 		.name = "ipv6_ext",
5115 		.help = "match presence of any IPv6 extension header",
5116 		.priv = PRIV_ITEM(IPV6_EXT,
5117 				  sizeof(struct rte_flow_item_ipv6_ext)),
5118 		.next = NEXT(item_ipv6_ext),
5119 		.call = parse_vc,
5120 	},
5121 	[ITEM_IPV6_EXT_NEXT_HDR] = {
5122 		.name = "next_hdr",
5123 		.help = "next header",
5124 		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5125 			     item_param),
5126 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
5127 					     next_hdr)),
5128 	},
5129 	[ITEM_IPV6_FRAG_EXT] = {
5130 		.name = "ipv6_frag_ext",
5131 		.help = "match presence of IPv6 fragment extension header",
5132 		.priv = PRIV_ITEM(IPV6_FRAG_EXT,
5133 				sizeof(struct rte_flow_item_ipv6_frag_ext)),
5134 		.next = NEXT(item_ipv6_frag_ext),
5135 		.call = parse_vc,
5136 	},
5137 	[ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
5138 		.name = "next_hdr",
5139 		.help = "next header",
5140 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5141 			     item_param),
5142 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
5143 					hdr.next_header)),
5144 	},
5145 	[ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
5146 		.name = "frag_data",
5147 		.help = "fragment flags and offset",
5148 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5149 			     item_param),
5150 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5151 					     hdr.frag_data)),
5152 	},
5153 	[ITEM_IPV6_FRAG_EXT_ID] = {
5154 		.name = "packet_id",
5155 		.help = "fragment packet id",
5156 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5157 			     item_param),
5158 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5159 					     hdr.id)),
5160 	},
5161 	[ITEM_ICMP6] = {
5162 		.name = "icmp6",
5163 		.help = "match any ICMPv6 header",
5164 		.priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
5165 		.next = NEXT(item_icmp6),
5166 		.call = parse_vc,
5167 	},
5168 	[ITEM_ICMP6_TYPE] = {
5169 		.name = "type",
5170 		.help = "ICMPv6 type",
5171 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5172 			     item_param),
5173 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5174 					     type)),
5175 	},
5176 	[ITEM_ICMP6_CODE] = {
5177 		.name = "code",
5178 		.help = "ICMPv6 code",
5179 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5180 			     item_param),
5181 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5182 					     code)),
5183 	},
5184 	[ITEM_ICMP6_ECHO_REQUEST] = {
5185 		.name = "icmp6_echo_request",
5186 		.help = "match ICMPv6 echo request",
5187 		.priv = PRIV_ITEM(ICMP6_ECHO_REQUEST,
5188 				  sizeof(struct rte_flow_item_icmp6_echo)),
5189 		.next = NEXT(item_icmp6_echo_request),
5190 		.call = parse_vc,
5191 	},
5192 	[ITEM_ICMP6_ECHO_REQUEST_ID] = {
5193 		.name = "ident",
5194 		.help = "ICMPv6 echo request identifier",
5195 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5196 			     item_param),
5197 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5198 					     hdr.identifier)),
5199 	},
5200 	[ITEM_ICMP6_ECHO_REQUEST_SEQ] = {
5201 		.name = "seq",
5202 		.help = "ICMPv6 echo request sequence",
5203 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5204 			     item_param),
5205 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5206 					     hdr.sequence)),
5207 	},
5208 	[ITEM_ICMP6_ECHO_REPLY] = {
5209 		.name = "icmp6_echo_reply",
5210 		.help = "match ICMPv6 echo reply",
5211 		.priv = PRIV_ITEM(ICMP6_ECHO_REPLY,
5212 				  sizeof(struct rte_flow_item_icmp6_echo)),
5213 		.next = NEXT(item_icmp6_echo_reply),
5214 		.call = parse_vc,
5215 	},
5216 	[ITEM_ICMP6_ECHO_REPLY_ID] = {
5217 		.name = "ident",
5218 		.help = "ICMPv6 echo reply identifier",
5219 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5220 			     item_param),
5221 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5222 					     hdr.identifier)),
5223 	},
5224 	[ITEM_ICMP6_ECHO_REPLY_SEQ] = {
5225 		.name = "seq",
5226 		.help = "ICMPv6 echo reply sequence",
5227 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5228 			     item_param),
5229 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5230 					     hdr.sequence)),
5231 	},
5232 	[ITEM_ICMP6_ND_NS] = {
5233 		.name = "icmp6_nd_ns",
5234 		.help = "match ICMPv6 neighbor discovery solicitation",
5235 		.priv = PRIV_ITEM(ICMP6_ND_NS,
5236 				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
5237 		.next = NEXT(item_icmp6_nd_ns),
5238 		.call = parse_vc,
5239 	},
5240 	[ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
5241 		.name = "target_addr",
5242 		.help = "target address",
5243 		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
5244 			     item_param),
5245 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
5246 					     target_addr)),
5247 	},
5248 	[ITEM_ICMP6_ND_NA] = {
5249 		.name = "icmp6_nd_na",
5250 		.help = "match ICMPv6 neighbor discovery advertisement",
5251 		.priv = PRIV_ITEM(ICMP6_ND_NA,
5252 				  sizeof(struct rte_flow_item_icmp6_nd_na)),
5253 		.next = NEXT(item_icmp6_nd_na),
5254 		.call = parse_vc,
5255 	},
5256 	[ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
5257 		.name = "target_addr",
5258 		.help = "target address",
5259 		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
5260 			     item_param),
5261 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
5262 					     target_addr)),
5263 	},
5264 	[ITEM_ICMP6_ND_OPT] = {
5265 		.name = "icmp6_nd_opt",
5266 		.help = "match presence of any ICMPv6 neighbor discovery"
5267 			" option",
5268 		.priv = PRIV_ITEM(ICMP6_ND_OPT,
5269 				  sizeof(struct rte_flow_item_icmp6_nd_opt)),
5270 		.next = NEXT(item_icmp6_nd_opt),
5271 		.call = parse_vc,
5272 	},
5273 	[ITEM_ICMP6_ND_OPT_TYPE] = {
5274 		.name = "type",
5275 		.help = "ND option type",
5276 		.next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5277 			     item_param),
5278 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
5279 					     type)),
5280 	},
5281 	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
5282 		.name = "icmp6_nd_opt_sla_eth",
5283 		.help = "match ICMPv6 neighbor discovery source Ethernet"
5284 			" link-layer address option",
5285 		.priv = PRIV_ITEM
5286 			(ICMP6_ND_OPT_SLA_ETH,
5287 			 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
5288 		.next = NEXT(item_icmp6_nd_opt_sla_eth),
5289 		.call = parse_vc,
5290 	},
5291 	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
5292 		.name = "sla",
5293 		.help = "source Ethernet LLA",
5294 		.next = NEXT(item_icmp6_nd_opt_sla_eth,
5295 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5296 		.args = ARGS(ARGS_ENTRY_HTON
5297 			     (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
5298 	},
5299 	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
5300 		.name = "icmp6_nd_opt_tla_eth",
5301 		.help = "match ICMPv6 neighbor discovery target Ethernet"
5302 			" link-layer address option",
5303 		.priv = PRIV_ITEM
5304 			(ICMP6_ND_OPT_TLA_ETH,
5305 			 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
5306 		.next = NEXT(item_icmp6_nd_opt_tla_eth),
5307 		.call = parse_vc,
5308 	},
5309 	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
5310 		.name = "tla",
5311 		.help = "target Ethernet LLA",
5312 		.next = NEXT(item_icmp6_nd_opt_tla_eth,
5313 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5314 		.args = ARGS(ARGS_ENTRY_HTON
5315 			     (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
5316 	},
5317 	[ITEM_META] = {
5318 		.name = "meta",
5319 		.help = "match metadata header",
5320 		.priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
5321 		.next = NEXT(item_meta),
5322 		.call = parse_vc,
5323 	},
5324 	[ITEM_META_DATA] = {
5325 		.name = "data",
5326 		.help = "metadata value",
5327 		.next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
5328 			     item_param),
5329 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
5330 					     data, "\xff\xff\xff\xff")),
5331 	},
5332 	[ITEM_RANDOM] = {
5333 		.name = "random",
5334 		.help = "match random value",
5335 		.priv = PRIV_ITEM(RANDOM, sizeof(struct rte_flow_item_random)),
5336 		.next = NEXT(item_random),
5337 		.call = parse_vc,
5338 	},
5339 	[ITEM_RANDOM_VALUE] = {
5340 		.name = "value",
5341 		.help = "random value",
5342 		.next = NEXT(item_random, NEXT_ENTRY(COMMON_UNSIGNED),
5343 			     item_param),
5344 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_random,
5345 					     value, "\xff\xff")),
5346 	},
5347 	[ITEM_GRE_KEY] = {
5348 		.name = "gre_key",
5349 		.help = "match GRE key",
5350 		.priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
5351 		.next = NEXT(item_gre_key),
5352 		.call = parse_vc,
5353 	},
5354 	[ITEM_GRE_KEY_VALUE] = {
5355 		.name = "value",
5356 		.help = "key value",
5357 		.next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
5358 			     item_param),
5359 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5360 	},
5361 	[ITEM_GRE_OPTION] = {
5362 		.name = "gre_option",
5363 		.help = "match GRE optional fields",
5364 		.priv = PRIV_ITEM(GRE_OPTION,
5365 				  sizeof(struct rte_flow_item_gre_opt)),
5366 		.next = NEXT(item_gre_option),
5367 		.call = parse_vc,
5368 	},
5369 	[ITEM_GRE_OPTION_CHECKSUM] = {
5370 		.name = "checksum",
5371 		.help = "match GRE checksum",
5372 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5373 			     item_param),
5374 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5375 					     checksum_rsvd.checksum)),
5376 	},
5377 	[ITEM_GRE_OPTION_KEY] = {
5378 		.name = "key",
5379 		.help = "match GRE key",
5380 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5381 			     item_param),
5382 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5383 					     key.key)),
5384 	},
5385 	[ITEM_GRE_OPTION_SEQUENCE] = {
5386 		.name = "sequence",
5387 		.help = "match GRE sequence",
5388 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5389 			     item_param),
5390 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5391 					     sequence.sequence)),
5392 	},
5393 	[ITEM_GTP_PSC] = {
5394 		.name = "gtp_psc",
5395 		.help = "match GTP extension header with type 0x85",
5396 		.priv = PRIV_ITEM(GTP_PSC,
5397 				sizeof(struct rte_flow_item_gtp_psc)),
5398 		.next = NEXT(item_gtp_psc),
5399 		.call = parse_vc,
5400 	},
5401 	[ITEM_GTP_PSC_QFI] = {
5402 		.name = "qfi",
5403 		.help = "QoS flow identifier",
5404 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5405 			     item_param),
5406 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5407 					hdr.qfi, 6)),
5408 	},
5409 	[ITEM_GTP_PSC_PDU_T] = {
5410 		.name = "pdu_t",
5411 		.help = "PDU type",
5412 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5413 			     item_param),
5414 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5415 					hdr.type, 4)),
5416 	},
5417 	[ITEM_PPPOES] = {
5418 		.name = "pppoes",
5419 		.help = "match PPPoE session header",
5420 		.priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
5421 		.next = NEXT(item_pppoes),
5422 		.call = parse_vc,
5423 	},
5424 	[ITEM_PPPOED] = {
5425 		.name = "pppoed",
5426 		.help = "match PPPoE discovery header",
5427 		.priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
5428 		.next = NEXT(item_pppoed),
5429 		.call = parse_vc,
5430 	},
5431 	[ITEM_PPPOE_SEID] = {
5432 		.name = "seid",
5433 		.help = "session identifier",
5434 		.next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
5435 			     item_param),
5436 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
5437 					session_id)),
5438 	},
5439 	[ITEM_PPPOE_PROTO_ID] = {
5440 		.name = "pppoe_proto_id",
5441 		.help = "match PPPoE session protocol identifier",
5442 		.priv = PRIV_ITEM(PPPOE_PROTO_ID,
5443 				sizeof(struct rte_flow_item_pppoe_proto_id)),
5444 		.next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
5445 			     item_param),
5446 		.args = ARGS(ARGS_ENTRY_HTON
5447 			     (struct rte_flow_item_pppoe_proto_id, proto_id)),
5448 		.call = parse_vc,
5449 	},
5450 	[ITEM_HIGIG2] = {
5451 		.name = "higig2",
5452 		.help = "matches higig2 header",
5453 		.priv = PRIV_ITEM(HIGIG2,
5454 				sizeof(struct rte_flow_item_higig2_hdr)),
5455 		.next = NEXT(item_higig2),
5456 		.call = parse_vc,
5457 	},
5458 	[ITEM_HIGIG2_CLASSIFICATION] = {
5459 		.name = "classification",
5460 		.help = "matches classification of higig2 header",
5461 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5462 			     item_param),
5463 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5464 					hdr.ppt1.classification)),
5465 	},
5466 	[ITEM_HIGIG2_VID] = {
5467 		.name = "vid",
5468 		.help = "matches vid of higig2 header",
5469 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5470 			     item_param),
5471 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5472 					hdr.ppt1.vid)),
5473 	},
5474 	[ITEM_TAG] = {
5475 		.name = "tag",
5476 		.help = "match tag value",
5477 		.priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
5478 		.next = NEXT(item_tag),
5479 		.call = parse_vc,
5480 	},
5481 	[ITEM_TAG_DATA] = {
5482 		.name = "data",
5483 		.help = "tag value to match",
5484 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5485 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
5486 	},
5487 	[ITEM_TAG_INDEX] = {
5488 		.name = "index",
5489 		.help = "index of tag array to match",
5490 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
5491 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5492 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
5493 	},
5494 	[ITEM_L2TPV3OIP] = {
5495 		.name = "l2tpv3oip",
5496 		.help = "match L2TPv3 over IP header",
5497 		.priv = PRIV_ITEM(L2TPV3OIP,
5498 				  sizeof(struct rte_flow_item_l2tpv3oip)),
5499 		.next = NEXT(item_l2tpv3oip),
5500 		.call = parse_vc,
5501 	},
5502 	[ITEM_L2TPV3OIP_SESSION_ID] = {
5503 		.name = "session_id",
5504 		.help = "session identifier",
5505 		.next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
5506 			     item_param),
5507 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
5508 					     session_id)),
5509 	},
5510 	[ITEM_ESP] = {
5511 		.name = "esp",
5512 		.help = "match ESP header",
5513 		.priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
5514 		.next = NEXT(item_esp),
5515 		.call = parse_vc,
5516 	},
5517 	[ITEM_ESP_SPI] = {
5518 		.name = "spi",
5519 		.help = "security policy index",
5520 		.next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5521 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
5522 				hdr.spi)),
5523 	},
5524 	[ITEM_AH] = {
5525 		.name = "ah",
5526 		.help = "match AH header",
5527 		.priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
5528 		.next = NEXT(item_ah),
5529 		.call = parse_vc,
5530 	},
5531 	[ITEM_AH_SPI] = {
5532 		.name = "spi",
5533 		.help = "security parameters index",
5534 		.next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5535 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
5536 	},
5537 	[ITEM_PFCP] = {
5538 		.name = "pfcp",
5539 		.help = "match pfcp header",
5540 		.priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
5541 		.next = NEXT(item_pfcp),
5542 		.call = parse_vc,
5543 	},
5544 	[ITEM_PFCP_S_FIELD] = {
5545 		.name = "s_field",
5546 		.help = "S field",
5547 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5548 			     item_param),
5549 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
5550 				s_field)),
5551 	},
5552 	[ITEM_PFCP_SEID] = {
5553 		.name = "seid",
5554 		.help = "session endpoint identifier",
5555 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5556 			     item_param),
5557 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
5558 	},
5559 	[ITEM_ECPRI] = {
5560 		.name = "ecpri",
5561 		.help = "match eCPRI header",
5562 		.priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
5563 		.next = NEXT(item_ecpri),
5564 		.call = parse_vc,
5565 	},
5566 	[ITEM_ECPRI_COMMON] = {
5567 		.name = "common",
5568 		.help = "eCPRI common header",
5569 		.next = NEXT(item_ecpri_common),
5570 	},
5571 	[ITEM_ECPRI_COMMON_TYPE] = {
5572 		.name = "type",
5573 		.help = "type of common header",
5574 		.next = NEXT(item_ecpri_common_type),
5575 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
5576 	},
5577 	[ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
5578 		.name = "iq_data",
5579 		.help = "Type #0: IQ Data",
5580 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5581 					ITEM_NEXT)),
5582 		.call = parse_vc_item_ecpri_type,
5583 	},
5584 	[ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
5585 		.name = "pc_id",
5586 		.help = "Physical Channel ID",
5587 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5588 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5589 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5590 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5591 				hdr.type0.pc_id)),
5592 	},
5593 	[ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
5594 		.name = "rtc_ctrl",
5595 		.help = "Type #2: Real-Time Control Data",
5596 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5597 					ITEM_NEXT)),
5598 		.call = parse_vc_item_ecpri_type,
5599 	},
5600 	[ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
5601 		.name = "rtc_id",
5602 		.help = "Real-Time Control Data ID",
5603 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5604 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5605 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5607 				hdr.type2.rtc_id)),
5608 	},
5609 	[ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
5610 		.name = "delay_measure",
5611 		.help = "Type #5: One-Way Delay Measurement",
5612 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5613 					ITEM_NEXT)),
5614 		.call = parse_vc_item_ecpri_type,
5615 	},
5616 	[ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
5617 		.name = "msr_id",
5618 		.help = "Measurement ID",
5619 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5620 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5621 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5622 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5623 				hdr.type5.msr_id)),
5624 	},
5625 	[ITEM_GENEVE_OPT] = {
5626 		.name = "geneve-opt",
5627 		.help = "GENEVE header option",
5628 		.priv = PRIV_ITEM(GENEVE_OPT,
5629 				  sizeof(struct rte_flow_item_geneve_opt) +
5630 				  ITEM_GENEVE_OPT_DATA_SIZE),
5631 		.next = NEXT(item_geneve_opt),
5632 		.call = parse_vc,
5633 	},
5634 	[ITEM_GENEVE_OPT_CLASS]	= {
5635 		.name = "class",
5636 		.help = "GENEVE option class",
5637 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5638 			     item_param),
5639 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
5640 					     option_class)),
5641 	},
5642 	[ITEM_GENEVE_OPT_TYPE] = {
5643 		.name = "type",
5644 		.help = "GENEVE option type",
5645 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5646 			     item_param),
5647 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
5648 					option_type)),
5649 	},
5650 	[ITEM_GENEVE_OPT_LENGTH] = {
5651 		.name = "length",
5652 		.help = "GENEVE option data length (in 32b words)",
5653 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5654 			     item_param),
5655 		.args = ARGS(ARGS_ENTRY_BOUNDED(
5656 				struct rte_flow_item_geneve_opt, option_len,
5657 				0, 31)),
5658 	},
5659 	[ITEM_GENEVE_OPT_DATA] = {
5660 		.name = "data",
5661 		.help = "GENEVE option data pattern",
5662 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
5663 			     item_param),
5664 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
5665 			     ARGS_ENTRY_ARB(0, 0),
5666 			     ARGS_ENTRY_ARB
5667 				(sizeof(struct rte_flow_item_geneve_opt),
5668 				ITEM_GENEVE_OPT_DATA_SIZE)),
5669 	},
5670 	[ITEM_INTEGRITY] = {
5671 		.name = "integrity",
5672 		.help = "match packet integrity",
5673 		.priv = PRIV_ITEM(INTEGRITY,
5674 				  sizeof(struct rte_flow_item_integrity)),
5675 		.next = NEXT(item_integrity),
5676 		.call = parse_vc,
5677 	},
5678 	[ITEM_INTEGRITY_LEVEL] = {
5679 		.name = "level",
5680 		.help = "integrity level",
5681 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5682 			     item_param),
5683 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
5684 	},
5685 	[ITEM_INTEGRITY_VALUE] = {
5686 		.name = "value",
5687 		.help = "integrity value",
5688 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5689 			     item_param),
5690 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
5691 	},
5692 	[ITEM_CONNTRACK] = {
5693 		.name = "conntrack",
5694 		.help = "conntrack state",
5695 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
5696 			     item_param),
5697 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
5698 	},
5699 	[ITEM_PORT_REPRESENTOR] = {
5700 		.name = "port_representor",
5701 		.help = "match traffic entering the embedded switch from the given ethdev",
5702 		.priv = PRIV_ITEM(PORT_REPRESENTOR,
5703 				  sizeof(struct rte_flow_item_ethdev)),
5704 		.next = NEXT(item_port_representor),
5705 		.call = parse_vc,
5706 	},
5707 	[ITEM_PORT_REPRESENTOR_PORT_ID] = {
5708 		.name = "port_id",
5709 		.help = "ethdev port ID",
5710 		.next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
5711 			     item_param),
5712 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5713 	},
5714 	[ITEM_REPRESENTED_PORT] = {
5715 		.name = "represented_port",
5716 		.help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
5717 		.priv = PRIV_ITEM(REPRESENTED_PORT,
5718 				  sizeof(struct rte_flow_item_ethdev)),
5719 		.next = NEXT(item_represented_port),
5720 		.call = parse_vc,
5721 	},
5722 	[ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
5723 		.name = "ethdev_port_id",
5724 		.help = "ethdev port ID",
5725 		.next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
5726 			     item_param),
5727 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5728 	},
5729 	[ITEM_FLEX] = {
5730 		.name = "flex",
5731 		.help = "match flex header",
5732 		.priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
5733 		.next = NEXT(item_flex),
5734 		.call = parse_vc,
5735 	},
5736 	[ITEM_FLEX_ITEM_HANDLE] = {
5737 		.name = "item",
5738 		.help = "flex item handle",
5739 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5740 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5741 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
5742 	},
5743 	[ITEM_FLEX_PATTERN_HANDLE] = {
5744 		.name = "pattern",
5745 		.help = "flex pattern handle",
5746 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5747 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5748 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
5749 	},
5750 	[ITEM_L2TPV2] = {
5751 		.name = "l2tpv2",
5752 		.help = "match L2TPv2 header",
5753 		.priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
5754 		.next = NEXT(item_l2tpv2),
5755 		.call = parse_vc,
5756 	},
5757 	[ITEM_L2TPV2_TYPE] = {
5758 		.name = "type",
5759 		.help = "type of l2tpv2",
5760 		.next = NEXT(item_l2tpv2_type),
5761 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
5762 	},
5763 	[ITEM_L2TPV2_TYPE_DATA] = {
5764 		.name = "data",
5765 		.help = "Type #7: data message without any options",
5766 		.next = NEXT(item_l2tpv2_type_data),
5767 		.call = parse_vc_item_l2tpv2_type,
5768 	},
5769 	[ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
5770 		.name = "tunnel_id",
5771 		.help = "tunnel identifier",
5772 		.next = NEXT(item_l2tpv2_type_data,
5773 			     NEXT_ENTRY(COMMON_UNSIGNED),
5774 			     item_param),
5775 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5776 					     hdr.type7.tunnel_id)),
5777 	},
5778 	[ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
5779 		.name = "session_id",
5780 		.help = "session identifier",
5781 		.next = NEXT(item_l2tpv2_type_data,
5782 			     NEXT_ENTRY(COMMON_UNSIGNED),
5783 			     item_param),
5784 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5785 					     hdr.type7.session_id)),
5786 	},
5787 	[ITEM_L2TPV2_TYPE_DATA_L] = {
5788 		.name = "data_l",
5789 		.help = "Type #6: data message with length option",
5790 		.next = NEXT(item_l2tpv2_type_data_l),
5791 		.call = parse_vc_item_l2tpv2_type,
5792 	},
5793 	[ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
5794 		.name = "length",
5795 		.help = "message length",
5796 		.next = NEXT(item_l2tpv2_type_data_l,
5797 			     NEXT_ENTRY(COMMON_UNSIGNED),
5798 			     item_param),
5799 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5800 					     hdr.type6.length)),
5801 	},
5802 	[ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
5803 		.name = "tunnel_id",
5804 		.help = "tunnel identifier",
5805 		.next = NEXT(item_l2tpv2_type_data_l,
5806 			     NEXT_ENTRY(COMMON_UNSIGNED),
5807 			     item_param),
5808 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5809 					     hdr.type6.tunnel_id)),
5810 	},
5811 	[ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
5812 		.name = "session_id",
5813 		.help = "session identifier",
5814 		.next = NEXT(item_l2tpv2_type_data_l,
5815 			     NEXT_ENTRY(COMMON_UNSIGNED),
5816 			     item_param),
5817 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5818 					     hdr.type6.session_id)),
5819 	},
5820 	[ITEM_L2TPV2_TYPE_DATA_S] = {
5821 		.name = "data_s",
5822 		.help = "Type #5: data message with ns, nr option",
5823 		.next = NEXT(item_l2tpv2_type_data_s),
5824 		.call = parse_vc_item_l2tpv2_type,
5825 	},
5826 	[ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
5827 		.name = "tunnel_id",
5828 		.help = "tunnel identifier",
5829 		.next = NEXT(item_l2tpv2_type_data_s,
5830 			     NEXT_ENTRY(COMMON_UNSIGNED),
5831 			     item_param),
5832 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5833 					     hdr.type5.tunnel_id)),
5834 	},
5835 	[ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
5836 		.name = "session_id",
5837 		.help = "session identifier",
5838 		.next = NEXT(item_l2tpv2_type_data_s,
5839 			     NEXT_ENTRY(COMMON_UNSIGNED),
5840 			     item_param),
5841 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5842 					     hdr.type5.session_id)),
5843 	},
5844 	[ITEM_L2TPV2_MSG_DATA_S_NS] = {
5845 		.name = "ns",
5846 		.help = "sequence number for message",
5847 		.next = NEXT(item_l2tpv2_type_data_s,
5848 			     NEXT_ENTRY(COMMON_UNSIGNED),
5849 			     item_param),
5850 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5851 					     hdr.type5.ns)),
5852 	},
5853 	[ITEM_L2TPV2_MSG_DATA_S_NR] = {
5854 		.name = "nr",
5855 		.help = "sequence number for next receive message",
5856 		.next = NEXT(item_l2tpv2_type_data_s,
5857 			     NEXT_ENTRY(COMMON_UNSIGNED),
5858 			     item_param),
5859 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5860 					     hdr.type5.nr)),
5861 	},
5862 	[ITEM_L2TPV2_TYPE_DATA_O] = {
5863 		.name = "data_o",
5864 		.help = "Type #4: data message with offset option",
5865 		.next = NEXT(item_l2tpv2_type_data_o),
5866 		.call = parse_vc_item_l2tpv2_type,
5867 	},
5868 	[ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
5869 		.name = "tunnel_id",
5870 		.help = "tunnel identifier",
5871 		.next = NEXT(item_l2tpv2_type_data_o,
5872 			     NEXT_ENTRY(COMMON_UNSIGNED),
5873 			     item_param),
5874 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5875 					     hdr.type4.tunnel_id)),
5876 	},
5877 	[ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
5878 		.name = "session_id",
5879 		.help = "session identifier",
5880 		.next = NEXT(item_l2tpv2_type_data_o,
5881 			     NEXT_ENTRY(COMMON_UNSIGNED),
5882 			     item_param),
5883 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5884 					     hdr.type5.session_id)),
5885 	},
5886 	[ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
5887 		.name = "offset_size",
5888 		.help = "the size of offset padding",
5889 		.next = NEXT(item_l2tpv2_type_data_o,
5890 			     NEXT_ENTRY(COMMON_UNSIGNED),
5891 			     item_param),
5892 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5893 					     hdr.type4.offset_size)),
5894 	},
5895 	[ITEM_L2TPV2_TYPE_DATA_L_S] = {
5896 		.name = "data_l_s",
5897 		.help = "Type #3: data message contains length, ns, nr "
5898 			"options",
5899 		.next = NEXT(item_l2tpv2_type_data_l_s),
5900 		.call = parse_vc_item_l2tpv2_type,
5901 	},
5902 	[ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
5903 		.name = "length",
5904 		.help = "message length",
5905 		.next = NEXT(item_l2tpv2_type_data_l_s,
5906 			     NEXT_ENTRY(COMMON_UNSIGNED),
5907 			     item_param),
5908 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5909 					     hdr.type3.length)),
5910 	},
5911 	[ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
5912 		.name = "tunnel_id",
5913 		.help = "tunnel identifier",
5914 		.next = NEXT(item_l2tpv2_type_data_l_s,
5915 			     NEXT_ENTRY(COMMON_UNSIGNED),
5916 			     item_param),
5917 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5918 					     hdr.type3.tunnel_id)),
5919 	},
5920 	[ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
5921 		.name = "session_id",
5922 		.help = "session identifier",
5923 		.next = NEXT(item_l2tpv2_type_data_l_s,
5924 			     NEXT_ENTRY(COMMON_UNSIGNED),
5925 			     item_param),
5926 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5927 					     hdr.type3.session_id)),
5928 	},
5929 	[ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
5930 		.name = "ns",
5931 		.help = "sequence number for message",
5932 		.next = NEXT(item_l2tpv2_type_data_l_s,
5933 			     NEXT_ENTRY(COMMON_UNSIGNED),
5934 			     item_param),
5935 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5936 					     hdr.type3.ns)),
5937 	},
5938 	[ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
5939 		.name = "nr",
5940 		.help = "sequence number for next receive message",
5941 		.next = NEXT(item_l2tpv2_type_data_l_s,
5942 			     NEXT_ENTRY(COMMON_UNSIGNED),
5943 			     item_param),
5944 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5945 					     hdr.type3.nr)),
5946 	},
5947 	[ITEM_L2TPV2_TYPE_CTRL] = {
5948 		.name = "control",
5949 		.help = "Type #3: conrtol message contains length, ns, nr "
5950 			"options",
5951 		.next = NEXT(item_l2tpv2_type_ctrl),
5952 		.call = parse_vc_item_l2tpv2_type,
5953 	},
5954 	[ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
5955 		.name = "length",
5956 		.help = "message length",
5957 		.next = NEXT(item_l2tpv2_type_ctrl,
5958 			     NEXT_ENTRY(COMMON_UNSIGNED),
5959 			     item_param),
5960 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5961 					     hdr.type3.length)),
5962 	},
5963 	[ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
5964 		.name = "tunnel_id",
5965 		.help = "tunnel identifier",
5966 		.next = NEXT(item_l2tpv2_type_ctrl,
5967 			     NEXT_ENTRY(COMMON_UNSIGNED),
5968 			     item_param),
5969 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5970 					     hdr.type3.tunnel_id)),
5971 	},
5972 	[ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
5973 		.name = "session_id",
5974 		.help = "session identifier",
5975 		.next = NEXT(item_l2tpv2_type_ctrl,
5976 			     NEXT_ENTRY(COMMON_UNSIGNED),
5977 			     item_param),
5978 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5979 					     hdr.type3.session_id)),
5980 	},
5981 	[ITEM_L2TPV2_MSG_CTRL_NS] = {
5982 		.name = "ns",
5983 		.help = "sequence number for message",
5984 		.next = NEXT(item_l2tpv2_type_ctrl,
5985 			     NEXT_ENTRY(COMMON_UNSIGNED),
5986 			     item_param),
5987 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5988 					     hdr.type3.ns)),
5989 	},
5990 	[ITEM_L2TPV2_MSG_CTRL_NR] = {
5991 		.name = "nr",
5992 		.help = "sequence number for next receive message",
5993 		.next = NEXT(item_l2tpv2_type_ctrl,
5994 			     NEXT_ENTRY(COMMON_UNSIGNED),
5995 			     item_param),
5996 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5997 					     hdr.type3.nr)),
5998 	},
5999 	[ITEM_PPP] = {
6000 		.name = "ppp",
6001 		.help = "match PPP header",
6002 		.priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
6003 		.next = NEXT(item_ppp),
6004 		.call = parse_vc,
6005 	},
6006 	[ITEM_PPP_ADDR] = {
6007 		.name = "addr",
6008 		.help = "PPP address",
6009 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6010 			     item_param),
6011 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
6012 	},
6013 	[ITEM_PPP_CTRL] = {
6014 		.name = "ctrl",
6015 		.help = "PPP control",
6016 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6017 			     item_param),
6018 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
6019 	},
6020 	[ITEM_PPP_PROTO_ID] = {
6021 		.name = "proto_id",
6022 		.help = "PPP protocol identifier",
6023 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6024 			     item_param),
6025 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
6026 					hdr.proto_id)),
6027 	},
6028 	[ITEM_METER] = {
6029 		.name = "meter",
6030 		.help = "match meter color",
6031 		.priv = PRIV_ITEM(METER_COLOR,
6032 				  sizeof(struct rte_flow_item_meter_color)),
6033 		.next = NEXT(item_meter),
6034 		.call = parse_vc,
6035 	},
6036 	[ITEM_METER_COLOR] = {
6037 		.name = "color",
6038 		.help = "meter color",
6039 		.next = NEXT(item_meter,
6040 			     NEXT_ENTRY(ITEM_METER_COLOR_NAME),
6041 			     item_param),
6042 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_meter_color,
6043 					color)),
6044 	},
6045 	[ITEM_METER_COLOR_NAME] = {
6046 		.name = "color_name",
6047 		.help = "meter color name",
6048 		.call = parse_meter_color,
6049 		.comp = comp_meter_color,
6050 	},
6051 	[ITEM_QUOTA] = {
6052 		.name = "quota",
6053 		.help = "match quota",
6054 		.priv = PRIV_ITEM(QUOTA, sizeof(struct rte_flow_item_quota)),
6055 		.next = NEXT(item_quota),
6056 		.call = parse_vc
6057 	},
6058 	[ITEM_QUOTA_STATE] = {
6059 		.name = "quota_state",
6060 		.help = "quota state",
6061 		.next = NEXT(item_quota, NEXT_ENTRY(ITEM_QUOTA_STATE_NAME),
6062 			     NEXT_ENTRY(ITEM_PARAM_SPEC, ITEM_PARAM_MASK)),
6063 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_quota, state))
6064 	},
6065 	[ITEM_QUOTA_STATE_NAME] = {
6066 		.name = "state_name",
6067 		.help = "quota state name",
6068 		.call = parse_quota_state_name,
6069 		.comp = comp_quota_state_name
6070 	},
6071 	[ITEM_IB_BTH] = {
6072 		.name = "ib_bth",
6073 		.help = "match ib bth fields",
6074 		.priv = PRIV_ITEM(IB_BTH,
6075 				  sizeof(struct rte_flow_item_ib_bth)),
6076 		.next = NEXT(item_ib_bth),
6077 		.call = parse_vc,
6078 	},
6079 	[ITEM_IB_BTH_OPCODE] = {
6080 		.name = "opcode",
6081 		.help = "match ib bth opcode",
6082 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6083 				 item_param),
6084 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6085 						 hdr.opcode)),
6086 	},
6087 	[ITEM_IB_BTH_PKEY] = {
6088 		.name = "pkey",
6089 		.help = "partition key",
6090 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6091 				 item_param),
6092 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6093 						 hdr.pkey)),
6094 	},
6095 	[ITEM_IB_BTH_DST_QPN] = {
6096 		.name = "dst_qp",
6097 		.help = "destination qp",
6098 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6099 				 item_param),
6100 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6101 						 hdr.dst_qp)),
6102 	},
6103 	[ITEM_IB_BTH_PSN] = {
6104 		.name = "psn",
6105 		.help = "packet sequence number",
6106 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6107 				 item_param),
6108 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6109 						 hdr.psn)),
6110 	},
6111 	[ITEM_PTYPE] = {
6112 		.name = "ptype",
6113 		.help = "match L2/L3/L4 and tunnel information",
6114 		.priv = PRIV_ITEM(PTYPE,
6115 				  sizeof(struct rte_flow_item_ptype)),
6116 		.next = NEXT(item_ptype),
6117 		.call = parse_vc,
6118 	},
6119 	[ITEM_PTYPE_VALUE] = {
6120 		.name = "packet_type",
6121 		.help = "packet type as defined in rte_mbuf_ptype",
6122 		.next = NEXT(item_ptype, NEXT_ENTRY(COMMON_UNSIGNED),
6123 			     item_param),
6124 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ptype, packet_type)),
6125 	},
6126 	[ITEM_NSH] = {
6127 		.name = "nsh",
6128 		.help = "match NSH header",
6129 		.priv = PRIV_ITEM(NSH,
6130 				  sizeof(struct rte_flow_item_nsh)),
6131 		.next = NEXT(item_nsh),
6132 		.call = parse_vc,
6133 	},
6134 	[ITEM_COMPARE] = {
6135 		.name = "compare",
6136 		.help = "match with the comparison result",
6137 		.priv = PRIV_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
6138 		.next = NEXT(NEXT_ENTRY(ITEM_COMPARE_OP)),
6139 		.call = parse_vc,
6140 	},
6141 	[ITEM_COMPARE_OP] = {
6142 		.name = "op",
6143 		.help = "operation type",
6144 		.next = NEXT(item_compare_field,
6145 			NEXT_ENTRY(ITEM_COMPARE_OP_VALUE), item_param),
6146 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, operation)),
6147 	},
6148 	[ITEM_COMPARE_OP_VALUE] = {
6149 		.name = "{operation}",
6150 		.help = "operation type value",
6151 		.call = parse_vc_compare_op,
6152 		.comp = comp_set_compare_op,
6153 	},
6154 	[ITEM_COMPARE_FIELD_A_TYPE] = {
6155 		.name = "a_type",
6156 		.help = "compared field type",
6157 		.next = NEXT(compare_field_a,
6158 			NEXT_ENTRY(ITEM_COMPARE_FIELD_A_TYPE_VALUE), item_param),
6159 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.field)),
6160 	},
6161 	[ITEM_COMPARE_FIELD_A_TYPE_VALUE] = {
6162 		.name = "{a_type}",
6163 		.help = "compared field type value",
6164 		.call = parse_vc_compare_field_id,
6165 		.comp = comp_set_compare_field_id,
6166 	},
6167 	[ITEM_COMPARE_FIELD_A_LEVEL] = {
6168 		.name = "a_level",
6169 		.help = "compared field level",
6170 		.next = NEXT(compare_field_a,
6171 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_A_LEVEL_VALUE), item_param),
6172 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.level)),
6173 	},
6174 	[ITEM_COMPARE_FIELD_A_LEVEL_VALUE] = {
6175 		.name = "{a_level}",
6176 		.help = "compared field level value",
6177 		.call = parse_vc_compare_field_level,
6178 		.comp = comp_none,
6179 	},
6180 	[ITEM_COMPARE_FIELD_A_TAG_INDEX] = {
6181 		.name = "a_tag_index",
6182 		.help = "compared field tag array",
6183 		.next = NEXT(compare_field_a,
6184 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6185 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6186 					a.tag_index)),
6187 	},
6188 	[ITEM_COMPARE_FIELD_A_TYPE_ID] = {
6189 		.name = "a_type_id",
6190 		.help = "compared field type ID",
6191 		.next = NEXT(compare_field_a,
6192 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6193 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6194 					a.type)),
6195 	},
6196 	[ITEM_COMPARE_FIELD_A_CLASS_ID] = {
6197 		.name = "a_class",
6198 		.help = "compared field class ID",
6199 		.next = NEXT(compare_field_a,
6200 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6201 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6202 					     a.class_id)),
6203 	},
6204 	[ITEM_COMPARE_FIELD_A_OFFSET] = {
6205 		.name = "a_offset",
6206 		.help = "compared field bit offset",
6207 		.next = NEXT(compare_field_a,
6208 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6209 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6210 					a.offset)),
6211 	},
6212 	[ITEM_COMPARE_FIELD_B_TYPE] = {
6213 		.name = "b_type",
6214 		.help = "comparator field type",
6215 		.next = NEXT(compare_field_b,
6216 			NEXT_ENTRY(ITEM_COMPARE_FIELD_B_TYPE_VALUE), item_param),
6217 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6218 					b.field)),
6219 	},
6220 	[ITEM_COMPARE_FIELD_B_TYPE_VALUE] = {
6221 		.name = "{b_type}",
6222 		.help = "comparator field type value",
6223 		.call = parse_vc_compare_field_id,
6224 		.comp = comp_set_compare_field_id,
6225 	},
6226 	[ITEM_COMPARE_FIELD_B_LEVEL] = {
6227 		.name = "b_level",
6228 		.help = "comparator field level",
6229 		.next = NEXT(compare_field_b,
6230 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_B_LEVEL_VALUE), item_param),
6231 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6232 					b.level)),
6233 	},
6234 	[ITEM_COMPARE_FIELD_B_LEVEL_VALUE] = {
6235 		.name = "{b_level}",
6236 		.help = "comparator field level value",
6237 		.call = parse_vc_compare_field_level,
6238 		.comp = comp_none,
6239 	},
6240 	[ITEM_COMPARE_FIELD_B_TAG_INDEX] = {
6241 		.name = "b_tag_index",
6242 		.help = "comparator field tag array",
6243 		.next = NEXT(compare_field_b,
6244 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6245 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6246 					b.tag_index)),
6247 	},
6248 	[ITEM_COMPARE_FIELD_B_TYPE_ID] = {
6249 		.name = "b_type_id",
6250 		.help = "comparator field type ID",
6251 		.next = NEXT(compare_field_b,
6252 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6253 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6254 					b.type)),
6255 	},
6256 	[ITEM_COMPARE_FIELD_B_CLASS_ID] = {
6257 		.name = "b_class",
6258 		.help = "comparator field class ID",
6259 		.next = NEXT(compare_field_b,
6260 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6261 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6262 					     b.class_id)),
6263 	},
6264 	[ITEM_COMPARE_FIELD_B_OFFSET] = {
6265 		.name = "b_offset",
6266 		.help = "comparator field bit offset",
6267 		.next = NEXT(compare_field_b,
6268 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6269 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6270 					b.offset)),
6271 	},
6272 	[ITEM_COMPARE_FIELD_B_VALUE] = {
6273 		.name = "b_value",
6274 		.help = "comparator immediate value",
6275 		.next = NEXT(compare_field_b,
6276 			     NEXT_ENTRY(COMMON_HEX), item_param),
6277 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
6278 			     ARGS_ENTRY_ARB(0, 0),
6279 			     ARGS_ENTRY(struct rte_flow_item_compare,
6280 					b.value)),
6281 	},
6282 	[ITEM_COMPARE_FIELD_B_POINTER] = {
6283 		.name = "b_ptr",
6284 		.help = "pointer to comparator immediate value",
6285 		.next = NEXT(compare_field_b,
6286 			     NEXT_ENTRY(COMMON_HEX), item_param),
6287 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6288 					b.pvalue),
6289 			     ARGS_ENTRY_ARB(0, 0),
6290 			     ARGS_ENTRY_ARB
6291 				(sizeof(struct rte_flow_item_compare),
6292 				 FLOW_FIELD_PATTERN_SIZE)),
6293 	},
6294 	[ITEM_COMPARE_FIELD_WIDTH] = {
6295 		.name = "width",
6296 		.help = "number of bits to compare",
6297 		.next = NEXT(item_compare_field,
6298 			NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6299 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6300 					width)),
6301 	},
6302 
6303 	/* Validate/create actions. */
6304 	[ACTIONS] = {
6305 		.name = "actions",
6306 		.help = "submit a list of associated actions",
6307 		.next = NEXT(next_action),
6308 		.call = parse_vc,
6309 	},
6310 	[ACTION_NEXT] = {
6311 		.name = "/",
6312 		.help = "specify next action",
6313 		.next = NEXT(next_action),
6314 	},
6315 	[ACTION_END] = {
6316 		.name = "end",
6317 		.help = "end list of actions",
6318 		.priv = PRIV_ACTION(END, 0),
6319 		.call = parse_vc,
6320 	},
6321 	[ACTION_VOID] = {
6322 		.name = "void",
6323 		.help = "no-op action",
6324 		.priv = PRIV_ACTION(VOID, 0),
6325 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6326 		.call = parse_vc,
6327 	},
6328 	[ACTION_PASSTHRU] = {
6329 		.name = "passthru",
6330 		.help = "let subsequent rule process matched packets",
6331 		.priv = PRIV_ACTION(PASSTHRU, 0),
6332 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6333 		.call = parse_vc,
6334 	},
6335 	[ACTION_SKIP_CMAN] = {
6336 		.name = "skip_cman",
6337 		.help = "bypass cman on received packets",
6338 		.priv = PRIV_ACTION(SKIP_CMAN, 0),
6339 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6340 		.call = parse_vc,
6341 	},
6342 	[ACTION_JUMP] = {
6343 		.name = "jump",
6344 		.help = "redirect traffic to a given group",
6345 		.priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
6346 		.next = NEXT(action_jump),
6347 		.call = parse_vc,
6348 	},
6349 	[ACTION_JUMP_GROUP] = {
6350 		.name = "group",
6351 		.help = "group to redirect traffic to",
6352 		.next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
6353 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
6354 		.call = parse_vc_conf,
6355 	},
6356 	[ACTION_MARK] = {
6357 		.name = "mark",
6358 		.help = "attach 32 bit value to packets",
6359 		.priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
6360 		.next = NEXT(action_mark),
6361 		.call = parse_vc,
6362 	},
6363 	[ACTION_MARK_ID] = {
6364 		.name = "id",
6365 		.help = "32 bit value to return with packets",
6366 		.next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6367 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
6368 		.call = parse_vc_conf,
6369 	},
6370 	[ACTION_FLAG] = {
6371 		.name = "flag",
6372 		.help = "flag packets",
6373 		.priv = PRIV_ACTION(FLAG, 0),
6374 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6375 		.call = parse_vc,
6376 	},
6377 	[ACTION_QUEUE] = {
6378 		.name = "queue",
6379 		.help = "assign packets to a given queue index",
6380 		.priv = PRIV_ACTION(QUEUE,
6381 				    sizeof(struct rte_flow_action_queue)),
6382 		.next = NEXT(action_queue),
6383 		.call = parse_vc,
6384 	},
6385 	[ACTION_QUEUE_INDEX] = {
6386 		.name = "index",
6387 		.help = "queue index to use",
6388 		.next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
6389 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
6390 		.call = parse_vc_conf,
6391 	},
6392 	[ACTION_DROP] = {
6393 		.name = "drop",
6394 		.help = "drop packets (note: passthru has priority)",
6395 		.priv = PRIV_ACTION(DROP, 0),
6396 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6397 		.call = parse_vc,
6398 	},
6399 	[ACTION_COUNT] = {
6400 		.name = "count",
6401 		.help = "enable counters for this rule",
6402 		.priv = PRIV_ACTION(COUNT,
6403 				    sizeof(struct rte_flow_action_count)),
6404 		.next = NEXT(action_count),
6405 		.call = parse_vc,
6406 	},
6407 	[ACTION_COUNT_ID] = {
6408 		.name = "identifier",
6409 		.help = "counter identifier to use",
6410 		.next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
6411 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
6412 		.call = parse_vc_conf,
6413 	},
6414 	[ACTION_RSS] = {
6415 		.name = "rss",
6416 		.help = "spread packets among several queues",
6417 		.priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
6418 		.next = NEXT(action_rss),
6419 		.call = parse_vc_action_rss,
6420 	},
6421 	[ACTION_RSS_FUNC] = {
6422 		.name = "func",
6423 		.help = "RSS hash function to apply",
6424 		.next = NEXT(action_rss,
6425 			     NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
6426 					ACTION_RSS_FUNC_TOEPLITZ,
6427 					ACTION_RSS_FUNC_SIMPLE_XOR,
6428 					ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
6429 	},
6430 	[ACTION_RSS_FUNC_DEFAULT] = {
6431 		.name = "default",
6432 		.help = "default hash function",
6433 		.call = parse_vc_action_rss_func,
6434 	},
6435 	[ACTION_RSS_FUNC_TOEPLITZ] = {
6436 		.name = "toeplitz",
6437 		.help = "Toeplitz hash function",
6438 		.call = parse_vc_action_rss_func,
6439 	},
6440 	[ACTION_RSS_FUNC_SIMPLE_XOR] = {
6441 		.name = "simple_xor",
6442 		.help = "simple XOR hash function",
6443 		.call = parse_vc_action_rss_func,
6444 	},
6445 	[ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
6446 		.name = "symmetric_toeplitz",
6447 		.help = "Symmetric Toeplitz hash function",
6448 		.call = parse_vc_action_rss_func,
6449 	},
6450 	[ACTION_RSS_LEVEL] = {
6451 		.name = "level",
6452 		.help = "encapsulation level for \"types\"",
6453 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6454 		.args = ARGS(ARGS_ENTRY_ARB
6455 			     (offsetof(struct action_rss_data, conf) +
6456 			      offsetof(struct rte_flow_action_rss, level),
6457 			      sizeof(((struct rte_flow_action_rss *)0)->
6458 				     level))),
6459 	},
6460 	[ACTION_RSS_TYPES] = {
6461 		.name = "types",
6462 		.help = "specific RSS hash types",
6463 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
6464 	},
6465 	[ACTION_RSS_TYPE] = {
6466 		.name = "{type}",
6467 		.help = "RSS hash type",
6468 		.call = parse_vc_action_rss_type,
6469 		.comp = comp_vc_action_rss_type,
6470 	},
6471 	[ACTION_RSS_KEY] = {
6472 		.name = "key",
6473 		.help = "RSS hash key",
6474 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
6475 		.args = ARGS(ARGS_ENTRY_ARB
6476 			     (offsetof(struct action_rss_data, conf) +
6477 			      offsetof(struct rte_flow_action_rss, key),
6478 			      sizeof(((struct rte_flow_action_rss *)0)->key)),
6479 			     ARGS_ENTRY_ARB
6480 			     (offsetof(struct action_rss_data, conf) +
6481 			      offsetof(struct rte_flow_action_rss, key_len),
6482 			      sizeof(((struct rte_flow_action_rss *)0)->
6483 				     key_len)),
6484 			     ARGS_ENTRY(struct action_rss_data, key)),
6485 	},
6486 	[ACTION_RSS_KEY_LEN] = {
6487 		.name = "key_len",
6488 		.help = "RSS hash key length in bytes",
6489 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6490 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
6491 			     (offsetof(struct action_rss_data, conf) +
6492 			      offsetof(struct rte_flow_action_rss, key_len),
6493 			      sizeof(((struct rte_flow_action_rss *)0)->
6494 				     key_len),
6495 			      0,
6496 			      RSS_HASH_KEY_LENGTH)),
6497 	},
6498 	[ACTION_RSS_QUEUES] = {
6499 		.name = "queues",
6500 		.help = "queue indices to use",
6501 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
6502 		.call = parse_vc_conf,
6503 	},
6504 	[ACTION_RSS_QUEUE] = {
6505 		.name = "{queue}",
6506 		.help = "queue index",
6507 		.call = parse_vc_action_rss_queue,
6508 		.comp = comp_vc_action_rss_queue,
6509 	},
6510 	[ACTION_PF] = {
6511 		.name = "pf",
6512 		.help = "direct traffic to physical function",
6513 		.priv = PRIV_ACTION(PF, 0),
6514 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6515 		.call = parse_vc,
6516 	},
6517 	[ACTION_VF] = {
6518 		.name = "vf",
6519 		.help = "direct traffic to a virtual function ID",
6520 		.priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
6521 		.next = NEXT(action_vf),
6522 		.call = parse_vc,
6523 	},
6524 	[ACTION_VF_ORIGINAL] = {
6525 		.name = "original",
6526 		.help = "use original VF ID if possible",
6527 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
6528 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
6529 					   original, 1)),
6530 		.call = parse_vc_conf,
6531 	},
6532 	[ACTION_VF_ID] = {
6533 		.name = "id",
6534 		.help = "VF ID",
6535 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
6536 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
6537 		.call = parse_vc_conf,
6538 	},
6539 	[ACTION_PORT_ID] = {
6540 		.name = "port_id",
6541 		.help = "direct matching traffic to a given DPDK port ID",
6542 		.priv = PRIV_ACTION(PORT_ID,
6543 				    sizeof(struct rte_flow_action_port_id)),
6544 		.next = NEXT(action_port_id),
6545 		.call = parse_vc,
6546 	},
6547 	[ACTION_PORT_ID_ORIGINAL] = {
6548 		.name = "original",
6549 		.help = "use original DPDK port ID if possible",
6550 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
6551 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
6552 					   original, 1)),
6553 		.call = parse_vc_conf,
6554 	},
6555 	[ACTION_PORT_ID_ID] = {
6556 		.name = "id",
6557 		.help = "DPDK port ID",
6558 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
6559 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
6560 		.call = parse_vc_conf,
6561 	},
6562 	[ACTION_METER] = {
6563 		.name = "meter",
6564 		.help = "meter the directed packets at given id",
6565 		.priv = PRIV_ACTION(METER,
6566 				    sizeof(struct rte_flow_action_meter)),
6567 		.next = NEXT(action_meter),
6568 		.call = parse_vc,
6569 	},
6570 	[ACTION_METER_COLOR] = {
6571 		.name = "color",
6572 		.help = "meter color for the packets",
6573 		.priv = PRIV_ACTION(METER_COLOR,
6574 				sizeof(struct rte_flow_action_meter_color)),
6575 		.next = NEXT(action_meter_color),
6576 		.call = parse_vc,
6577 	},
6578 	[ACTION_METER_COLOR_TYPE] = {
6579 		.name = "type",
6580 		.help = "specific meter color",
6581 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
6582 				NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
6583 					ACTION_METER_COLOR_YELLOW,
6584 					ACTION_METER_COLOR_RED)),
6585 	},
6586 	[ACTION_METER_COLOR_GREEN] = {
6587 		.name = "green",
6588 		.help = "meter color green",
6589 		.call = parse_vc_action_meter_color_type,
6590 	},
6591 	[ACTION_METER_COLOR_YELLOW] = {
6592 		.name = "yellow",
6593 		.help = "meter color yellow",
6594 		.call = parse_vc_action_meter_color_type,
6595 	},
6596 	[ACTION_METER_COLOR_RED] = {
6597 		.name = "red",
6598 		.help = "meter color red",
6599 		.call = parse_vc_action_meter_color_type,
6600 	},
6601 	[ACTION_METER_ID] = {
6602 		.name = "mtr_id",
6603 		.help = "meter id to use",
6604 		.next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
6605 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
6606 		.call = parse_vc_conf,
6607 	},
6608 	[ACTION_METER_MARK] = {
6609 		.name = "meter_mark",
6610 		.help = "meter the directed packets using profile and policy",
6611 		.priv = PRIV_ACTION(METER_MARK,
6612 				    sizeof(struct rte_flow_action_meter_mark)),
6613 		.next = NEXT(action_meter_mark),
6614 		.call = parse_vc,
6615 	},
6616 	[ACTION_METER_PROFILE] = {
6617 		.name = "mtr_profile",
6618 		.help = "meter profile id to use",
6619 		.next = NEXT(NEXT_ENTRY(ACTION_METER_PROFILE_ID2PTR)),
6620 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6621 	},
6622 	[ACTION_METER_PROFILE_ID2PTR] = {
6623 		.name = "{mtr_profile_id}",
6624 		.type = "PROFILE_ID",
6625 		.help = "meter profile id",
6626 		.next = NEXT(action_meter_mark),
6627 		.call = parse_meter_profile_id2ptr,
6628 		.comp = comp_none,
6629 	},
6630 	[ACTION_METER_POLICY] = {
6631 		.name = "mtr_policy",
6632 		.help = "meter policy id to use",
6633 		.next = NEXT(NEXT_ENTRY(ACTION_METER_POLICY_ID2PTR)),
6634 		ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6635 	},
6636 	[ACTION_METER_POLICY_ID2PTR] = {
6637 		.name = "{mtr_policy_id}",
6638 		.type = "POLICY_ID",
6639 		.help = "meter policy id",
6640 		.next = NEXT(action_meter_mark),
6641 		.call = parse_meter_policy_id2ptr,
6642 		.comp = comp_none,
6643 	},
6644 	[ACTION_METER_COLOR_MODE] = {
6645 		.name = "mtr_color_mode",
6646 		.help = "meter color awareness mode",
6647 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6648 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, color_mode)),
6649 		.call = parse_vc_conf,
6650 	},
6651 	[ACTION_METER_STATE] = {
6652 		.name = "mtr_state",
6653 		.help = "meter state",
6654 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6655 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, state)),
6656 		.call = parse_vc_conf,
6657 	},
6658 	[ACTION_OF_DEC_NW_TTL] = {
6659 		.name = "of_dec_nw_ttl",
6660 		.help = "OpenFlow's OFPAT_DEC_NW_TTL",
6661 		.priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
6662 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6663 		.call = parse_vc,
6664 	},
6665 	[ACTION_OF_POP_VLAN] = {
6666 		.name = "of_pop_vlan",
6667 		.help = "OpenFlow's OFPAT_POP_VLAN",
6668 		.priv = PRIV_ACTION(OF_POP_VLAN, 0),
6669 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6670 		.call = parse_vc,
6671 	},
6672 	[ACTION_OF_PUSH_VLAN] = {
6673 		.name = "of_push_vlan",
6674 		.help = "OpenFlow's OFPAT_PUSH_VLAN",
6675 		.priv = PRIV_ACTION
6676 			(OF_PUSH_VLAN,
6677 			 sizeof(struct rte_flow_action_of_push_vlan)),
6678 		.next = NEXT(action_of_push_vlan),
6679 		.call = parse_vc,
6680 	},
6681 	[ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
6682 		.name = "ethertype",
6683 		.help = "EtherType",
6684 		.next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
6685 		.args = ARGS(ARGS_ENTRY_HTON
6686 			     (struct rte_flow_action_of_push_vlan,
6687 			      ethertype)),
6688 		.call = parse_vc_conf,
6689 	},
6690 	[ACTION_OF_SET_VLAN_VID] = {
6691 		.name = "of_set_vlan_vid",
6692 		.help = "OpenFlow's OFPAT_SET_VLAN_VID",
6693 		.priv = PRIV_ACTION
6694 			(OF_SET_VLAN_VID,
6695 			 sizeof(struct rte_flow_action_of_set_vlan_vid)),
6696 		.next = NEXT(action_of_set_vlan_vid),
6697 		.call = parse_vc,
6698 	},
6699 	[ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
6700 		.name = "vlan_vid",
6701 		.help = "VLAN id",
6702 		.next = NEXT(action_of_set_vlan_vid,
6703 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6704 		.args = ARGS(ARGS_ENTRY_HTON
6705 			     (struct rte_flow_action_of_set_vlan_vid,
6706 			      vlan_vid)),
6707 		.call = parse_vc_conf,
6708 	},
6709 	[ACTION_OF_SET_VLAN_PCP] = {
6710 		.name = "of_set_vlan_pcp",
6711 		.help = "OpenFlow's OFPAT_SET_VLAN_PCP",
6712 		.priv = PRIV_ACTION
6713 			(OF_SET_VLAN_PCP,
6714 			 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
6715 		.next = NEXT(action_of_set_vlan_pcp),
6716 		.call = parse_vc,
6717 	},
6718 	[ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
6719 		.name = "vlan_pcp",
6720 		.help = "VLAN priority",
6721 		.next = NEXT(action_of_set_vlan_pcp,
6722 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6723 		.args = ARGS(ARGS_ENTRY_HTON
6724 			     (struct rte_flow_action_of_set_vlan_pcp,
6725 			      vlan_pcp)),
6726 		.call = parse_vc_conf,
6727 	},
6728 	[ACTION_OF_POP_MPLS] = {
6729 		.name = "of_pop_mpls",
6730 		.help = "OpenFlow's OFPAT_POP_MPLS",
6731 		.priv = PRIV_ACTION(OF_POP_MPLS,
6732 				    sizeof(struct rte_flow_action_of_pop_mpls)),
6733 		.next = NEXT(action_of_pop_mpls),
6734 		.call = parse_vc,
6735 	},
6736 	[ACTION_OF_POP_MPLS_ETHERTYPE] = {
6737 		.name = "ethertype",
6738 		.help = "EtherType",
6739 		.next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6740 		.args = ARGS(ARGS_ENTRY_HTON
6741 			     (struct rte_flow_action_of_pop_mpls,
6742 			      ethertype)),
6743 		.call = parse_vc_conf,
6744 	},
6745 	[ACTION_OF_PUSH_MPLS] = {
6746 		.name = "of_push_mpls",
6747 		.help = "OpenFlow's OFPAT_PUSH_MPLS",
6748 		.priv = PRIV_ACTION
6749 			(OF_PUSH_MPLS,
6750 			 sizeof(struct rte_flow_action_of_push_mpls)),
6751 		.next = NEXT(action_of_push_mpls),
6752 		.call = parse_vc,
6753 	},
6754 	[ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
6755 		.name = "ethertype",
6756 		.help = "EtherType",
6757 		.next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6758 		.args = ARGS(ARGS_ENTRY_HTON
6759 			     (struct rte_flow_action_of_push_mpls,
6760 			      ethertype)),
6761 		.call = parse_vc_conf,
6762 	},
6763 	[ACTION_VXLAN_ENCAP] = {
6764 		.name = "vxlan_encap",
6765 		.help = "VXLAN encapsulation, uses configuration set by \"set"
6766 			" vxlan\"",
6767 		.priv = PRIV_ACTION(VXLAN_ENCAP,
6768 				    sizeof(struct action_vxlan_encap_data)),
6769 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6770 		.call = parse_vc_action_vxlan_encap,
6771 	},
6772 	[ACTION_VXLAN_DECAP] = {
6773 		.name = "vxlan_decap",
6774 		.help = "Performs a decapsulation action by stripping all"
6775 			" headers of the VXLAN tunnel network overlay from the"
6776 			" matched flow.",
6777 		.priv = PRIV_ACTION(VXLAN_DECAP, 0),
6778 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6779 		.call = parse_vc,
6780 	},
6781 	[ACTION_NVGRE_ENCAP] = {
6782 		.name = "nvgre_encap",
6783 		.help = "NVGRE encapsulation, uses configuration set by \"set"
6784 			" nvgre\"",
6785 		.priv = PRIV_ACTION(NVGRE_ENCAP,
6786 				    sizeof(struct action_nvgre_encap_data)),
6787 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6788 		.call = parse_vc_action_nvgre_encap,
6789 	},
6790 	[ACTION_NVGRE_DECAP] = {
6791 		.name = "nvgre_decap",
6792 		.help = "Performs a decapsulation action by stripping all"
6793 			" headers of the NVGRE tunnel network overlay from the"
6794 			" matched flow.",
6795 		.priv = PRIV_ACTION(NVGRE_DECAP, 0),
6796 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6797 		.call = parse_vc,
6798 	},
6799 	[ACTION_L2_ENCAP] = {
6800 		.name = "l2_encap",
6801 		.help = "l2 encap, uses configuration set by"
6802 			" \"set l2_encap\"",
6803 		.priv = PRIV_ACTION(RAW_ENCAP,
6804 				    sizeof(struct action_raw_encap_data)),
6805 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6806 		.call = parse_vc_action_l2_encap,
6807 	},
6808 	[ACTION_L2_DECAP] = {
6809 		.name = "l2_decap",
6810 		.help = "l2 decap, uses configuration set by"
6811 			" \"set l2_decap\"",
6812 		.priv = PRIV_ACTION(RAW_DECAP,
6813 				    sizeof(struct action_raw_decap_data)),
6814 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6815 		.call = parse_vc_action_l2_decap,
6816 	},
6817 	[ACTION_MPLSOGRE_ENCAP] = {
6818 		.name = "mplsogre_encap",
6819 		.help = "mplsogre encapsulation, uses configuration set by"
6820 			" \"set mplsogre_encap\"",
6821 		.priv = PRIV_ACTION(RAW_ENCAP,
6822 				    sizeof(struct action_raw_encap_data)),
6823 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6824 		.call = parse_vc_action_mplsogre_encap,
6825 	},
6826 	[ACTION_MPLSOGRE_DECAP] = {
6827 		.name = "mplsogre_decap",
6828 		.help = "mplsogre decapsulation, uses configuration set by"
6829 			" \"set mplsogre_decap\"",
6830 		.priv = PRIV_ACTION(RAW_DECAP,
6831 				    sizeof(struct action_raw_decap_data)),
6832 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6833 		.call = parse_vc_action_mplsogre_decap,
6834 	},
6835 	[ACTION_MPLSOUDP_ENCAP] = {
6836 		.name = "mplsoudp_encap",
6837 		.help = "mplsoudp encapsulation, uses configuration set by"
6838 			" \"set mplsoudp_encap\"",
6839 		.priv = PRIV_ACTION(RAW_ENCAP,
6840 				    sizeof(struct action_raw_encap_data)),
6841 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6842 		.call = parse_vc_action_mplsoudp_encap,
6843 	},
6844 	[ACTION_MPLSOUDP_DECAP] = {
6845 		.name = "mplsoudp_decap",
6846 		.help = "mplsoudp decapsulation, uses configuration set by"
6847 			" \"set mplsoudp_decap\"",
6848 		.priv = PRIV_ACTION(RAW_DECAP,
6849 				    sizeof(struct action_raw_decap_data)),
6850 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6851 		.call = parse_vc_action_mplsoudp_decap,
6852 	},
6853 	[ACTION_SET_IPV4_SRC] = {
6854 		.name = "set_ipv4_src",
6855 		.help = "Set a new IPv4 source address in the outermost"
6856 			" IPv4 header",
6857 		.priv = PRIV_ACTION(SET_IPV4_SRC,
6858 			sizeof(struct rte_flow_action_set_ipv4)),
6859 		.next = NEXT(action_set_ipv4_src),
6860 		.call = parse_vc,
6861 	},
6862 	[ACTION_SET_IPV4_SRC_IPV4_SRC] = {
6863 		.name = "ipv4_addr",
6864 		.help = "new IPv4 source address to set",
6865 		.next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
6866 		.args = ARGS(ARGS_ENTRY_HTON
6867 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
6868 		.call = parse_vc_conf,
6869 	},
6870 	[ACTION_SET_IPV4_DST] = {
6871 		.name = "set_ipv4_dst",
6872 		.help = "Set a new IPv4 destination address in the outermost"
6873 			" IPv4 header",
6874 		.priv = PRIV_ACTION(SET_IPV4_DST,
6875 			sizeof(struct rte_flow_action_set_ipv4)),
6876 		.next = NEXT(action_set_ipv4_dst),
6877 		.call = parse_vc,
6878 	},
6879 	[ACTION_SET_IPV4_DST_IPV4_DST] = {
6880 		.name = "ipv4_addr",
6881 		.help = "new IPv4 destination address to set",
6882 		.next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
6883 		.args = ARGS(ARGS_ENTRY_HTON
6884 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
6885 		.call = parse_vc_conf,
6886 	},
6887 	[ACTION_SET_IPV6_SRC] = {
6888 		.name = "set_ipv6_src",
6889 		.help = "Set a new IPv6 source address in the outermost"
6890 			" IPv6 header",
6891 		.priv = PRIV_ACTION(SET_IPV6_SRC,
6892 			sizeof(struct rte_flow_action_set_ipv6)),
6893 		.next = NEXT(action_set_ipv6_src),
6894 		.call = parse_vc,
6895 	},
6896 	[ACTION_SET_IPV6_SRC_IPV6_SRC] = {
6897 		.name = "ipv6_addr",
6898 		.help = "new IPv6 source address to set",
6899 		.next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
6900 		.args = ARGS(ARGS_ENTRY_HTON
6901 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
6902 		.call = parse_vc_conf,
6903 	},
6904 	[ACTION_SET_IPV6_DST] = {
6905 		.name = "set_ipv6_dst",
6906 		.help = "Set a new IPv6 destination address in the outermost"
6907 			" IPv6 header",
6908 		.priv = PRIV_ACTION(SET_IPV6_DST,
6909 			sizeof(struct rte_flow_action_set_ipv6)),
6910 		.next = NEXT(action_set_ipv6_dst),
6911 		.call = parse_vc,
6912 	},
6913 	[ACTION_SET_IPV6_DST_IPV6_DST] = {
6914 		.name = "ipv6_addr",
6915 		.help = "new IPv6 destination address to set",
6916 		.next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
6917 		.args = ARGS(ARGS_ENTRY_HTON
6918 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
6919 		.call = parse_vc_conf,
6920 	},
6921 	[ACTION_SET_TP_SRC] = {
6922 		.name = "set_tp_src",
6923 		.help = "set a new source port number in the outermost"
6924 			" TCP/UDP header",
6925 		.priv = PRIV_ACTION(SET_TP_SRC,
6926 			sizeof(struct rte_flow_action_set_tp)),
6927 		.next = NEXT(action_set_tp_src),
6928 		.call = parse_vc,
6929 	},
6930 	[ACTION_SET_TP_SRC_TP_SRC] = {
6931 		.name = "port",
6932 		.help = "new source port number to set",
6933 		.next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
6934 		.args = ARGS(ARGS_ENTRY_HTON
6935 			     (struct rte_flow_action_set_tp, port)),
6936 		.call = parse_vc_conf,
6937 	},
6938 	[ACTION_SET_TP_DST] = {
6939 		.name = "set_tp_dst",
6940 		.help = "set a new destination port number in the outermost"
6941 			" TCP/UDP header",
6942 		.priv = PRIV_ACTION(SET_TP_DST,
6943 			sizeof(struct rte_flow_action_set_tp)),
6944 		.next = NEXT(action_set_tp_dst),
6945 		.call = parse_vc,
6946 	},
6947 	[ACTION_SET_TP_DST_TP_DST] = {
6948 		.name = "port",
6949 		.help = "new destination port number to set",
6950 		.next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
6951 		.args = ARGS(ARGS_ENTRY_HTON
6952 			     (struct rte_flow_action_set_tp, port)),
6953 		.call = parse_vc_conf,
6954 	},
6955 	[ACTION_MAC_SWAP] = {
6956 		.name = "mac_swap",
6957 		.help = "Swap the source and destination MAC addresses"
6958 			" in the outermost Ethernet header",
6959 		.priv = PRIV_ACTION(MAC_SWAP, 0),
6960 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6961 		.call = parse_vc,
6962 	},
6963 	[ACTION_DEC_TTL] = {
6964 		.name = "dec_ttl",
6965 		.help = "decrease network TTL if available",
6966 		.priv = PRIV_ACTION(DEC_TTL, 0),
6967 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6968 		.call = parse_vc,
6969 	},
6970 	[ACTION_SET_TTL] = {
6971 		.name = "set_ttl",
6972 		.help = "set ttl value",
6973 		.priv = PRIV_ACTION(SET_TTL,
6974 			sizeof(struct rte_flow_action_set_ttl)),
6975 		.next = NEXT(action_set_ttl),
6976 		.call = parse_vc,
6977 	},
6978 	[ACTION_SET_TTL_TTL] = {
6979 		.name = "ttl_value",
6980 		.help = "new ttl value to set",
6981 		.next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
6982 		.args = ARGS(ARGS_ENTRY_HTON
6983 			     (struct rte_flow_action_set_ttl, ttl_value)),
6984 		.call = parse_vc_conf,
6985 	},
6986 	[ACTION_SET_MAC_SRC] = {
6987 		.name = "set_mac_src",
6988 		.help = "set source mac address",
6989 		.priv = PRIV_ACTION(SET_MAC_SRC,
6990 			sizeof(struct rte_flow_action_set_mac)),
6991 		.next = NEXT(action_set_mac_src),
6992 		.call = parse_vc,
6993 	},
6994 	[ACTION_SET_MAC_SRC_MAC_SRC] = {
6995 		.name = "mac_addr",
6996 		.help = "new source mac address",
6997 		.next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
6998 		.args = ARGS(ARGS_ENTRY_HTON
6999 			     (struct rte_flow_action_set_mac, mac_addr)),
7000 		.call = parse_vc_conf,
7001 	},
7002 	[ACTION_SET_MAC_DST] = {
7003 		.name = "set_mac_dst",
7004 		.help = "set destination mac address",
7005 		.priv = PRIV_ACTION(SET_MAC_DST,
7006 			sizeof(struct rte_flow_action_set_mac)),
7007 		.next = NEXT(action_set_mac_dst),
7008 		.call = parse_vc,
7009 	},
7010 	[ACTION_SET_MAC_DST_MAC_DST] = {
7011 		.name = "mac_addr",
7012 		.help = "new destination mac address to set",
7013 		.next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
7014 		.args = ARGS(ARGS_ENTRY_HTON
7015 			     (struct rte_flow_action_set_mac, mac_addr)),
7016 		.call = parse_vc_conf,
7017 	},
7018 	[ACTION_INC_TCP_SEQ] = {
7019 		.name = "inc_tcp_seq",
7020 		.help = "increase TCP sequence number",
7021 		.priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
7022 		.next = NEXT(action_inc_tcp_seq),
7023 		.call = parse_vc,
7024 	},
7025 	[ACTION_INC_TCP_SEQ_VALUE] = {
7026 		.name = "value",
7027 		.help = "the value to increase TCP sequence number by",
7028 		.next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7029 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7030 		.call = parse_vc_conf,
7031 	},
7032 	[ACTION_DEC_TCP_SEQ] = {
7033 		.name = "dec_tcp_seq",
7034 		.help = "decrease TCP sequence number",
7035 		.priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
7036 		.next = NEXT(action_dec_tcp_seq),
7037 		.call = parse_vc,
7038 	},
7039 	[ACTION_DEC_TCP_SEQ_VALUE] = {
7040 		.name = "value",
7041 		.help = "the value to decrease TCP sequence number by",
7042 		.next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7043 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7044 		.call = parse_vc_conf,
7045 	},
7046 	[ACTION_INC_TCP_ACK] = {
7047 		.name = "inc_tcp_ack",
7048 		.help = "increase TCP acknowledgment number",
7049 		.priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
7050 		.next = NEXT(action_inc_tcp_ack),
7051 		.call = parse_vc,
7052 	},
7053 	[ACTION_INC_TCP_ACK_VALUE] = {
7054 		.name = "value",
7055 		.help = "the value to increase TCP acknowledgment number by",
7056 		.next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7057 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7058 		.call = parse_vc_conf,
7059 	},
7060 	[ACTION_DEC_TCP_ACK] = {
7061 		.name = "dec_tcp_ack",
7062 		.help = "decrease TCP acknowledgment number",
7063 		.priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
7064 		.next = NEXT(action_dec_tcp_ack),
7065 		.call = parse_vc,
7066 	},
7067 	[ACTION_DEC_TCP_ACK_VALUE] = {
7068 		.name = "value",
7069 		.help = "the value to decrease TCP acknowledgment number by",
7070 		.next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7071 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7072 		.call = parse_vc_conf,
7073 	},
7074 	[ACTION_RAW_ENCAP] = {
7075 		.name = "raw_encap",
7076 		.help = "encapsulation data, defined by set raw_encap",
7077 		.priv = PRIV_ACTION(RAW_ENCAP,
7078 			sizeof(struct action_raw_encap_data)),
7079 		.next = NEXT(action_raw_encap),
7080 		.call = parse_vc_action_raw_encap,
7081 	},
7082 	[ACTION_RAW_ENCAP_SIZE] = {
7083 		.name = "size",
7084 		.help = "raw encap size",
7085 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7086 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7087 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_raw_encap, size)),
7088 		.call = parse_vc_conf,
7089 	},
7090 	[ACTION_RAW_ENCAP_INDEX] = {
7091 		.name = "index",
7092 		.help = "the index of raw_encap_confs",
7093 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
7094 	},
7095 	[ACTION_RAW_ENCAP_INDEX_VALUE] = {
7096 		.name = "{index}",
7097 		.type = "UNSIGNED",
7098 		.help = "unsigned integer value",
7099 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7100 		.call = parse_vc_action_raw_encap_index,
7101 		.comp = comp_set_raw_index,
7102 	},
7103 	[ACTION_RAW_DECAP] = {
7104 		.name = "raw_decap",
7105 		.help = "decapsulation data, defined by set raw_encap",
7106 		.priv = PRIV_ACTION(RAW_DECAP,
7107 			sizeof(struct action_raw_decap_data)),
7108 		.next = NEXT(action_raw_decap),
7109 		.call = parse_vc_action_raw_decap,
7110 	},
7111 	[ACTION_RAW_DECAP_INDEX] = {
7112 		.name = "index",
7113 		.help = "the index of raw_encap_confs",
7114 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
7115 	},
7116 	[ACTION_RAW_DECAP_INDEX_VALUE] = {
7117 		.name = "{index}",
7118 		.type = "UNSIGNED",
7119 		.help = "unsigned integer value",
7120 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7121 		.call = parse_vc_action_raw_decap_index,
7122 		.comp = comp_set_raw_index,
7123 	},
7124 	[ACTION_MODIFY_FIELD] = {
7125 		.name = "modify_field",
7126 		.help = "modify destination field with data from source field",
7127 		.priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
7128 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
7129 		.call = parse_vc,
7130 	},
7131 	[ACTION_MODIFY_FIELD_OP] = {
7132 		.name = "op",
7133 		.help = "operation type",
7134 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
7135 			NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
7136 		.call = parse_vc_conf,
7137 	},
7138 	[ACTION_MODIFY_FIELD_OP_VALUE] = {
7139 		.name = "{operation}",
7140 		.help = "operation type value",
7141 		.call = parse_vc_modify_field_op,
7142 		.comp = comp_set_modify_field_op,
7143 	},
7144 	[ACTION_MODIFY_FIELD_DST_TYPE] = {
7145 		.name = "dst_type",
7146 		.help = "destination field type",
7147 		.next = NEXT(action_modify_field_dst,
7148 			NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
7149 		.call = parse_vc_conf,
7150 	},
7151 	[ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
7152 		.name = "{dst_type}",
7153 		.help = "destination field type value",
7154 		.call = parse_vc_modify_field_id,
7155 		.comp = comp_set_modify_field_id,
7156 	},
7157 	[ACTION_MODIFY_FIELD_DST_LEVEL] = {
7158 		.name = "dst_level",
7159 		.help = "destination field level",
7160 		.next = NEXT(action_modify_field_dst,
7161 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)),
7162 		.call = parse_vc_conf,
7163 	},
7164 	[ACTION_MODIFY_FIELD_DST_LEVEL_VALUE] = {
7165 		.name = "{dst_level}",
7166 		.help = "destination field level value",
7167 		.call = parse_vc_modify_field_level,
7168 		.comp = comp_none,
7169 	},
7170 	[ACTION_MODIFY_FIELD_DST_TAG_INDEX] = {
7171 		.name = "dst_tag_index",
7172 		.help = "destination field tag array",
7173 		.next = NEXT(action_modify_field_dst,
7174 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7175 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7176 					dst.tag_index)),
7177 		.call = parse_vc_conf,
7178 	},
7179 	[ACTION_MODIFY_FIELD_DST_TYPE_ID] = {
7180 		.name = "dst_type_id",
7181 		.help = "destination field type ID",
7182 		.next = NEXT(action_modify_field_dst,
7183 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7184 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7185 					dst.type)),
7186 		.call = parse_vc_conf,
7187 	},
7188 	[ACTION_MODIFY_FIELD_DST_CLASS_ID] = {
7189 		.name = "dst_class",
7190 		.help = "destination field class ID",
7191 		.next = NEXT(action_modify_field_dst,
7192 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7193 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7194 					     dst.class_id)),
7195 		.call = parse_vc_conf,
7196 	},
7197 	[ACTION_MODIFY_FIELD_DST_OFFSET] = {
7198 		.name = "dst_offset",
7199 		.help = "destination field bit offset",
7200 		.next = NEXT(action_modify_field_dst,
7201 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7202 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7203 					dst.offset)),
7204 		.call = parse_vc_conf,
7205 	},
7206 	[ACTION_MODIFY_FIELD_SRC_TYPE] = {
7207 		.name = "src_type",
7208 		.help = "source field type",
7209 		.next = NEXT(action_modify_field_src,
7210 			NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
7211 		.call = parse_vc_conf,
7212 	},
7213 	[ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
7214 		.name = "{src_type}",
7215 		.help = "source field type value",
7216 		.call = parse_vc_modify_field_id,
7217 		.comp = comp_set_modify_field_id,
7218 	},
7219 	[ACTION_MODIFY_FIELD_SRC_LEVEL] = {
7220 		.name = "src_level",
7221 		.help = "source field level",
7222 		.next = NEXT(action_modify_field_src,
7223 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)),
7224 		.call = parse_vc_conf,
7225 	},
7226 	[ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE] = {
7227 		.name = "{src_level}",
7228 		.help = "source field level value",
7229 		.call = parse_vc_modify_field_level,
7230 		.comp = comp_none,
7231 	},
7232 	[ACTION_MODIFY_FIELD_SRC_TAG_INDEX] = {
7233 		.name = "stc_tag_index",
7234 		.help = "source field tag array",
7235 		.next = NEXT(action_modify_field_src,
7236 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7237 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7238 					src.tag_index)),
7239 		.call = parse_vc_conf,
7240 	},
7241 	[ACTION_MODIFY_FIELD_SRC_TYPE_ID] = {
7242 		.name = "src_type_id",
7243 		.help = "source field type ID",
7244 		.next = NEXT(action_modify_field_src,
7245 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7246 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7247 					src.type)),
7248 		.call = parse_vc_conf,
7249 	},
7250 	[ACTION_MODIFY_FIELD_SRC_CLASS_ID] = {
7251 		.name = "src_class",
7252 		.help = "source field class ID",
7253 		.next = NEXT(action_modify_field_src,
7254 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7255 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7256 					     src.class_id)),
7257 		.call = parse_vc_conf,
7258 	},
7259 	[ACTION_MODIFY_FIELD_SRC_OFFSET] = {
7260 		.name = "src_offset",
7261 		.help = "source field bit offset",
7262 		.next = NEXT(action_modify_field_src,
7263 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7264 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7265 					src.offset)),
7266 		.call = parse_vc_conf,
7267 	},
7268 	[ACTION_MODIFY_FIELD_SRC_VALUE] = {
7269 		.name = "src_value",
7270 		.help = "source immediate value",
7271 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7272 			     NEXT_ENTRY(COMMON_HEX)),
7273 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
7274 			     ARGS_ENTRY_ARB(0, 0),
7275 			     ARGS_ENTRY(struct rte_flow_action_modify_field,
7276 					src.value)),
7277 		.call = parse_vc_conf,
7278 	},
7279 	[ACTION_MODIFY_FIELD_SRC_POINTER] = {
7280 		.name = "src_ptr",
7281 		.help = "pointer to source immediate value",
7282 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7283 			     NEXT_ENTRY(COMMON_HEX)),
7284 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7285 					src.pvalue),
7286 			     ARGS_ENTRY_ARB(0, 0),
7287 			     ARGS_ENTRY_ARB
7288 				(sizeof(struct rte_flow_action_modify_field),
7289 				 FLOW_FIELD_PATTERN_SIZE)),
7290 		.call = parse_vc_conf,
7291 	},
7292 	[ACTION_MODIFY_FIELD_WIDTH] = {
7293 		.name = "width",
7294 		.help = "number of bits to copy",
7295 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7296 			NEXT_ENTRY(COMMON_UNSIGNED)),
7297 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7298 					width)),
7299 		.call = parse_vc_conf,
7300 	},
7301 	[ACTION_SEND_TO_KERNEL] = {
7302 		.name = "send_to_kernel",
7303 		.help = "send packets to kernel",
7304 		.priv = PRIV_ACTION(SEND_TO_KERNEL, 0),
7305 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7306 		.call = parse_vc,
7307 	},
7308 	[ACTION_IPV6_EXT_REMOVE] = {
7309 		.name = "ipv6_ext_remove",
7310 		.help = "IPv6 extension type, defined by set ipv6_ext_remove",
7311 		.priv = PRIV_ACTION(IPV6_EXT_REMOVE,
7312 			sizeof(struct action_ipv6_ext_remove_data)),
7313 		.next = NEXT(action_ipv6_ext_remove),
7314 		.call = parse_vc_action_ipv6_ext_remove,
7315 	},
7316 	[ACTION_IPV6_EXT_REMOVE_INDEX] = {
7317 		.name = "index",
7318 		.help = "the index of ipv6_ext_remove",
7319 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_REMOVE_INDEX_VALUE)),
7320 	},
7321 	[ACTION_IPV6_EXT_REMOVE_INDEX_VALUE] = {
7322 		.name = "{index}",
7323 		.type = "UNSIGNED",
7324 		.help = "unsigned integer value",
7325 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7326 		.call = parse_vc_action_ipv6_ext_remove_index,
7327 		.comp = comp_set_ipv6_ext_index,
7328 	},
7329 	[ACTION_IPV6_EXT_PUSH] = {
7330 		.name = "ipv6_ext_push",
7331 		.help = "IPv6 extension data, defined by set ipv6_ext_push",
7332 		.priv = PRIV_ACTION(IPV6_EXT_PUSH,
7333 			sizeof(struct action_ipv6_ext_push_data)),
7334 		.next = NEXT(action_ipv6_ext_push),
7335 		.call = parse_vc_action_ipv6_ext_push,
7336 	},
7337 	[ACTION_IPV6_EXT_PUSH_INDEX] = {
7338 		.name = "index",
7339 		.help = "the index of ipv6_ext_push",
7340 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_PUSH_INDEX_VALUE)),
7341 	},
7342 	[ACTION_IPV6_EXT_PUSH_INDEX_VALUE] = {
7343 		.name = "{index}",
7344 		.type = "UNSIGNED",
7345 		.help = "unsigned integer value",
7346 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7347 		.call = parse_vc_action_ipv6_ext_push_index,
7348 		.comp = comp_set_ipv6_ext_index,
7349 	},
7350 	[ACTION_NAT64] = {
7351 		.name = "nat64",
7352 		.help = "NAT64 IP headers translation",
7353 		.priv = PRIV_ACTION(NAT64, sizeof(struct rte_flow_action_nat64)),
7354 		.next = NEXT(action_nat64),
7355 		.call = parse_vc,
7356 	},
7357 	[ACTION_NAT64_MODE] = {
7358 		.name = "type",
7359 		.help = "NAT64 translation type",
7360 		.next = NEXT(action_nat64, NEXT_ENTRY(COMMON_UNSIGNED)),
7361 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_nat64, type)),
7362 		.call = parse_vc_conf,
7363 	},
7364 	/* Top level command. */
7365 	[SET] = {
7366 		.name = "set",
7367 		.help = "set raw encap/decap/sample data",
7368 		.type = "set raw_encap|raw_decap <index> <pattern>"
7369 				" or set sample_actions <index> <action>",
7370 		.next = NEXT(NEXT_ENTRY
7371 			     (SET_RAW_ENCAP,
7372 			      SET_RAW_DECAP,
7373 			      SET_SAMPLE_ACTIONS,
7374 			      SET_IPV6_EXT_REMOVE,
7375 			      SET_IPV6_EXT_PUSH)),
7376 		.call = parse_set_init,
7377 	},
7378 	/* Sub-level commands. */
7379 	[SET_RAW_ENCAP] = {
7380 		.name = "raw_encap",
7381 		.help = "set raw encap data",
7382 		.next = NEXT(next_set_raw),
7383 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7384 				(offsetof(struct buffer, port),
7385 				 sizeof(((struct buffer *)0)->port),
7386 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7387 		.call = parse_set_raw_encap_decap,
7388 	},
7389 	[SET_RAW_DECAP] = {
7390 		.name = "raw_decap",
7391 		.help = "set raw decap data",
7392 		.next = NEXT(next_set_raw),
7393 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7394 				(offsetof(struct buffer, port),
7395 				 sizeof(((struct buffer *)0)->port),
7396 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7397 		.call = parse_set_raw_encap_decap,
7398 	},
7399 	[SET_RAW_INDEX] = {
7400 		.name = "{index}",
7401 		.type = "COMMON_UNSIGNED",
7402 		.help = "index of raw_encap/raw_decap data",
7403 		.next = NEXT(next_item),
7404 		.call = parse_port,
7405 	},
7406 	[SET_SAMPLE_INDEX] = {
7407 		.name = "{index}",
7408 		.type = "UNSIGNED",
7409 		.help = "index of sample actions",
7410 		.next = NEXT(next_action_sample),
7411 		.call = parse_port,
7412 	},
7413 	[SET_SAMPLE_ACTIONS] = {
7414 		.name = "sample_actions",
7415 		.help = "set sample actions list",
7416 		.next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
7417 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7418 				(offsetof(struct buffer, port),
7419 				 sizeof(((struct buffer *)0)->port),
7420 				 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
7421 		.call = parse_set_sample_action,
7422 	},
7423 	[SET_IPV6_EXT_PUSH] = {
7424 		.name = "ipv6_ext_push",
7425 		.help = "set IPv6 extension header",
7426 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7427 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7428 				(offsetof(struct buffer, port),
7429 				 sizeof(((struct buffer *)0)->port),
7430 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7431 		.call = parse_set_ipv6_ext_action,
7432 	},
7433 	[SET_IPV6_EXT_REMOVE] = {
7434 		.name = "ipv6_ext_remove",
7435 		.help = "set IPv6 extension header",
7436 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7437 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7438 				(offsetof(struct buffer, port),
7439 				 sizeof(((struct buffer *)0)->port),
7440 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7441 		.call = parse_set_ipv6_ext_action,
7442 	},
7443 	[SET_IPV6_EXT_INDEX] = {
7444 		.name = "{index}",
7445 		.type = "UNSIGNED",
7446 		.help = "index of ipv6 extension push/remove actions",
7447 		.next = NEXT(item_ipv6_push_ext),
7448 		.call = parse_port,
7449 	},
7450 	[ITEM_IPV6_PUSH_REMOVE_EXT] = {
7451 		.name = "ipv6_ext",
7452 		.help = "set IPv6 extension header",
7453 		.priv = PRIV_ITEM(IPV6_EXT,
7454 				  sizeof(struct rte_flow_item_ipv6_ext)),
7455 		.next = NEXT(item_ipv6_push_ext_type),
7456 		.call = parse_vc,
7457 	},
7458 	[ITEM_IPV6_PUSH_REMOVE_EXT_TYPE] = {
7459 		.name = "type",
7460 		.help = "set IPv6 extension type",
7461 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
7462 					     next_hdr)),
7463 		.next = NEXT(item_ipv6_push_ext_header, NEXT_ENTRY(COMMON_UNSIGNED),
7464 			     item_param),
7465 	},
7466 	[ACTION_SET_TAG] = {
7467 		.name = "set_tag",
7468 		.help = "set tag",
7469 		.priv = PRIV_ACTION(SET_TAG,
7470 			sizeof(struct rte_flow_action_set_tag)),
7471 		.next = NEXT(action_set_tag),
7472 		.call = parse_vc,
7473 	},
7474 	[ACTION_SET_TAG_INDEX] = {
7475 		.name = "index",
7476 		.help = "index of tag array",
7477 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7478 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
7479 		.call = parse_vc_conf,
7480 	},
7481 	[ACTION_SET_TAG_DATA] = {
7482 		.name = "data",
7483 		.help = "tag value",
7484 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7485 		.args = ARGS(ARGS_ENTRY
7486 			     (struct rte_flow_action_set_tag, data)),
7487 		.call = parse_vc_conf,
7488 	},
7489 	[ACTION_SET_TAG_MASK] = {
7490 		.name = "mask",
7491 		.help = "mask for tag value",
7492 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7493 		.args = ARGS(ARGS_ENTRY
7494 			     (struct rte_flow_action_set_tag, mask)),
7495 		.call = parse_vc_conf,
7496 	},
7497 	[ACTION_SET_META] = {
7498 		.name = "set_meta",
7499 		.help = "set metadata",
7500 		.priv = PRIV_ACTION(SET_META,
7501 			sizeof(struct rte_flow_action_set_meta)),
7502 		.next = NEXT(action_set_meta),
7503 		.call = parse_vc_action_set_meta,
7504 	},
7505 	[ACTION_SET_META_DATA] = {
7506 		.name = "data",
7507 		.help = "metadata value",
7508 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7509 		.args = ARGS(ARGS_ENTRY
7510 			     (struct rte_flow_action_set_meta, data)),
7511 		.call = parse_vc_conf,
7512 	},
7513 	[ACTION_SET_META_MASK] = {
7514 		.name = "mask",
7515 		.help = "mask for metadata value",
7516 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7517 		.args = ARGS(ARGS_ENTRY
7518 			     (struct rte_flow_action_set_meta, mask)),
7519 		.call = parse_vc_conf,
7520 	},
7521 	[ACTION_SET_IPV4_DSCP] = {
7522 		.name = "set_ipv4_dscp",
7523 		.help = "set DSCP value",
7524 		.priv = PRIV_ACTION(SET_IPV4_DSCP,
7525 			sizeof(struct rte_flow_action_set_dscp)),
7526 		.next = NEXT(action_set_ipv4_dscp),
7527 		.call = parse_vc,
7528 	},
7529 	[ACTION_SET_IPV4_DSCP_VALUE] = {
7530 		.name = "dscp_value",
7531 		.help = "new IPv4 DSCP value to set",
7532 		.next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7533 		.args = ARGS(ARGS_ENTRY
7534 			     (struct rte_flow_action_set_dscp, dscp)),
7535 		.call = parse_vc_conf,
7536 	},
7537 	[ACTION_SET_IPV6_DSCP] = {
7538 		.name = "set_ipv6_dscp",
7539 		.help = "set DSCP value",
7540 		.priv = PRIV_ACTION(SET_IPV6_DSCP,
7541 			sizeof(struct rte_flow_action_set_dscp)),
7542 		.next = NEXT(action_set_ipv6_dscp),
7543 		.call = parse_vc,
7544 	},
7545 	[ACTION_SET_IPV6_DSCP_VALUE] = {
7546 		.name = "dscp_value",
7547 		.help = "new IPv6 DSCP value to set",
7548 		.next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7549 		.args = ARGS(ARGS_ENTRY
7550 			     (struct rte_flow_action_set_dscp, dscp)),
7551 		.call = parse_vc_conf,
7552 	},
7553 	[ACTION_AGE] = {
7554 		.name = "age",
7555 		.help = "set a specific metadata header",
7556 		.next = NEXT(action_age),
7557 		.priv = PRIV_ACTION(AGE,
7558 			sizeof(struct rte_flow_action_age)),
7559 		.call = parse_vc,
7560 	},
7561 	[ACTION_AGE_TIMEOUT] = {
7562 		.name = "timeout",
7563 		.help = "flow age timeout value",
7564 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
7565 					   timeout, 24)),
7566 		.next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
7567 		.call = parse_vc_conf,
7568 	},
7569 	[ACTION_AGE_UPDATE] = {
7570 		.name = "age_update",
7571 		.help = "update aging parameter",
7572 		.next = NEXT(action_age_update),
7573 		.priv = PRIV_ACTION(AGE,
7574 				    sizeof(struct rte_flow_update_age)),
7575 		.call = parse_vc,
7576 	},
7577 	[ACTION_AGE_UPDATE_TIMEOUT] = {
7578 		.name = "timeout",
7579 		.help = "age timeout update value",
7580 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7581 					   timeout, 24)),
7582 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_UNSIGNED)),
7583 		.call = parse_vc_conf_timeout,
7584 	},
7585 	[ACTION_AGE_UPDATE_TOUCH] = {
7586 		.name = "touch",
7587 		.help = "this flow is touched",
7588 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_BOOLEAN)),
7589 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7590 					   touch, 1)),
7591 		.call = parse_vc_conf,
7592 	},
7593 	[ACTION_SAMPLE] = {
7594 		.name = "sample",
7595 		.help = "set a sample action",
7596 		.next = NEXT(action_sample),
7597 		.priv = PRIV_ACTION(SAMPLE,
7598 			sizeof(struct action_sample_data)),
7599 		.call = parse_vc_action_sample,
7600 	},
7601 	[ACTION_SAMPLE_RATIO] = {
7602 		.name = "ratio",
7603 		.help = "flow sample ratio value",
7604 		.next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
7605 		.args = ARGS(ARGS_ENTRY_ARB
7606 			     (offsetof(struct action_sample_data, conf) +
7607 			      offsetof(struct rte_flow_action_sample, ratio),
7608 			      sizeof(((struct rte_flow_action_sample *)0)->
7609 				     ratio))),
7610 	},
7611 	[ACTION_SAMPLE_INDEX] = {
7612 		.name = "index",
7613 		.help = "the index of sample actions list",
7614 		.next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
7615 	},
7616 	[ACTION_SAMPLE_INDEX_VALUE] = {
7617 		.name = "{index}",
7618 		.type = "COMMON_UNSIGNED",
7619 		.help = "unsigned integer value",
7620 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7621 		.call = parse_vc_action_sample_index,
7622 		.comp = comp_set_sample_index,
7623 	},
7624 	[ACTION_CONNTRACK] = {
7625 		.name = "conntrack",
7626 		.help = "create a conntrack object",
7627 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7628 		.priv = PRIV_ACTION(CONNTRACK,
7629 				    sizeof(struct rte_flow_action_conntrack)),
7630 		.call = parse_vc,
7631 	},
7632 	[ACTION_CONNTRACK_UPDATE] = {
7633 		.name = "conntrack_update",
7634 		.help = "update a conntrack object",
7635 		.next = NEXT(action_update_conntrack),
7636 		.priv = PRIV_ACTION(CONNTRACK,
7637 				    sizeof(struct rte_flow_modify_conntrack)),
7638 		.call = parse_vc,
7639 	},
7640 	[ACTION_CONNTRACK_UPDATE_DIR] = {
7641 		.name = "dir",
7642 		.help = "update a conntrack object direction",
7643 		.next = NEXT(action_update_conntrack),
7644 		.call = parse_vc_action_conntrack_update,
7645 	},
7646 	[ACTION_CONNTRACK_UPDATE_CTX] = {
7647 		.name = "ctx",
7648 		.help = "update a conntrack object context",
7649 		.next = NEXT(action_update_conntrack),
7650 		.call = parse_vc_action_conntrack_update,
7651 	},
7652 	[ACTION_PORT_REPRESENTOR] = {
7653 		.name = "port_representor",
7654 		.help = "at embedded switch level, send matching traffic to the given ethdev",
7655 		.priv = PRIV_ACTION(PORT_REPRESENTOR,
7656 				    sizeof(struct rte_flow_action_ethdev)),
7657 		.next = NEXT(action_port_representor),
7658 		.call = parse_vc,
7659 	},
7660 	[ACTION_PORT_REPRESENTOR_PORT_ID] = {
7661 		.name = "port_id",
7662 		.help = "ethdev port ID",
7663 		.next = NEXT(action_port_representor,
7664 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7665 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7666 					port_id)),
7667 		.call = parse_vc_conf,
7668 	},
7669 	[ACTION_REPRESENTED_PORT] = {
7670 		.name = "represented_port",
7671 		.help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
7672 		.priv = PRIV_ACTION(REPRESENTED_PORT,
7673 				sizeof(struct rte_flow_action_ethdev)),
7674 		.next = NEXT(action_represented_port),
7675 		.call = parse_vc,
7676 	},
7677 	[ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
7678 		.name = "ethdev_port_id",
7679 		.help = "ethdev port ID",
7680 		.next = NEXT(action_represented_port,
7681 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7682 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7683 					port_id)),
7684 		.call = parse_vc_conf,
7685 	},
7686 	/* Indirect action destroy arguments. */
7687 	[INDIRECT_ACTION_DESTROY_ID] = {
7688 		.name = "action_id",
7689 		.help = "specify a indirect action id to destroy",
7690 		.next = NEXT(next_ia_destroy_attr,
7691 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7692 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
7693 					    args.ia_destroy.action_id)),
7694 		.call = parse_ia_destroy,
7695 	},
7696 	/* Indirect action create arguments. */
7697 	[INDIRECT_ACTION_CREATE_ID] = {
7698 		.name = "action_id",
7699 		.help = "specify a indirect action id to create",
7700 		.next = NEXT(next_ia_create_attr,
7701 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7702 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
7703 	},
7704 	[ACTION_INDIRECT] = {
7705 		.name = "indirect",
7706 		.help = "apply indirect action by id",
7707 		.priv = PRIV_ACTION(INDIRECT, 0),
7708 		.next = NEXT(next_ia),
7709 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7710 		.call = parse_vc,
7711 	},
7712 	[ACTION_INDIRECT_LIST] = {
7713 		.name = "indirect_list",
7714 		.help = "apply indirect list action by id",
7715 		.priv = PRIV_ACTION(INDIRECT_LIST,
7716 				    sizeof(struct
7717 					   rte_flow_action_indirect_list)),
7718 		.next = NEXT(next_ial),
7719 		.call = parse_vc,
7720 	},
7721 	[ACTION_INDIRECT_LIST_HANDLE] = {
7722 		.name = "handle",
7723 		.help = "indirect list handle",
7724 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_HANDLE)),
7725 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7726 	},
7727 	[ACTION_INDIRECT_LIST_CONF] = {
7728 		.name = "conf",
7729 		.help = "indirect list configuration",
7730 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_CONF)),
7731 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7732 	},
7733 	[INDIRECT_LIST_ACTION_ID2PTR_HANDLE] = {
7734 		.type = "UNSIGNED",
7735 		.help = "unsigned integer value",
7736 		.call = parse_indlst_id2ptr,
7737 	},
7738 	[INDIRECT_LIST_ACTION_ID2PTR_CONF] = {
7739 		.type = "UNSIGNED",
7740 		.help = "unsigned integer value",
7741 		.call = parse_indlst_id2ptr,
7742 	},
7743 	[ACTION_SHARED_INDIRECT] = {
7744 		.name = "shared_indirect",
7745 		.help = "apply indirect action by id and port",
7746 		.priv = PRIV_ACTION(INDIRECT, 0),
7747 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_PORT)),
7748 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t)),
7749 			     ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7750 		.call = parse_vc,
7751 	},
7752 	[INDIRECT_ACTION_PORT] = {
7753 		.name = "{indirect_action_port}",
7754 		.type = "INDIRECT_ACTION_PORT",
7755 		.help = "indirect action port",
7756 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
7757 		.call = parse_ia_port,
7758 		.comp = comp_none,
7759 	},
7760 	[INDIRECT_ACTION_ID2PTR] = {
7761 		.name = "{action_id}",
7762 		.type = "INDIRECT_ACTION_ID",
7763 		.help = "indirect action id",
7764 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7765 		.call = parse_ia_id2ptr,
7766 		.comp = comp_none,
7767 	},
7768 	[INDIRECT_ACTION_INGRESS] = {
7769 		.name = "ingress",
7770 		.help = "affect rule to ingress",
7771 		.next = NEXT(next_ia_create_attr),
7772 		.call = parse_ia,
7773 	},
7774 	[INDIRECT_ACTION_EGRESS] = {
7775 		.name = "egress",
7776 		.help = "affect rule to egress",
7777 		.next = NEXT(next_ia_create_attr),
7778 		.call = parse_ia,
7779 	},
7780 	[INDIRECT_ACTION_TRANSFER] = {
7781 		.name = "transfer",
7782 		.help = "affect rule to transfer",
7783 		.next = NEXT(next_ia_create_attr),
7784 		.call = parse_ia,
7785 	},
7786 	[INDIRECT_ACTION_SPEC] = {
7787 		.name = "action",
7788 		.help = "specify action to create indirect handle",
7789 		.next = NEXT(next_action),
7790 	},
7791 	[INDIRECT_ACTION_LIST] = {
7792 		.name = "list",
7793 		.help = "specify actions for indirect handle list",
7794 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
7795 		.call = parse_ia,
7796 	},
7797 	[INDIRECT_ACTION_FLOW_CONF] = {
7798 		.name = "flow_conf",
7799 		.help = "specify actions configuration for indirect handle list",
7800 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
7801 		.call = parse_ia,
7802 	},
7803 	[ACTION_POL_G] = {
7804 		.name = "g_actions",
7805 		.help = "submit a list of associated actions for green",
7806 		.next = NEXT(next_action),
7807 		.call = parse_mp,
7808 	},
7809 	[ACTION_POL_Y] = {
7810 		.name = "y_actions",
7811 		.help = "submit a list of associated actions for yellow",
7812 		.next = NEXT(next_action),
7813 	},
7814 	[ACTION_POL_R] = {
7815 		.name = "r_actions",
7816 		.help = "submit a list of associated actions for red",
7817 		.next = NEXT(next_action),
7818 	},
7819 	[ACTION_QUOTA_CREATE] = {
7820 		.name = "quota_create",
7821 		.help = "create quota action",
7822 		.priv = PRIV_ACTION(QUOTA,
7823 				    sizeof(struct rte_flow_action_quota)),
7824 		.next = NEXT(action_quota_create),
7825 		.call = parse_vc
7826 	},
7827 	[ACTION_QUOTA_CREATE_LIMIT] = {
7828 		.name = "limit",
7829 		.help = "quota limit",
7830 		.next = NEXT(action_quota_create, NEXT_ENTRY(COMMON_UNSIGNED)),
7831 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, quota)),
7832 		.call = parse_vc_conf
7833 	},
7834 	[ACTION_QUOTA_CREATE_MODE] = {
7835 		.name = "mode",
7836 		.help = "quota mode",
7837 		.next = NEXT(action_quota_create,
7838 			     NEXT_ENTRY(ACTION_QUOTA_CREATE_MODE_NAME)),
7839 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, mode)),
7840 		.call = parse_vc_conf
7841 	},
7842 	[ACTION_QUOTA_CREATE_MODE_NAME] = {
7843 		.name = "mode_name",
7844 		.help = "quota mode name",
7845 		.call = parse_quota_mode_name,
7846 		.comp = comp_quota_mode_name
7847 	},
7848 	[ACTION_QUOTA_QU] = {
7849 		.name = "quota_update",
7850 		.help = "update quota action",
7851 		.priv = PRIV_ACTION(QUOTA,
7852 				    sizeof(struct rte_flow_update_quota)),
7853 		.next = NEXT(action_quota_update),
7854 		.call = parse_vc
7855 	},
7856 	[ACTION_QUOTA_QU_LIMIT] = {
7857 		.name = "limit",
7858 		.help = "quota limit",
7859 		.next = NEXT(action_quota_update, NEXT_ENTRY(COMMON_UNSIGNED)),
7860 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, quota)),
7861 		.call = parse_vc_conf
7862 	},
7863 	[ACTION_QUOTA_QU_UPDATE_OP] = {
7864 		.name = "update_op",
7865 		.help = "query update op SET|ADD",
7866 		.next = NEXT(action_quota_update,
7867 			     NEXT_ENTRY(ACTION_QUOTA_QU_UPDATE_OP_NAME)),
7868 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, op)),
7869 		.call = parse_vc_conf
7870 	},
7871 	[ACTION_QUOTA_QU_UPDATE_OP_NAME] = {
7872 		.name = "update_op_name",
7873 		.help = "quota update op name",
7874 		.call = parse_quota_update_name,
7875 		.comp = comp_quota_update_name
7876 	},
7877 
7878 	/* Top-level command. */
7879 	[ADD] = {
7880 		.name = "add",
7881 		.type = "port meter policy {port_id} {arg}",
7882 		.help = "add port meter policy",
7883 		.next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
7884 		.call = parse_init,
7885 	},
7886 	/* Sub-level commands. */
7887 	[ITEM_POL_PORT] = {
7888 		.name = "port",
7889 		.help = "add port meter policy",
7890 		.next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
7891 	},
7892 	[ITEM_POL_METER] = {
7893 		.name = "meter",
7894 		.help = "add port meter policy",
7895 		.next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
7896 	},
7897 	[ITEM_POL_POLICY] = {
7898 		.name = "policy",
7899 		.help = "add port meter policy",
7900 		.next = NEXT(NEXT_ENTRY(ACTION_POL_R),
7901 				NEXT_ENTRY(ACTION_POL_Y),
7902 				NEXT_ENTRY(ACTION_POL_G),
7903 				NEXT_ENTRY(COMMON_POLICY_ID),
7904 				NEXT_ENTRY(COMMON_PORT_ID)),
7905 		.args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
7906 				ARGS_ENTRY(struct buffer, port)),
7907 		.call = parse_mp,
7908 	},
7909 	[ITEM_AGGR_AFFINITY] = {
7910 		.name = "aggr_affinity",
7911 		.help = "match on the aggregated port receiving the packets",
7912 		.priv = PRIV_ITEM(AGGR_AFFINITY,
7913 				  sizeof(struct rte_flow_item_aggr_affinity)),
7914 		.next = NEXT(item_aggr_affinity),
7915 		.call = parse_vc,
7916 	},
7917 	[ITEM_AGGR_AFFINITY_VALUE] = {
7918 		.name = "affinity",
7919 		.help = "aggregated affinity value",
7920 		.next = NEXT(item_aggr_affinity, NEXT_ENTRY(COMMON_UNSIGNED),
7921 			     item_param),
7922 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_aggr_affinity,
7923 					affinity)),
7924 	},
7925 	[ITEM_TX_QUEUE] = {
7926 		.name = "tx_queue",
7927 		.help = "match on the tx queue of send packet",
7928 		.priv = PRIV_ITEM(TX_QUEUE,
7929 				  sizeof(struct rte_flow_item_tx_queue)),
7930 		.next = NEXT(item_tx_queue),
7931 		.call = parse_vc,
7932 	},
7933 	[ITEM_TX_QUEUE_VALUE] = {
7934 		.name = "tx_queue_value",
7935 		.help = "tx queue value",
7936 		.next = NEXT(item_tx_queue, NEXT_ENTRY(COMMON_UNSIGNED),
7937 			     item_param),
7938 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tx_queue,
7939 					tx_queue)),
7940 	},
7941 };
7942 
7943 /** Remove and return last entry from argument stack. */
7944 static const struct arg *
7945 pop_args(struct context *ctx)
7946 {
7947 	return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
7948 }
7949 
7950 /** Add entry on top of the argument stack. */
7951 static int
7952 push_args(struct context *ctx, const struct arg *arg)
7953 {
7954 	if (ctx->args_num == CTX_STACK_SIZE)
7955 		return -1;
7956 	ctx->args[ctx->args_num++] = arg;
7957 	return 0;
7958 }
7959 
7960 /** Spread value into buffer according to bit-mask. */
7961 static size_t
7962 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
7963 {
7964 	uint32_t i = arg->size;
7965 	uint32_t end = 0;
7966 	int sub = 1;
7967 	int add = 0;
7968 	size_t len = 0;
7969 
7970 	if (!arg->mask)
7971 		return 0;
7972 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
7973 	if (!arg->hton) {
7974 		i = 0;
7975 		end = arg->size;
7976 		sub = 0;
7977 		add = 1;
7978 	}
7979 #endif
7980 	while (i != end) {
7981 		unsigned int shift = 0;
7982 		uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
7983 
7984 		for (shift = 0; arg->mask[i] >> shift; ++shift) {
7985 			if (!(arg->mask[i] & (1 << shift)))
7986 				continue;
7987 			++len;
7988 			if (!dst)
7989 				continue;
7990 			*buf &= ~(1 << shift);
7991 			*buf |= (val & 1) << shift;
7992 			val >>= 1;
7993 		}
7994 		i += add;
7995 	}
7996 	return len;
7997 }
7998 
7999 /** Compare a string with a partial one of a given length. */
8000 static int
8001 strcmp_partial(const char *full, const char *partial, size_t partial_len)
8002 {
8003 	int r = strncmp(full, partial, partial_len);
8004 
8005 	if (r)
8006 		return r;
8007 	if (strlen(full) <= partial_len)
8008 		return 0;
8009 	return full[partial_len];
8010 }
8011 
8012 /**
8013  * Parse a prefix length and generate a bit-mask.
8014  *
8015  * Last argument (ctx->args) is retrieved to determine mask size, storage
8016  * location and whether the result must use network byte ordering.
8017  */
8018 static int
8019 parse_prefix(struct context *ctx, const struct token *token,
8020 	     const char *str, unsigned int len,
8021 	     void *buf, unsigned int size)
8022 {
8023 	const struct arg *arg = pop_args(ctx);
8024 	static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
8025 	char *end;
8026 	uintmax_t u;
8027 	unsigned int bytes;
8028 	unsigned int extra;
8029 
8030 	(void)token;
8031 	/* Argument is expected. */
8032 	if (!arg)
8033 		return -1;
8034 	errno = 0;
8035 	u = strtoumax(str, &end, 0);
8036 	if (errno || (size_t)(end - str) != len)
8037 		goto error;
8038 	if (arg->mask) {
8039 		uintmax_t v = 0;
8040 
8041 		extra = arg_entry_bf_fill(NULL, 0, arg);
8042 		if (u > extra)
8043 			goto error;
8044 		if (!ctx->object)
8045 			return len;
8046 		extra -= u;
8047 		while (u--)
8048 			(v <<= 1, v |= 1);
8049 		v <<= extra;
8050 		if (!arg_entry_bf_fill(ctx->object, v, arg) ||
8051 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
8052 			goto error;
8053 		return len;
8054 	}
8055 	bytes = u / 8;
8056 	extra = u % 8;
8057 	size = arg->size;
8058 	if (bytes > size || bytes + !!extra > size)
8059 		goto error;
8060 	if (!ctx->object)
8061 		return len;
8062 	buf = (uint8_t *)ctx->object + arg->offset;
8063 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8064 	if (!arg->hton) {
8065 		memset((uint8_t *)buf + size - bytes, 0xff, bytes);
8066 		memset(buf, 0x00, size - bytes);
8067 		if (extra)
8068 			((uint8_t *)buf)[size - bytes - 1] = conv[extra];
8069 	} else
8070 #endif
8071 	{
8072 		memset(buf, 0xff, bytes);
8073 		memset((uint8_t *)buf + bytes, 0x00, size - bytes);
8074 		if (extra)
8075 			((uint8_t *)buf)[bytes] = conv[extra];
8076 	}
8077 	if (ctx->objmask)
8078 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8079 	return len;
8080 error:
8081 	push_args(ctx, arg);
8082 	return -1;
8083 }
8084 
8085 /** Default parsing function for token name matching. */
8086 static int
8087 parse_default(struct context *ctx, const struct token *token,
8088 	      const char *str, unsigned int len,
8089 	      void *buf, unsigned int size)
8090 {
8091 	(void)ctx;
8092 	(void)buf;
8093 	(void)size;
8094 	if (strcmp_partial(token->name, str, len))
8095 		return -1;
8096 	return len;
8097 }
8098 
8099 /** Parse flow command, initialize output buffer for subsequent tokens. */
8100 static int
8101 parse_init(struct context *ctx, const struct token *token,
8102 	   const char *str, unsigned int len,
8103 	   void *buf, unsigned int size)
8104 {
8105 	struct buffer *out = buf;
8106 
8107 	/* Token name must match. */
8108 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8109 		return -1;
8110 	/* Nothing else to do if there is no buffer. */
8111 	if (!out)
8112 		return len;
8113 	/* Make sure buffer is large enough. */
8114 	if (size < sizeof(*out))
8115 		return -1;
8116 	/* Initialize buffer. */
8117 	memset(out, 0x00, sizeof(*out));
8118 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
8119 	ctx->objdata = 0;
8120 	ctx->object = out;
8121 	ctx->objmask = NULL;
8122 	return len;
8123 }
8124 
8125 /** Parse tokens for indirect action commands. */
8126 static int
8127 parse_ia(struct context *ctx, const struct token *token,
8128 	 const char *str, unsigned int len,
8129 	 void *buf, unsigned int size)
8130 {
8131 	struct buffer *out = buf;
8132 
8133 	/* Token name must match. */
8134 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8135 		return -1;
8136 	/* Nothing else to do if there is no buffer. */
8137 	if (!out)
8138 		return len;
8139 	if (!out->command) {
8140 		if (ctx->curr != INDIRECT_ACTION)
8141 			return -1;
8142 		if (sizeof(*out) > size)
8143 			return -1;
8144 		out->command = ctx->curr;
8145 		ctx->objdata = 0;
8146 		ctx->object = out;
8147 		ctx->objmask = NULL;
8148 		out->args.vc.data = (uint8_t *)out + size;
8149 		return len;
8150 	}
8151 	switch (ctx->curr) {
8152 	case INDIRECT_ACTION_CREATE:
8153 	case INDIRECT_ACTION_UPDATE:
8154 	case INDIRECT_ACTION_QUERY_UPDATE:
8155 		out->args.vc.actions =
8156 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8157 					       sizeof(double));
8158 		out->args.vc.attr.group = UINT32_MAX;
8159 		/* fallthrough */
8160 	case INDIRECT_ACTION_QUERY:
8161 		out->command = ctx->curr;
8162 		ctx->objdata = 0;
8163 		ctx->object = out;
8164 		ctx->objmask = NULL;
8165 		return len;
8166 	case INDIRECT_ACTION_EGRESS:
8167 		out->args.vc.attr.egress = 1;
8168 		return len;
8169 	case INDIRECT_ACTION_INGRESS:
8170 		out->args.vc.attr.ingress = 1;
8171 		return len;
8172 	case INDIRECT_ACTION_TRANSFER:
8173 		out->args.vc.attr.transfer = 1;
8174 		return len;
8175 	case INDIRECT_ACTION_QU_MODE:
8176 		return len;
8177 	case INDIRECT_ACTION_LIST:
8178 		out->command = INDIRECT_ACTION_LIST_CREATE;
8179 		return len;
8180 	case INDIRECT_ACTION_FLOW_CONF:
8181 		out->command = INDIRECT_ACTION_FLOW_CONF_CREATE;
8182 		return len;
8183 	default:
8184 		return -1;
8185 	}
8186 }
8187 
8188 
8189 /** Parse tokens for indirect action destroy command. */
8190 static int
8191 parse_ia_destroy(struct context *ctx, const struct token *token,
8192 		 const char *str, unsigned int len,
8193 		 void *buf, unsigned int size)
8194 {
8195 	struct buffer *out = buf;
8196 	uint32_t *action_id;
8197 
8198 	/* Token name must match. */
8199 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8200 		return -1;
8201 	/* Nothing else to do if there is no buffer. */
8202 	if (!out)
8203 		return len;
8204 	if (!out->command || out->command == INDIRECT_ACTION) {
8205 		if (ctx->curr != INDIRECT_ACTION_DESTROY)
8206 			return -1;
8207 		if (sizeof(*out) > size)
8208 			return -1;
8209 		out->command = ctx->curr;
8210 		ctx->objdata = 0;
8211 		ctx->object = out;
8212 		ctx->objmask = NULL;
8213 		out->args.ia_destroy.action_id =
8214 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8215 					       sizeof(double));
8216 		return len;
8217 	}
8218 	action_id = out->args.ia_destroy.action_id
8219 		    + out->args.ia_destroy.action_id_n++;
8220 	if ((uint8_t *)action_id > (uint8_t *)out + size)
8221 		return -1;
8222 	ctx->objdata = 0;
8223 	ctx->object = action_id;
8224 	ctx->objmask = NULL;
8225 	return len;
8226 }
8227 
8228 /** Parse tokens for indirect action commands. */
8229 static int
8230 parse_qia(struct context *ctx, const struct token *token,
8231 	  const char *str, unsigned int len,
8232 	  void *buf, unsigned int size)
8233 {
8234 	struct buffer *out = buf;
8235 
8236 	/* Token name must match. */
8237 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8238 		return -1;
8239 	/* Nothing else to do if there is no buffer. */
8240 	if (!out)
8241 		return len;
8242 	if (!out->command) {
8243 		if (ctx->curr != QUEUE)
8244 			return -1;
8245 		if (sizeof(*out) > size)
8246 			return -1;
8247 		out->args.vc.data = (uint8_t *)out + size;
8248 		return len;
8249 	}
8250 	switch (ctx->curr) {
8251 	case QUEUE_INDIRECT_ACTION:
8252 		return len;
8253 	case QUEUE_INDIRECT_ACTION_CREATE:
8254 	case QUEUE_INDIRECT_ACTION_UPDATE:
8255 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
8256 		out->args.vc.actions =
8257 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8258 					       sizeof(double));
8259 		out->args.vc.attr.group = UINT32_MAX;
8260 		/* fallthrough */
8261 	case QUEUE_INDIRECT_ACTION_QUERY:
8262 		out->command = ctx->curr;
8263 		ctx->objdata = 0;
8264 		ctx->object = out;
8265 		ctx->objmask = NULL;
8266 		return len;
8267 	case QUEUE_INDIRECT_ACTION_EGRESS:
8268 		out->args.vc.attr.egress = 1;
8269 		return len;
8270 	case QUEUE_INDIRECT_ACTION_INGRESS:
8271 		out->args.vc.attr.ingress = 1;
8272 		return len;
8273 	case QUEUE_INDIRECT_ACTION_TRANSFER:
8274 		out->args.vc.attr.transfer = 1;
8275 		return len;
8276 	case QUEUE_INDIRECT_ACTION_CREATE_POSTPONE:
8277 		return len;
8278 	case QUEUE_INDIRECT_ACTION_QU_MODE:
8279 		return len;
8280 	case QUEUE_INDIRECT_ACTION_LIST:
8281 		out->command = QUEUE_INDIRECT_ACTION_LIST_CREATE;
8282 		return len;
8283 	default:
8284 		return -1;
8285 	}
8286 }
8287 
8288 /** Parse tokens for indirect action destroy command. */
8289 static int
8290 parse_qia_destroy(struct context *ctx, const struct token *token,
8291 		  const char *str, unsigned int len,
8292 		  void *buf, unsigned int size)
8293 {
8294 	struct buffer *out = buf;
8295 	uint32_t *action_id;
8296 
8297 	/* Token name must match. */
8298 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8299 		return -1;
8300 	/* Nothing else to do if there is no buffer. */
8301 	if (!out)
8302 		return len;
8303 	if (!out->command || out->command == QUEUE) {
8304 		if (ctx->curr != QUEUE_INDIRECT_ACTION_DESTROY)
8305 			return -1;
8306 		if (sizeof(*out) > size)
8307 			return -1;
8308 		out->command = ctx->curr;
8309 		ctx->objdata = 0;
8310 		ctx->object = out;
8311 		ctx->objmask = NULL;
8312 		out->args.ia_destroy.action_id =
8313 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8314 					       sizeof(double));
8315 		return len;
8316 	}
8317 	switch (ctx->curr) {
8318 	case QUEUE_INDIRECT_ACTION:
8319 		out->command = ctx->curr;
8320 		ctx->objdata = 0;
8321 		ctx->object = out;
8322 		ctx->objmask = NULL;
8323 		return len;
8324 	case QUEUE_INDIRECT_ACTION_DESTROY_ID:
8325 		action_id = out->args.ia_destroy.action_id
8326 				+ out->args.ia_destroy.action_id_n++;
8327 		if ((uint8_t *)action_id > (uint8_t *)out + size)
8328 			return -1;
8329 		ctx->objdata = 0;
8330 		ctx->object = action_id;
8331 		ctx->objmask = NULL;
8332 		return len;
8333 	case QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE:
8334 		return len;
8335 	default:
8336 		return -1;
8337 	}
8338 }
8339 
8340 /** Parse tokens for meter policy action commands. */
8341 static int
8342 parse_mp(struct context *ctx, const struct token *token,
8343 	const char *str, unsigned int len,
8344 	void *buf, unsigned int size)
8345 {
8346 	struct buffer *out = buf;
8347 
8348 	/* Token name must match. */
8349 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8350 		return -1;
8351 	/* Nothing else to do if there is no buffer. */
8352 	if (!out)
8353 		return len;
8354 	if (!out->command) {
8355 		if (ctx->curr != ITEM_POL_POLICY)
8356 			return -1;
8357 		if (sizeof(*out) > size)
8358 			return -1;
8359 		out->command = ctx->curr;
8360 		ctx->objdata = 0;
8361 		ctx->object = out;
8362 		ctx->objmask = NULL;
8363 		out->args.vc.data = (uint8_t *)out + size;
8364 		return len;
8365 	}
8366 	switch (ctx->curr) {
8367 	case ACTION_POL_G:
8368 		out->args.vc.actions =
8369 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8370 					sizeof(double));
8371 		out->command = ctx->curr;
8372 		ctx->objdata = 0;
8373 		ctx->object = out;
8374 		ctx->objmask = NULL;
8375 		return len;
8376 	default:
8377 		return -1;
8378 	}
8379 }
8380 
8381 /** Parse tokens for validate/create commands. */
8382 static int
8383 parse_vc(struct context *ctx, const struct token *token,
8384 	 const char *str, unsigned int len,
8385 	 void *buf, unsigned int size)
8386 {
8387 	struct buffer *out = buf;
8388 	uint8_t *data;
8389 	uint32_t data_size;
8390 
8391 	/* Token name must match. */
8392 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8393 		return -1;
8394 	/* Nothing else to do if there is no buffer. */
8395 	if (!out)
8396 		return len;
8397 	if (!out->command) {
8398 		if (ctx->curr != VALIDATE && ctx->curr != CREATE &&
8399 		    ctx->curr != PATTERN_TEMPLATE_CREATE &&
8400 		    ctx->curr != ACTIONS_TEMPLATE_CREATE)
8401 			return -1;
8402 		if (sizeof(*out) > size)
8403 			return -1;
8404 		out->command = ctx->curr;
8405 		ctx->objdata = 0;
8406 		ctx->object = out;
8407 		ctx->objmask = NULL;
8408 		out->args.vc.data = (uint8_t *)out + size;
8409 		return len;
8410 	}
8411 	ctx->objdata = 0;
8412 	switch (ctx->curr) {
8413 	default:
8414 		ctx->object = &out->args.vc.attr;
8415 		break;
8416 	case VC_TUNNEL_SET:
8417 	case VC_TUNNEL_MATCH:
8418 		ctx->object = &out->args.vc.tunnel_ops;
8419 		break;
8420 	case VC_USER_ID:
8421 		ctx->object = out;
8422 		break;
8423 	}
8424 	ctx->objmask = NULL;
8425 	switch (ctx->curr) {
8426 	case VC_GROUP:
8427 	case VC_PRIORITY:
8428 	case VC_USER_ID:
8429 		return len;
8430 	case VC_TUNNEL_SET:
8431 		out->args.vc.tunnel_ops.enabled = 1;
8432 		out->args.vc.tunnel_ops.actions = 1;
8433 		return len;
8434 	case VC_TUNNEL_MATCH:
8435 		out->args.vc.tunnel_ops.enabled = 1;
8436 		out->args.vc.tunnel_ops.items = 1;
8437 		return len;
8438 	case VC_INGRESS:
8439 		out->args.vc.attr.ingress = 1;
8440 		return len;
8441 	case VC_EGRESS:
8442 		out->args.vc.attr.egress = 1;
8443 		return len;
8444 	case VC_TRANSFER:
8445 		out->args.vc.attr.transfer = 1;
8446 		return len;
8447 	case ITEM_PATTERN:
8448 		out->args.vc.pattern =
8449 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8450 					       sizeof(double));
8451 		ctx->object = out->args.vc.pattern;
8452 		ctx->objmask = NULL;
8453 		return len;
8454 	case ITEM_END:
8455 		if ((out->command == VALIDATE || out->command == CREATE) &&
8456 		    ctx->last)
8457 			return -1;
8458 		if (out->command == PATTERN_TEMPLATE_CREATE &&
8459 		    !ctx->last)
8460 			return -1;
8461 		break;
8462 	case ACTIONS:
8463 		out->args.vc.actions = out->args.vc.pattern ?
8464 			(void *)RTE_ALIGN_CEIL((uintptr_t)
8465 					       (out->args.vc.pattern +
8466 						out->args.vc.pattern_n),
8467 					       sizeof(double)) :
8468 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8469 					       sizeof(double));
8470 		ctx->object = out->args.vc.actions;
8471 		ctx->objmask = NULL;
8472 		return len;
8473 	default:
8474 		if (!token->priv)
8475 			return -1;
8476 		break;
8477 	}
8478 	if (!out->args.vc.actions) {
8479 		const struct parse_item_priv *priv = token->priv;
8480 		struct rte_flow_item *item =
8481 			out->args.vc.pattern + out->args.vc.pattern_n;
8482 
8483 		data_size = priv->size * 3; /* spec, last, mask */
8484 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8485 					       (out->args.vc.data - data_size),
8486 					       sizeof(double));
8487 		if ((uint8_t *)item + sizeof(*item) > data)
8488 			return -1;
8489 		*item = (struct rte_flow_item){
8490 			.type = priv->type,
8491 		};
8492 		++out->args.vc.pattern_n;
8493 		ctx->object = item;
8494 		ctx->objmask = NULL;
8495 	} else {
8496 		const struct parse_action_priv *priv = token->priv;
8497 		struct rte_flow_action *action =
8498 			out->args.vc.actions + out->args.vc.actions_n;
8499 
8500 		data_size = priv->size; /* configuration */
8501 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8502 					       (out->args.vc.data - data_size),
8503 					       sizeof(double));
8504 		if ((uint8_t *)action + sizeof(*action) > data)
8505 			return -1;
8506 		*action = (struct rte_flow_action){
8507 			.type = priv->type,
8508 			.conf = data_size ? data : NULL,
8509 		};
8510 		++out->args.vc.actions_n;
8511 		ctx->object = action;
8512 		ctx->objmask = NULL;
8513 	}
8514 	memset(data, 0, data_size);
8515 	out->args.vc.data = data;
8516 	ctx->objdata = data_size;
8517 	return len;
8518 }
8519 
8520 /** Parse pattern item parameter type. */
8521 static int
8522 parse_vc_spec(struct context *ctx, const struct token *token,
8523 	      const char *str, unsigned int len,
8524 	      void *buf, unsigned int size)
8525 {
8526 	struct buffer *out = buf;
8527 	struct rte_flow_item *item;
8528 	uint32_t data_size;
8529 	int index;
8530 	int objmask = 0;
8531 
8532 	(void)size;
8533 	/* Token name must match. */
8534 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8535 		return -1;
8536 	/* Parse parameter types. */
8537 	switch (ctx->curr) {
8538 		static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
8539 
8540 	case ITEM_PARAM_IS:
8541 		index = 0;
8542 		objmask = 1;
8543 		break;
8544 	case ITEM_PARAM_SPEC:
8545 		index = 0;
8546 		break;
8547 	case ITEM_PARAM_LAST:
8548 		index = 1;
8549 		break;
8550 	case ITEM_PARAM_PREFIX:
8551 		/* Modify next token to expect a prefix. */
8552 		if (ctx->next_num < 2)
8553 			return -1;
8554 		ctx->next[ctx->next_num - 2] = prefix;
8555 		/* Fall through. */
8556 	case ITEM_PARAM_MASK:
8557 		index = 2;
8558 		break;
8559 	default:
8560 		return -1;
8561 	}
8562 	/* Nothing else to do if there is no buffer. */
8563 	if (!out)
8564 		return len;
8565 	if (!out->args.vc.pattern_n)
8566 		return -1;
8567 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8568 	data_size = ctx->objdata / 3; /* spec, last, mask */
8569 	/* Point to selected object. */
8570 	ctx->object = out->args.vc.data + (data_size * index);
8571 	if (objmask) {
8572 		ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
8573 		item->mask = ctx->objmask;
8574 	} else
8575 		ctx->objmask = NULL;
8576 	/* Update relevant item pointer. */
8577 	*((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
8578 		ctx->object;
8579 	return len;
8580 }
8581 
8582 /** Parse action configuration field. */
8583 static int
8584 parse_vc_conf(struct context *ctx, const struct token *token,
8585 	      const char *str, unsigned int len,
8586 	      void *buf, unsigned int size)
8587 {
8588 	struct buffer *out = buf;
8589 
8590 	(void)size;
8591 	/* Token name must match. */
8592 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8593 		return -1;
8594 	/* Nothing else to do if there is no buffer. */
8595 	if (!out)
8596 		return len;
8597 	/* Point to selected object. */
8598 	ctx->object = out->args.vc.data;
8599 	ctx->objmask = NULL;
8600 	return len;
8601 }
8602 
8603 /** Parse action configuration field. */
8604 static int
8605 parse_vc_conf_timeout(struct context *ctx, const struct token *token,
8606 		      const char *str, unsigned int len,
8607 		      void *buf, unsigned int size)
8608 {
8609 	struct buffer *out = buf;
8610 	struct rte_flow_update_age *update;
8611 
8612 	(void)size;
8613 	if (ctx->curr != ACTION_AGE_UPDATE_TIMEOUT)
8614 		return -1;
8615 	/* Token name must match. */
8616 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8617 		return -1;
8618 	/* Nothing else to do if there is no buffer. */
8619 	if (!out)
8620 		return len;
8621 	/* Point to selected object. */
8622 	ctx->object = out->args.vc.data;
8623 	ctx->objmask = NULL;
8624 	/* Update the timeout is valid. */
8625 	update = (struct rte_flow_update_age *)out->args.vc.data;
8626 	update->timeout_valid = 1;
8627 	return len;
8628 }
8629 
8630 /** Parse eCPRI common header type field. */
8631 static int
8632 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
8633 			 const char *str, unsigned int len,
8634 			 void *buf, unsigned int size)
8635 {
8636 	struct rte_flow_item_ecpri *ecpri;
8637 	struct rte_flow_item_ecpri *ecpri_mask;
8638 	struct rte_flow_item *item;
8639 	uint32_t data_size;
8640 	uint8_t msg_type;
8641 	struct buffer *out = buf;
8642 	const struct arg *arg;
8643 
8644 	(void)size;
8645 	/* Token name must match. */
8646 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8647 		return -1;
8648 	switch (ctx->curr) {
8649 	case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
8650 		msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
8651 		break;
8652 	case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
8653 		msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
8654 		break;
8655 	case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
8656 		msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
8657 		break;
8658 	default:
8659 		return -1;
8660 	}
8661 	if (!ctx->object)
8662 		return len;
8663 	arg = pop_args(ctx);
8664 	if (!arg)
8665 		return -1;
8666 	ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
8667 	ecpri->hdr.common.type = msg_type;
8668 	data_size = ctx->objdata / 3; /* spec, last, mask */
8669 	ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
8670 						    (data_size * 2));
8671 	ecpri_mask->hdr.common.type = 0xFF;
8672 	if (arg->hton) {
8673 		ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
8674 		ecpri_mask->hdr.common.u32 =
8675 				rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
8676 	}
8677 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8678 	item->spec = ecpri;
8679 	item->mask = ecpri_mask;
8680 	return len;
8681 }
8682 
8683 /** Parse L2TPv2 common header type field. */
8684 static int
8685 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
8686 			 const char *str, unsigned int len,
8687 			 void *buf, unsigned int size)
8688 {
8689 	struct rte_flow_item_l2tpv2 *l2tpv2;
8690 	struct rte_flow_item_l2tpv2 *l2tpv2_mask;
8691 	struct rte_flow_item *item;
8692 	uint32_t data_size;
8693 	uint16_t msg_type = 0;
8694 	struct buffer *out = buf;
8695 	const struct arg *arg;
8696 
8697 	(void)size;
8698 	/* Token name must match. */
8699 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8700 		return -1;
8701 	switch (ctx->curr) {
8702 	case ITEM_L2TPV2_TYPE_DATA:
8703 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
8704 		break;
8705 	case ITEM_L2TPV2_TYPE_DATA_L:
8706 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
8707 		break;
8708 	case ITEM_L2TPV2_TYPE_DATA_S:
8709 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
8710 		break;
8711 	case ITEM_L2TPV2_TYPE_DATA_O:
8712 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
8713 		break;
8714 	case ITEM_L2TPV2_TYPE_DATA_L_S:
8715 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
8716 		break;
8717 	case ITEM_L2TPV2_TYPE_CTRL:
8718 		msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
8719 		break;
8720 	default:
8721 		return -1;
8722 	}
8723 	if (!ctx->object)
8724 		return len;
8725 	arg = pop_args(ctx);
8726 	if (!arg)
8727 		return -1;
8728 	l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
8729 	l2tpv2->hdr.common.flags_version |= msg_type;
8730 	data_size = ctx->objdata / 3; /* spec, last, mask */
8731 	l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
8732 						    (data_size * 2));
8733 	l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
8734 	if (arg->hton) {
8735 		l2tpv2->hdr.common.flags_version =
8736 			rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
8737 		l2tpv2_mask->hdr.common.flags_version =
8738 		    rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
8739 	}
8740 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8741 	item->spec = l2tpv2;
8742 	item->mask = l2tpv2_mask;
8743 	return len;
8744 }
8745 
8746 /** Parse operation for compare match item. */
8747 static int
8748 parse_vc_compare_op(struct context *ctx, const struct token *token,
8749 			 const char *str, unsigned int len, void *buf,
8750 			 unsigned int size)
8751 {
8752 	struct rte_flow_item_compare *compare_item;
8753 	unsigned int i;
8754 
8755 	(void)token;
8756 	(void)buf;
8757 	(void)size;
8758 	if (ctx->curr != ITEM_COMPARE_OP_VALUE)
8759 		return -1;
8760 	for (i = 0; compare_ops[i]; ++i)
8761 		if (!strcmp_partial(compare_ops[i], str, len))
8762 			break;
8763 	if (!compare_ops[i])
8764 		return -1;
8765 	if (!ctx->object)
8766 		return len;
8767 	compare_item = ctx->object;
8768 	compare_item->operation = (enum rte_flow_item_compare_op)i;
8769 	return len;
8770 }
8771 
8772 /** Parse id for compare match item. */
8773 static int
8774 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
8775 			  const char *str, unsigned int len, void *buf,
8776 			  unsigned int size)
8777 {
8778 	struct rte_flow_item_compare *compare_item;
8779 	unsigned int i;
8780 
8781 	(void)token;
8782 	(void)buf;
8783 	(void)size;
8784 	if (ctx->curr != ITEM_COMPARE_FIELD_A_TYPE_VALUE &&
8785 		ctx->curr != ITEM_COMPARE_FIELD_B_TYPE_VALUE)
8786 		return -1;
8787 	for (i = 0; flow_field_ids[i]; ++i)
8788 		if (!strcmp_partial(flow_field_ids[i], str, len))
8789 			break;
8790 	if (!flow_field_ids[i])
8791 		return -1;
8792 	if (!ctx->object)
8793 		return len;
8794 	compare_item = ctx->object;
8795 	if (ctx->curr == ITEM_COMPARE_FIELD_A_TYPE_VALUE)
8796 		compare_item->a.field = (enum rte_flow_field_id)i;
8797 	else
8798 		compare_item->b.field = (enum rte_flow_field_id)i;
8799 	return len;
8800 }
8801 
8802 /** Parse level for compare match item. */
8803 static int
8804 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
8805 			     const char *str, unsigned int len, void *buf,
8806 			     unsigned int size)
8807 {
8808 	struct rte_flow_item_compare *compare_item;
8809 	struct flex_item *fp = NULL;
8810 	uint32_t val;
8811 	struct buffer *out = buf;
8812 	char *end;
8813 
8814 	(void)token;
8815 	(void)size;
8816 	if (ctx->curr != ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
8817 		ctx->curr != ITEM_COMPARE_FIELD_B_LEVEL_VALUE)
8818 		return -1;
8819 	if (!ctx->object)
8820 		return len;
8821 	compare_item = ctx->object;
8822 	errno = 0;
8823 	val = strtoumax(str, &end, 0);
8824 	if (errno || (size_t)(end - str) != len)
8825 		return -1;
8826 	/* No need to validate action template mask value */
8827 	if (out->args.vc.masks) {
8828 		if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE)
8829 			compare_item->a.level = val;
8830 		else
8831 			compare_item->b.level = val;
8832 		return len;
8833 	}
8834 	if ((ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
8835 		compare_item->a.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
8836 		(ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE &&
8837 		compare_item->b.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
8838 		if (val >= FLEX_MAX_PARSERS_NUM) {
8839 			printf("Bad flex item handle\n");
8840 			return -1;
8841 		}
8842 		fp = flex_items[ctx->port][val];
8843 		if (!fp) {
8844 			printf("Bad flex item handle\n");
8845 			return -1;
8846 		}
8847 	}
8848 	if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE) {
8849 		if (compare_item->a.field != RTE_FLOW_FIELD_FLEX_ITEM)
8850 			compare_item->a.level = val;
8851 		else
8852 			compare_item->a.flex_handle = fp->flex_handle;
8853 	} else if (ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE) {
8854 		if (compare_item->b.field != RTE_FLOW_FIELD_FLEX_ITEM)
8855 			compare_item->b.level = val;
8856 		else
8857 			compare_item->b.flex_handle = fp->flex_handle;
8858 	}
8859 	return len;
8860 }
8861 
8862 /** Parse meter color action type. */
8863 static int
8864 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
8865 				const char *str, unsigned int len,
8866 				void *buf, unsigned int size)
8867 {
8868 	struct rte_flow_action *action_data;
8869 	struct rte_flow_action_meter_color *conf;
8870 	enum rte_color color;
8871 
8872 	(void)buf;
8873 	(void)size;
8874 	/* Token name must match. */
8875 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8876 		return -1;
8877 	switch (ctx->curr) {
8878 	case ACTION_METER_COLOR_GREEN:
8879 		color = RTE_COLOR_GREEN;
8880 	break;
8881 	case ACTION_METER_COLOR_YELLOW:
8882 		color = RTE_COLOR_YELLOW;
8883 	break;
8884 	case ACTION_METER_COLOR_RED:
8885 		color = RTE_COLOR_RED;
8886 	break;
8887 	default:
8888 		return -1;
8889 	}
8890 
8891 	if (!ctx->object)
8892 		return len;
8893 	action_data = ctx->object;
8894 	conf = (struct rte_flow_action_meter_color *)
8895 					(uintptr_t)(action_data->conf);
8896 	conf->color = color;
8897 	return len;
8898 }
8899 
8900 /** Parse RSS action. */
8901 static int
8902 parse_vc_action_rss(struct context *ctx, const struct token *token,
8903 		    const char *str, unsigned int len,
8904 		    void *buf, unsigned int size)
8905 {
8906 	struct buffer *out = buf;
8907 	struct rte_flow_action *action;
8908 	struct action_rss_data *action_rss_data;
8909 	unsigned int i;
8910 	int ret;
8911 
8912 	ret = parse_vc(ctx, token, str, len, buf, size);
8913 	if (ret < 0)
8914 		return ret;
8915 	/* Nothing else to do if there is no buffer. */
8916 	if (!out)
8917 		return ret;
8918 	if (!out->args.vc.actions_n)
8919 		return -1;
8920 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8921 	/* Point to selected object. */
8922 	ctx->object = out->args.vc.data;
8923 	ctx->objmask = NULL;
8924 	/* Set up default configuration. */
8925 	action_rss_data = ctx->object;
8926 	*action_rss_data = (struct action_rss_data){
8927 		.conf = (struct rte_flow_action_rss){
8928 			.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
8929 			.level = 0,
8930 			.types = rss_hf,
8931 			.key_len = 0,
8932 			.queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
8933 			.key = NULL,
8934 			.queue = action_rss_data->queue,
8935 		},
8936 		.queue = { 0 },
8937 	};
8938 	for (i = 0; i < action_rss_data->conf.queue_num; ++i)
8939 		action_rss_data->queue[i] = i;
8940 	action->conf = &action_rss_data->conf;
8941 	return ret;
8942 }
8943 
8944 /**
8945  * Parse func field for RSS action.
8946  *
8947  * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
8948  * ACTION_RSS_FUNC_* index that called this function.
8949  */
8950 static int
8951 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
8952 			 const char *str, unsigned int len,
8953 			 void *buf, unsigned int size)
8954 {
8955 	struct action_rss_data *action_rss_data;
8956 	enum rte_eth_hash_function func;
8957 
8958 	(void)buf;
8959 	(void)size;
8960 	/* Token name must match. */
8961 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8962 		return -1;
8963 	switch (ctx->curr) {
8964 	case ACTION_RSS_FUNC_DEFAULT:
8965 		func = RTE_ETH_HASH_FUNCTION_DEFAULT;
8966 		break;
8967 	case ACTION_RSS_FUNC_TOEPLITZ:
8968 		func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
8969 		break;
8970 	case ACTION_RSS_FUNC_SIMPLE_XOR:
8971 		func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
8972 		break;
8973 	case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
8974 		func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
8975 		break;
8976 	default:
8977 		return -1;
8978 	}
8979 	if (!ctx->object)
8980 		return len;
8981 	action_rss_data = ctx->object;
8982 	action_rss_data->conf.func = func;
8983 	return len;
8984 }
8985 
8986 /**
8987  * Parse type field for RSS action.
8988  *
8989  * Valid tokens are type field names and the "end" token.
8990  */
8991 static int
8992 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
8993 			  const char *str, unsigned int len,
8994 			  void *buf, unsigned int size)
8995 {
8996 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
8997 	struct action_rss_data *action_rss_data;
8998 	unsigned int i;
8999 
9000 	(void)token;
9001 	(void)buf;
9002 	(void)size;
9003 	if (ctx->curr != ACTION_RSS_TYPE)
9004 		return -1;
9005 	if (!(ctx->objdata >> 16) && ctx->object) {
9006 		action_rss_data = ctx->object;
9007 		action_rss_data->conf.types = 0;
9008 	}
9009 	if (!strcmp_partial("end", str, len)) {
9010 		ctx->objdata &= 0xffff;
9011 		return len;
9012 	}
9013 	for (i = 0; rss_type_table[i].str; ++i)
9014 		if (!strcmp_partial(rss_type_table[i].str, str, len))
9015 			break;
9016 	if (!rss_type_table[i].str)
9017 		return -1;
9018 	ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
9019 	/* Repeat token. */
9020 	if (ctx->next_num == RTE_DIM(ctx->next))
9021 		return -1;
9022 	ctx->next[ctx->next_num++] = next;
9023 	if (!ctx->object)
9024 		return len;
9025 	action_rss_data = ctx->object;
9026 	action_rss_data->conf.types |= rss_type_table[i].rss_type;
9027 	return len;
9028 }
9029 
9030 /**
9031  * Parse queue field for RSS action.
9032  *
9033  * Valid tokens are queue indices and the "end" token.
9034  */
9035 static int
9036 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
9037 			  const char *str, unsigned int len,
9038 			  void *buf, unsigned int size)
9039 {
9040 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
9041 	struct action_rss_data *action_rss_data;
9042 	const struct arg *arg;
9043 	int ret;
9044 	int i;
9045 
9046 	(void)token;
9047 	(void)buf;
9048 	(void)size;
9049 	if (ctx->curr != ACTION_RSS_QUEUE)
9050 		return -1;
9051 	i = ctx->objdata >> 16;
9052 	if (!strcmp_partial("end", str, len)) {
9053 		ctx->objdata &= 0xffff;
9054 		goto end;
9055 	}
9056 	if (i >= ACTION_RSS_QUEUE_NUM)
9057 		return -1;
9058 	arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
9059 			     i * sizeof(action_rss_data->queue[i]),
9060 			     sizeof(action_rss_data->queue[i]));
9061 	if (push_args(ctx, arg))
9062 		return -1;
9063 	ret = parse_int(ctx, token, str, len, NULL, 0);
9064 	if (ret < 0) {
9065 		pop_args(ctx);
9066 		return -1;
9067 	}
9068 	++i;
9069 	ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
9070 	/* Repeat token. */
9071 	if (ctx->next_num == RTE_DIM(ctx->next))
9072 		return -1;
9073 	ctx->next[ctx->next_num++] = next;
9074 end:
9075 	if (!ctx->object)
9076 		return len;
9077 	action_rss_data = ctx->object;
9078 	action_rss_data->conf.queue_num = i;
9079 	action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
9080 	return len;
9081 }
9082 
9083 /** Setup VXLAN encap configuration. */
9084 static int
9085 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
9086 {
9087 	/* Set up default configuration. */
9088 	*action_vxlan_encap_data = (struct action_vxlan_encap_data){
9089 		.conf = (struct rte_flow_action_vxlan_encap){
9090 			.definition = action_vxlan_encap_data->items,
9091 		},
9092 		.items = {
9093 			{
9094 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9095 				.spec = &action_vxlan_encap_data->item_eth,
9096 				.mask = &rte_flow_item_eth_mask,
9097 			},
9098 			{
9099 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9100 				.spec = &action_vxlan_encap_data->item_vlan,
9101 				.mask = &rte_flow_item_vlan_mask,
9102 			},
9103 			{
9104 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9105 				.spec = &action_vxlan_encap_data->item_ipv4,
9106 				.mask = &rte_flow_item_ipv4_mask,
9107 			},
9108 			{
9109 				.type = RTE_FLOW_ITEM_TYPE_UDP,
9110 				.spec = &action_vxlan_encap_data->item_udp,
9111 				.mask = &rte_flow_item_udp_mask,
9112 			},
9113 			{
9114 				.type = RTE_FLOW_ITEM_TYPE_VXLAN,
9115 				.spec = &action_vxlan_encap_data->item_vxlan,
9116 				.mask = &rte_flow_item_vxlan_mask,
9117 			},
9118 			{
9119 				.type = RTE_FLOW_ITEM_TYPE_END,
9120 			},
9121 		},
9122 		.item_eth.hdr.ether_type = 0,
9123 		.item_vlan = {
9124 			.hdr.vlan_tci = vxlan_encap_conf.vlan_tci,
9125 			.hdr.eth_proto = 0,
9126 		},
9127 		.item_ipv4.hdr = {
9128 			.src_addr = vxlan_encap_conf.ipv4_src,
9129 			.dst_addr = vxlan_encap_conf.ipv4_dst,
9130 		},
9131 		.item_udp.hdr = {
9132 			.src_port = vxlan_encap_conf.udp_src,
9133 			.dst_port = vxlan_encap_conf.udp_dst,
9134 		},
9135 		.item_vxlan.hdr.flags = 0,
9136 	};
9137 	memcpy(action_vxlan_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9138 	       vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9139 	memcpy(action_vxlan_encap_data->item_eth.hdr.src_addr.addr_bytes,
9140 	       vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9141 	if (!vxlan_encap_conf.select_ipv4) {
9142 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
9143 		       &vxlan_encap_conf.ipv6_src,
9144 		       sizeof(vxlan_encap_conf.ipv6_src));
9145 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
9146 		       &vxlan_encap_conf.ipv6_dst,
9147 		       sizeof(vxlan_encap_conf.ipv6_dst));
9148 		action_vxlan_encap_data->items[2] = (struct rte_flow_item){
9149 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9150 			.spec = &action_vxlan_encap_data->item_ipv6,
9151 			.mask = &rte_flow_item_ipv6_mask,
9152 		};
9153 	}
9154 	if (!vxlan_encap_conf.select_vlan)
9155 		action_vxlan_encap_data->items[1].type =
9156 			RTE_FLOW_ITEM_TYPE_VOID;
9157 	if (vxlan_encap_conf.select_tos_ttl) {
9158 		if (vxlan_encap_conf.select_ipv4) {
9159 			static struct rte_flow_item_ipv4 ipv4_mask_tos;
9160 
9161 			memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
9162 			       sizeof(ipv4_mask_tos));
9163 			ipv4_mask_tos.hdr.type_of_service = 0xff;
9164 			ipv4_mask_tos.hdr.time_to_live = 0xff;
9165 			action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
9166 					vxlan_encap_conf.ip_tos;
9167 			action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
9168 					vxlan_encap_conf.ip_ttl;
9169 			action_vxlan_encap_data->items[2].mask =
9170 							&ipv4_mask_tos;
9171 		} else {
9172 			static struct rte_flow_item_ipv6 ipv6_mask_tos;
9173 
9174 			memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
9175 			       sizeof(ipv6_mask_tos));
9176 			ipv6_mask_tos.hdr.vtc_flow |=
9177 				RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
9178 			ipv6_mask_tos.hdr.hop_limits = 0xff;
9179 			action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
9180 				rte_cpu_to_be_32
9181 					((uint32_t)vxlan_encap_conf.ip_tos <<
9182 					 RTE_IPV6_HDR_TC_SHIFT);
9183 			action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
9184 					vxlan_encap_conf.ip_ttl;
9185 			action_vxlan_encap_data->items[2].mask =
9186 							&ipv6_mask_tos;
9187 		}
9188 	}
9189 	memcpy(action_vxlan_encap_data->item_vxlan.hdr.vni, vxlan_encap_conf.vni,
9190 	       RTE_DIM(vxlan_encap_conf.vni));
9191 	return 0;
9192 }
9193 
9194 /** Parse VXLAN encap action. */
9195 static int
9196 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
9197 			    const char *str, unsigned int len,
9198 			    void *buf, unsigned int size)
9199 {
9200 	struct buffer *out = buf;
9201 	struct rte_flow_action *action;
9202 	struct action_vxlan_encap_data *action_vxlan_encap_data;
9203 	int ret;
9204 
9205 	ret = parse_vc(ctx, token, str, len, buf, size);
9206 	if (ret < 0)
9207 		return ret;
9208 	/* Nothing else to do if there is no buffer. */
9209 	if (!out)
9210 		return ret;
9211 	if (!out->args.vc.actions_n)
9212 		return -1;
9213 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9214 	/* Point to selected object. */
9215 	ctx->object = out->args.vc.data;
9216 	ctx->objmask = NULL;
9217 	action_vxlan_encap_data = ctx->object;
9218 	parse_setup_vxlan_encap_data(action_vxlan_encap_data);
9219 	action->conf = &action_vxlan_encap_data->conf;
9220 	return ret;
9221 }
9222 
9223 /** Setup NVGRE encap configuration. */
9224 static int
9225 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
9226 {
9227 	/* Set up default configuration. */
9228 	*action_nvgre_encap_data = (struct action_nvgre_encap_data){
9229 		.conf = (struct rte_flow_action_nvgre_encap){
9230 			.definition = action_nvgre_encap_data->items,
9231 		},
9232 		.items = {
9233 			{
9234 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9235 				.spec = &action_nvgre_encap_data->item_eth,
9236 				.mask = &rte_flow_item_eth_mask,
9237 			},
9238 			{
9239 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9240 				.spec = &action_nvgre_encap_data->item_vlan,
9241 				.mask = &rte_flow_item_vlan_mask,
9242 			},
9243 			{
9244 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9245 				.spec = &action_nvgre_encap_data->item_ipv4,
9246 				.mask = &rte_flow_item_ipv4_mask,
9247 			},
9248 			{
9249 				.type = RTE_FLOW_ITEM_TYPE_NVGRE,
9250 				.spec = &action_nvgre_encap_data->item_nvgre,
9251 				.mask = &rte_flow_item_nvgre_mask,
9252 			},
9253 			{
9254 				.type = RTE_FLOW_ITEM_TYPE_END,
9255 			},
9256 		},
9257 		.item_eth.hdr.ether_type = 0,
9258 		.item_vlan = {
9259 			.hdr.vlan_tci = nvgre_encap_conf.vlan_tci,
9260 			.hdr.eth_proto = 0,
9261 		},
9262 		.item_ipv4.hdr = {
9263 		       .src_addr = nvgre_encap_conf.ipv4_src,
9264 		       .dst_addr = nvgre_encap_conf.ipv4_dst,
9265 		},
9266 		.item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
9267 		.item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
9268 		.item_nvgre.flow_id = 0,
9269 	};
9270 	memcpy(action_nvgre_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9271 	       nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9272 	memcpy(action_nvgre_encap_data->item_eth.hdr.src_addr.addr_bytes,
9273 	       nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9274 	if (!nvgre_encap_conf.select_ipv4) {
9275 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
9276 		       &nvgre_encap_conf.ipv6_src,
9277 		       sizeof(nvgre_encap_conf.ipv6_src));
9278 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
9279 		       &nvgre_encap_conf.ipv6_dst,
9280 		       sizeof(nvgre_encap_conf.ipv6_dst));
9281 		action_nvgre_encap_data->items[2] = (struct rte_flow_item){
9282 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9283 			.spec = &action_nvgre_encap_data->item_ipv6,
9284 			.mask = &rte_flow_item_ipv6_mask,
9285 		};
9286 	}
9287 	if (!nvgre_encap_conf.select_vlan)
9288 		action_nvgre_encap_data->items[1].type =
9289 			RTE_FLOW_ITEM_TYPE_VOID;
9290 	memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
9291 	       RTE_DIM(nvgre_encap_conf.tni));
9292 	return 0;
9293 }
9294 
9295 /** Parse NVGRE encap action. */
9296 static int
9297 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
9298 			    const char *str, unsigned int len,
9299 			    void *buf, unsigned int size)
9300 {
9301 	struct buffer *out = buf;
9302 	struct rte_flow_action *action;
9303 	struct action_nvgre_encap_data *action_nvgre_encap_data;
9304 	int ret;
9305 
9306 	ret = parse_vc(ctx, token, str, len, buf, size);
9307 	if (ret < 0)
9308 		return ret;
9309 	/* Nothing else to do if there is no buffer. */
9310 	if (!out)
9311 		return ret;
9312 	if (!out->args.vc.actions_n)
9313 		return -1;
9314 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9315 	/* Point to selected object. */
9316 	ctx->object = out->args.vc.data;
9317 	ctx->objmask = NULL;
9318 	action_nvgre_encap_data = ctx->object;
9319 	parse_setup_nvgre_encap_data(action_nvgre_encap_data);
9320 	action->conf = &action_nvgre_encap_data->conf;
9321 	return ret;
9322 }
9323 
9324 /** Parse l2 encap action. */
9325 static int
9326 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
9327 			 const char *str, unsigned int len,
9328 			 void *buf, unsigned int size)
9329 {
9330 	struct buffer *out = buf;
9331 	struct rte_flow_action *action;
9332 	struct action_raw_encap_data *action_encap_data;
9333 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9334 	struct rte_flow_item_vlan vlan = {
9335 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9336 		.hdr.eth_proto = 0,
9337 	};
9338 	uint8_t *header;
9339 	int ret;
9340 
9341 	ret = parse_vc(ctx, token, str, len, buf, size);
9342 	if (ret < 0)
9343 		return ret;
9344 	/* Nothing else to do if there is no buffer. */
9345 	if (!out)
9346 		return ret;
9347 	if (!out->args.vc.actions_n)
9348 		return -1;
9349 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9350 	/* Point to selected object. */
9351 	ctx->object = out->args.vc.data;
9352 	ctx->objmask = NULL;
9353 	/* Copy the headers to the buffer. */
9354 	action_encap_data = ctx->object;
9355 	*action_encap_data = (struct action_raw_encap_data) {
9356 		.conf = (struct rte_flow_action_raw_encap){
9357 			.data = action_encap_data->data,
9358 		},
9359 		.data = {},
9360 	};
9361 	header = action_encap_data->data;
9362 	if (l2_encap_conf.select_vlan)
9363 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9364 	else if (l2_encap_conf.select_ipv4)
9365 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9366 	else
9367 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9368 	memcpy(eth.hdr.dst_addr.addr_bytes,
9369 	       l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9370 	memcpy(eth.hdr.src_addr.addr_bytes,
9371 	       l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9372 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9373 	header += sizeof(struct rte_ether_hdr);
9374 	if (l2_encap_conf.select_vlan) {
9375 		if (l2_encap_conf.select_ipv4)
9376 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9377 		else
9378 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9379 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9380 		header += sizeof(struct rte_vlan_hdr);
9381 	}
9382 	action_encap_data->conf.size = header -
9383 		action_encap_data->data;
9384 	action->conf = &action_encap_data->conf;
9385 	return ret;
9386 }
9387 
9388 /** Parse l2 decap action. */
9389 static int
9390 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
9391 			 const char *str, unsigned int len,
9392 			 void *buf, unsigned int size)
9393 {
9394 	struct buffer *out = buf;
9395 	struct rte_flow_action *action;
9396 	struct action_raw_decap_data *action_decap_data;
9397 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9398 	struct rte_flow_item_vlan vlan = {
9399 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9400 		.hdr.eth_proto = 0,
9401 	};
9402 	uint8_t *header;
9403 	int ret;
9404 
9405 	ret = parse_vc(ctx, token, str, len, buf, size);
9406 	if (ret < 0)
9407 		return ret;
9408 	/* Nothing else to do if there is no buffer. */
9409 	if (!out)
9410 		return ret;
9411 	if (!out->args.vc.actions_n)
9412 		return -1;
9413 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9414 	/* Point to selected object. */
9415 	ctx->object = out->args.vc.data;
9416 	ctx->objmask = NULL;
9417 	/* Copy the headers to the buffer. */
9418 	action_decap_data = ctx->object;
9419 	*action_decap_data = (struct action_raw_decap_data) {
9420 		.conf = (struct rte_flow_action_raw_decap){
9421 			.data = action_decap_data->data,
9422 		},
9423 		.data = {},
9424 	};
9425 	header = action_decap_data->data;
9426 	if (l2_decap_conf.select_vlan)
9427 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9428 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9429 	header += sizeof(struct rte_ether_hdr);
9430 	if (l2_decap_conf.select_vlan) {
9431 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9432 		header += sizeof(struct rte_vlan_hdr);
9433 	}
9434 	action_decap_data->conf.size = header -
9435 		action_decap_data->data;
9436 	action->conf = &action_decap_data->conf;
9437 	return ret;
9438 }
9439 
9440 #define ETHER_TYPE_MPLS_UNICAST 0x8847
9441 
9442 /** Parse MPLSOGRE encap action. */
9443 static int
9444 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
9445 			       const char *str, unsigned int len,
9446 			       void *buf, unsigned int size)
9447 {
9448 	struct buffer *out = buf;
9449 	struct rte_flow_action *action;
9450 	struct action_raw_encap_data *action_encap_data;
9451 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9452 	struct rte_flow_item_vlan vlan = {
9453 		.hdr.vlan_tci = mplsogre_encap_conf.vlan_tci,
9454 		.hdr.eth_proto = 0,
9455 	};
9456 	struct rte_flow_item_ipv4 ipv4 = {
9457 		.hdr =  {
9458 			.src_addr = mplsogre_encap_conf.ipv4_src,
9459 			.dst_addr = mplsogre_encap_conf.ipv4_dst,
9460 			.next_proto_id = IPPROTO_GRE,
9461 			.version_ihl = RTE_IPV4_VHL_DEF,
9462 			.time_to_live = IPDEFTTL,
9463 		},
9464 	};
9465 	struct rte_flow_item_ipv6 ipv6 = {
9466 		.hdr =  {
9467 			.proto = IPPROTO_GRE,
9468 			.hop_limits = IPDEFTTL,
9469 		},
9470 	};
9471 	struct rte_flow_item_gre gre = {
9472 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9473 	};
9474 	struct rte_flow_item_mpls mpls = {
9475 		.ttl = 0,
9476 	};
9477 	uint8_t *header;
9478 	int ret;
9479 
9480 	ret = parse_vc(ctx, token, str, len, buf, size);
9481 	if (ret < 0)
9482 		return ret;
9483 	/* Nothing else to do if there is no buffer. */
9484 	if (!out)
9485 		return ret;
9486 	if (!out->args.vc.actions_n)
9487 		return -1;
9488 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9489 	/* Point to selected object. */
9490 	ctx->object = out->args.vc.data;
9491 	ctx->objmask = NULL;
9492 	/* Copy the headers to the buffer. */
9493 	action_encap_data = ctx->object;
9494 	*action_encap_data = (struct action_raw_encap_data) {
9495 		.conf = (struct rte_flow_action_raw_encap){
9496 			.data = action_encap_data->data,
9497 		},
9498 		.data = {},
9499 		.preserve = {},
9500 	};
9501 	header = action_encap_data->data;
9502 	if (mplsogre_encap_conf.select_vlan)
9503 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9504 	else if (mplsogre_encap_conf.select_ipv4)
9505 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9506 	else
9507 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9508 	memcpy(eth.hdr.dst_addr.addr_bytes,
9509 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9510 	memcpy(eth.hdr.src_addr.addr_bytes,
9511 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9512 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9513 	header += sizeof(struct rte_ether_hdr);
9514 	if (mplsogre_encap_conf.select_vlan) {
9515 		if (mplsogre_encap_conf.select_ipv4)
9516 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9517 		else
9518 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9519 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9520 		header += sizeof(struct rte_vlan_hdr);
9521 	}
9522 	if (mplsogre_encap_conf.select_ipv4) {
9523 		memcpy(header, &ipv4, sizeof(ipv4));
9524 		header += sizeof(ipv4);
9525 	} else {
9526 		memcpy(&ipv6.hdr.src_addr,
9527 		       &mplsogre_encap_conf.ipv6_src,
9528 		       sizeof(mplsogre_encap_conf.ipv6_src));
9529 		memcpy(&ipv6.hdr.dst_addr,
9530 		       &mplsogre_encap_conf.ipv6_dst,
9531 		       sizeof(mplsogre_encap_conf.ipv6_dst));
9532 		memcpy(header, &ipv6, sizeof(ipv6));
9533 		header += sizeof(ipv6);
9534 	}
9535 	memcpy(header, &gre, sizeof(gre));
9536 	header += sizeof(gre);
9537 	memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
9538 	       RTE_DIM(mplsogre_encap_conf.label));
9539 	mpls.label_tc_s[2] |= 0x1;
9540 	memcpy(header, &mpls, sizeof(mpls));
9541 	header += sizeof(mpls);
9542 	action_encap_data->conf.size = header -
9543 		action_encap_data->data;
9544 	action->conf = &action_encap_data->conf;
9545 	return ret;
9546 }
9547 
9548 /** Parse MPLSOGRE decap action. */
9549 static int
9550 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
9551 			       const char *str, unsigned int len,
9552 			       void *buf, unsigned int size)
9553 {
9554 	struct buffer *out = buf;
9555 	struct rte_flow_action *action;
9556 	struct action_raw_decap_data *action_decap_data;
9557 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9558 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
9559 	struct rte_flow_item_ipv4 ipv4 = {
9560 		.hdr =  {
9561 			.next_proto_id = IPPROTO_GRE,
9562 		},
9563 	};
9564 	struct rte_flow_item_ipv6 ipv6 = {
9565 		.hdr =  {
9566 			.proto = IPPROTO_GRE,
9567 		},
9568 	};
9569 	struct rte_flow_item_gre gre = {
9570 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9571 	};
9572 	struct rte_flow_item_mpls mpls;
9573 	uint8_t *header;
9574 	int ret;
9575 
9576 	ret = parse_vc(ctx, token, str, len, buf, size);
9577 	if (ret < 0)
9578 		return ret;
9579 	/* Nothing else to do if there is no buffer. */
9580 	if (!out)
9581 		return ret;
9582 	if (!out->args.vc.actions_n)
9583 		return -1;
9584 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9585 	/* Point to selected object. */
9586 	ctx->object = out->args.vc.data;
9587 	ctx->objmask = NULL;
9588 	/* Copy the headers to the buffer. */
9589 	action_decap_data = ctx->object;
9590 	*action_decap_data = (struct action_raw_decap_data) {
9591 		.conf = (struct rte_flow_action_raw_decap){
9592 			.data = action_decap_data->data,
9593 		},
9594 		.data = {},
9595 	};
9596 	header = action_decap_data->data;
9597 	if (mplsogre_decap_conf.select_vlan)
9598 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9599 	else if (mplsogre_encap_conf.select_ipv4)
9600 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9601 	else
9602 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9603 	memcpy(eth.hdr.dst_addr.addr_bytes,
9604 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9605 	memcpy(eth.hdr.src_addr.addr_bytes,
9606 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9607 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9608 	header += sizeof(struct rte_ether_hdr);
9609 	if (mplsogre_encap_conf.select_vlan) {
9610 		if (mplsogre_encap_conf.select_ipv4)
9611 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9612 		else
9613 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9614 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9615 		header += sizeof(struct rte_vlan_hdr);
9616 	}
9617 	if (mplsogre_encap_conf.select_ipv4) {
9618 		memcpy(header, &ipv4, sizeof(ipv4));
9619 		header += sizeof(ipv4);
9620 	} else {
9621 		memcpy(header, &ipv6, sizeof(ipv6));
9622 		header += sizeof(ipv6);
9623 	}
9624 	memcpy(header, &gre, sizeof(gre));
9625 	header += sizeof(gre);
9626 	memset(&mpls, 0, sizeof(mpls));
9627 	memcpy(header, &mpls, sizeof(mpls));
9628 	header += sizeof(mpls);
9629 	action_decap_data->conf.size = header -
9630 		action_decap_data->data;
9631 	action->conf = &action_decap_data->conf;
9632 	return ret;
9633 }
9634 
9635 /** Parse MPLSOUDP encap action. */
9636 static int
9637 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
9638 			       const char *str, unsigned int len,
9639 			       void *buf, unsigned int size)
9640 {
9641 	struct buffer *out = buf;
9642 	struct rte_flow_action *action;
9643 	struct action_raw_encap_data *action_encap_data;
9644 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9645 	struct rte_flow_item_vlan vlan = {
9646 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9647 		.hdr.eth_proto = 0,
9648 	};
9649 	struct rte_flow_item_ipv4 ipv4 = {
9650 		.hdr =  {
9651 			.src_addr = mplsoudp_encap_conf.ipv4_src,
9652 			.dst_addr = mplsoudp_encap_conf.ipv4_dst,
9653 			.next_proto_id = IPPROTO_UDP,
9654 			.version_ihl = RTE_IPV4_VHL_DEF,
9655 			.time_to_live = IPDEFTTL,
9656 		},
9657 	};
9658 	struct rte_flow_item_ipv6 ipv6 = {
9659 		.hdr =  {
9660 			.proto = IPPROTO_UDP,
9661 			.hop_limits = IPDEFTTL,
9662 		},
9663 	};
9664 	struct rte_flow_item_udp udp = {
9665 		.hdr = {
9666 			.src_port = mplsoudp_encap_conf.udp_src,
9667 			.dst_port = mplsoudp_encap_conf.udp_dst,
9668 		},
9669 	};
9670 	struct rte_flow_item_mpls mpls;
9671 	uint8_t *header;
9672 	int ret;
9673 
9674 	ret = parse_vc(ctx, token, str, len, buf, size);
9675 	if (ret < 0)
9676 		return ret;
9677 	/* Nothing else to do if there is no buffer. */
9678 	if (!out)
9679 		return ret;
9680 	if (!out->args.vc.actions_n)
9681 		return -1;
9682 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9683 	/* Point to selected object. */
9684 	ctx->object = out->args.vc.data;
9685 	ctx->objmask = NULL;
9686 	/* Copy the headers to the buffer. */
9687 	action_encap_data = ctx->object;
9688 	*action_encap_data = (struct action_raw_encap_data) {
9689 		.conf = (struct rte_flow_action_raw_encap){
9690 			.data = action_encap_data->data,
9691 		},
9692 		.data = {},
9693 		.preserve = {},
9694 	};
9695 	header = action_encap_data->data;
9696 	if (mplsoudp_encap_conf.select_vlan)
9697 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9698 	else if (mplsoudp_encap_conf.select_ipv4)
9699 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9700 	else
9701 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9702 	memcpy(eth.hdr.dst_addr.addr_bytes,
9703 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9704 	memcpy(eth.hdr.src_addr.addr_bytes,
9705 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9706 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9707 	header += sizeof(struct rte_ether_hdr);
9708 	if (mplsoudp_encap_conf.select_vlan) {
9709 		if (mplsoudp_encap_conf.select_ipv4)
9710 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9711 		else
9712 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9713 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9714 		header += sizeof(struct rte_vlan_hdr);
9715 	}
9716 	if (mplsoudp_encap_conf.select_ipv4) {
9717 		memcpy(header, &ipv4, sizeof(ipv4));
9718 		header += sizeof(ipv4);
9719 	} else {
9720 		memcpy(&ipv6.hdr.src_addr,
9721 		       &mplsoudp_encap_conf.ipv6_src,
9722 		       sizeof(mplsoudp_encap_conf.ipv6_src));
9723 		memcpy(&ipv6.hdr.dst_addr,
9724 		       &mplsoudp_encap_conf.ipv6_dst,
9725 		       sizeof(mplsoudp_encap_conf.ipv6_dst));
9726 		memcpy(header, &ipv6, sizeof(ipv6));
9727 		header += sizeof(ipv6);
9728 	}
9729 	memcpy(header, &udp, sizeof(udp));
9730 	header += sizeof(udp);
9731 	memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
9732 	       RTE_DIM(mplsoudp_encap_conf.label));
9733 	mpls.label_tc_s[2] |= 0x1;
9734 	memcpy(header, &mpls, sizeof(mpls));
9735 	header += sizeof(mpls);
9736 	action_encap_data->conf.size = header -
9737 		action_encap_data->data;
9738 	action->conf = &action_encap_data->conf;
9739 	return ret;
9740 }
9741 
9742 /** Parse MPLSOUDP decap action. */
9743 static int
9744 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
9745 			       const char *str, unsigned int len,
9746 			       void *buf, unsigned int size)
9747 {
9748 	struct buffer *out = buf;
9749 	struct rte_flow_action *action;
9750 	struct action_raw_decap_data *action_decap_data;
9751 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9752 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
9753 	struct rte_flow_item_ipv4 ipv4 = {
9754 		.hdr =  {
9755 			.next_proto_id = IPPROTO_UDP,
9756 		},
9757 	};
9758 	struct rte_flow_item_ipv6 ipv6 = {
9759 		.hdr =  {
9760 			.proto = IPPROTO_UDP,
9761 		},
9762 	};
9763 	struct rte_flow_item_udp udp = {
9764 		.hdr = {
9765 			.dst_port = rte_cpu_to_be_16(6635),
9766 		},
9767 	};
9768 	struct rte_flow_item_mpls mpls;
9769 	uint8_t *header;
9770 	int ret;
9771 
9772 	ret = parse_vc(ctx, token, str, len, buf, size);
9773 	if (ret < 0)
9774 		return ret;
9775 	/* Nothing else to do if there is no buffer. */
9776 	if (!out)
9777 		return ret;
9778 	if (!out->args.vc.actions_n)
9779 		return -1;
9780 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9781 	/* Point to selected object. */
9782 	ctx->object = out->args.vc.data;
9783 	ctx->objmask = NULL;
9784 	/* Copy the headers to the buffer. */
9785 	action_decap_data = ctx->object;
9786 	*action_decap_data = (struct action_raw_decap_data) {
9787 		.conf = (struct rte_flow_action_raw_decap){
9788 			.data = action_decap_data->data,
9789 		},
9790 		.data = {},
9791 	};
9792 	header = action_decap_data->data;
9793 	if (mplsoudp_decap_conf.select_vlan)
9794 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9795 	else if (mplsoudp_encap_conf.select_ipv4)
9796 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9797 	else
9798 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9799 	memcpy(eth.hdr.dst_addr.addr_bytes,
9800 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9801 	memcpy(eth.hdr.src_addr.addr_bytes,
9802 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9803 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9804 	header += sizeof(struct rte_ether_hdr);
9805 	if (mplsoudp_encap_conf.select_vlan) {
9806 		if (mplsoudp_encap_conf.select_ipv4)
9807 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9808 		else
9809 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9810 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9811 		header += sizeof(struct rte_vlan_hdr);
9812 	}
9813 	if (mplsoudp_encap_conf.select_ipv4) {
9814 		memcpy(header, &ipv4, sizeof(ipv4));
9815 		header += sizeof(ipv4);
9816 	} else {
9817 		memcpy(header, &ipv6, sizeof(ipv6));
9818 		header += sizeof(ipv6);
9819 	}
9820 	memcpy(header, &udp, sizeof(udp));
9821 	header += sizeof(udp);
9822 	memset(&mpls, 0, sizeof(mpls));
9823 	memcpy(header, &mpls, sizeof(mpls));
9824 	header += sizeof(mpls);
9825 	action_decap_data->conf.size = header -
9826 		action_decap_data->data;
9827 	action->conf = &action_decap_data->conf;
9828 	return ret;
9829 }
9830 
9831 static int
9832 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
9833 				const char *str, unsigned int len, void *buf,
9834 				unsigned int size)
9835 {
9836 	struct action_raw_decap_data *action_raw_decap_data;
9837 	struct rte_flow_action *action;
9838 	const struct arg *arg;
9839 	struct buffer *out = buf;
9840 	int ret;
9841 	uint16_t idx;
9842 
9843 	RTE_SET_USED(token);
9844 	RTE_SET_USED(buf);
9845 	RTE_SET_USED(size);
9846 	arg = ARGS_ENTRY_ARB_BOUNDED
9847 		(offsetof(struct action_raw_decap_data, idx),
9848 		 sizeof(((struct action_raw_decap_data *)0)->idx),
9849 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
9850 	if (push_args(ctx, arg))
9851 		return -1;
9852 	ret = parse_int(ctx, token, str, len, NULL, 0);
9853 	if (ret < 0) {
9854 		pop_args(ctx);
9855 		return -1;
9856 	}
9857 	if (!ctx->object)
9858 		return len;
9859 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9860 	action_raw_decap_data = ctx->object;
9861 	idx = action_raw_decap_data->idx;
9862 	action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
9863 	action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
9864 	action->conf = &action_raw_decap_data->conf;
9865 	return len;
9866 }
9867 
9868 
9869 static int
9870 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
9871 				const char *str, unsigned int len, void *buf,
9872 				unsigned int size)
9873 {
9874 	struct action_raw_encap_data *action_raw_encap_data;
9875 	struct rte_flow_action *action;
9876 	const struct arg *arg;
9877 	struct buffer *out = buf;
9878 	int ret;
9879 	uint16_t idx;
9880 
9881 	RTE_SET_USED(token);
9882 	RTE_SET_USED(buf);
9883 	RTE_SET_USED(size);
9884 	if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
9885 		return -1;
9886 	arg = ARGS_ENTRY_ARB_BOUNDED
9887 		(offsetof(struct action_raw_encap_data, idx),
9888 		 sizeof(((struct action_raw_encap_data *)0)->idx),
9889 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
9890 	if (push_args(ctx, arg))
9891 		return -1;
9892 	ret = parse_int(ctx, token, str, len, NULL, 0);
9893 	if (ret < 0) {
9894 		pop_args(ctx);
9895 		return -1;
9896 	}
9897 	if (!ctx->object)
9898 		return len;
9899 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9900 	action_raw_encap_data = ctx->object;
9901 	idx = action_raw_encap_data->idx;
9902 	action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
9903 	action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
9904 	action_raw_encap_data->conf.preserve = NULL;
9905 	action->conf = &action_raw_encap_data->conf;
9906 	return len;
9907 }
9908 
9909 static int
9910 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
9911 			  const char *str, unsigned int len, void *buf,
9912 			  unsigned int size)
9913 {
9914 	struct buffer *out = buf;
9915 	int ret;
9916 
9917 	ret = parse_vc(ctx, token, str, len, buf, size);
9918 	if (ret < 0)
9919 		return ret;
9920 	/* Nothing else to do if there is no buffer. */
9921 	if (!out)
9922 		return ret;
9923 	if (!out->args.vc.actions_n)
9924 		return -1;
9925 	/* Point to selected object. */
9926 	ctx->object = out->args.vc.data;
9927 	ctx->objmask = NULL;
9928 	return ret;
9929 }
9930 
9931 static int
9932 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
9933 			  const char *str, unsigned int len, void *buf,
9934 			  unsigned int size)
9935 {
9936 	struct buffer *out = buf;
9937 	struct rte_flow_action *action;
9938 	struct action_raw_decap_data *action_raw_decap_data = NULL;
9939 	int ret;
9940 
9941 	ret = parse_vc(ctx, token, str, len, buf, size);
9942 	if (ret < 0)
9943 		return ret;
9944 	/* Nothing else to do if there is no buffer. */
9945 	if (!out)
9946 		return ret;
9947 	if (!out->args.vc.actions_n)
9948 		return -1;
9949 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9950 	/* Point to selected object. */
9951 	ctx->object = out->args.vc.data;
9952 	ctx->objmask = NULL;
9953 	/* Copy the headers to the buffer. */
9954 	action_raw_decap_data = ctx->object;
9955 	action_raw_decap_data->conf.data = raw_decap_confs[0].data;
9956 	action_raw_decap_data->conf.size = raw_decap_confs[0].size;
9957 	action->conf = &action_raw_decap_data->conf;
9958 	return ret;
9959 }
9960 
9961 static int
9962 parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
9963 				const char *str, unsigned int len, void *buf,
9964 				unsigned int size)
9965 {
9966 	struct buffer *out = buf;
9967 	struct rte_flow_action *action;
9968 	struct action_ipv6_ext_remove_data *ipv6_ext_remove_data = NULL;
9969 	int ret;
9970 
9971 	ret = parse_vc(ctx, token, str, len, buf, size);
9972 	if (ret < 0)
9973 		return ret;
9974 	/* Nothing else to do if there is no buffer. */
9975 	if (!out)
9976 		return ret;
9977 	if (!out->args.vc.actions_n)
9978 		return -1;
9979 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9980 	/* Point to selected object. */
9981 	ctx->object = out->args.vc.data;
9982 	ctx->objmask = NULL;
9983 	/* Copy the headers to the buffer. */
9984 	ipv6_ext_remove_data = ctx->object;
9985 	ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[0].type;
9986 	action->conf = &ipv6_ext_remove_data->conf;
9987 	return ret;
9988 }
9989 
9990 static int
9991 parse_vc_action_ipv6_ext_remove_index(struct context *ctx, const struct token *token,
9992 				      const char *str, unsigned int len, void *buf,
9993 				      unsigned int size)
9994 {
9995 	struct action_ipv6_ext_remove_data *action_ipv6_ext_remove_data;
9996 	struct rte_flow_action *action;
9997 	const struct arg *arg;
9998 	struct buffer *out = buf;
9999 	int ret;
10000 	uint16_t idx;
10001 
10002 	RTE_SET_USED(token);
10003 	RTE_SET_USED(buf);
10004 	RTE_SET_USED(size);
10005 	arg = ARGS_ENTRY_ARB_BOUNDED
10006 		(offsetof(struct action_ipv6_ext_remove_data, idx),
10007 		 sizeof(((struct action_ipv6_ext_remove_data *)0)->idx),
10008 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10009 	if (push_args(ctx, arg))
10010 		return -1;
10011 	ret = parse_int(ctx, token, str, len, NULL, 0);
10012 	if (ret < 0) {
10013 		pop_args(ctx);
10014 		return -1;
10015 	}
10016 	if (!ctx->object)
10017 		return len;
10018 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10019 	action_ipv6_ext_remove_data = ctx->object;
10020 	idx = action_ipv6_ext_remove_data->idx;
10021 	action_ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[idx].type;
10022 	action->conf = &action_ipv6_ext_remove_data->conf;
10023 	return len;
10024 }
10025 
10026 static int
10027 parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
10028 			      const char *str, unsigned int len, void *buf,
10029 			      unsigned int size)
10030 {
10031 	struct buffer *out = buf;
10032 	struct rte_flow_action *action;
10033 	struct action_ipv6_ext_push_data *ipv6_ext_push_data = NULL;
10034 	int ret;
10035 
10036 	ret = parse_vc(ctx, token, str, len, buf, size);
10037 	if (ret < 0)
10038 		return ret;
10039 	/* Nothing else to do if there is no buffer. */
10040 	if (!out)
10041 		return ret;
10042 	if (!out->args.vc.actions_n)
10043 		return -1;
10044 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10045 	/* Point to selected object. */
10046 	ctx->object = out->args.vc.data;
10047 	ctx->objmask = NULL;
10048 	/* Copy the headers to the buffer. */
10049 	ipv6_ext_push_data = ctx->object;
10050 	ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[0].type;
10051 	ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[0].data;
10052 	ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[0].size;
10053 	action->conf = &ipv6_ext_push_data->conf;
10054 	return ret;
10055 }
10056 
10057 static int
10058 parse_vc_action_ipv6_ext_push_index(struct context *ctx, const struct token *token,
10059 				    const char *str, unsigned int len, void *buf,
10060 				    unsigned int size)
10061 {
10062 	struct action_ipv6_ext_push_data *action_ipv6_ext_push_data;
10063 	struct rte_flow_action *action;
10064 	const struct arg *arg;
10065 	struct buffer *out = buf;
10066 	int ret;
10067 	uint16_t idx;
10068 
10069 	RTE_SET_USED(token);
10070 	RTE_SET_USED(buf);
10071 	RTE_SET_USED(size);
10072 	arg = ARGS_ENTRY_ARB_BOUNDED
10073 		(offsetof(struct action_ipv6_ext_push_data, idx),
10074 		 sizeof(((struct action_ipv6_ext_push_data *)0)->idx),
10075 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10076 	if (push_args(ctx, arg))
10077 		return -1;
10078 	ret = parse_int(ctx, token, str, len, NULL, 0);
10079 	if (ret < 0) {
10080 		pop_args(ctx);
10081 		return -1;
10082 	}
10083 	if (!ctx->object)
10084 		return len;
10085 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10086 	action_ipv6_ext_push_data = ctx->object;
10087 	idx = action_ipv6_ext_push_data->idx;
10088 	action_ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[idx].type;
10089 	action_ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[idx].size;
10090 	action_ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[idx].data;
10091 	action->conf = &action_ipv6_ext_push_data->conf;
10092 	return len;
10093 }
10094 
10095 static int
10096 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
10097 			 const char *str, unsigned int len, void *buf,
10098 			 unsigned int size)
10099 {
10100 	int ret;
10101 
10102 	ret = parse_vc(ctx, token, str, len, buf, size);
10103 	if (ret < 0)
10104 		return ret;
10105 	ret = rte_flow_dynf_metadata_register();
10106 	if (ret < 0)
10107 		return -1;
10108 	return len;
10109 }
10110 
10111 static int
10112 parse_vc_action_sample(struct context *ctx, const struct token *token,
10113 			 const char *str, unsigned int len, void *buf,
10114 			 unsigned int size)
10115 {
10116 	struct buffer *out = buf;
10117 	struct rte_flow_action *action;
10118 	struct action_sample_data *action_sample_data = NULL;
10119 	static struct rte_flow_action end_action = {
10120 		RTE_FLOW_ACTION_TYPE_END, 0
10121 	};
10122 	int ret;
10123 
10124 	ret = parse_vc(ctx, token, str, len, buf, size);
10125 	if (ret < 0)
10126 		return ret;
10127 	/* Nothing else to do if there is no buffer. */
10128 	if (!out)
10129 		return ret;
10130 	if (!out->args.vc.actions_n)
10131 		return -1;
10132 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10133 	/* Point to selected object. */
10134 	ctx->object = out->args.vc.data;
10135 	ctx->objmask = NULL;
10136 	/* Copy the headers to the buffer. */
10137 	action_sample_data = ctx->object;
10138 	action_sample_data->conf.actions = &end_action;
10139 	action->conf = &action_sample_data->conf;
10140 	return ret;
10141 }
10142 
10143 static int
10144 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
10145 				const char *str, unsigned int len, void *buf,
10146 				unsigned int size)
10147 {
10148 	struct action_sample_data *action_sample_data;
10149 	struct rte_flow_action *action;
10150 	const struct arg *arg;
10151 	struct buffer *out = buf;
10152 	int ret;
10153 	uint16_t idx;
10154 
10155 	RTE_SET_USED(token);
10156 	RTE_SET_USED(buf);
10157 	RTE_SET_USED(size);
10158 	if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
10159 		return -1;
10160 	arg = ARGS_ENTRY_ARB_BOUNDED
10161 		(offsetof(struct action_sample_data, idx),
10162 		 sizeof(((struct action_sample_data *)0)->idx),
10163 		 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
10164 	if (push_args(ctx, arg))
10165 		return -1;
10166 	ret = parse_int(ctx, token, str, len, NULL, 0);
10167 	if (ret < 0) {
10168 		pop_args(ctx);
10169 		return -1;
10170 	}
10171 	if (!ctx->object)
10172 		return len;
10173 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10174 	action_sample_data = ctx->object;
10175 	idx = action_sample_data->idx;
10176 	action_sample_data->conf.actions = raw_sample_confs[idx].data;
10177 	action->conf = &action_sample_data->conf;
10178 	return len;
10179 }
10180 
10181 /** Parse operation for modify_field command. */
10182 static int
10183 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
10184 			 const char *str, unsigned int len, void *buf,
10185 			 unsigned int size)
10186 {
10187 	struct rte_flow_action_modify_field *action_modify_field;
10188 	unsigned int i;
10189 
10190 	(void)token;
10191 	(void)buf;
10192 	(void)size;
10193 	if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
10194 		return -1;
10195 	for (i = 0; modify_field_ops[i]; ++i)
10196 		if (!strcmp_partial(modify_field_ops[i], str, len))
10197 			break;
10198 	if (!modify_field_ops[i])
10199 		return -1;
10200 	if (!ctx->object)
10201 		return len;
10202 	action_modify_field = ctx->object;
10203 	action_modify_field->operation = (enum rte_flow_modify_op)i;
10204 	return len;
10205 }
10206 
10207 /** Parse id for modify_field command. */
10208 static int
10209 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
10210 			 const char *str, unsigned int len, void *buf,
10211 			 unsigned int size)
10212 {
10213 	struct rte_flow_action_modify_field *action_modify_field;
10214 	unsigned int i;
10215 
10216 	(void)token;
10217 	(void)buf;
10218 	(void)size;
10219 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
10220 		ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
10221 		return -1;
10222 	for (i = 0; flow_field_ids[i]; ++i)
10223 		if (!strcmp_partial(flow_field_ids[i], str, len))
10224 			break;
10225 	if (!flow_field_ids[i])
10226 		return -1;
10227 	if (!ctx->object)
10228 		return len;
10229 	action_modify_field = ctx->object;
10230 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
10231 		action_modify_field->dst.field = (enum rte_flow_field_id)i;
10232 	else
10233 		action_modify_field->src.field = (enum rte_flow_field_id)i;
10234 	return len;
10235 }
10236 
10237 /** Parse level for modify_field command. */
10238 static int
10239 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
10240 			 const char *str, unsigned int len, void *buf,
10241 			 unsigned int size)
10242 {
10243 	struct rte_flow_action_modify_field *action;
10244 	struct flex_item *fp = NULL;
10245 	uint32_t val;
10246 	struct buffer *out = buf;
10247 	char *end;
10248 
10249 	(void)token;
10250 	(void)size;
10251 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10252 		ctx->curr != ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)
10253 		return -1;
10254 	if (!ctx->object)
10255 		return len;
10256 	action = ctx->object;
10257 	errno = 0;
10258 	val = strtoumax(str, &end, 0);
10259 	if (errno || (size_t)(end - str) != len)
10260 		return -1;
10261 	/* No need to validate action template mask value */
10262 	if (out->args.vc.masks) {
10263 		if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)
10264 			action->dst.level = val;
10265 		else
10266 			action->src.level = val;
10267 		return len;
10268 	}
10269 	if ((ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10270 		action->dst.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
10271 		(ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE &&
10272 		action->src.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
10273 		if (val >= FLEX_MAX_PARSERS_NUM) {
10274 			printf("Bad flex item handle\n");
10275 			return -1;
10276 		}
10277 		fp = flex_items[ctx->port][val];
10278 		if (!fp) {
10279 			printf("Bad flex item handle\n");
10280 			return -1;
10281 		}
10282 	}
10283 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE) {
10284 		if (action->dst.field != RTE_FLOW_FIELD_FLEX_ITEM)
10285 			action->dst.level = val;
10286 		else
10287 			action->dst.flex_handle = fp->flex_handle;
10288 	} else if (ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE) {
10289 		if (action->src.field != RTE_FLOW_FIELD_FLEX_ITEM)
10290 			action->src.level = val;
10291 		else
10292 			action->src.flex_handle = fp->flex_handle;
10293 	}
10294 	return len;
10295 }
10296 
10297 /** Parse the conntrack update, not a rte_flow_action. */
10298 static int
10299 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
10300 			 const char *str, unsigned int len, void *buf,
10301 			 unsigned int size)
10302 {
10303 	struct buffer *out = buf;
10304 	struct rte_flow_modify_conntrack *ct_modify = NULL;
10305 
10306 	(void)size;
10307 	if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
10308 	    ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
10309 		return -1;
10310 	/* Token name must match. */
10311 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10312 		return -1;
10313 	/* Nothing else to do if there is no buffer. */
10314 	if (!out)
10315 		return len;
10316 	ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
10317 	if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
10318 		ct_modify->new_ct.is_original_dir =
10319 				conntrack_context.is_original_dir;
10320 		ct_modify->direction = 1;
10321 	} else {
10322 		uint32_t old_dir;
10323 
10324 		old_dir = ct_modify->new_ct.is_original_dir;
10325 		memcpy(&ct_modify->new_ct, &conntrack_context,
10326 		       sizeof(conntrack_context));
10327 		ct_modify->new_ct.is_original_dir = old_dir;
10328 		ct_modify->state = 1;
10329 	}
10330 	return len;
10331 }
10332 
10333 /** Parse tokens for destroy command. */
10334 static int
10335 parse_destroy(struct context *ctx, const struct token *token,
10336 	      const char *str, unsigned int len,
10337 	      void *buf, unsigned int size)
10338 {
10339 	struct buffer *out = buf;
10340 
10341 	/* Token name must match. */
10342 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10343 		return -1;
10344 	/* Nothing else to do if there is no buffer. */
10345 	if (!out)
10346 		return len;
10347 	if (!out->command) {
10348 		if (ctx->curr != DESTROY)
10349 			return -1;
10350 		if (sizeof(*out) > size)
10351 			return -1;
10352 		out->command = ctx->curr;
10353 		ctx->objdata = 0;
10354 		ctx->object = out;
10355 		ctx->objmask = NULL;
10356 		out->args.destroy.rule =
10357 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10358 					       sizeof(double));
10359 		return len;
10360 	}
10361 	if (ctx->curr == DESTROY_IS_USER_ID) {
10362 		out->args.destroy.is_user_id = true;
10363 		return len;
10364 	}
10365 	if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
10366 	     sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
10367 		return -1;
10368 	ctx->objdata = 0;
10369 	ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
10370 	ctx->objmask = NULL;
10371 	return len;
10372 }
10373 
10374 /** Parse tokens for flush command. */
10375 static int
10376 parse_flush(struct context *ctx, const struct token *token,
10377 	    const char *str, unsigned int len,
10378 	    void *buf, unsigned int size)
10379 {
10380 	struct buffer *out = buf;
10381 
10382 	/* Token name must match. */
10383 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10384 		return -1;
10385 	/* Nothing else to do if there is no buffer. */
10386 	if (!out)
10387 		return len;
10388 	if (!out->command) {
10389 		if (ctx->curr != FLUSH)
10390 			return -1;
10391 		if (sizeof(*out) > size)
10392 			return -1;
10393 		out->command = ctx->curr;
10394 		ctx->objdata = 0;
10395 		ctx->object = out;
10396 		ctx->objmask = NULL;
10397 	}
10398 	return len;
10399 }
10400 
10401 /** Parse tokens for dump command. */
10402 static int
10403 parse_dump(struct context *ctx, const struct token *token,
10404 	    const char *str, unsigned int len,
10405 	    void *buf, unsigned int size)
10406 {
10407 	struct buffer *out = buf;
10408 
10409 	/* Token name must match. */
10410 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10411 		return -1;
10412 	/* Nothing else to do if there is no buffer. */
10413 	if (!out)
10414 		return len;
10415 	if (!out->command) {
10416 		if (ctx->curr != DUMP)
10417 			return -1;
10418 		if (sizeof(*out) > size)
10419 			return -1;
10420 		out->command = ctx->curr;
10421 		ctx->objdata = 0;
10422 		ctx->object = out;
10423 		ctx->objmask = NULL;
10424 		return len;
10425 	}
10426 	switch (ctx->curr) {
10427 	case DUMP_ALL:
10428 	case DUMP_ONE:
10429 		out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
10430 		out->command = ctx->curr;
10431 		ctx->objdata = 0;
10432 		ctx->object = out;
10433 		ctx->objmask = NULL;
10434 		return len;
10435 	case DUMP_IS_USER_ID:
10436 		out->args.dump.is_user_id = true;
10437 		return len;
10438 	default:
10439 		return -1;
10440 	}
10441 }
10442 
10443 /** Parse tokens for query command. */
10444 static int
10445 parse_query(struct context *ctx, const struct token *token,
10446 	    const char *str, unsigned int len,
10447 	    void *buf, unsigned int size)
10448 {
10449 	struct buffer *out = buf;
10450 
10451 	/* Token name must match. */
10452 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10453 		return -1;
10454 	/* Nothing else to do if there is no buffer. */
10455 	if (!out)
10456 		return len;
10457 	if (!out->command) {
10458 		if (ctx->curr != QUERY)
10459 			return -1;
10460 		if (sizeof(*out) > size)
10461 			return -1;
10462 		out->command = ctx->curr;
10463 		ctx->objdata = 0;
10464 		ctx->object = out;
10465 		ctx->objmask = NULL;
10466 	}
10467 	if (ctx->curr == QUERY_IS_USER_ID) {
10468 		out->args.query.is_user_id = true;
10469 		return len;
10470 	}
10471 	return len;
10472 }
10473 
10474 /** Parse action names. */
10475 static int
10476 parse_action(struct context *ctx, const struct token *token,
10477 	     const char *str, unsigned int len,
10478 	     void *buf, unsigned int size)
10479 {
10480 	struct buffer *out = buf;
10481 	const struct arg *arg = pop_args(ctx);
10482 	unsigned int i;
10483 
10484 	(void)size;
10485 	/* Argument is expected. */
10486 	if (!arg)
10487 		return -1;
10488 	/* Parse action name. */
10489 	for (i = 0; next_action[i]; ++i) {
10490 		const struct parse_action_priv *priv;
10491 
10492 		token = &token_list[next_action[i]];
10493 		if (strcmp_partial(token->name, str, len))
10494 			continue;
10495 		priv = token->priv;
10496 		if (!priv)
10497 			goto error;
10498 		if (out)
10499 			memcpy((uint8_t *)ctx->object + arg->offset,
10500 			       &priv->type,
10501 			       arg->size);
10502 		return len;
10503 	}
10504 error:
10505 	push_args(ctx, arg);
10506 	return -1;
10507 }
10508 
10509 /** Parse tokens for list command. */
10510 static int
10511 parse_list(struct context *ctx, const struct token *token,
10512 	   const char *str, unsigned int len,
10513 	   void *buf, unsigned int size)
10514 {
10515 	struct buffer *out = buf;
10516 
10517 	/* Token name must match. */
10518 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10519 		return -1;
10520 	/* Nothing else to do if there is no buffer. */
10521 	if (!out)
10522 		return len;
10523 	if (!out->command) {
10524 		if (ctx->curr != LIST)
10525 			return -1;
10526 		if (sizeof(*out) > size)
10527 			return -1;
10528 		out->command = ctx->curr;
10529 		ctx->objdata = 0;
10530 		ctx->object = out;
10531 		ctx->objmask = NULL;
10532 		out->args.list.group =
10533 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10534 					       sizeof(double));
10535 		return len;
10536 	}
10537 	if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
10538 	     sizeof(*out->args.list.group)) > (uint8_t *)out + size)
10539 		return -1;
10540 	ctx->objdata = 0;
10541 	ctx->object = out->args.list.group + out->args.list.group_n++;
10542 	ctx->objmask = NULL;
10543 	return len;
10544 }
10545 
10546 /** Parse tokens for list all aged flows command. */
10547 static int
10548 parse_aged(struct context *ctx, const struct token *token,
10549 	   const char *str, unsigned int len,
10550 	   void *buf, unsigned int size)
10551 {
10552 	struct buffer *out = buf;
10553 
10554 	/* Token name must match. */
10555 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10556 		return -1;
10557 	/* Nothing else to do if there is no buffer. */
10558 	if (!out)
10559 		return len;
10560 	if (!out->command || out->command == QUEUE) {
10561 		if (ctx->curr != AGED && ctx->curr != QUEUE_AGED)
10562 			return -1;
10563 		if (sizeof(*out) > size)
10564 			return -1;
10565 		out->command = ctx->curr;
10566 		ctx->objdata = 0;
10567 		ctx->object = out;
10568 		ctx->objmask = NULL;
10569 	}
10570 	if (ctx->curr == AGED_DESTROY)
10571 		out->args.aged.destroy = 1;
10572 	return len;
10573 }
10574 
10575 /** Parse tokens for isolate command. */
10576 static int
10577 parse_isolate(struct context *ctx, const struct token *token,
10578 	      const char *str, unsigned int len,
10579 	      void *buf, unsigned int size)
10580 {
10581 	struct buffer *out = buf;
10582 
10583 	/* Token name must match. */
10584 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10585 		return -1;
10586 	/* Nothing else to do if there is no buffer. */
10587 	if (!out)
10588 		return len;
10589 	if (!out->command) {
10590 		if (ctx->curr != ISOLATE)
10591 			return -1;
10592 		if (sizeof(*out) > size)
10593 			return -1;
10594 		out->command = ctx->curr;
10595 		ctx->objdata = 0;
10596 		ctx->object = out;
10597 		ctx->objmask = NULL;
10598 	}
10599 	return len;
10600 }
10601 
10602 /** Parse tokens for info/configure command. */
10603 static int
10604 parse_configure(struct context *ctx, const struct token *token,
10605 		const char *str, unsigned int len,
10606 		void *buf, unsigned int size)
10607 {
10608 	struct buffer *out = buf;
10609 
10610 	/* Token name must match. */
10611 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10612 		return -1;
10613 	/* Nothing else to do if there is no buffer. */
10614 	if (!out)
10615 		return len;
10616 	if (!out->command) {
10617 		if (ctx->curr != INFO && ctx->curr != CONFIGURE)
10618 			return -1;
10619 		if (sizeof(*out) > size)
10620 			return -1;
10621 		out->command = ctx->curr;
10622 		ctx->objdata = 0;
10623 		ctx->object = out;
10624 		ctx->objmask = NULL;
10625 	}
10626 	return len;
10627 }
10628 
10629 /** Parse tokens for template create command. */
10630 static int
10631 parse_template(struct context *ctx, const struct token *token,
10632 	       const char *str, unsigned int len,
10633 	       void *buf, unsigned int size)
10634 {
10635 	struct buffer *out = buf;
10636 
10637 	/* Token name must match. */
10638 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10639 		return -1;
10640 	/* Nothing else to do if there is no buffer. */
10641 	if (!out)
10642 		return len;
10643 	if (!out->command) {
10644 		if (ctx->curr != PATTERN_TEMPLATE &&
10645 		    ctx->curr != ACTIONS_TEMPLATE)
10646 			return -1;
10647 		if (sizeof(*out) > size)
10648 			return -1;
10649 		out->command = ctx->curr;
10650 		ctx->objdata = 0;
10651 		ctx->object = out;
10652 		ctx->objmask = NULL;
10653 		out->args.vc.data = (uint8_t *)out + size;
10654 		return len;
10655 	}
10656 	switch (ctx->curr) {
10657 	case PATTERN_TEMPLATE_CREATE:
10658 		out->args.vc.pattern =
10659 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10660 					       sizeof(double));
10661 		out->args.vc.pat_templ_id = UINT32_MAX;
10662 		out->command = ctx->curr;
10663 		ctx->objdata = 0;
10664 		ctx->object = out;
10665 		ctx->objmask = NULL;
10666 		return len;
10667 	case PATTERN_TEMPLATE_EGRESS:
10668 		out->args.vc.attr.egress = 1;
10669 		return len;
10670 	case PATTERN_TEMPLATE_INGRESS:
10671 		out->args.vc.attr.ingress = 1;
10672 		return len;
10673 	case PATTERN_TEMPLATE_TRANSFER:
10674 		out->args.vc.attr.transfer = 1;
10675 		return len;
10676 	case ACTIONS_TEMPLATE_CREATE:
10677 		out->args.vc.act_templ_id = UINT32_MAX;
10678 		out->command = ctx->curr;
10679 		ctx->objdata = 0;
10680 		ctx->object = out;
10681 		ctx->objmask = NULL;
10682 		return len;
10683 	case ACTIONS_TEMPLATE_SPEC:
10684 		out->args.vc.actions =
10685 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10686 					       sizeof(double));
10687 		ctx->object = out->args.vc.actions;
10688 		ctx->objmask = NULL;
10689 		return len;
10690 	case ACTIONS_TEMPLATE_MASK:
10691 		out->args.vc.masks =
10692 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10693 					       (out->args.vc.actions +
10694 						out->args.vc.actions_n),
10695 					       sizeof(double));
10696 		ctx->object = out->args.vc.masks;
10697 		ctx->objmask = NULL;
10698 		return len;
10699 	case ACTIONS_TEMPLATE_EGRESS:
10700 		out->args.vc.attr.egress = 1;
10701 		return len;
10702 	case ACTIONS_TEMPLATE_INGRESS:
10703 		out->args.vc.attr.ingress = 1;
10704 		return len;
10705 	case ACTIONS_TEMPLATE_TRANSFER:
10706 		out->args.vc.attr.transfer = 1;
10707 		return len;
10708 	default:
10709 		return -1;
10710 	}
10711 }
10712 
10713 /** Parse tokens for template destroy command. */
10714 static int
10715 parse_template_destroy(struct context *ctx, const struct token *token,
10716 		       const char *str, unsigned int len,
10717 		       void *buf, unsigned int size)
10718 {
10719 	struct buffer *out = buf;
10720 	uint32_t *template_id;
10721 
10722 	/* Token name must match. */
10723 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10724 		return -1;
10725 	/* Nothing else to do if there is no buffer. */
10726 	if (!out)
10727 		return len;
10728 	if (!out->command ||
10729 		out->command == PATTERN_TEMPLATE ||
10730 		out->command == ACTIONS_TEMPLATE) {
10731 		if (ctx->curr != PATTERN_TEMPLATE_DESTROY &&
10732 			ctx->curr != ACTIONS_TEMPLATE_DESTROY)
10733 			return -1;
10734 		if (sizeof(*out) > size)
10735 			return -1;
10736 		out->command = ctx->curr;
10737 		ctx->objdata = 0;
10738 		ctx->object = out;
10739 		ctx->objmask = NULL;
10740 		out->args.templ_destroy.template_id =
10741 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10742 					       sizeof(double));
10743 		return len;
10744 	}
10745 	template_id = out->args.templ_destroy.template_id
10746 		    + out->args.templ_destroy.template_id_n++;
10747 	if ((uint8_t *)template_id > (uint8_t *)out + size)
10748 		return -1;
10749 	ctx->objdata = 0;
10750 	ctx->object = template_id;
10751 	ctx->objmask = NULL;
10752 	return len;
10753 }
10754 
10755 /** Parse tokens for table create command. */
10756 static int
10757 parse_table(struct context *ctx, const struct token *token,
10758 	    const char *str, unsigned int len,
10759 	    void *buf, unsigned int size)
10760 {
10761 	struct buffer *out = buf;
10762 	uint32_t *template_id;
10763 
10764 	/* Token name must match. */
10765 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10766 		return -1;
10767 	/* Nothing else to do if there is no buffer. */
10768 	if (!out)
10769 		return len;
10770 	if (!out->command) {
10771 		if (ctx->curr != TABLE)
10772 			return -1;
10773 		if (sizeof(*out) > size)
10774 			return -1;
10775 		out->command = ctx->curr;
10776 		ctx->objdata = 0;
10777 		ctx->object = out;
10778 		ctx->objmask = NULL;
10779 		return len;
10780 	}
10781 	switch (ctx->curr) {
10782 	case TABLE_CREATE:
10783 		out->command = ctx->curr;
10784 		ctx->objdata = 0;
10785 		ctx->object = out;
10786 		ctx->objmask = NULL;
10787 		out->args.table.id = UINT32_MAX;
10788 		return len;
10789 	case TABLE_PATTERN_TEMPLATE:
10790 		out->args.table.pat_templ_id =
10791 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10792 					       sizeof(double));
10793 		template_id = out->args.table.pat_templ_id
10794 				+ out->args.table.pat_templ_id_n++;
10795 		if ((uint8_t *)template_id > (uint8_t *)out + size)
10796 			return -1;
10797 		ctx->objdata = 0;
10798 		ctx->object = template_id;
10799 		ctx->objmask = NULL;
10800 		return len;
10801 	case TABLE_ACTIONS_TEMPLATE:
10802 		out->args.table.act_templ_id =
10803 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10804 					       (out->args.table.pat_templ_id +
10805 						out->args.table.pat_templ_id_n),
10806 					       sizeof(double));
10807 		template_id = out->args.table.act_templ_id
10808 				+ out->args.table.act_templ_id_n++;
10809 		if ((uint8_t *)template_id > (uint8_t *)out + size)
10810 			return -1;
10811 		ctx->objdata = 0;
10812 		ctx->object = template_id;
10813 		ctx->objmask = NULL;
10814 		return len;
10815 	case TABLE_INGRESS:
10816 		out->args.table.attr.flow_attr.ingress = 1;
10817 		return len;
10818 	case TABLE_EGRESS:
10819 		out->args.table.attr.flow_attr.egress = 1;
10820 		return len;
10821 	case TABLE_TRANSFER:
10822 		out->args.table.attr.flow_attr.transfer = 1;
10823 		return len;
10824 	case TABLE_TRANSFER_WIRE_ORIG:
10825 		if (!out->args.table.attr.flow_attr.transfer)
10826 			return -1;
10827 		out->args.table.attr.specialize = RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_WIRE_ORIG;
10828 		return len;
10829 	case TABLE_TRANSFER_VPORT_ORIG:
10830 		if (!out->args.table.attr.flow_attr.transfer)
10831 			return -1;
10832 		out->args.table.attr.specialize = RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_VPORT_ORIG;
10833 		return len;
10834 	case TABLE_RULES_NUMBER:
10835 		ctx->objdata = 0;
10836 		ctx->object = out;
10837 		ctx->objmask = NULL;
10838 		return len;
10839 	default:
10840 		return -1;
10841 	}
10842 }
10843 
10844 /** Parse tokens for table destroy command. */
10845 static int
10846 parse_table_destroy(struct context *ctx, const struct token *token,
10847 		    const char *str, unsigned int len,
10848 		    void *buf, unsigned int size)
10849 {
10850 	struct buffer *out = buf;
10851 	uint32_t *table_id;
10852 
10853 	/* Token name must match. */
10854 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10855 		return -1;
10856 	/* Nothing else to do if there is no buffer. */
10857 	if (!out)
10858 		return len;
10859 	if (!out->command || out->command == TABLE) {
10860 		if (ctx->curr != TABLE_DESTROY)
10861 			return -1;
10862 		if (sizeof(*out) > size)
10863 			return -1;
10864 		out->command = ctx->curr;
10865 		ctx->objdata = 0;
10866 		ctx->object = out;
10867 		ctx->objmask = NULL;
10868 		out->args.table_destroy.table_id =
10869 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10870 					       sizeof(double));
10871 		return len;
10872 	}
10873 	table_id = out->args.table_destroy.table_id
10874 		    + out->args.table_destroy.table_id_n++;
10875 	if ((uint8_t *)table_id > (uint8_t *)out + size)
10876 		return -1;
10877 	ctx->objdata = 0;
10878 	ctx->object = table_id;
10879 	ctx->objmask = NULL;
10880 	return len;
10881 }
10882 
10883 /** Parse tokens for queue create commands. */
10884 static int
10885 parse_qo(struct context *ctx, const struct token *token,
10886 	 const char *str, unsigned int len,
10887 	 void *buf, unsigned int size)
10888 {
10889 	struct buffer *out = buf;
10890 
10891 	/* Token name must match. */
10892 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10893 		return -1;
10894 	/* Nothing else to do if there is no buffer. */
10895 	if (!out)
10896 		return len;
10897 	if (!out->command) {
10898 		if (ctx->curr != QUEUE)
10899 			return -1;
10900 		if (sizeof(*out) > size)
10901 			return -1;
10902 		out->command = ctx->curr;
10903 		ctx->objdata = 0;
10904 		ctx->object = out;
10905 		ctx->objmask = NULL;
10906 		out->args.vc.data = (uint8_t *)out + size;
10907 		return len;
10908 	}
10909 	switch (ctx->curr) {
10910 	case QUEUE_CREATE:
10911 	case QUEUE_UPDATE:
10912 		out->command = ctx->curr;
10913 		ctx->objdata = 0;
10914 		ctx->object = out;
10915 		ctx->objmask = NULL;
10916 		out->args.vc.rule_id = UINT32_MAX;
10917 		return len;
10918 	case QUEUE_TEMPLATE_TABLE:
10919 	case QUEUE_PATTERN_TEMPLATE:
10920 	case QUEUE_ACTIONS_TEMPLATE:
10921 	case QUEUE_CREATE_POSTPONE:
10922 	case QUEUE_RULE_ID:
10923 	case QUEUE_UPDATE_ID:
10924 		return len;
10925 	case ITEM_PATTERN:
10926 		out->args.vc.pattern =
10927 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10928 					       sizeof(double));
10929 		ctx->object = out->args.vc.pattern;
10930 		ctx->objmask = NULL;
10931 		return len;
10932 	case ACTIONS:
10933 		out->args.vc.actions =
10934 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10935 					       (out->args.vc.pattern +
10936 						out->args.vc.pattern_n),
10937 					       sizeof(double));
10938 		ctx->object = out->args.vc.actions;
10939 		ctx->objmask = NULL;
10940 		return len;
10941 	default:
10942 		return -1;
10943 	}
10944 }
10945 
10946 /** Parse tokens for queue destroy command. */
10947 static int
10948 parse_qo_destroy(struct context *ctx, const struct token *token,
10949 		 const char *str, unsigned int len,
10950 		 void *buf, unsigned int size)
10951 {
10952 	struct buffer *out = buf;
10953 	uint64_t *flow_id;
10954 
10955 	/* Token name must match. */
10956 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10957 		return -1;
10958 	/* Nothing else to do if there is no buffer. */
10959 	if (!out)
10960 		return len;
10961 	if (!out->command || out->command == QUEUE) {
10962 		if (ctx->curr != QUEUE_DESTROY)
10963 			return -1;
10964 		if (sizeof(*out) > size)
10965 			return -1;
10966 		out->command = ctx->curr;
10967 		ctx->objdata = 0;
10968 		ctx->object = out;
10969 		ctx->objmask = NULL;
10970 		out->args.destroy.rule =
10971 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10972 					       sizeof(double));
10973 		return len;
10974 	}
10975 	switch (ctx->curr) {
10976 	case QUEUE_DESTROY_ID:
10977 		flow_id = out->args.destroy.rule
10978 				+ out->args.destroy.rule_n++;
10979 		if ((uint8_t *)flow_id > (uint8_t *)out + size)
10980 			return -1;
10981 		ctx->objdata = 0;
10982 		ctx->object = flow_id;
10983 		ctx->objmask = NULL;
10984 		return len;
10985 	case QUEUE_DESTROY_POSTPONE:
10986 		return len;
10987 	default:
10988 		return -1;
10989 	}
10990 }
10991 
10992 /** Parse tokens for push queue command. */
10993 static int
10994 parse_push(struct context *ctx, const struct token *token,
10995 	   const char *str, unsigned int len,
10996 	   void *buf, unsigned int size)
10997 {
10998 	struct buffer *out = buf;
10999 
11000 	/* Token name must match. */
11001 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11002 		return -1;
11003 	/* Nothing else to do if there is no buffer. */
11004 	if (!out)
11005 		return len;
11006 	if (!out->command) {
11007 		if (ctx->curr != PUSH)
11008 			return -1;
11009 		if (sizeof(*out) > size)
11010 			return -1;
11011 		out->command = ctx->curr;
11012 		ctx->objdata = 0;
11013 		ctx->object = out;
11014 		ctx->objmask = NULL;
11015 		out->args.vc.data = (uint8_t *)out + size;
11016 	}
11017 	return len;
11018 }
11019 
11020 /** Parse tokens for pull command. */
11021 static int
11022 parse_pull(struct context *ctx, const struct token *token,
11023 	   const char *str, unsigned int len,
11024 	   void *buf, unsigned int size)
11025 {
11026 	struct buffer *out = buf;
11027 
11028 	/* Token name must match. */
11029 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11030 		return -1;
11031 	/* Nothing else to do if there is no buffer. */
11032 	if (!out)
11033 		return len;
11034 	if (!out->command) {
11035 		if (ctx->curr != PULL)
11036 			return -1;
11037 		if (sizeof(*out) > size)
11038 			return -1;
11039 		out->command = ctx->curr;
11040 		ctx->objdata = 0;
11041 		ctx->object = out;
11042 		ctx->objmask = NULL;
11043 		out->args.vc.data = (uint8_t *)out + size;
11044 	}
11045 	return len;
11046 }
11047 
11048 /** Parse tokens for hash calculation commands. */
11049 static int
11050 parse_hash(struct context *ctx, const struct token *token,
11051 	 const char *str, unsigned int len,
11052 	 void *buf, unsigned int size)
11053 {
11054 	struct buffer *out = buf;
11055 
11056 	/* Token name must match. */
11057 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11058 		return -1;
11059 	/* Nothing else to do if there is no buffer. */
11060 	if (!out)
11061 		return len;
11062 	if (!out->command) {
11063 		if (ctx->curr != HASH)
11064 			return -1;
11065 		if (sizeof(*out) > size)
11066 			return -1;
11067 		out->command = ctx->curr;
11068 		ctx->objdata = 0;
11069 		ctx->object = out;
11070 		ctx->objmask = NULL;
11071 		out->args.vc.data = (uint8_t *)out + size;
11072 		return len;
11073 	}
11074 	switch (ctx->curr) {
11075 	case HASH_CALC_TABLE:
11076 	case HASH_CALC_PATTERN_INDEX:
11077 		return len;
11078 	case ITEM_PATTERN:
11079 		out->args.vc.pattern =
11080 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11081 					       sizeof(double));
11082 		ctx->object = out->args.vc.pattern;
11083 		ctx->objmask = NULL;
11084 		return len;
11085 	case HASH_CALC_ENCAP:
11086 		out->args.vc.encap_hash = 1;
11087 		return len;
11088 	case ENCAP_HASH_FIELD_SRC_PORT:
11089 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_SRC_PORT;
11090 		return len;
11091 	case ENCAP_HASH_FIELD_GRE_FLOW_ID:
11092 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_NVGRE_FLOW_ID;
11093 		return len;
11094 	default:
11095 		return -1;
11096 	}
11097 }
11098 
11099 static int
11100 parse_group(struct context *ctx, const struct token *token,
11101 	    const char *str, unsigned int len,
11102 	    void *buf, unsigned int size)
11103 {
11104 	struct buffer *out = buf;
11105 
11106 	/* Token name must match. */
11107 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11108 		return -1;
11109 	/* Nothing else to do if there is no buffer. */
11110 	if (!out)
11111 		return len;
11112 	if (!out->command) {
11113 		if (ctx->curr != FLOW_GROUP)
11114 			return -1;
11115 		if (sizeof(*out) > size)
11116 			return -1;
11117 		out->command = ctx->curr;
11118 		ctx->objdata = 0;
11119 		ctx->object = out;
11120 		ctx->objmask = NULL;
11121 		out->args.vc.data = (uint8_t *)out + size;
11122 		return len;
11123 	}
11124 	switch (ctx->curr) {
11125 	case GROUP_INGRESS:
11126 		out->args.vc.attr.ingress = 1;
11127 		return len;
11128 	case GROUP_EGRESS:
11129 		out->args.vc.attr.egress = 1;
11130 		return len;
11131 	case GROUP_TRANSFER:
11132 		out->args.vc.attr.transfer = 1;
11133 		return len;
11134 	case GROUP_SET_MISS_ACTIONS:
11135 		out->command = ctx->curr;
11136 		ctx->objdata = 0;
11137 		ctx->object = out;
11138 		ctx->objmask = NULL;
11139 		out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11140 							       sizeof(double));
11141 		return len;
11142 	default:
11143 		return -1;
11144 	}
11145 }
11146 
11147 static int
11148 parse_flex(struct context *ctx, const struct token *token,
11149 	     const char *str, unsigned int len,
11150 	     void *buf, unsigned int size)
11151 {
11152 	struct buffer *out = buf;
11153 
11154 	/* Token name must match. */
11155 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11156 		return -1;
11157 	/* Nothing else to do if there is no buffer. */
11158 	if (!out)
11159 		return len;
11160 	if (out->command == ZERO) {
11161 		if (ctx->curr != FLEX)
11162 			return -1;
11163 		if (sizeof(*out) > size)
11164 			return -1;
11165 		out->command = ctx->curr;
11166 		ctx->objdata = 0;
11167 		ctx->object = out;
11168 		ctx->objmask = NULL;
11169 	} else {
11170 		switch (ctx->curr) {
11171 		default:
11172 			break;
11173 		case FLEX_ITEM_INIT:
11174 		case FLEX_ITEM_CREATE:
11175 		case FLEX_ITEM_DESTROY:
11176 			out->command = ctx->curr;
11177 			break;
11178 		}
11179 	}
11180 
11181 	return len;
11182 }
11183 
11184 static int
11185 parse_tunnel(struct context *ctx, const struct token *token,
11186 	     const char *str, unsigned int len,
11187 	     void *buf, unsigned int size)
11188 {
11189 	struct buffer *out = buf;
11190 
11191 	/* Token name must match. */
11192 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11193 		return -1;
11194 	/* Nothing else to do if there is no buffer. */
11195 	if (!out)
11196 		return len;
11197 	if (!out->command) {
11198 		if (ctx->curr != TUNNEL)
11199 			return -1;
11200 		if (sizeof(*out) > size)
11201 			return -1;
11202 		out->command = ctx->curr;
11203 		ctx->objdata = 0;
11204 		ctx->object = out;
11205 		ctx->objmask = NULL;
11206 	} else {
11207 		switch (ctx->curr) {
11208 		default:
11209 			break;
11210 		case TUNNEL_CREATE:
11211 		case TUNNEL_DESTROY:
11212 		case TUNNEL_LIST:
11213 			out->command = ctx->curr;
11214 			break;
11215 		case TUNNEL_CREATE_TYPE:
11216 		case TUNNEL_DESTROY_ID:
11217 			ctx->object = &out->args.vc.tunnel_ops;
11218 			break;
11219 		}
11220 	}
11221 
11222 	return len;
11223 }
11224 
11225 /**
11226  * Parse signed/unsigned integers 8 to 64-bit long.
11227  *
11228  * Last argument (ctx->args) is retrieved to determine integer type and
11229  * storage location.
11230  */
11231 static int
11232 parse_int(struct context *ctx, const struct token *token,
11233 	  const char *str, unsigned int len,
11234 	  void *buf, unsigned int size)
11235 {
11236 	const struct arg *arg = pop_args(ctx);
11237 	uintmax_t u;
11238 	char *end;
11239 
11240 	(void)token;
11241 	/* Argument is expected. */
11242 	if (!arg)
11243 		return -1;
11244 	errno = 0;
11245 	u = arg->sign ?
11246 		(uintmax_t)strtoimax(str, &end, 0) :
11247 		strtoumax(str, &end, 0);
11248 	if (errno || (size_t)(end - str) != len)
11249 		goto error;
11250 	if (arg->bounded &&
11251 	    ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
11252 			    (intmax_t)u > (intmax_t)arg->max)) ||
11253 	     (!arg->sign && (u < arg->min || u > arg->max))))
11254 		goto error;
11255 	if (!ctx->object)
11256 		return len;
11257 	if (arg->mask) {
11258 		if (!arg_entry_bf_fill(ctx->object, u, arg) ||
11259 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
11260 			goto error;
11261 		return len;
11262 	}
11263 	buf = (uint8_t *)ctx->object + arg->offset;
11264 	size = arg->size;
11265 	if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
11266 		return -1;
11267 objmask:
11268 	switch (size) {
11269 	case sizeof(uint8_t):
11270 		*(uint8_t *)buf = u;
11271 		break;
11272 	case sizeof(uint16_t):
11273 		*(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
11274 		break;
11275 	case sizeof(uint8_t [3]):
11276 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
11277 		if (!arg->hton) {
11278 			((uint8_t *)buf)[0] = u;
11279 			((uint8_t *)buf)[1] = u >> 8;
11280 			((uint8_t *)buf)[2] = u >> 16;
11281 			break;
11282 		}
11283 #endif
11284 		((uint8_t *)buf)[0] = u >> 16;
11285 		((uint8_t *)buf)[1] = u >> 8;
11286 		((uint8_t *)buf)[2] = u;
11287 		break;
11288 	case sizeof(uint32_t):
11289 		*(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
11290 		break;
11291 	case sizeof(uint64_t):
11292 		*(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
11293 		break;
11294 	default:
11295 		goto error;
11296 	}
11297 	if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
11298 		u = -1;
11299 		buf = (uint8_t *)ctx->objmask + arg->offset;
11300 		goto objmask;
11301 	}
11302 	return len;
11303 error:
11304 	push_args(ctx, arg);
11305 	return -1;
11306 }
11307 
11308 /**
11309  * Parse a string.
11310  *
11311  * Three arguments (ctx->args) are retrieved from the stack to store data,
11312  * its actual length and address (in that order).
11313  */
11314 static int
11315 parse_string(struct context *ctx, const struct token *token,
11316 	     const char *str, unsigned int len,
11317 	     void *buf, unsigned int size)
11318 {
11319 	const struct arg *arg_data = pop_args(ctx);
11320 	const struct arg *arg_len = pop_args(ctx);
11321 	const struct arg *arg_addr = pop_args(ctx);
11322 	char tmp[16]; /* Ought to be enough. */
11323 	int ret;
11324 
11325 	/* Arguments are expected. */
11326 	if (!arg_data)
11327 		return -1;
11328 	if (!arg_len) {
11329 		push_args(ctx, arg_data);
11330 		return -1;
11331 	}
11332 	if (!arg_addr) {
11333 		push_args(ctx, arg_len);
11334 		push_args(ctx, arg_data);
11335 		return -1;
11336 	}
11337 	size = arg_data->size;
11338 	/* Bit-mask fill is not supported. */
11339 	if (arg_data->mask || size < len)
11340 		goto error;
11341 	if (!ctx->object)
11342 		return len;
11343 	/* Let parse_int() fill length information first. */
11344 	ret = snprintf(tmp, sizeof(tmp), "%u", len);
11345 	if (ret < 0)
11346 		goto error;
11347 	push_args(ctx, arg_len);
11348 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11349 	if (ret < 0) {
11350 		pop_args(ctx);
11351 		goto error;
11352 	}
11353 	buf = (uint8_t *)ctx->object + arg_data->offset;
11354 	/* Output buffer is not necessarily NUL-terminated. */
11355 	memcpy(buf, str, len);
11356 	memset((uint8_t *)buf + len, 0x00, size - len);
11357 	if (ctx->objmask)
11358 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11359 	/* Save address if requested. */
11360 	if (arg_addr->size) {
11361 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11362 		       (void *[]){
11363 			(uint8_t *)ctx->object + arg_data->offset
11364 		       },
11365 		       arg_addr->size);
11366 		if (ctx->objmask)
11367 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11368 			       (void *[]){
11369 				(uint8_t *)ctx->objmask + arg_data->offset
11370 			       },
11371 			       arg_addr->size);
11372 	}
11373 	return len;
11374 error:
11375 	push_args(ctx, arg_addr);
11376 	push_args(ctx, arg_len);
11377 	push_args(ctx, arg_data);
11378 	return -1;
11379 }
11380 
11381 static int
11382 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
11383 {
11384 	const uint8_t *head = dst;
11385 	uint32_t left;
11386 
11387 	if (*size == 0)
11388 		return -1;
11389 
11390 	left = *size;
11391 
11392 	/* Convert chars to bytes */
11393 	while (left) {
11394 		char tmp[3], *end = tmp;
11395 		uint32_t read_lim = left & 1 ? 1 : 2;
11396 
11397 		snprintf(tmp, read_lim + 1, "%s", src);
11398 		*dst = strtoul(tmp, &end, 16);
11399 		if (*end) {
11400 			*dst = 0;
11401 			*size = (uint32_t)(dst - head);
11402 			return -1;
11403 		}
11404 		left -= read_lim;
11405 		src += read_lim;
11406 		dst++;
11407 	}
11408 	*dst = 0;
11409 	*size = (uint32_t)(dst - head);
11410 	return 0;
11411 }
11412 
11413 static int
11414 parse_hex(struct context *ctx, const struct token *token,
11415 		const char *str, unsigned int len,
11416 		void *buf, unsigned int size)
11417 {
11418 	const struct arg *arg_data = pop_args(ctx);
11419 	const struct arg *arg_len = pop_args(ctx);
11420 	const struct arg *arg_addr = pop_args(ctx);
11421 	char tmp[16]; /* Ought to be enough. */
11422 	int ret;
11423 	unsigned int hexlen = len;
11424 	unsigned int length = 256;
11425 	uint8_t hex_tmp[length];
11426 
11427 	/* Arguments are expected. */
11428 	if (!arg_data)
11429 		return -1;
11430 	if (!arg_len) {
11431 		push_args(ctx, arg_data);
11432 		return -1;
11433 	}
11434 	if (!arg_addr) {
11435 		push_args(ctx, arg_len);
11436 		push_args(ctx, arg_data);
11437 		return -1;
11438 	}
11439 	size = arg_data->size;
11440 	/* Bit-mask fill is not supported. */
11441 	if (arg_data->mask)
11442 		goto error;
11443 	if (!ctx->object)
11444 		return len;
11445 
11446 	/* translate bytes string to array. */
11447 	if (str[0] == '0' && ((str[1] == 'x') ||
11448 			(str[1] == 'X'))) {
11449 		str += 2;
11450 		hexlen -= 2;
11451 	}
11452 	if (hexlen > length)
11453 		goto error;
11454 	ret = parse_hex_string(str, hex_tmp, &hexlen);
11455 	if (ret < 0)
11456 		goto error;
11457 	/* Check the converted binary fits into data buffer. */
11458 	if (hexlen > size)
11459 		goto error;
11460 	/* Let parse_int() fill length information first. */
11461 	ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
11462 	if (ret < 0)
11463 		goto error;
11464 	/* Save length if requested. */
11465 	if (arg_len->size) {
11466 		push_args(ctx, arg_len);
11467 		ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11468 		if (ret < 0) {
11469 			pop_args(ctx);
11470 			goto error;
11471 		}
11472 	}
11473 	buf = (uint8_t *)ctx->object + arg_data->offset;
11474 	/* Output buffer is not necessarily NUL-terminated. */
11475 	memcpy(buf, hex_tmp, hexlen);
11476 	memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
11477 	if (ctx->objmask)
11478 		memset((uint8_t *)ctx->objmask + arg_data->offset,
11479 					0xff, hexlen);
11480 	/* Save address if requested. */
11481 	if (arg_addr->size) {
11482 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11483 		       (void *[]){
11484 			(uint8_t *)ctx->object + arg_data->offset
11485 		       },
11486 		       arg_addr->size);
11487 		if (ctx->objmask)
11488 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11489 			       (void *[]){
11490 				(uint8_t *)ctx->objmask + arg_data->offset
11491 			       },
11492 			       arg_addr->size);
11493 	}
11494 	return len;
11495 error:
11496 	push_args(ctx, arg_addr);
11497 	push_args(ctx, arg_len);
11498 	push_args(ctx, arg_data);
11499 	return -1;
11500 
11501 }
11502 
11503 /**
11504  * Parse a zero-ended string.
11505  */
11506 static int
11507 parse_string0(struct context *ctx, const struct token *token __rte_unused,
11508 	     const char *str, unsigned int len,
11509 	     void *buf, unsigned int size)
11510 {
11511 	const struct arg *arg_data = pop_args(ctx);
11512 
11513 	/* Arguments are expected. */
11514 	if (!arg_data)
11515 		return -1;
11516 	size = arg_data->size;
11517 	/* Bit-mask fill is not supported. */
11518 	if (arg_data->mask || size < len + 1)
11519 		goto error;
11520 	if (!ctx->object)
11521 		return len;
11522 	buf = (uint8_t *)ctx->object + arg_data->offset;
11523 	strncpy(buf, str, len);
11524 	if (ctx->objmask)
11525 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11526 	return len;
11527 error:
11528 	push_args(ctx, arg_data);
11529 	return -1;
11530 }
11531 
11532 /**
11533  * Parse a MAC address.
11534  *
11535  * Last argument (ctx->args) is retrieved to determine storage size and
11536  * location.
11537  */
11538 static int
11539 parse_mac_addr(struct context *ctx, const struct token *token,
11540 	       const char *str, unsigned int len,
11541 	       void *buf, unsigned int size)
11542 {
11543 	const struct arg *arg = pop_args(ctx);
11544 	struct rte_ether_addr tmp;
11545 	int ret;
11546 
11547 	(void)token;
11548 	/* Argument is expected. */
11549 	if (!arg)
11550 		return -1;
11551 	size = arg->size;
11552 	/* Bit-mask fill is not supported. */
11553 	if (arg->mask || size != sizeof(tmp))
11554 		goto error;
11555 	/* Only network endian is supported. */
11556 	if (!arg->hton)
11557 		goto error;
11558 	ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
11559 	if (ret < 0 || (unsigned int)ret != len)
11560 		goto error;
11561 	if (!ctx->object)
11562 		return len;
11563 	buf = (uint8_t *)ctx->object + arg->offset;
11564 	memcpy(buf, &tmp, size);
11565 	if (ctx->objmask)
11566 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11567 	return len;
11568 error:
11569 	push_args(ctx, arg);
11570 	return -1;
11571 }
11572 
11573 /**
11574  * Parse an IPv4 address.
11575  *
11576  * Last argument (ctx->args) is retrieved to determine storage size and
11577  * location.
11578  */
11579 static int
11580 parse_ipv4_addr(struct context *ctx, const struct token *token,
11581 		const char *str, unsigned int len,
11582 		void *buf, unsigned int size)
11583 {
11584 	const struct arg *arg = pop_args(ctx);
11585 	char str2[len + 1];
11586 	struct in_addr tmp;
11587 	int ret;
11588 
11589 	/* Argument is expected. */
11590 	if (!arg)
11591 		return -1;
11592 	size = arg->size;
11593 	/* Bit-mask fill is not supported. */
11594 	if (arg->mask || size != sizeof(tmp))
11595 		goto error;
11596 	/* Only network endian is supported. */
11597 	if (!arg->hton)
11598 		goto error;
11599 	memcpy(str2, str, len);
11600 	str2[len] = '\0';
11601 	ret = inet_pton(AF_INET, str2, &tmp);
11602 	if (ret != 1) {
11603 		/* Attempt integer parsing. */
11604 		push_args(ctx, arg);
11605 		return parse_int(ctx, token, str, len, buf, size);
11606 	}
11607 	if (!ctx->object)
11608 		return len;
11609 	buf = (uint8_t *)ctx->object + arg->offset;
11610 	memcpy(buf, &tmp, size);
11611 	if (ctx->objmask)
11612 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11613 	return len;
11614 error:
11615 	push_args(ctx, arg);
11616 	return -1;
11617 }
11618 
11619 /**
11620  * Parse an IPv6 address.
11621  *
11622  * Last argument (ctx->args) is retrieved to determine storage size and
11623  * location.
11624  */
11625 static int
11626 parse_ipv6_addr(struct context *ctx, const struct token *token,
11627 		const char *str, unsigned int len,
11628 		void *buf, unsigned int size)
11629 {
11630 	const struct arg *arg = pop_args(ctx);
11631 	char str2[len + 1];
11632 	struct in6_addr tmp;
11633 	int ret;
11634 
11635 	(void)token;
11636 	/* Argument is expected. */
11637 	if (!arg)
11638 		return -1;
11639 	size = arg->size;
11640 	/* Bit-mask fill is not supported. */
11641 	if (arg->mask || size != sizeof(tmp))
11642 		goto error;
11643 	/* Only network endian is supported. */
11644 	if (!arg->hton)
11645 		goto error;
11646 	memcpy(str2, str, len);
11647 	str2[len] = '\0';
11648 	ret = inet_pton(AF_INET6, str2, &tmp);
11649 	if (ret != 1)
11650 		goto error;
11651 	if (!ctx->object)
11652 		return len;
11653 	buf = (uint8_t *)ctx->object + arg->offset;
11654 	memcpy(buf, &tmp, size);
11655 	if (ctx->objmask)
11656 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11657 	return len;
11658 error:
11659 	push_args(ctx, arg);
11660 	return -1;
11661 }
11662 
11663 /** Boolean values (even indices stand for false). */
11664 static const char *const boolean_name[] = {
11665 	"0", "1",
11666 	"false", "true",
11667 	"no", "yes",
11668 	"N", "Y",
11669 	"off", "on",
11670 	NULL,
11671 };
11672 
11673 /**
11674  * Parse a boolean value.
11675  *
11676  * Last argument (ctx->args) is retrieved to determine storage size and
11677  * location.
11678  */
11679 static int
11680 parse_boolean(struct context *ctx, const struct token *token,
11681 	      const char *str, unsigned int len,
11682 	      void *buf, unsigned int size)
11683 {
11684 	const struct arg *arg = pop_args(ctx);
11685 	unsigned int i;
11686 	int ret;
11687 
11688 	/* Argument is expected. */
11689 	if (!arg)
11690 		return -1;
11691 	for (i = 0; boolean_name[i]; ++i)
11692 		if (!strcmp_partial(boolean_name[i], str, len))
11693 			break;
11694 	/* Process token as integer. */
11695 	if (boolean_name[i])
11696 		str = i & 1 ? "1" : "0";
11697 	push_args(ctx, arg);
11698 	ret = parse_int(ctx, token, str, strlen(str), buf, size);
11699 	return ret > 0 ? (int)len : ret;
11700 }
11701 
11702 /** Parse port and update context. */
11703 static int
11704 parse_port(struct context *ctx, const struct token *token,
11705 	   const char *str, unsigned int len,
11706 	   void *buf, unsigned int size)
11707 {
11708 	struct buffer *out = &(struct buffer){ .port = 0 };
11709 	int ret;
11710 
11711 	if (buf)
11712 		out = buf;
11713 	else {
11714 		ctx->objdata = 0;
11715 		ctx->object = out;
11716 		ctx->objmask = NULL;
11717 		size = sizeof(*out);
11718 	}
11719 	ret = parse_int(ctx, token, str, len, out, size);
11720 	if (ret >= 0)
11721 		ctx->port = out->port;
11722 	if (!buf)
11723 		ctx->object = NULL;
11724 	return ret;
11725 }
11726 
11727 /** Parse tokens for shared indirect actions. */
11728 static int
11729 parse_ia_port(struct context *ctx, const struct token *token,
11730 	      const char *str, unsigned int len,
11731 	      void *buf, unsigned int size)
11732 {
11733 	struct rte_flow_action *action = ctx->object;
11734 	uint32_t id;
11735 	int ret;
11736 
11737 	(void)buf;
11738 	(void)size;
11739 	ctx->objdata = 0;
11740 	ctx->object = &id;
11741 	ctx->objmask = NULL;
11742 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11743 	ctx->object = action;
11744 	if (ret != (int)len)
11745 		return ret;
11746 	/* set indirect action */
11747 	if (action)
11748 		action->conf = (void *)(uintptr_t)id;
11749 	return ret;
11750 }
11751 
11752 static int
11753 parse_ia_id2ptr(struct context *ctx, const struct token *token,
11754 		const char *str, unsigned int len,
11755 		void *buf, unsigned int size)
11756 {
11757 	struct rte_flow_action *action = ctx->object;
11758 	uint32_t id;
11759 	int ret;
11760 
11761 	(void)buf;
11762 	(void)size;
11763 	ctx->objdata = 0;
11764 	ctx->object = &id;
11765 	ctx->objmask = NULL;
11766 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11767 	ctx->object = action;
11768 	if (ret != (int)len)
11769 		return ret;
11770 	/* set indirect action */
11771 	if (action) {
11772 		portid_t port_id = ctx->port;
11773 		if (ctx->prev == INDIRECT_ACTION_PORT)
11774 			port_id = (portid_t)(uintptr_t)action->conf;
11775 		action->conf = port_action_handle_get_by_id(port_id, id);
11776 		ret = (action->conf) ? ret : -1;
11777 	}
11778 	return ret;
11779 }
11780 
11781 static int
11782 parse_indlst_id2ptr(struct context *ctx, const struct token *token,
11783 		    const char *str, unsigned int len,
11784 		    __rte_unused void *buf, __rte_unused unsigned int size)
11785 {
11786 	struct rte_flow_action *action = ctx->object;
11787 	struct rte_flow_action_indirect_list *action_conf;
11788 	const struct indlst_conf *indlst_conf;
11789 	uint32_t id;
11790 	int ret;
11791 
11792 	if (!action)
11793 		return -1;
11794 	ctx->objdata = 0;
11795 	ctx->object = &id;
11796 	ctx->objmask = NULL;
11797 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11798 	if (ret != (int)len)
11799 		return ret;
11800 	ctx->object = action;
11801 	action_conf = (void *)(uintptr_t)action->conf;
11802 	action_conf->conf = NULL;
11803 	switch (ctx->curr) {
11804 	case INDIRECT_LIST_ACTION_ID2PTR_HANDLE:
11805 	action_conf->handle = (typeof(action_conf->handle))
11806 				port_action_handle_get_by_id(ctx->port, id);
11807 		if (!action_conf->handle) {
11808 			printf("no indirect list handle for id %u\n", id);
11809 			return -1;
11810 		}
11811 		break;
11812 	case INDIRECT_LIST_ACTION_ID2PTR_CONF:
11813 		indlst_conf = indirect_action_list_conf_get(id);
11814 		if (!indlst_conf)
11815 			return -1;
11816 		action_conf->conf = (const void **)indlst_conf->conf;
11817 		break;
11818 	default:
11819 		break;
11820 	}
11821 	return ret;
11822 }
11823 
11824 static int
11825 parse_meter_profile_id2ptr(struct context *ctx, const struct token *token,
11826 		const char *str, unsigned int len,
11827 		void *buf, unsigned int size)
11828 {
11829 	struct rte_flow_action *action = ctx->object;
11830 	struct rte_flow_action_meter_mark *meter;
11831 	struct rte_flow_meter_profile *profile = NULL;
11832 	uint32_t id = 0;
11833 	int ret;
11834 
11835 	(void)buf;
11836 	(void)size;
11837 	ctx->objdata = 0;
11838 	ctx->object = &id;
11839 	ctx->objmask = NULL;
11840 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11841 	ctx->object = action;
11842 	if (ret != (int)len)
11843 		return ret;
11844 	/* set meter profile */
11845 	if (action) {
11846 		meter = (struct rte_flow_action_meter_mark *)
11847 			(uintptr_t)(action->conf);
11848 		profile = port_meter_profile_get_by_id(ctx->port, id);
11849 		meter->profile = profile;
11850 		ret = (profile) ? ret : -1;
11851 	}
11852 	return ret;
11853 }
11854 
11855 static int
11856 parse_meter_policy_id2ptr(struct context *ctx, const struct token *token,
11857 		const char *str, unsigned int len,
11858 		void *buf, unsigned int size)
11859 {
11860 	struct rte_flow_action *action = ctx->object;
11861 	struct rte_flow_action_meter_mark *meter;
11862 	struct rte_flow_meter_policy *policy = NULL;
11863 	uint32_t id = 0;
11864 	int ret;
11865 
11866 	(void)buf;
11867 	(void)size;
11868 	ctx->objdata = 0;
11869 	ctx->object = &id;
11870 	ctx->objmask = NULL;
11871 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11872 	ctx->object = action;
11873 	if (ret != (int)len)
11874 		return ret;
11875 	/* set meter policy */
11876 	if (action) {
11877 		meter = (struct rte_flow_action_meter_mark *)
11878 			(uintptr_t)(action->conf);
11879 		policy = port_meter_policy_get_by_id(ctx->port, id);
11880 		meter->policy = policy;
11881 		ret = (policy) ? ret : -1;
11882 	}
11883 	return ret;
11884 }
11885 
11886 /** Parse set command, initialize output buffer for subsequent tokens. */
11887 static int
11888 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
11889 			  const char *str, unsigned int len,
11890 			  void *buf, unsigned int size)
11891 {
11892 	struct buffer *out = buf;
11893 
11894 	/* Token name must match. */
11895 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11896 		return -1;
11897 	/* Nothing else to do if there is no buffer. */
11898 	if (!out)
11899 		return len;
11900 	/* Make sure buffer is large enough. */
11901 	if (size < sizeof(*out))
11902 		return -1;
11903 	ctx->objdata = 0;
11904 	ctx->objmask = NULL;
11905 	ctx->object = out;
11906 	if (!out->command)
11907 		return -1;
11908 	out->command = ctx->curr;
11909 	/* For encap/decap we need is pattern */
11910 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11911 						       sizeof(double));
11912 	return len;
11913 }
11914 
11915 /** Parse set command, initialize output buffer for subsequent tokens. */
11916 static int
11917 parse_set_sample_action(struct context *ctx, const struct token *token,
11918 			  const char *str, unsigned int len,
11919 			  void *buf, unsigned int size)
11920 {
11921 	struct buffer *out = buf;
11922 
11923 	/* Token name must match. */
11924 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11925 		return -1;
11926 	/* Nothing else to do if there is no buffer. */
11927 	if (!out)
11928 		return len;
11929 	/* Make sure buffer is large enough. */
11930 	if (size < sizeof(*out))
11931 		return -1;
11932 	ctx->objdata = 0;
11933 	ctx->objmask = NULL;
11934 	ctx->object = out;
11935 	if (!out->command)
11936 		return -1;
11937 	out->command = ctx->curr;
11938 	/* For sampler we need is actions */
11939 	out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11940 						       sizeof(double));
11941 	return len;
11942 }
11943 
11944 /** Parse set command, initialize output buffer for subsequent tokens. */
11945 static int
11946 parse_set_ipv6_ext_action(struct context *ctx, const struct token *token,
11947 			  const char *str, unsigned int len,
11948 			  void *buf, unsigned int size)
11949 {
11950 	struct buffer *out = buf;
11951 
11952 	/* Token name must match. */
11953 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11954 		return -1;
11955 	/* Nothing else to do if there is no buffer. */
11956 	if (!out)
11957 		return len;
11958 	/* Make sure buffer is large enough. */
11959 	if (size < sizeof(*out))
11960 		return -1;
11961 	ctx->objdata = 0;
11962 	ctx->objmask = NULL;
11963 	ctx->object = out;
11964 	if (!out->command)
11965 		return -1;
11966 	out->command = ctx->curr;
11967 	/* For ipv6_ext_push/remove we need is pattern */
11968 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11969 						       sizeof(double));
11970 	return len;
11971 }
11972 
11973 /**
11974  * Parse set raw_encap/raw_decap command,
11975  * initialize output buffer for subsequent tokens.
11976  */
11977 static int
11978 parse_set_init(struct context *ctx, const struct token *token,
11979 	       const char *str, unsigned int len,
11980 	       void *buf, unsigned int size)
11981 {
11982 	struct buffer *out = buf;
11983 
11984 	/* Token name must match. */
11985 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11986 		return -1;
11987 	/* Nothing else to do if there is no buffer. */
11988 	if (!out)
11989 		return len;
11990 	/* Make sure buffer is large enough. */
11991 	if (size < sizeof(*out))
11992 		return -1;
11993 	/* Initialize buffer. */
11994 	memset(out, 0x00, sizeof(*out));
11995 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
11996 	ctx->objdata = 0;
11997 	ctx->object = out;
11998 	ctx->objmask = NULL;
11999 	if (!out->command) {
12000 		if (ctx->curr != SET)
12001 			return -1;
12002 		if (sizeof(*out) > size)
12003 			return -1;
12004 		out->command = ctx->curr;
12005 		out->args.vc.data = (uint8_t *)out + size;
12006 		ctx->object  = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12007 						       sizeof(double));
12008 	}
12009 	return len;
12010 }
12011 
12012 /*
12013  * Replace testpmd handles in a flex flow item with real values.
12014  */
12015 static int
12016 parse_flex_handle(struct context *ctx, const struct token *token,
12017 		  const char *str, unsigned int len,
12018 		  void *buf, unsigned int size)
12019 {
12020 	struct rte_flow_item_flex *spec, *mask;
12021 	const struct rte_flow_item_flex *src_spec, *src_mask;
12022 	const struct arg *arg = pop_args(ctx);
12023 	uint32_t offset;
12024 	uint16_t handle;
12025 	int ret;
12026 
12027 	if (!arg) {
12028 		printf("Bad environment\n");
12029 		return -1;
12030 	}
12031 	offset = arg->offset;
12032 	push_args(ctx, arg);
12033 	ret = parse_int(ctx, token, str, len, buf, size);
12034 	if (ret <= 0 || !ctx->object)
12035 		return ret;
12036 	if (ctx->port >= RTE_MAX_ETHPORTS) {
12037 		printf("Bad port\n");
12038 		return -1;
12039 	}
12040 	if (offset == offsetof(struct rte_flow_item_flex, handle)) {
12041 		const struct flex_item *fp;
12042 		spec = ctx->object;
12043 		handle = (uint16_t)(uintptr_t)spec->handle;
12044 		if (handle >= FLEX_MAX_PARSERS_NUM) {
12045 			printf("Bad flex item handle\n");
12046 			return -1;
12047 		}
12048 		fp = flex_items[ctx->port][handle];
12049 		if (!fp) {
12050 			printf("Bad flex item handle\n");
12051 			return -1;
12052 		}
12053 		spec->handle = fp->flex_handle;
12054 		mask = spec + 2; /* spec, last, mask */
12055 		mask->handle = fp->flex_handle;
12056 	} else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
12057 		handle = (uint16_t)(uintptr_t)
12058 			((struct rte_flow_item_flex *)ctx->object)->pattern;
12059 		if (handle >= FLEX_MAX_PATTERNS_NUM) {
12060 			printf("Bad pattern handle\n");
12061 			return -1;
12062 		}
12063 		src_spec = &flex_patterns[handle].spec;
12064 		src_mask = &flex_patterns[handle].mask;
12065 		spec = ctx->object;
12066 		mask = spec + 2; /* spec, last, mask */
12067 		/* fill flow rule spec and mask parameters */
12068 		spec->length = src_spec->length;
12069 		spec->pattern = src_spec->pattern;
12070 		mask->length = src_mask->length;
12071 		mask->pattern = src_mask->pattern;
12072 	} else {
12073 		printf("Bad arguments - unknown flex item offset\n");
12074 		return -1;
12075 	}
12076 	return ret;
12077 }
12078 
12079 /** Parse Meter color name */
12080 static int
12081 parse_meter_color(struct context *ctx, const struct token *token,
12082 		  const char *str, unsigned int len, void *buf,
12083 		  unsigned int size)
12084 {
12085 	struct rte_flow_item_meter_color *meter_color;
12086 	unsigned int i;
12087 
12088 	(void)token;
12089 	(void)buf;
12090 	(void)size;
12091 	for (i = 0; meter_colors[i]; ++i)
12092 		if (!strcmp_partial(meter_colors[i], str, len))
12093 			break;
12094 	if (!meter_colors[i])
12095 		return -1;
12096 	if (!ctx->object)
12097 		return len;
12098 	meter_color = ctx->object;
12099 	meter_color->color = (enum rte_color)i;
12100 	return len;
12101 }
12102 
12103 /** Parse Insertion Table Type name */
12104 static int
12105 parse_insertion_table_type(struct context *ctx, const struct token *token,
12106 			   const char *str, unsigned int len, void *buf,
12107 			   unsigned int size)
12108 {
12109 	const struct arg *arg = pop_args(ctx);
12110 	unsigned int i;
12111 	char tmp[2];
12112 	int ret;
12113 
12114 	(void)size;
12115 	/* Argument is expected. */
12116 	if (!arg)
12117 		return -1;
12118 	for (i = 0; table_insertion_types[i]; ++i)
12119 		if (!strcmp_partial(table_insertion_types[i], str, len))
12120 			break;
12121 	if (!table_insertion_types[i])
12122 		return -1;
12123 	push_args(ctx, arg);
12124 	snprintf(tmp, sizeof(tmp), "%u", i);
12125 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12126 	return ret > 0 ? (int)len : ret;
12127 }
12128 
12129 /** Parse Hash Calculation Table Type name */
12130 static int
12131 parse_hash_table_type(struct context *ctx, const struct token *token,
12132 		      const char *str, unsigned int len, void *buf,
12133 		      unsigned int size)
12134 {
12135 	const struct arg *arg = pop_args(ctx);
12136 	unsigned int i;
12137 	char tmp[2];
12138 	int ret;
12139 
12140 	(void)size;
12141 	/* Argument is expected. */
12142 	if (!arg)
12143 		return -1;
12144 	for (i = 0; table_hash_funcs[i]; ++i)
12145 		if (!strcmp_partial(table_hash_funcs[i], str, len))
12146 			break;
12147 	if (!table_hash_funcs[i])
12148 		return -1;
12149 	push_args(ctx, arg);
12150 	snprintf(tmp, sizeof(tmp), "%u", i);
12151 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12152 	return ret > 0 ? (int)len : ret;
12153 }
12154 
12155 static int
12156 parse_name_to_index(struct context *ctx, const struct token *token,
12157 		    const char *str, unsigned int len, void *buf,
12158 		    unsigned int size,
12159 		    const char *const names[], size_t names_size, uint32_t *dst)
12160 {
12161 	int ret;
12162 	uint32_t i;
12163 
12164 	RTE_SET_USED(token);
12165 	RTE_SET_USED(buf);
12166 	RTE_SET_USED(size);
12167 	if (!ctx->object)
12168 		return len;
12169 	for (i = 0; i < names_size; i++) {
12170 		if (!names[i])
12171 			continue;
12172 		ret = strcmp_partial(names[i], str,
12173 				     RTE_MIN(len, strlen(names[i])));
12174 		if (!ret) {
12175 			*dst = i;
12176 			return len;
12177 		}
12178 	}
12179 	return -1;
12180 }
12181 
12182 static const char *const quota_mode_names[] = {
12183 	NULL,
12184 	[RTE_FLOW_QUOTA_MODE_PACKET] = "packet",
12185 	[RTE_FLOW_QUOTA_MODE_L2] = "l2",
12186 	[RTE_FLOW_QUOTA_MODE_L3] = "l3"
12187 };
12188 
12189 static const char *const quota_state_names[] = {
12190 	[RTE_FLOW_QUOTA_STATE_PASS] = "pass",
12191 	[RTE_FLOW_QUOTA_STATE_BLOCK] = "block"
12192 };
12193 
12194 static const char *const quota_update_names[] = {
12195 	[RTE_FLOW_UPDATE_QUOTA_SET] = "set",
12196 	[RTE_FLOW_UPDATE_QUOTA_ADD] = "add"
12197 };
12198 
12199 static const char *const query_update_mode_names[] = {
12200 	[RTE_FLOW_QU_QUERY_FIRST] = "query_first",
12201 	[RTE_FLOW_QU_UPDATE_FIRST] = "update_first"
12202 };
12203 
12204 static int
12205 parse_quota_state_name(struct context *ctx, const struct token *token,
12206 		       const char *str, unsigned int len, void *buf,
12207 		       unsigned int size)
12208 {
12209 	struct rte_flow_item_quota *quota = ctx->object;
12210 
12211 	return parse_name_to_index(ctx, token, str, len, buf, size,
12212 				   quota_state_names,
12213 				   RTE_DIM(quota_state_names),
12214 				   (uint32_t *)&quota->state);
12215 }
12216 
12217 static int
12218 parse_quota_mode_name(struct context *ctx, const struct token *token,
12219 		      const char *str, unsigned int len, void *buf,
12220 		      unsigned int size)
12221 {
12222 	struct rte_flow_action_quota *quota = ctx->object;
12223 
12224 	return parse_name_to_index(ctx, token, str, len, buf, size,
12225 				   quota_mode_names,
12226 				   RTE_DIM(quota_mode_names),
12227 				   (uint32_t *)&quota->mode);
12228 }
12229 
12230 static int
12231 parse_quota_update_name(struct context *ctx, const struct token *token,
12232 			const char *str, unsigned int len, void *buf,
12233 			unsigned int size)
12234 {
12235 	struct rte_flow_update_quota *update = ctx->object;
12236 
12237 	return parse_name_to_index(ctx, token, str, len, buf, size,
12238 				   quota_update_names,
12239 				   RTE_DIM(quota_update_names),
12240 				   (uint32_t *)&update->op);
12241 }
12242 
12243 static int
12244 parse_qu_mode_name(struct context *ctx, const struct token *token,
12245 		   const char *str, unsigned int len, void *buf,
12246 		   unsigned int size)
12247 {
12248 	struct buffer *out = ctx->object;
12249 
12250 	return parse_name_to_index(ctx, token, str, len, buf, size,
12251 				   query_update_mode_names,
12252 				   RTE_DIM(query_update_mode_names),
12253 				   (uint32_t *)&out->args.ia.qu_mode);
12254 }
12255 
12256 /** No completion. */
12257 static int
12258 comp_none(struct context *ctx, const struct token *token,
12259 	  unsigned int ent, char *buf, unsigned int size)
12260 {
12261 	(void)ctx;
12262 	(void)token;
12263 	(void)ent;
12264 	(void)buf;
12265 	(void)size;
12266 	return 0;
12267 }
12268 
12269 /** Complete boolean values. */
12270 static int
12271 comp_boolean(struct context *ctx, const struct token *token,
12272 	     unsigned int ent, char *buf, unsigned int size)
12273 {
12274 	unsigned int i;
12275 
12276 	(void)ctx;
12277 	(void)token;
12278 	for (i = 0; boolean_name[i]; ++i)
12279 		if (buf && i == ent)
12280 			return strlcpy(buf, boolean_name[i], size);
12281 	if (buf)
12282 		return -1;
12283 	return i;
12284 }
12285 
12286 /** Complete action names. */
12287 static int
12288 comp_action(struct context *ctx, const struct token *token,
12289 	    unsigned int ent, char *buf, unsigned int size)
12290 {
12291 	unsigned int i;
12292 
12293 	(void)ctx;
12294 	(void)token;
12295 	for (i = 0; next_action[i]; ++i)
12296 		if (buf && i == ent)
12297 			return strlcpy(buf, token_list[next_action[i]].name,
12298 				       size);
12299 	if (buf)
12300 		return -1;
12301 	return i;
12302 }
12303 
12304 /** Complete available ports. */
12305 static int
12306 comp_port(struct context *ctx, const struct token *token,
12307 	  unsigned int ent, char *buf, unsigned int size)
12308 {
12309 	unsigned int i = 0;
12310 	portid_t p;
12311 
12312 	(void)ctx;
12313 	(void)token;
12314 	RTE_ETH_FOREACH_DEV(p) {
12315 		if (buf && i == ent)
12316 			return snprintf(buf, size, "%u", p);
12317 		++i;
12318 	}
12319 	if (buf)
12320 		return -1;
12321 	return i;
12322 }
12323 
12324 /** Complete available rule IDs. */
12325 static int
12326 comp_rule_id(struct context *ctx, const struct token *token,
12327 	     unsigned int ent, char *buf, unsigned int size)
12328 {
12329 	unsigned int i = 0;
12330 	struct rte_port *port;
12331 	struct port_flow *pf;
12332 
12333 	(void)token;
12334 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12335 	    ctx->port == (portid_t)RTE_PORT_ALL)
12336 		return -1;
12337 	port = &ports[ctx->port];
12338 	for (pf = port->flow_list; pf != NULL; pf = pf->next) {
12339 		if (buf && i == ent)
12340 			return snprintf(buf, size, "%"PRIu64, pf->id);
12341 		++i;
12342 	}
12343 	if (buf)
12344 		return -1;
12345 	return i;
12346 }
12347 
12348 /** Complete operation for compare match item. */
12349 static int
12350 comp_set_compare_op(struct context *ctx, const struct token *token,
12351 		    unsigned int ent, char *buf, unsigned int size)
12352 {
12353 	RTE_SET_USED(ctx);
12354 	RTE_SET_USED(token);
12355 	if (!buf)
12356 		return RTE_DIM(compare_ops);
12357 	if (ent < RTE_DIM(compare_ops) - 1)
12358 		return strlcpy(buf, compare_ops[ent], size);
12359 	return -1;
12360 }
12361 
12362 /** Complete field id for compare match item. */
12363 static int
12364 comp_set_compare_field_id(struct context *ctx, const struct token *token,
12365 			  unsigned int ent, char *buf, unsigned int size)
12366 {
12367 	const char *name;
12368 
12369 	RTE_SET_USED(token);
12370 	if (!buf)
12371 		return RTE_DIM(flow_field_ids);
12372 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12373 		return -1;
12374 	name = flow_field_ids[ent];
12375 	if (ctx->curr == ITEM_COMPARE_FIELD_B_TYPE ||
12376 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12377 		return strlcpy(buf, name, size);
12378 	return -1;
12379 }
12380 
12381 /** Complete type field for RSS action. */
12382 static int
12383 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
12384 			unsigned int ent, char *buf, unsigned int size)
12385 {
12386 	unsigned int i;
12387 
12388 	(void)ctx;
12389 	(void)token;
12390 	for (i = 0; rss_type_table[i].str; ++i)
12391 		;
12392 	if (!buf)
12393 		return i + 1;
12394 	if (ent < i)
12395 		return strlcpy(buf, rss_type_table[ent].str, size);
12396 	if (ent == i)
12397 		return snprintf(buf, size, "end");
12398 	return -1;
12399 }
12400 
12401 /** Complete queue field for RSS action. */
12402 static int
12403 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
12404 			 unsigned int ent, char *buf, unsigned int size)
12405 {
12406 	(void)ctx;
12407 	(void)token;
12408 	if (!buf)
12409 		return nb_rxq + 1;
12410 	if (ent < nb_rxq)
12411 		return snprintf(buf, size, "%u", ent);
12412 	if (ent == nb_rxq)
12413 		return snprintf(buf, size, "end");
12414 	return -1;
12415 }
12416 
12417 /** Complete index number for set raw_encap/raw_decap commands. */
12418 static int
12419 comp_set_raw_index(struct context *ctx, const struct token *token,
12420 		   unsigned int ent, char *buf, unsigned int size)
12421 {
12422 	uint16_t idx = 0;
12423 	uint16_t nb = 0;
12424 
12425 	RTE_SET_USED(ctx);
12426 	RTE_SET_USED(token);
12427 	for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
12428 		if (buf && idx == ent)
12429 			return snprintf(buf, size, "%u", idx);
12430 		++nb;
12431 	}
12432 	return nb;
12433 }
12434 
12435 /** Complete index number for set raw_ipv6_ext_push/ipv6_ext_remove commands. */
12436 static int
12437 comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
12438 			unsigned int ent, char *buf, unsigned int size)
12439 {
12440 	uint16_t idx = 0;
12441 	uint16_t nb = 0;
12442 
12443 	RTE_SET_USED(ctx);
12444 	RTE_SET_USED(token);
12445 	for (idx = 0; idx < IPV6_EXT_PUSH_CONFS_MAX_NUM; ++idx) {
12446 		if (buf && idx == ent)
12447 			return snprintf(buf, size, "%u", idx);
12448 		++nb;
12449 	}
12450 	return nb;
12451 }
12452 
12453 /** Complete index number for set raw_encap/raw_decap commands. */
12454 static int
12455 comp_set_sample_index(struct context *ctx, const struct token *token,
12456 		   unsigned int ent, char *buf, unsigned int size)
12457 {
12458 	uint16_t idx = 0;
12459 	uint16_t nb = 0;
12460 
12461 	RTE_SET_USED(ctx);
12462 	RTE_SET_USED(token);
12463 	for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
12464 		if (buf && idx == ent)
12465 			return snprintf(buf, size, "%u", idx);
12466 		++nb;
12467 	}
12468 	return nb;
12469 }
12470 
12471 /** Complete operation for modify_field command. */
12472 static int
12473 comp_set_modify_field_op(struct context *ctx, const struct token *token,
12474 		   unsigned int ent, char *buf, unsigned int size)
12475 {
12476 	RTE_SET_USED(ctx);
12477 	RTE_SET_USED(token);
12478 	if (!buf)
12479 		return RTE_DIM(modify_field_ops);
12480 	if (ent < RTE_DIM(modify_field_ops) - 1)
12481 		return strlcpy(buf, modify_field_ops[ent], size);
12482 	return -1;
12483 }
12484 
12485 /** Complete field id for modify_field command. */
12486 static int
12487 comp_set_modify_field_id(struct context *ctx, const struct token *token,
12488 		   unsigned int ent, char *buf, unsigned int size)
12489 {
12490 	const char *name;
12491 
12492 	RTE_SET_USED(token);
12493 	if (!buf)
12494 		return RTE_DIM(flow_field_ids);
12495 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12496 		return -1;
12497 	name = flow_field_ids[ent];
12498 	if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
12499 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12500 		return strlcpy(buf, name, size);
12501 	return -1;
12502 }
12503 
12504 /** Complete available pattern template IDs. */
12505 static int
12506 comp_pattern_template_id(struct context *ctx, const struct token *token,
12507 			 unsigned int ent, char *buf, unsigned int size)
12508 {
12509 	unsigned int i = 0;
12510 	struct rte_port *port;
12511 	struct port_template *pt;
12512 
12513 	(void)token;
12514 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12515 	    ctx->port == (portid_t)RTE_PORT_ALL)
12516 		return -1;
12517 	port = &ports[ctx->port];
12518 	for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) {
12519 		if (buf && i == ent)
12520 			return snprintf(buf, size, "%u", pt->id);
12521 		++i;
12522 	}
12523 	if (buf)
12524 		return -1;
12525 	return i;
12526 }
12527 
12528 /** Complete available actions template IDs. */
12529 static int
12530 comp_actions_template_id(struct context *ctx, const struct token *token,
12531 			 unsigned int ent, char *buf, unsigned int size)
12532 {
12533 	unsigned int i = 0;
12534 	struct rte_port *port;
12535 	struct port_template *pt;
12536 
12537 	(void)token;
12538 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12539 	    ctx->port == (portid_t)RTE_PORT_ALL)
12540 		return -1;
12541 	port = &ports[ctx->port];
12542 	for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) {
12543 		if (buf && i == ent)
12544 			return snprintf(buf, size, "%u", pt->id);
12545 		++i;
12546 	}
12547 	if (buf)
12548 		return -1;
12549 	return i;
12550 }
12551 
12552 /** Complete available table IDs. */
12553 static int
12554 comp_table_id(struct context *ctx, const struct token *token,
12555 	      unsigned int ent, char *buf, unsigned int size)
12556 {
12557 	unsigned int i = 0;
12558 	struct rte_port *port;
12559 	struct port_table *pt;
12560 
12561 	(void)token;
12562 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12563 	    ctx->port == (portid_t)RTE_PORT_ALL)
12564 		return -1;
12565 	port = &ports[ctx->port];
12566 	for (pt = port->table_list; pt != NULL; pt = pt->next) {
12567 		if (buf && i == ent)
12568 			return snprintf(buf, size, "%u", pt->id);
12569 		++i;
12570 	}
12571 	if (buf)
12572 		return -1;
12573 	return i;
12574 }
12575 
12576 /** Complete available queue IDs. */
12577 static int
12578 comp_queue_id(struct context *ctx, const struct token *token,
12579 	      unsigned int ent, char *buf, unsigned int size)
12580 {
12581 	unsigned int i = 0;
12582 	struct rte_port *port;
12583 
12584 	(void)token;
12585 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12586 	    ctx->port == (portid_t)RTE_PORT_ALL)
12587 		return -1;
12588 	port = &ports[ctx->port];
12589 	for (i = 0; i < port->queue_nb; i++) {
12590 		if (buf && i == ent)
12591 			return snprintf(buf, size, "%u", i);
12592 	}
12593 	if (buf)
12594 		return -1;
12595 	return i;
12596 }
12597 
12598 static int
12599 comp_names_to_index(struct context *ctx, const struct token *token,
12600 		    unsigned int ent, char *buf, unsigned int size,
12601 		    const char *const names[], size_t names_size)
12602 {
12603 	RTE_SET_USED(ctx);
12604 	RTE_SET_USED(token);
12605 	if (!buf)
12606 		return names_size;
12607 	if (names[ent] && ent < names_size)
12608 		return rte_strscpy(buf, names[ent], size);
12609 	return -1;
12610 
12611 }
12612 
12613 /** Complete available Meter colors. */
12614 static int
12615 comp_meter_color(struct context *ctx, const struct token *token,
12616 		 unsigned int ent, char *buf, unsigned int size)
12617 {
12618 	RTE_SET_USED(ctx);
12619 	RTE_SET_USED(token);
12620 	if (!buf)
12621 		return RTE_DIM(meter_colors);
12622 	if (ent < RTE_DIM(meter_colors) - 1)
12623 		return strlcpy(buf, meter_colors[ent], size);
12624 	return -1;
12625 }
12626 
12627 /** Complete available Insertion Table types. */
12628 static int
12629 comp_insertion_table_type(struct context *ctx, const struct token *token,
12630 			  unsigned int ent, char *buf, unsigned int size)
12631 {
12632 	RTE_SET_USED(ctx);
12633 	RTE_SET_USED(token);
12634 	if (!buf)
12635 		return RTE_DIM(table_insertion_types);
12636 	if (ent < RTE_DIM(table_insertion_types) - 1)
12637 		return rte_strscpy(buf, table_insertion_types[ent], size);
12638 	return -1;
12639 }
12640 
12641 /** Complete available Hash Calculation Table types. */
12642 static int
12643 comp_hash_table_type(struct context *ctx, const struct token *token,
12644 		     unsigned int ent, char *buf, unsigned int size)
12645 {
12646 	RTE_SET_USED(ctx);
12647 	RTE_SET_USED(token);
12648 	if (!buf)
12649 		return RTE_DIM(table_hash_funcs);
12650 	if (ent < RTE_DIM(table_hash_funcs) - 1)
12651 		return rte_strscpy(buf, table_hash_funcs[ent], size);
12652 	return -1;
12653 }
12654 
12655 static int
12656 comp_quota_state_name(struct context *ctx, const struct token *token,
12657 		      unsigned int ent, char *buf, unsigned int size)
12658 {
12659 	return comp_names_to_index(ctx, token, ent, buf, size,
12660 				   quota_state_names,
12661 				   RTE_DIM(quota_state_names));
12662 }
12663 
12664 static int
12665 comp_quota_mode_name(struct context *ctx, const struct token *token,
12666 		     unsigned int ent, char *buf, unsigned int size)
12667 {
12668 	return comp_names_to_index(ctx, token, ent, buf, size,
12669 				   quota_mode_names,
12670 				   RTE_DIM(quota_mode_names));
12671 }
12672 
12673 static int
12674 comp_quota_update_name(struct context *ctx, const struct token *token,
12675 		       unsigned int ent, char *buf, unsigned int size)
12676 {
12677 	return comp_names_to_index(ctx, token, ent, buf, size,
12678 				   quota_update_names,
12679 				   RTE_DIM(quota_update_names));
12680 }
12681 
12682 static int
12683 comp_qu_mode_name(struct context *ctx, const struct token *token,
12684 		  unsigned int ent, char *buf, unsigned int size)
12685 {
12686 	return comp_names_to_index(ctx, token, ent, buf, size,
12687 				   query_update_mode_names,
12688 				   RTE_DIM(query_update_mode_names));
12689 }
12690 
12691 /** Internal context. */
12692 static struct context cmd_flow_context;
12693 
12694 /** Global parser instance (cmdline API). */
12695 cmdline_parse_inst_t cmd_flow;
12696 cmdline_parse_inst_t cmd_set_raw;
12697 
12698 /** Initialize context. */
12699 static void
12700 cmd_flow_context_init(struct context *ctx)
12701 {
12702 	/* A full memset() is not necessary. */
12703 	ctx->curr = ZERO;
12704 	ctx->prev = ZERO;
12705 	ctx->next_num = 0;
12706 	ctx->args_num = 0;
12707 	ctx->eol = 0;
12708 	ctx->last = 0;
12709 	ctx->port = 0;
12710 	ctx->objdata = 0;
12711 	ctx->object = NULL;
12712 	ctx->objmask = NULL;
12713 }
12714 
12715 /** Parse a token (cmdline API). */
12716 static int
12717 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
12718 	       unsigned int size)
12719 {
12720 	struct context *ctx = &cmd_flow_context;
12721 	const struct token *token;
12722 	const enum index *list;
12723 	int len;
12724 	int i;
12725 
12726 	(void)hdr;
12727 	token = &token_list[ctx->curr];
12728 	/* Check argument length. */
12729 	ctx->eol = 0;
12730 	ctx->last = 1;
12731 	for (len = 0; src[len]; ++len)
12732 		if (src[len] == '#' || isspace(src[len]))
12733 			break;
12734 	if (!len)
12735 		return -1;
12736 	/* Last argument and EOL detection. */
12737 	for (i = len; src[i]; ++i)
12738 		if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
12739 			break;
12740 		else if (!isspace(src[i])) {
12741 			ctx->last = 0;
12742 			break;
12743 		}
12744 	for (; src[i]; ++i)
12745 		if (src[i] == '\r' || src[i] == '\n') {
12746 			ctx->eol = 1;
12747 			break;
12748 		}
12749 	/* Initialize context if necessary. */
12750 	if (!ctx->next_num) {
12751 		if (!token->next)
12752 			return 0;
12753 		ctx->next[ctx->next_num++] = token->next[0];
12754 	}
12755 	/* Process argument through candidates. */
12756 	ctx->prev = ctx->curr;
12757 	list = ctx->next[ctx->next_num - 1];
12758 	for (i = 0; list[i]; ++i) {
12759 		const struct token *next = &token_list[list[i]];
12760 		int tmp;
12761 
12762 		ctx->curr = list[i];
12763 		if (next->call)
12764 			tmp = next->call(ctx, next, src, len, result, size);
12765 		else
12766 			tmp = parse_default(ctx, next, src, len, result, size);
12767 		if (tmp == -1 || tmp != len)
12768 			continue;
12769 		token = next;
12770 		break;
12771 	}
12772 	if (!list[i])
12773 		return -1;
12774 	--ctx->next_num;
12775 	/* Push subsequent tokens if any. */
12776 	if (token->next)
12777 		for (i = 0; token->next[i]; ++i) {
12778 			if (ctx->next_num == RTE_DIM(ctx->next))
12779 				return -1;
12780 			ctx->next[ctx->next_num++] = token->next[i];
12781 		}
12782 	/* Push arguments if any. */
12783 	if (token->args)
12784 		for (i = 0; token->args[i]; ++i) {
12785 			if (ctx->args_num == RTE_DIM(ctx->args))
12786 				return -1;
12787 			ctx->args[ctx->args_num++] = token->args[i];
12788 		}
12789 	return len;
12790 }
12791 
12792 int
12793 flow_parse(const char *src, void *result, unsigned int size,
12794 	   struct rte_flow_attr **attr,
12795 	   struct rte_flow_item **pattern, struct rte_flow_action **actions)
12796 {
12797 	int ret;
12798 	struct context saved_flow_ctx = cmd_flow_context;
12799 
12800 	cmd_flow_context_init(&cmd_flow_context);
12801 	do {
12802 		ret = cmd_flow_parse(NULL, src, result, size);
12803 		if (ret > 0) {
12804 			src += ret;
12805 			while (isspace(*src))
12806 				src++;
12807 		}
12808 	} while (ret > 0 && strlen(src));
12809 	cmd_flow_context = saved_flow_ctx;
12810 	*attr = &((struct buffer *)result)->args.vc.attr;
12811 	*pattern = ((struct buffer *)result)->args.vc.pattern;
12812 	*actions = ((struct buffer *)result)->args.vc.actions;
12813 	return (ret >= 0 && !strlen(src)) ? 0 : -1;
12814 }
12815 
12816 /** Return number of completion entries (cmdline API). */
12817 static int
12818 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
12819 {
12820 	struct context *ctx = &cmd_flow_context;
12821 	const struct token *token = &token_list[ctx->curr];
12822 	const enum index *list;
12823 	int i;
12824 
12825 	(void)hdr;
12826 	/* Count number of tokens in current list. */
12827 	if (ctx->next_num)
12828 		list = ctx->next[ctx->next_num - 1];
12829 	else
12830 		list = token->next[0];
12831 	for (i = 0; list[i]; ++i)
12832 		;
12833 	if (!i)
12834 		return 0;
12835 	/*
12836 	 * If there is a single token, use its completion callback, otherwise
12837 	 * return the number of entries.
12838 	 */
12839 	token = &token_list[list[0]];
12840 	if (i == 1 && token->comp) {
12841 		/* Save index for cmd_flow_get_help(). */
12842 		ctx->prev = list[0];
12843 		return token->comp(ctx, token, 0, NULL, 0);
12844 	}
12845 	return i;
12846 }
12847 
12848 /** Return a completion entry (cmdline API). */
12849 static int
12850 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
12851 			  char *dst, unsigned int size)
12852 {
12853 	struct context *ctx = &cmd_flow_context;
12854 	const struct token *token = &token_list[ctx->curr];
12855 	const enum index *list;
12856 	int i;
12857 
12858 	(void)hdr;
12859 	/* Count number of tokens in current list. */
12860 	if (ctx->next_num)
12861 		list = ctx->next[ctx->next_num - 1];
12862 	else
12863 		list = token->next[0];
12864 	for (i = 0; list[i]; ++i)
12865 		;
12866 	if (!i)
12867 		return -1;
12868 	/* If there is a single token, use its completion callback. */
12869 	token = &token_list[list[0]];
12870 	if (i == 1 && token->comp) {
12871 		/* Save index for cmd_flow_get_help(). */
12872 		ctx->prev = list[0];
12873 		return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
12874 	}
12875 	/* Otherwise make sure the index is valid and use defaults. */
12876 	if (index >= i)
12877 		return -1;
12878 	token = &token_list[list[index]];
12879 	strlcpy(dst, token->name, size);
12880 	/* Save index for cmd_flow_get_help(). */
12881 	ctx->prev = list[index];
12882 	return 0;
12883 }
12884 
12885 /** Populate help strings for current token (cmdline API). */
12886 static int
12887 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
12888 {
12889 	struct context *ctx = &cmd_flow_context;
12890 	const struct token *token = &token_list[ctx->prev];
12891 
12892 	(void)hdr;
12893 	if (!size)
12894 		return -1;
12895 	/* Set token type and update global help with details. */
12896 	strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
12897 	if (token->help)
12898 		cmd_flow.help_str = token->help;
12899 	else
12900 		cmd_flow.help_str = token->name;
12901 	return 0;
12902 }
12903 
12904 /** Token definition template (cmdline API). */
12905 static struct cmdline_token_hdr cmd_flow_token_hdr = {
12906 	.ops = &(struct cmdline_token_ops){
12907 		.parse = cmd_flow_parse,
12908 		.complete_get_nb = cmd_flow_complete_get_nb,
12909 		.complete_get_elt = cmd_flow_complete_get_elt,
12910 		.get_help = cmd_flow_get_help,
12911 	},
12912 	.offset = 0,
12913 };
12914 
12915 /** Populate the next dynamic token. */
12916 static void
12917 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
12918 	     cmdline_parse_token_hdr_t **hdr_inst)
12919 {
12920 	struct context *ctx = &cmd_flow_context;
12921 
12922 	/* Always reinitialize context before requesting the first token. */
12923 	if (!(hdr_inst - cmd_flow.tokens))
12924 		cmd_flow_context_init(ctx);
12925 	/* Return NULL when no more tokens are expected. */
12926 	if (!ctx->next_num && ctx->curr) {
12927 		*hdr = NULL;
12928 		return;
12929 	}
12930 	/* Determine if command should end here. */
12931 	if (ctx->eol && ctx->last && ctx->next_num) {
12932 		const enum index *list = ctx->next[ctx->next_num - 1];
12933 		int i;
12934 
12935 		for (i = 0; list[i]; ++i) {
12936 			if (list[i] != END)
12937 				continue;
12938 			*hdr = NULL;
12939 			return;
12940 		}
12941 	}
12942 	*hdr = &cmd_flow_token_hdr;
12943 }
12944 
12945 static SLIST_HEAD(, indlst_conf) indlst_conf_head =
12946 	SLIST_HEAD_INITIALIZER();
12947 
12948 static void
12949 indirect_action_flow_conf_create(const struct buffer *in)
12950 {
12951 	int len, ret;
12952 	uint32_t i;
12953 	struct indlst_conf *indlst_conf = NULL;
12954 	size_t base = RTE_ALIGN(sizeof(*indlst_conf), 8);
12955 	struct rte_flow_action *src = in->args.vc.actions;
12956 
12957 	if (!in->args.vc.actions_n)
12958 		goto end;
12959 	len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, src, NULL);
12960 	if (len <= 0)
12961 		goto end;
12962 	len = RTE_ALIGN(len, 16);
12963 
12964 	indlst_conf = calloc(1, base + len +
12965 			     in->args.vc.actions_n * sizeof(uintptr_t));
12966 	if (!indlst_conf)
12967 		goto end;
12968 	indlst_conf->id = in->args.vc.attr.group;
12969 	indlst_conf->conf_num = in->args.vc.actions_n - 1;
12970 	indlst_conf->actions = RTE_PTR_ADD(indlst_conf, base);
12971 	ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, indlst_conf->actions,
12972 			    len, src, NULL);
12973 	if (ret <= 0) {
12974 		free(indlst_conf);
12975 		indlst_conf = NULL;
12976 		goto end;
12977 	}
12978 	indlst_conf->conf = RTE_PTR_ADD(indlst_conf, base + len);
12979 	for (i = 0; i < indlst_conf->conf_num; i++)
12980 		indlst_conf->conf[i] = indlst_conf->actions[i].conf;
12981 	SLIST_INSERT_HEAD(&indlst_conf_head, indlst_conf, next);
12982 end:
12983 	if (indlst_conf)
12984 		printf("created indirect action list configuration %u\n",
12985 		       in->args.vc.attr.group);
12986 	else
12987 		printf("cannot create indirect action list configuration %u\n",
12988 		       in->args.vc.attr.group);
12989 }
12990 
12991 static const struct indlst_conf *
12992 indirect_action_list_conf_get(uint32_t conf_id)
12993 {
12994 	const struct indlst_conf *conf;
12995 
12996 	SLIST_FOREACH(conf, &indlst_conf_head, next) {
12997 		if (conf->id == conf_id)
12998 			return conf;
12999 	}
13000 	return NULL;
13001 }
13002 
13003 /** Dispatch parsed buffer to function calls. */
13004 static void
13005 cmd_flow_parsed(const struct buffer *in)
13006 {
13007 	switch (in->command) {
13008 	case INFO:
13009 		port_flow_get_info(in->port);
13010 		break;
13011 	case CONFIGURE:
13012 		port_flow_configure(in->port,
13013 				    &in->args.configure.port_attr,
13014 				    in->args.configure.nb_queue,
13015 				    &in->args.configure.queue_attr);
13016 		break;
13017 	case PATTERN_TEMPLATE_CREATE:
13018 		port_flow_pattern_template_create(in->port,
13019 				in->args.vc.pat_templ_id,
13020 				&((const struct rte_flow_pattern_template_attr) {
13021 					.relaxed_matching = in->args.vc.attr.reserved,
13022 					.ingress = in->args.vc.attr.ingress,
13023 					.egress = in->args.vc.attr.egress,
13024 					.transfer = in->args.vc.attr.transfer,
13025 				}),
13026 				in->args.vc.pattern);
13027 		break;
13028 	case PATTERN_TEMPLATE_DESTROY:
13029 		port_flow_pattern_template_destroy(in->port,
13030 				in->args.templ_destroy.template_id_n,
13031 				in->args.templ_destroy.template_id);
13032 		break;
13033 	case ACTIONS_TEMPLATE_CREATE:
13034 		port_flow_actions_template_create(in->port,
13035 				in->args.vc.act_templ_id,
13036 				&((const struct rte_flow_actions_template_attr) {
13037 					.ingress = in->args.vc.attr.ingress,
13038 					.egress = in->args.vc.attr.egress,
13039 					.transfer = in->args.vc.attr.transfer,
13040 				}),
13041 				in->args.vc.actions,
13042 				in->args.vc.masks);
13043 		break;
13044 	case ACTIONS_TEMPLATE_DESTROY:
13045 		port_flow_actions_template_destroy(in->port,
13046 				in->args.templ_destroy.template_id_n,
13047 				in->args.templ_destroy.template_id);
13048 		break;
13049 	case TABLE_CREATE:
13050 		port_flow_template_table_create(in->port, in->args.table.id,
13051 			&in->args.table.attr, in->args.table.pat_templ_id_n,
13052 			in->args.table.pat_templ_id, in->args.table.act_templ_id_n,
13053 			in->args.table.act_templ_id);
13054 		break;
13055 	case TABLE_DESTROY:
13056 		port_flow_template_table_destroy(in->port,
13057 					in->args.table_destroy.table_id_n,
13058 					in->args.table_destroy.table_id);
13059 		break;
13060 	case GROUP_SET_MISS_ACTIONS:
13061 		port_queue_group_set_miss_actions(in->port, &in->args.vc.attr,
13062 						  in->args.vc.actions);
13063 		break;
13064 	case QUEUE_CREATE:
13065 		port_queue_flow_create(in->port, in->queue, in->postpone,
13066 			in->args.vc.table_id, in->args.vc.rule_id,
13067 			in->args.vc.pat_templ_id, in->args.vc.act_templ_id,
13068 			in->args.vc.pattern, in->args.vc.actions);
13069 		break;
13070 	case QUEUE_DESTROY:
13071 		port_queue_flow_destroy(in->port, in->queue, in->postpone,
13072 					in->args.destroy.rule_n,
13073 					in->args.destroy.rule);
13074 		break;
13075 	case QUEUE_UPDATE:
13076 		port_queue_flow_update(in->port, in->queue, in->postpone,
13077 				in->args.vc.rule_id, in->args.vc.act_templ_id,
13078 				in->args.vc.actions);
13079 		break;
13080 	case PUSH:
13081 		port_queue_flow_push(in->port, in->queue);
13082 		break;
13083 	case PULL:
13084 		port_queue_flow_pull(in->port, in->queue);
13085 		break;
13086 	case HASH:
13087 		if (!in->args.vc.encap_hash)
13088 			port_flow_hash_calc(in->port, in->args.vc.table_id,
13089 					    in->args.vc.pat_templ_id,
13090 					    in->args.vc.pattern);
13091 		else
13092 			port_flow_hash_calc_encap(in->port, in->args.vc.field,
13093 						  in->args.vc.pattern);
13094 		break;
13095 	case QUEUE_AGED:
13096 		port_queue_flow_aged(in->port, in->queue,
13097 				     in->args.aged.destroy);
13098 		break;
13099 	case QUEUE_INDIRECT_ACTION_CREATE:
13100 	case QUEUE_INDIRECT_ACTION_LIST_CREATE:
13101 		port_queue_action_handle_create(
13102 				in->port, in->queue, in->postpone,
13103 				in->args.vc.attr.group,
13104 				&((const struct rte_flow_indir_action_conf) {
13105 					.ingress = in->args.vc.attr.ingress,
13106 					.egress = in->args.vc.attr.egress,
13107 					.transfer = in->args.vc.attr.transfer,
13108 				}),
13109 				in->args.vc.actions);
13110 		break;
13111 	case QUEUE_INDIRECT_ACTION_DESTROY:
13112 		port_queue_action_handle_destroy(in->port,
13113 					   in->queue, in->postpone,
13114 					   in->args.ia_destroy.action_id_n,
13115 					   in->args.ia_destroy.action_id);
13116 		break;
13117 	case QUEUE_INDIRECT_ACTION_UPDATE:
13118 		port_queue_action_handle_update(in->port,
13119 						in->queue, in->postpone,
13120 						in->args.vc.attr.group,
13121 						in->args.vc.actions);
13122 		break;
13123 	case QUEUE_INDIRECT_ACTION_QUERY:
13124 		port_queue_action_handle_query(in->port,
13125 					       in->queue, in->postpone,
13126 					       in->args.ia.action_id);
13127 		break;
13128 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
13129 		port_queue_action_handle_query_update(in->port, in->queue,
13130 						      in->postpone,
13131 						      in->args.ia.action_id,
13132 						      in->args.ia.qu_mode,
13133 						      in->args.vc.actions);
13134 		break;
13135 	case INDIRECT_ACTION_CREATE:
13136 	case INDIRECT_ACTION_LIST_CREATE:
13137 		port_action_handle_create(
13138 				in->port, in->args.vc.attr.group,
13139 				in->command == INDIRECT_ACTION_LIST_CREATE,
13140 				&((const struct rte_flow_indir_action_conf) {
13141 					.ingress = in->args.vc.attr.ingress,
13142 					.egress = in->args.vc.attr.egress,
13143 					.transfer = in->args.vc.attr.transfer,
13144 				}),
13145 				in->args.vc.actions);
13146 		break;
13147 	case INDIRECT_ACTION_FLOW_CONF_CREATE:
13148 		indirect_action_flow_conf_create(in);
13149 		break;
13150 	case INDIRECT_ACTION_DESTROY:
13151 		port_action_handle_destroy(in->port,
13152 					   in->args.ia_destroy.action_id_n,
13153 					   in->args.ia_destroy.action_id);
13154 		break;
13155 	case INDIRECT_ACTION_UPDATE:
13156 		port_action_handle_update(in->port, in->args.vc.attr.group,
13157 					  in->args.vc.actions);
13158 		break;
13159 	case INDIRECT_ACTION_QUERY:
13160 		port_action_handle_query(in->port, in->args.ia.action_id);
13161 		break;
13162 	case INDIRECT_ACTION_QUERY_UPDATE:
13163 		port_action_handle_query_update(in->port,
13164 						in->args.ia.action_id,
13165 						in->args.ia.qu_mode,
13166 						in->args.vc.actions);
13167 		break;
13168 	case VALIDATE:
13169 		port_flow_validate(in->port, &in->args.vc.attr,
13170 				   in->args.vc.pattern, in->args.vc.actions,
13171 				   &in->args.vc.tunnel_ops);
13172 		break;
13173 	case CREATE:
13174 		port_flow_create(in->port, &in->args.vc.attr,
13175 				 in->args.vc.pattern, in->args.vc.actions,
13176 				 &in->args.vc.tunnel_ops, in->args.vc.user_id);
13177 		break;
13178 	case DESTROY:
13179 		port_flow_destroy(in->port, in->args.destroy.rule_n,
13180 				  in->args.destroy.rule,
13181 				  in->args.destroy.is_user_id);
13182 		break;
13183 	case FLUSH:
13184 		port_flow_flush(in->port);
13185 		break;
13186 	case DUMP_ONE:
13187 	case DUMP_ALL:
13188 		port_flow_dump(in->port, in->args.dump.mode,
13189 				in->args.dump.rule, in->args.dump.file,
13190 				in->args.dump.is_user_id);
13191 		break;
13192 	case QUERY:
13193 		port_flow_query(in->port, in->args.query.rule,
13194 				&in->args.query.action,
13195 				in->args.query.is_user_id);
13196 		break;
13197 	case LIST:
13198 		port_flow_list(in->port, in->args.list.group_n,
13199 			       in->args.list.group);
13200 		break;
13201 	case ISOLATE:
13202 		port_flow_isolate(in->port, in->args.isolate.set);
13203 		break;
13204 	case AGED:
13205 		port_flow_aged(in->port, in->args.aged.destroy);
13206 		break;
13207 	case TUNNEL_CREATE:
13208 		port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
13209 		break;
13210 	case TUNNEL_DESTROY:
13211 		port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
13212 		break;
13213 	case TUNNEL_LIST:
13214 		port_flow_tunnel_list(in->port);
13215 		break;
13216 	case ACTION_POL_G:
13217 		port_meter_policy_add(in->port, in->args.policy.policy_id,
13218 					in->args.vc.actions);
13219 		break;
13220 	case FLEX_ITEM_CREATE:
13221 		flex_item_create(in->port, in->args.flex.token,
13222 				 in->args.flex.filename);
13223 		break;
13224 	case FLEX_ITEM_DESTROY:
13225 		flex_item_destroy(in->port, in->args.flex.token);
13226 		break;
13227 	default:
13228 		break;
13229 	}
13230 	fflush(stdout);
13231 }
13232 
13233 /** Token generator and output processing callback (cmdline API). */
13234 static void
13235 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
13236 {
13237 	if (cl == NULL)
13238 		cmd_flow_tok(arg0, arg2);
13239 	else
13240 		cmd_flow_parsed(arg0);
13241 }
13242 
13243 /** Global parser instance (cmdline API). */
13244 cmdline_parse_inst_t cmd_flow = {
13245 	.f = cmd_flow_cb,
13246 	.data = NULL, /**< Unused. */
13247 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
13248 	.tokens = {
13249 		NULL,
13250 	}, /**< Tokens are returned by cmd_flow_tok(). */
13251 };
13252 
13253 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
13254 
13255 static void
13256 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
13257 {
13258 	struct rte_ipv4_hdr *ipv4;
13259 	struct rte_ether_hdr *eth;
13260 	struct rte_ipv6_hdr *ipv6;
13261 	struct rte_vxlan_hdr *vxlan;
13262 	struct rte_vxlan_gpe_hdr *gpe;
13263 	struct rte_flow_item_nvgre *nvgre;
13264 	uint32_t ipv6_vtc_flow;
13265 
13266 	switch (item->type) {
13267 	case RTE_FLOW_ITEM_TYPE_ETH:
13268 		eth = (struct rte_ether_hdr *)buf;
13269 		if (next_proto)
13270 			eth->ether_type = rte_cpu_to_be_16(next_proto);
13271 		break;
13272 	case RTE_FLOW_ITEM_TYPE_IPV4:
13273 		ipv4 = (struct rte_ipv4_hdr *)buf;
13274 		if (!ipv4->version_ihl)
13275 			ipv4->version_ihl = RTE_IPV4_VHL_DEF;
13276 		if (next_proto && ipv4->next_proto_id == 0)
13277 			ipv4->next_proto_id = (uint8_t)next_proto;
13278 		break;
13279 	case RTE_FLOW_ITEM_TYPE_IPV6:
13280 		ipv6 = (struct rte_ipv6_hdr *)buf;
13281 		if (next_proto && ipv6->proto == 0)
13282 			ipv6->proto = (uint8_t)next_proto;
13283 		ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
13284 		ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
13285 		ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
13286 		ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
13287 		break;
13288 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13289 		vxlan = (struct rte_vxlan_hdr *)buf;
13290 		vxlan->vx_flags = 0x08;
13291 		break;
13292 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13293 		gpe = (struct rte_vxlan_gpe_hdr *)buf;
13294 		gpe->vx_flags = 0x0C;
13295 		break;
13296 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13297 		nvgre = (struct rte_flow_item_nvgre *)buf;
13298 		nvgre->protocol = rte_cpu_to_be_16(0x6558);
13299 		nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
13300 		break;
13301 	default:
13302 		break;
13303 	}
13304 }
13305 
13306 /** Helper of get item's default mask. */
13307 static const void *
13308 flow_item_default_mask(const struct rte_flow_item *item)
13309 {
13310 	const void *mask = NULL;
13311 	static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
13312 	static struct rte_flow_item_ipv6_routing_ext ipv6_routing_ext_default_mask = {
13313 		.hdr = {
13314 			.next_hdr = 0xff,
13315 			.type = 0xff,
13316 			.segments_left = 0xff,
13317 		},
13318 	};
13319 
13320 	switch (item->type) {
13321 	case RTE_FLOW_ITEM_TYPE_ANY:
13322 		mask = &rte_flow_item_any_mask;
13323 		break;
13324 	case RTE_FLOW_ITEM_TYPE_PORT_ID:
13325 		mask = &rte_flow_item_port_id_mask;
13326 		break;
13327 	case RTE_FLOW_ITEM_TYPE_RAW:
13328 		mask = &rte_flow_item_raw_mask;
13329 		break;
13330 	case RTE_FLOW_ITEM_TYPE_ETH:
13331 		mask = &rte_flow_item_eth_mask;
13332 		break;
13333 	case RTE_FLOW_ITEM_TYPE_VLAN:
13334 		mask = &rte_flow_item_vlan_mask;
13335 		break;
13336 	case RTE_FLOW_ITEM_TYPE_IPV4:
13337 		mask = &rte_flow_item_ipv4_mask;
13338 		break;
13339 	case RTE_FLOW_ITEM_TYPE_IPV6:
13340 		mask = &rte_flow_item_ipv6_mask;
13341 		break;
13342 	case RTE_FLOW_ITEM_TYPE_ICMP:
13343 		mask = &rte_flow_item_icmp_mask;
13344 		break;
13345 	case RTE_FLOW_ITEM_TYPE_UDP:
13346 		mask = &rte_flow_item_udp_mask;
13347 		break;
13348 	case RTE_FLOW_ITEM_TYPE_TCP:
13349 		mask = &rte_flow_item_tcp_mask;
13350 		break;
13351 	case RTE_FLOW_ITEM_TYPE_SCTP:
13352 		mask = &rte_flow_item_sctp_mask;
13353 		break;
13354 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13355 		mask = &rte_flow_item_vxlan_mask;
13356 		break;
13357 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13358 		mask = &rte_flow_item_vxlan_gpe_mask;
13359 		break;
13360 	case RTE_FLOW_ITEM_TYPE_E_TAG:
13361 		mask = &rte_flow_item_e_tag_mask;
13362 		break;
13363 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13364 		mask = &rte_flow_item_nvgre_mask;
13365 		break;
13366 	case RTE_FLOW_ITEM_TYPE_MPLS:
13367 		mask = &rte_flow_item_mpls_mask;
13368 		break;
13369 	case RTE_FLOW_ITEM_TYPE_GRE:
13370 		mask = &rte_flow_item_gre_mask;
13371 		break;
13372 	case RTE_FLOW_ITEM_TYPE_GRE_KEY:
13373 		mask = &gre_key_default_mask;
13374 		break;
13375 	case RTE_FLOW_ITEM_TYPE_META:
13376 		mask = &rte_flow_item_meta_mask;
13377 		break;
13378 	case RTE_FLOW_ITEM_TYPE_RANDOM:
13379 		mask = &rte_flow_item_random_mask;
13380 		break;
13381 	case RTE_FLOW_ITEM_TYPE_FUZZY:
13382 		mask = &rte_flow_item_fuzzy_mask;
13383 		break;
13384 	case RTE_FLOW_ITEM_TYPE_GTP:
13385 		mask = &rte_flow_item_gtp_mask;
13386 		break;
13387 	case RTE_FLOW_ITEM_TYPE_GTP_PSC:
13388 		mask = &rte_flow_item_gtp_psc_mask;
13389 		break;
13390 	case RTE_FLOW_ITEM_TYPE_GENEVE:
13391 		mask = &rte_flow_item_geneve_mask;
13392 		break;
13393 	case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
13394 		mask = &rte_flow_item_geneve_opt_mask;
13395 		break;
13396 	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
13397 		mask = &rte_flow_item_pppoe_proto_id_mask;
13398 		break;
13399 	case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
13400 		mask = &rte_flow_item_l2tpv3oip_mask;
13401 		break;
13402 	case RTE_FLOW_ITEM_TYPE_ESP:
13403 		mask = &rte_flow_item_esp_mask;
13404 		break;
13405 	case RTE_FLOW_ITEM_TYPE_AH:
13406 		mask = &rte_flow_item_ah_mask;
13407 		break;
13408 	case RTE_FLOW_ITEM_TYPE_PFCP:
13409 		mask = &rte_flow_item_pfcp_mask;
13410 		break;
13411 	case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
13412 	case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
13413 		mask = &rte_flow_item_ethdev_mask;
13414 		break;
13415 	case RTE_FLOW_ITEM_TYPE_L2TPV2:
13416 		mask = &rte_flow_item_l2tpv2_mask;
13417 		break;
13418 	case RTE_FLOW_ITEM_TYPE_PPP:
13419 		mask = &rte_flow_item_ppp_mask;
13420 		break;
13421 	case RTE_FLOW_ITEM_TYPE_METER_COLOR:
13422 		mask = &rte_flow_item_meter_color_mask;
13423 		break;
13424 	case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13425 		mask = &ipv6_routing_ext_default_mask;
13426 		break;
13427 	case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
13428 		mask = &rte_flow_item_aggr_affinity_mask;
13429 		break;
13430 	case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
13431 		mask = &rte_flow_item_tx_queue_mask;
13432 		break;
13433 	case RTE_FLOW_ITEM_TYPE_IB_BTH:
13434 		mask = &rte_flow_item_ib_bth_mask;
13435 		break;
13436 	case RTE_FLOW_ITEM_TYPE_PTYPE:
13437 		mask = &rte_flow_item_ptype_mask;
13438 		break;
13439 	default:
13440 		break;
13441 	}
13442 	return mask;
13443 }
13444 
13445 /** Dispatch parsed buffer to function calls. */
13446 static void
13447 cmd_set_ipv6_ext_parsed(const struct buffer *in)
13448 {
13449 	uint32_t n = in->args.vc.pattern_n;
13450 	int i = 0;
13451 	struct rte_flow_item *item = NULL;
13452 	size_t size = 0;
13453 	uint8_t *data = NULL;
13454 	uint8_t *type = NULL;
13455 	size_t *total_size = NULL;
13456 	uint16_t idx = in->port; /* We borrow port field as index */
13457 	struct rte_flow_item_ipv6_routing_ext *ext;
13458 	const struct rte_flow_item_ipv6_ext *ipv6_ext;
13459 
13460 	RTE_ASSERT(in->command == SET_IPV6_EXT_PUSH ||
13461 		   in->command == SET_IPV6_EXT_REMOVE);
13462 
13463 	if (in->command == SET_IPV6_EXT_REMOVE) {
13464 		if (n != 1 || in->args.vc.pattern->type !=
13465 		    RTE_FLOW_ITEM_TYPE_IPV6_EXT) {
13466 			fprintf(stderr, "Error - Not supported item\n");
13467 			return;
13468 		}
13469 		type = (uint8_t *)&ipv6_ext_remove_confs[idx].type;
13470 		item = in->args.vc.pattern;
13471 		ipv6_ext = item->spec;
13472 		*type = ipv6_ext->next_hdr;
13473 		return;
13474 	}
13475 
13476 	total_size = &ipv6_ext_push_confs[idx].size;
13477 	data = (uint8_t *)&ipv6_ext_push_confs[idx].data;
13478 	type = (uint8_t *)&ipv6_ext_push_confs[idx].type;
13479 
13480 	*total_size = 0;
13481 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13482 	for (i = n - 1 ; i >= 0; --i) {
13483 		item = in->args.vc.pattern + i;
13484 		switch (item->type) {
13485 		case RTE_FLOW_ITEM_TYPE_IPV6_EXT:
13486 			ipv6_ext = item->spec;
13487 			*type = ipv6_ext->next_hdr;
13488 			break;
13489 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13490 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13491 			if (!ext->hdr.hdr_len) {
13492 				size = sizeof(struct rte_ipv6_routing_ext) +
13493 				(ext->hdr.segments_left << 4);
13494 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
13495 				/* Indicate no TLV once SRH. */
13496 				if (ext->hdr.type == 4)
13497 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
13498 			} else {
13499 				size = sizeof(struct rte_ipv6_routing_ext) +
13500 				(ext->hdr.hdr_len << 3);
13501 			}
13502 			*total_size += size;
13503 			memcpy(data, ext, size);
13504 			break;
13505 		default:
13506 			fprintf(stderr, "Error - Not supported item\n");
13507 			goto error;
13508 		}
13509 	}
13510 	RTE_ASSERT((*total_size) <= ACTION_IPV6_EXT_PUSH_MAX_DATA);
13511 	return;
13512 error:
13513 	*total_size = 0;
13514 	memset(data, 0x00, ACTION_IPV6_EXT_PUSH_MAX_DATA);
13515 }
13516 
13517 /** Dispatch parsed buffer to function calls. */
13518 static void
13519 cmd_set_raw_parsed_sample(const struct buffer *in)
13520 {
13521 	uint32_t n = in->args.vc.actions_n;
13522 	uint32_t i = 0;
13523 	struct rte_flow_action *action = NULL;
13524 	struct rte_flow_action *data = NULL;
13525 	const struct rte_flow_action_rss *rss = NULL;
13526 	size_t size = 0;
13527 	uint16_t idx = in->port; /* We borrow port field as index */
13528 	uint32_t max_size = sizeof(struct rte_flow_action) *
13529 						ACTION_SAMPLE_ACTIONS_NUM;
13530 
13531 	RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
13532 	data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
13533 	memset(data, 0x00, max_size);
13534 	for (; i <= n - 1; i++) {
13535 		action = in->args.vc.actions + i;
13536 		if (action->type == RTE_FLOW_ACTION_TYPE_END)
13537 			break;
13538 		switch (action->type) {
13539 		case RTE_FLOW_ACTION_TYPE_MARK:
13540 			size = sizeof(struct rte_flow_action_mark);
13541 			rte_memcpy(&sample_mark[idx],
13542 				(const void *)action->conf, size);
13543 			action->conf = &sample_mark[idx];
13544 			break;
13545 		case RTE_FLOW_ACTION_TYPE_COUNT:
13546 			size = sizeof(struct rte_flow_action_count);
13547 			rte_memcpy(&sample_count[idx],
13548 				(const void *)action->conf, size);
13549 			action->conf = &sample_count[idx];
13550 			break;
13551 		case RTE_FLOW_ACTION_TYPE_QUEUE:
13552 			size = sizeof(struct rte_flow_action_queue);
13553 			rte_memcpy(&sample_queue[idx],
13554 				(const void *)action->conf, size);
13555 			action->conf = &sample_queue[idx];
13556 			break;
13557 		case RTE_FLOW_ACTION_TYPE_RSS:
13558 			size = sizeof(struct rte_flow_action_rss);
13559 			rss = action->conf;
13560 			rte_memcpy(&sample_rss_data[idx].conf,
13561 				   (const void *)rss, size);
13562 			if (rss->key_len && rss->key) {
13563 				sample_rss_data[idx].conf.key =
13564 						sample_rss_data[idx].key;
13565 				rte_memcpy((void *)((uintptr_t)
13566 					   sample_rss_data[idx].conf.key),
13567 					   (const void *)rss->key,
13568 					   sizeof(uint8_t) * rss->key_len);
13569 			}
13570 			if (rss->queue_num && rss->queue) {
13571 				sample_rss_data[idx].conf.queue =
13572 						sample_rss_data[idx].queue;
13573 				rte_memcpy((void *)((uintptr_t)
13574 					   sample_rss_data[idx].conf.queue),
13575 					   (const void *)rss->queue,
13576 					   sizeof(uint16_t) * rss->queue_num);
13577 			}
13578 			action->conf = &sample_rss_data[idx].conf;
13579 			break;
13580 		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
13581 			size = sizeof(struct rte_flow_action_raw_encap);
13582 			rte_memcpy(&sample_encap[idx],
13583 				(const void *)action->conf, size);
13584 			action->conf = &sample_encap[idx];
13585 			break;
13586 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
13587 			size = sizeof(struct rte_flow_action_port_id);
13588 			rte_memcpy(&sample_port_id[idx],
13589 				(const void *)action->conf, size);
13590 			action->conf = &sample_port_id[idx];
13591 			break;
13592 		case RTE_FLOW_ACTION_TYPE_PF:
13593 			break;
13594 		case RTE_FLOW_ACTION_TYPE_VF:
13595 			size = sizeof(struct rte_flow_action_vf);
13596 			rte_memcpy(&sample_vf[idx],
13597 					(const void *)action->conf, size);
13598 			action->conf = &sample_vf[idx];
13599 			break;
13600 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
13601 			size = sizeof(struct rte_flow_action_vxlan_encap);
13602 			parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
13603 			action->conf = &sample_vxlan_encap[idx].conf;
13604 			break;
13605 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
13606 			size = sizeof(struct rte_flow_action_nvgre_encap);
13607 			parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
13608 			action->conf = &sample_nvgre_encap[idx];
13609 			break;
13610 		case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
13611 			size = sizeof(struct rte_flow_action_ethdev);
13612 			rte_memcpy(&sample_port_representor[idx],
13613 					(const void *)action->conf, size);
13614 			action->conf = &sample_port_representor[idx];
13615 			break;
13616 		case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
13617 			size = sizeof(struct rte_flow_action_ethdev);
13618 			rte_memcpy(&sample_represented_port[idx],
13619 					(const void *)action->conf, size);
13620 			action->conf = &sample_represented_port[idx];
13621 			break;
13622 		default:
13623 			fprintf(stderr, "Error - Not supported action\n");
13624 			return;
13625 		}
13626 		rte_memcpy(data, action, sizeof(struct rte_flow_action));
13627 		data++;
13628 	}
13629 }
13630 
13631 /** Dispatch parsed buffer to function calls. */
13632 static void
13633 cmd_set_raw_parsed(const struct buffer *in)
13634 {
13635 	uint32_t n = in->args.vc.pattern_n;
13636 	int i = 0;
13637 	struct rte_flow_item *item = NULL;
13638 	size_t size = 0;
13639 	uint8_t *data = NULL;
13640 	uint8_t *data_tail = NULL;
13641 	size_t *total_size = NULL;
13642 	uint16_t upper_layer = 0;
13643 	uint16_t proto = 0;
13644 	uint16_t idx = in->port; /* We borrow port field as index */
13645 	int gtp_psc = -1; /* GTP PSC option index. */
13646 	const void *src_spec;
13647 
13648 	if (in->command == SET_SAMPLE_ACTIONS)
13649 		return cmd_set_raw_parsed_sample(in);
13650 	else if (in->command == SET_IPV6_EXT_PUSH ||
13651 		 in->command == SET_IPV6_EXT_REMOVE)
13652 		return cmd_set_ipv6_ext_parsed(in);
13653 	RTE_ASSERT(in->command == SET_RAW_ENCAP ||
13654 		   in->command == SET_RAW_DECAP);
13655 	if (in->command == SET_RAW_ENCAP) {
13656 		total_size = &raw_encap_confs[idx].size;
13657 		data = (uint8_t *)&raw_encap_confs[idx].data;
13658 	} else {
13659 		total_size = &raw_decap_confs[idx].size;
13660 		data = (uint8_t *)&raw_decap_confs[idx].data;
13661 	}
13662 	*total_size = 0;
13663 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13664 	/* process hdr from upper layer to low layer (L3/L4 -> L2). */
13665 	data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
13666 	for (i = n - 1 ; i >= 0; --i) {
13667 		const struct rte_flow_item_gtp *gtp;
13668 		const struct rte_flow_item_geneve_opt *opt;
13669 		struct rte_flow_item_ipv6_routing_ext *ext;
13670 
13671 		item = in->args.vc.pattern + i;
13672 		if (item->spec == NULL)
13673 			item->spec = flow_item_default_mask(item);
13674 		src_spec = item->spec;
13675 		switch (item->type) {
13676 		case RTE_FLOW_ITEM_TYPE_ETH:
13677 			size = sizeof(struct rte_ether_hdr);
13678 			break;
13679 		case RTE_FLOW_ITEM_TYPE_VLAN:
13680 			size = sizeof(struct rte_vlan_hdr);
13681 			proto = RTE_ETHER_TYPE_VLAN;
13682 			break;
13683 		case RTE_FLOW_ITEM_TYPE_IPV4:
13684 			size = sizeof(struct rte_ipv4_hdr);
13685 			proto = RTE_ETHER_TYPE_IPV4;
13686 			break;
13687 		case RTE_FLOW_ITEM_TYPE_IPV6:
13688 			size = sizeof(struct rte_ipv6_hdr);
13689 			proto = RTE_ETHER_TYPE_IPV6;
13690 			break;
13691 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13692 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13693 			if (!ext->hdr.hdr_len) {
13694 				size = sizeof(struct rte_ipv6_routing_ext) +
13695 					(ext->hdr.segments_left << 4);
13696 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
13697 				/* SRv6 without TLV. */
13698 				if (ext->hdr.type == RTE_IPV6_SRCRT_TYPE_4)
13699 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
13700 			} else {
13701 				size = sizeof(struct rte_ipv6_routing_ext) +
13702 					(ext->hdr.hdr_len << 3);
13703 			}
13704 			proto = IPPROTO_ROUTING;
13705 			break;
13706 		case RTE_FLOW_ITEM_TYPE_UDP:
13707 			size = sizeof(struct rte_udp_hdr);
13708 			proto = 0x11;
13709 			break;
13710 		case RTE_FLOW_ITEM_TYPE_TCP:
13711 			size = sizeof(struct rte_tcp_hdr);
13712 			proto = 0x06;
13713 			break;
13714 		case RTE_FLOW_ITEM_TYPE_VXLAN:
13715 			size = sizeof(struct rte_vxlan_hdr);
13716 			break;
13717 		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13718 			size = sizeof(struct rte_vxlan_gpe_hdr);
13719 			break;
13720 		case RTE_FLOW_ITEM_TYPE_GRE:
13721 			size = sizeof(struct rte_gre_hdr);
13722 			proto = 0x2F;
13723 			break;
13724 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
13725 			size = sizeof(rte_be32_t);
13726 			proto = 0x0;
13727 			break;
13728 		case RTE_FLOW_ITEM_TYPE_MPLS:
13729 			size = sizeof(struct rte_mpls_hdr);
13730 			proto = 0x0;
13731 			break;
13732 		case RTE_FLOW_ITEM_TYPE_NVGRE:
13733 			size = sizeof(struct rte_flow_item_nvgre);
13734 			proto = 0x2F;
13735 			break;
13736 		case RTE_FLOW_ITEM_TYPE_GENEVE:
13737 			size = sizeof(struct rte_geneve_hdr);
13738 			break;
13739 		case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
13740 			opt = (const struct rte_flow_item_geneve_opt *)
13741 								item->spec;
13742 			size = offsetof(struct rte_flow_item_geneve_opt,
13743 					option_len) + sizeof(uint8_t);
13744 			if (opt->option_len && opt->data) {
13745 				*total_size += opt->option_len *
13746 					       sizeof(uint32_t);
13747 				rte_memcpy(data_tail - (*total_size),
13748 					   opt->data,
13749 					   opt->option_len * sizeof(uint32_t));
13750 			}
13751 			break;
13752 		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
13753 			size = sizeof(rte_be32_t);
13754 			proto = 0x73;
13755 			break;
13756 		case RTE_FLOW_ITEM_TYPE_ESP:
13757 			size = sizeof(struct rte_esp_hdr);
13758 			proto = 0x32;
13759 			break;
13760 		case RTE_FLOW_ITEM_TYPE_AH:
13761 			size = sizeof(struct rte_flow_item_ah);
13762 			proto = 0x33;
13763 			break;
13764 		case RTE_FLOW_ITEM_TYPE_GTP:
13765 			if (gtp_psc < 0) {
13766 				size = sizeof(struct rte_gtp_hdr);
13767 				break;
13768 			}
13769 			if (gtp_psc != i + 1) {
13770 				fprintf(stderr,
13771 					"Error - GTP PSC does not follow GTP\n");
13772 				goto error;
13773 			}
13774 			gtp = item->spec;
13775 			if (gtp->hdr.s == 1 || gtp->hdr.pn == 1) {
13776 				/* Only E flag should be set. */
13777 				fprintf(stderr,
13778 					"Error - GTP unsupported flags\n");
13779 				goto error;
13780 			} else {
13781 				struct rte_gtp_hdr_ext_word ext_word = {
13782 					.next_ext = 0x85
13783 				};
13784 
13785 				/* We have to add GTP header extra word. */
13786 				*total_size += sizeof(ext_word);
13787 				rte_memcpy(data_tail - (*total_size),
13788 					   &ext_word, sizeof(ext_word));
13789 			}
13790 			size = sizeof(struct rte_gtp_hdr);
13791 			break;
13792 		case RTE_FLOW_ITEM_TYPE_GTP_PSC:
13793 			if (gtp_psc >= 0) {
13794 				fprintf(stderr,
13795 					"Error - Multiple GTP PSC items\n");
13796 				goto error;
13797 			} else {
13798 				const struct rte_flow_item_gtp_psc
13799 					*opt = item->spec;
13800 				struct rte_gtp_psc_generic_hdr *hdr;
13801 				size_t hdr_size = RTE_ALIGN(sizeof(*hdr),
13802 							 sizeof(int32_t));
13803 
13804 				*total_size += hdr_size;
13805 				hdr = (typeof(hdr))(data_tail - (*total_size));
13806 				memset(hdr, 0, hdr_size);
13807 				*hdr = opt->hdr;
13808 				hdr->ext_hdr_len = 1;
13809 				gtp_psc = i;
13810 				size = 0;
13811 			}
13812 			break;
13813 		case RTE_FLOW_ITEM_TYPE_PFCP:
13814 			size = sizeof(struct rte_flow_item_pfcp);
13815 			break;
13816 		case RTE_FLOW_ITEM_TYPE_FLEX:
13817 			if (item->spec != NULL) {
13818 				size = ((const struct rte_flow_item_flex *)item->spec)->length;
13819 				src_spec = ((const struct rte_flow_item_flex *)item->spec)->pattern;
13820 			} else {
13821 				size = 0;
13822 				src_spec = NULL;
13823 			}
13824 			break;
13825 		case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
13826 			size = 0;
13827 			if (item->spec) {
13828 				const struct rte_flow_item_gre_opt
13829 					*opt = item->spec;
13830 				if (opt->checksum_rsvd.checksum) {
13831 					*total_size +=
13832 						sizeof(opt->checksum_rsvd);
13833 					rte_memcpy(data_tail - (*total_size),
13834 						   &opt->checksum_rsvd,
13835 						   sizeof(opt->checksum_rsvd));
13836 				}
13837 				if (opt->key.key) {
13838 					*total_size += sizeof(opt->key.key);
13839 					rte_memcpy(data_tail - (*total_size),
13840 						   &opt->key.key,
13841 						   sizeof(opt->key.key));
13842 				}
13843 				if (opt->sequence.sequence) {
13844 					*total_size += sizeof(opt->sequence.sequence);
13845 					rte_memcpy(data_tail - (*total_size),
13846 						   &opt->sequence.sequence,
13847 						   sizeof(opt->sequence.sequence));
13848 				}
13849 			}
13850 			proto = 0x2F;
13851 			break;
13852 		default:
13853 			fprintf(stderr, "Error - Not supported item\n");
13854 			goto error;
13855 		}
13856 		if (size) {
13857 			*total_size += size;
13858 			rte_memcpy(data_tail - (*total_size), src_spec, size);
13859 			/* update some fields which cannot be set by cmdline */
13860 			update_fields((data_tail - (*total_size)), item,
13861 				      upper_layer);
13862 			upper_layer = proto;
13863 		}
13864 	}
13865 	if (verbose_level & 0x1)
13866 		printf("total data size is %zu\n", (*total_size));
13867 	RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
13868 	memmove(data, (data_tail - (*total_size)), *total_size);
13869 	return;
13870 
13871 error:
13872 	*total_size = 0;
13873 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13874 }
13875 
13876 /** Populate help strings for current token (cmdline API). */
13877 static int
13878 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
13879 		     unsigned int size)
13880 {
13881 	struct context *ctx = &cmd_flow_context;
13882 	const struct token *token = &token_list[ctx->prev];
13883 
13884 	(void)hdr;
13885 	if (!size)
13886 		return -1;
13887 	/* Set token type and update global help with details. */
13888 	snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
13889 	if (token->help)
13890 		cmd_set_raw.help_str = token->help;
13891 	else
13892 		cmd_set_raw.help_str = token->name;
13893 	return 0;
13894 }
13895 
13896 /** Token definition template (cmdline API). */
13897 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
13898 	.ops = &(struct cmdline_token_ops){
13899 		.parse = cmd_flow_parse,
13900 		.complete_get_nb = cmd_flow_complete_get_nb,
13901 		.complete_get_elt = cmd_flow_complete_get_elt,
13902 		.get_help = cmd_set_raw_get_help,
13903 	},
13904 	.offset = 0,
13905 };
13906 
13907 /** Populate the next dynamic token. */
13908 static void
13909 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
13910 	     cmdline_parse_token_hdr_t **hdr_inst)
13911 {
13912 	struct context *ctx = &cmd_flow_context;
13913 
13914 	/* Always reinitialize context before requesting the first token. */
13915 	if (!(hdr_inst - cmd_set_raw.tokens)) {
13916 		cmd_flow_context_init(ctx);
13917 		ctx->curr = START_SET;
13918 	}
13919 	/* Return NULL when no more tokens are expected. */
13920 	if (!ctx->next_num && (ctx->curr != START_SET)) {
13921 		*hdr = NULL;
13922 		return;
13923 	}
13924 	/* Determine if command should end here. */
13925 	if (ctx->eol && ctx->last && ctx->next_num) {
13926 		const enum index *list = ctx->next[ctx->next_num - 1];
13927 		int i;
13928 
13929 		for (i = 0; list[i]; ++i) {
13930 			if (list[i] != END)
13931 				continue;
13932 			*hdr = NULL;
13933 			return;
13934 		}
13935 	}
13936 	*hdr = &cmd_set_raw_token_hdr;
13937 }
13938 
13939 /** Token generator and output processing callback (cmdline API). */
13940 static void
13941 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
13942 {
13943 	if (cl == NULL)
13944 		cmd_set_raw_tok(arg0, arg2);
13945 	else
13946 		cmd_set_raw_parsed(arg0);
13947 }
13948 
13949 /** Global parser instance (cmdline API). */
13950 cmdline_parse_inst_t cmd_set_raw = {
13951 	.f = cmd_set_raw_cb,
13952 	.data = NULL, /**< Unused. */
13953 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
13954 	.tokens = {
13955 		NULL,
13956 	}, /**< Tokens are returned by cmd_flow_tok(). */
13957 };
13958 
13959 /* *** display raw_encap/raw_decap buf */
13960 struct cmd_show_set_raw_result {
13961 	cmdline_fixed_string_t cmd_show;
13962 	cmdline_fixed_string_t cmd_what;
13963 	cmdline_fixed_string_t cmd_all;
13964 	uint16_t cmd_index;
13965 };
13966 
13967 static void
13968 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
13969 {
13970 	struct cmd_show_set_raw_result *res = parsed_result;
13971 	uint16_t index = res->cmd_index;
13972 	uint8_t all = 0;
13973 	uint8_t *raw_data = NULL;
13974 	size_t raw_size = 0;
13975 	char title[16] = {0};
13976 
13977 	RTE_SET_USED(cl);
13978 	RTE_SET_USED(data);
13979 	if (!strcmp(res->cmd_all, "all")) {
13980 		all = 1;
13981 		index = 0;
13982 	} else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
13983 		fprintf(stderr, "index should be 0-%u\n",
13984 			RAW_ENCAP_CONFS_MAX_NUM - 1);
13985 		return;
13986 	}
13987 	do {
13988 		if (!strcmp(res->cmd_what, "raw_encap")) {
13989 			raw_data = (uint8_t *)&raw_encap_confs[index].data;
13990 			raw_size = raw_encap_confs[index].size;
13991 			snprintf(title, 16, "\nindex: %u", index);
13992 			rte_hexdump(stdout, title, raw_data, raw_size);
13993 		} else {
13994 			raw_data = (uint8_t *)&raw_decap_confs[index].data;
13995 			raw_size = raw_decap_confs[index].size;
13996 			snprintf(title, 16, "\nindex: %u", index);
13997 			rte_hexdump(stdout, title, raw_data, raw_size);
13998 		}
13999 	} while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
14000 }
14001 
14002 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
14003 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14004 			cmd_show, "show");
14005 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
14006 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14007 			cmd_what, "raw_encap#raw_decap");
14008 static cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
14009 	TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
14010 			cmd_index, RTE_UINT16);
14011 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
14012 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14013 			cmd_all, "all");
14014 cmdline_parse_inst_t cmd_show_set_raw = {
14015 	.f = cmd_show_set_raw_parsed,
14016 	.data = NULL,
14017 	.help_str = "show <raw_encap|raw_decap> <index>",
14018 	.tokens = {
14019 		(void *)&cmd_show_set_raw_cmd_show,
14020 		(void *)&cmd_show_set_raw_cmd_what,
14021 		(void *)&cmd_show_set_raw_cmd_index,
14022 		NULL,
14023 	},
14024 };
14025 cmdline_parse_inst_t cmd_show_set_raw_all = {
14026 	.f = cmd_show_set_raw_parsed,
14027 	.data = NULL,
14028 	.help_str = "show <raw_encap|raw_decap> all",
14029 	.tokens = {
14030 		(void *)&cmd_show_set_raw_cmd_show,
14031 		(void *)&cmd_show_set_raw_cmd_what,
14032 		(void *)&cmd_show_set_raw_cmd_all,
14033 		NULL,
14034 	},
14035 };
14036