xref: /dpdk/app/test-pmd/cmdline_flow.c (revision 0f1dc8cb671203d52488fd66936f2fe6dcca03cc)
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_FLOW_UPDATE_RESIZED,
138 	QUEUE_UPDATE,
139 	QUEUE_AGED,
140 	QUEUE_INDIRECT_ACTION,
141 
142 	/* Queue create arguments. */
143 	QUEUE_CREATE_POSTPONE,
144 	QUEUE_TEMPLATE_TABLE,
145 	QUEUE_PATTERN_TEMPLATE,
146 	QUEUE_ACTIONS_TEMPLATE,
147 	QUEUE_RULE_ID,
148 
149 	/* Queue destroy arguments. */
150 	QUEUE_DESTROY_ID,
151 	QUEUE_DESTROY_POSTPONE,
152 
153 	/* Queue update arguments. */
154 	QUEUE_UPDATE_ID,
155 
156 	/* Queue indirect action arguments */
157 	QUEUE_INDIRECT_ACTION_CREATE,
158 	QUEUE_INDIRECT_ACTION_LIST_CREATE,
159 	QUEUE_INDIRECT_ACTION_UPDATE,
160 	QUEUE_INDIRECT_ACTION_DESTROY,
161 	QUEUE_INDIRECT_ACTION_QUERY,
162 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
163 
164 	/* Queue indirect action create arguments */
165 	QUEUE_INDIRECT_ACTION_CREATE_ID,
166 	QUEUE_INDIRECT_ACTION_INGRESS,
167 	QUEUE_INDIRECT_ACTION_EGRESS,
168 	QUEUE_INDIRECT_ACTION_TRANSFER,
169 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
170 	QUEUE_INDIRECT_ACTION_SPEC,
171 	QUEUE_INDIRECT_ACTION_LIST,
172 
173 	/* Queue indirect action update arguments */
174 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
175 
176 	/* Queue indirect action destroy arguments */
177 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
178 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
179 
180 	/* Queue indirect action query arguments */
181 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
182 
183 	/* Queue indirect action query_update arguments */
184 	QUEUE_INDIRECT_ACTION_QU_MODE,
185 
186 	/* Push arguments. */
187 	PUSH_QUEUE,
188 
189 	/* Pull arguments. */
190 	PULL_QUEUE,
191 
192 	/* Table arguments. */
193 	TABLE_CREATE,
194 	TABLE_DESTROY,
195 	TABLE_RESIZE,
196 	TABLE_RESIZE_COMPLETE,
197 	TABLE_CREATE_ID,
198 	TABLE_DESTROY_ID,
199 	TABLE_RESIZE_ID,
200 	TABLE_RESIZE_RULES_NUMBER,
201 	TABLE_INSERTION_TYPE,
202 	TABLE_INSERTION_TYPE_NAME,
203 	TABLE_HASH_FUNC,
204 	TABLE_HASH_FUNC_NAME,
205 	TABLE_GROUP,
206 	TABLE_PRIORITY,
207 	TABLE_INGRESS,
208 	TABLE_EGRESS,
209 	TABLE_TRANSFER,
210 	TABLE_TRANSFER_WIRE_ORIG,
211 	TABLE_TRANSFER_VPORT_ORIG,
212 	TABLE_RESIZABLE,
213 	TABLE_RULES_NUMBER,
214 	TABLE_PATTERN_TEMPLATE,
215 	TABLE_ACTIONS_TEMPLATE,
216 
217 	/* Group arguments */
218 	GROUP_ID,
219 	GROUP_INGRESS,
220 	GROUP_EGRESS,
221 	GROUP_TRANSFER,
222 	GROUP_SET_MISS_ACTIONS,
223 
224 	/* Hash calculation arguments. */
225 	HASH_CALC_TABLE,
226 	HASH_CALC_PATTERN_INDEX,
227 	HASH_CALC_PATTERN,
228 	HASH_CALC_ENCAP,
229 	HASH_CALC_DEST,
230 	ENCAP_HASH_FIELD_SRC_PORT,
231 	ENCAP_HASH_FIELD_GRE_FLOW_ID,
232 
233 	/* Tunnel arguments. */
234 	TUNNEL_CREATE,
235 	TUNNEL_CREATE_TYPE,
236 	TUNNEL_LIST,
237 	TUNNEL_DESTROY,
238 	TUNNEL_DESTROY_ID,
239 
240 	/* Destroy arguments. */
241 	DESTROY_RULE,
242 	DESTROY_IS_USER_ID,
243 
244 	/* Query arguments. */
245 	QUERY_ACTION,
246 	QUERY_IS_USER_ID,
247 
248 	/* List arguments. */
249 	LIST_GROUP,
250 
251 	/* Destroy aged flow arguments. */
252 	AGED_DESTROY,
253 
254 	/* Validate/create arguments. */
255 	VC_GROUP,
256 	VC_PRIORITY,
257 	VC_INGRESS,
258 	VC_EGRESS,
259 	VC_TRANSFER,
260 	VC_TUNNEL_SET,
261 	VC_TUNNEL_MATCH,
262 	VC_USER_ID,
263 
264 	/* Dump arguments */
265 	DUMP_ALL,
266 	DUMP_ONE,
267 	DUMP_IS_USER_ID,
268 
269 	/* Configure arguments */
270 	CONFIG_QUEUES_NUMBER,
271 	CONFIG_QUEUES_SIZE,
272 	CONFIG_COUNTERS_NUMBER,
273 	CONFIG_AGING_OBJECTS_NUMBER,
274 	CONFIG_METERS_NUMBER,
275 	CONFIG_CONN_TRACK_NUMBER,
276 	CONFIG_QUOTAS_NUMBER,
277 	CONFIG_FLAGS,
278 	CONFIG_HOST_PORT,
279 
280 	/* Indirect action arguments */
281 	INDIRECT_ACTION_CREATE,
282 	INDIRECT_ACTION_LIST_CREATE,
283 	INDIRECT_ACTION_FLOW_CONF_CREATE,
284 	INDIRECT_ACTION_UPDATE,
285 	INDIRECT_ACTION_DESTROY,
286 	INDIRECT_ACTION_QUERY,
287 	INDIRECT_ACTION_QUERY_UPDATE,
288 
289 	/* Indirect action create arguments */
290 	INDIRECT_ACTION_CREATE_ID,
291 	INDIRECT_ACTION_INGRESS,
292 	INDIRECT_ACTION_EGRESS,
293 	INDIRECT_ACTION_TRANSFER,
294 	INDIRECT_ACTION_SPEC,
295 	INDIRECT_ACTION_LIST,
296 	INDIRECT_ACTION_FLOW_CONF,
297 
298 	/* Indirect action destroy arguments */
299 	INDIRECT_ACTION_DESTROY_ID,
300 
301 	/* Indirect action query-and-update arguments */
302 	INDIRECT_ACTION_QU_MODE,
303 	INDIRECT_ACTION_QU_MODE_NAME,
304 
305 	/* Validate/create pattern. */
306 	ITEM_PATTERN,
307 	ITEM_PARAM_IS,
308 	ITEM_PARAM_SPEC,
309 	ITEM_PARAM_LAST,
310 	ITEM_PARAM_MASK,
311 	ITEM_PARAM_PREFIX,
312 	ITEM_NEXT,
313 	ITEM_END,
314 	ITEM_VOID,
315 	ITEM_INVERT,
316 	ITEM_ANY,
317 	ITEM_ANY_NUM,
318 	ITEM_PORT_ID,
319 	ITEM_PORT_ID_ID,
320 	ITEM_MARK,
321 	ITEM_MARK_ID,
322 	ITEM_RAW,
323 	ITEM_RAW_RELATIVE,
324 	ITEM_RAW_SEARCH,
325 	ITEM_RAW_OFFSET,
326 	ITEM_RAW_LIMIT,
327 	ITEM_RAW_PATTERN,
328 	ITEM_RAW_PATTERN_HEX,
329 	ITEM_ETH,
330 	ITEM_ETH_DST,
331 	ITEM_ETH_SRC,
332 	ITEM_ETH_TYPE,
333 	ITEM_ETH_HAS_VLAN,
334 	ITEM_VLAN,
335 	ITEM_VLAN_TCI,
336 	ITEM_VLAN_PCP,
337 	ITEM_VLAN_DEI,
338 	ITEM_VLAN_VID,
339 	ITEM_VLAN_INNER_TYPE,
340 	ITEM_VLAN_HAS_MORE_VLAN,
341 	ITEM_IPV4,
342 	ITEM_IPV4_VER_IHL,
343 	ITEM_IPV4_TOS,
344 	ITEM_IPV4_LENGTH,
345 	ITEM_IPV4_ID,
346 	ITEM_IPV4_FRAGMENT_OFFSET,
347 	ITEM_IPV4_TTL,
348 	ITEM_IPV4_PROTO,
349 	ITEM_IPV4_SRC,
350 	ITEM_IPV4_DST,
351 	ITEM_IPV6,
352 	ITEM_IPV6_TC,
353 	ITEM_IPV6_FLOW,
354 	ITEM_IPV6_LEN,
355 	ITEM_IPV6_PROTO,
356 	ITEM_IPV6_HOP,
357 	ITEM_IPV6_SRC,
358 	ITEM_IPV6_DST,
359 	ITEM_IPV6_HAS_FRAG_EXT,
360 	ITEM_IPV6_ROUTING_EXT,
361 	ITEM_IPV6_ROUTING_EXT_TYPE,
362 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
363 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
364 	ITEM_ICMP,
365 	ITEM_ICMP_TYPE,
366 	ITEM_ICMP_CODE,
367 	ITEM_ICMP_IDENT,
368 	ITEM_ICMP_SEQ,
369 	ITEM_UDP,
370 	ITEM_UDP_SRC,
371 	ITEM_UDP_DST,
372 	ITEM_TCP,
373 	ITEM_TCP_SRC,
374 	ITEM_TCP_DST,
375 	ITEM_TCP_FLAGS,
376 	ITEM_SCTP,
377 	ITEM_SCTP_SRC,
378 	ITEM_SCTP_DST,
379 	ITEM_SCTP_TAG,
380 	ITEM_SCTP_CKSUM,
381 	ITEM_VXLAN,
382 	ITEM_VXLAN_VNI,
383 	ITEM_VXLAN_LAST_RSVD,
384 	ITEM_E_TAG,
385 	ITEM_E_TAG_GRP_ECID_B,
386 	ITEM_NVGRE,
387 	ITEM_NVGRE_TNI,
388 	ITEM_MPLS,
389 	ITEM_MPLS_LABEL,
390 	ITEM_MPLS_TC,
391 	ITEM_MPLS_S,
392 	ITEM_MPLS_TTL,
393 	ITEM_GRE,
394 	ITEM_GRE_PROTO,
395 	ITEM_GRE_C_RSVD0_VER,
396 	ITEM_GRE_C_BIT,
397 	ITEM_GRE_K_BIT,
398 	ITEM_GRE_S_BIT,
399 	ITEM_FUZZY,
400 	ITEM_FUZZY_THRESH,
401 	ITEM_GTP,
402 	ITEM_GTP_FLAGS,
403 	ITEM_GTP_MSG_TYPE,
404 	ITEM_GTP_TEID,
405 	ITEM_GTPC,
406 	ITEM_GTPU,
407 	ITEM_GENEVE,
408 	ITEM_GENEVE_VNI,
409 	ITEM_GENEVE_PROTO,
410 	ITEM_GENEVE_OPTLEN,
411 	ITEM_VXLAN_GPE,
412 	ITEM_VXLAN_GPE_VNI,
413 	ITEM_VXLAN_GPE_PROTO,
414 	ITEM_VXLAN_GPE_FLAGS,
415 	ITEM_VXLAN_GPE_RSVD0,
416 	ITEM_VXLAN_GPE_RSVD1,
417 	ITEM_ARP_ETH_IPV4,
418 	ITEM_ARP_ETH_IPV4_SHA,
419 	ITEM_ARP_ETH_IPV4_SPA,
420 	ITEM_ARP_ETH_IPV4_THA,
421 	ITEM_ARP_ETH_IPV4_TPA,
422 	ITEM_IPV6_EXT,
423 	ITEM_IPV6_EXT_NEXT_HDR,
424 	ITEM_IPV6_FRAG_EXT,
425 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
426 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
427 	ITEM_IPV6_FRAG_EXT_ID,
428 	ITEM_ICMP6,
429 	ITEM_ICMP6_TYPE,
430 	ITEM_ICMP6_CODE,
431 	ITEM_ICMP6_ECHO_REQUEST,
432 	ITEM_ICMP6_ECHO_REQUEST_ID,
433 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
434 	ITEM_ICMP6_ECHO_REPLY,
435 	ITEM_ICMP6_ECHO_REPLY_ID,
436 	ITEM_ICMP6_ECHO_REPLY_SEQ,
437 	ITEM_ICMP6_ND_NS,
438 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
439 	ITEM_ICMP6_ND_NA,
440 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
441 	ITEM_ICMP6_ND_OPT,
442 	ITEM_ICMP6_ND_OPT_TYPE,
443 	ITEM_ICMP6_ND_OPT_SLA_ETH,
444 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
445 	ITEM_ICMP6_ND_OPT_TLA_ETH,
446 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
447 	ITEM_META,
448 	ITEM_META_DATA,
449 	ITEM_RANDOM,
450 	ITEM_RANDOM_VALUE,
451 	ITEM_GRE_KEY,
452 	ITEM_GRE_KEY_VALUE,
453 	ITEM_GRE_OPTION,
454 	ITEM_GRE_OPTION_CHECKSUM,
455 	ITEM_GRE_OPTION_KEY,
456 	ITEM_GRE_OPTION_SEQUENCE,
457 	ITEM_GTP_PSC,
458 	ITEM_GTP_PSC_QFI,
459 	ITEM_GTP_PSC_PDU_T,
460 	ITEM_PPPOES,
461 	ITEM_PPPOED,
462 	ITEM_PPPOE_SEID,
463 	ITEM_PPPOE_PROTO_ID,
464 	ITEM_HIGIG2,
465 	ITEM_HIGIG2_CLASSIFICATION,
466 	ITEM_HIGIG2_VID,
467 	ITEM_TAG,
468 	ITEM_TAG_DATA,
469 	ITEM_TAG_INDEX,
470 	ITEM_L2TPV3OIP,
471 	ITEM_L2TPV3OIP_SESSION_ID,
472 	ITEM_ESP,
473 	ITEM_ESP_SPI,
474 	ITEM_AH,
475 	ITEM_AH_SPI,
476 	ITEM_PFCP,
477 	ITEM_PFCP_S_FIELD,
478 	ITEM_PFCP_SEID,
479 	ITEM_ECPRI,
480 	ITEM_ECPRI_COMMON,
481 	ITEM_ECPRI_COMMON_TYPE,
482 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
483 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
484 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
485 	ITEM_ECPRI_MSG_IQ_DATA_PCID,
486 	ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
487 	ITEM_ECPRI_MSG_DLY_MSR_MSRID,
488 	ITEM_GENEVE_OPT,
489 	ITEM_GENEVE_OPT_CLASS,
490 	ITEM_GENEVE_OPT_TYPE,
491 	ITEM_GENEVE_OPT_LENGTH,
492 	ITEM_GENEVE_OPT_DATA,
493 	ITEM_INTEGRITY,
494 	ITEM_INTEGRITY_LEVEL,
495 	ITEM_INTEGRITY_VALUE,
496 	ITEM_CONNTRACK,
497 	ITEM_POL_PORT,
498 	ITEM_POL_METER,
499 	ITEM_POL_POLICY,
500 	ITEM_PORT_REPRESENTOR,
501 	ITEM_PORT_REPRESENTOR_PORT_ID,
502 	ITEM_REPRESENTED_PORT,
503 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
504 	ITEM_FLEX,
505 	ITEM_FLEX_ITEM_HANDLE,
506 	ITEM_FLEX_PATTERN_HANDLE,
507 	ITEM_L2TPV2,
508 	ITEM_L2TPV2_TYPE,
509 	ITEM_L2TPV2_TYPE_DATA,
510 	ITEM_L2TPV2_TYPE_DATA_L,
511 	ITEM_L2TPV2_TYPE_DATA_S,
512 	ITEM_L2TPV2_TYPE_DATA_O,
513 	ITEM_L2TPV2_TYPE_DATA_L_S,
514 	ITEM_L2TPV2_TYPE_CTRL,
515 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
516 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
517 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
518 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
519 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
520 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
521 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
522 	ITEM_L2TPV2_MSG_DATA_S_NS,
523 	ITEM_L2TPV2_MSG_DATA_S_NR,
524 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
525 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
526 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
527 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
528 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
529 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
530 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
531 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
532 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
533 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
534 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
535 	ITEM_L2TPV2_MSG_CTRL_NS,
536 	ITEM_L2TPV2_MSG_CTRL_NR,
537 	ITEM_PPP,
538 	ITEM_PPP_ADDR,
539 	ITEM_PPP_CTRL,
540 	ITEM_PPP_PROTO_ID,
541 	ITEM_METER,
542 	ITEM_METER_COLOR,
543 	ITEM_METER_COLOR_NAME,
544 	ITEM_QUOTA,
545 	ITEM_QUOTA_STATE,
546 	ITEM_QUOTA_STATE_NAME,
547 	ITEM_AGGR_AFFINITY,
548 	ITEM_AGGR_AFFINITY_VALUE,
549 	ITEM_TX_QUEUE,
550 	ITEM_TX_QUEUE_VALUE,
551 	ITEM_IB_BTH,
552 	ITEM_IB_BTH_OPCODE,
553 	ITEM_IB_BTH_PKEY,
554 	ITEM_IB_BTH_DST_QPN,
555 	ITEM_IB_BTH_PSN,
556 	ITEM_IPV6_PUSH_REMOVE_EXT,
557 	ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
558 	ITEM_PTYPE,
559 	ITEM_PTYPE_VALUE,
560 	ITEM_NSH,
561 	ITEM_COMPARE,
562 	ITEM_COMPARE_OP,
563 	ITEM_COMPARE_OP_VALUE,
564 	ITEM_COMPARE_FIELD_A_TYPE,
565 	ITEM_COMPARE_FIELD_A_TYPE_VALUE,
566 	ITEM_COMPARE_FIELD_A_LEVEL,
567 	ITEM_COMPARE_FIELD_A_LEVEL_VALUE,
568 	ITEM_COMPARE_FIELD_A_TAG_INDEX,
569 	ITEM_COMPARE_FIELD_A_TYPE_ID,
570 	ITEM_COMPARE_FIELD_A_CLASS_ID,
571 	ITEM_COMPARE_FIELD_A_OFFSET,
572 	ITEM_COMPARE_FIELD_B_TYPE,
573 	ITEM_COMPARE_FIELD_B_TYPE_VALUE,
574 	ITEM_COMPARE_FIELD_B_LEVEL,
575 	ITEM_COMPARE_FIELD_B_LEVEL_VALUE,
576 	ITEM_COMPARE_FIELD_B_TAG_INDEX,
577 	ITEM_COMPARE_FIELD_B_TYPE_ID,
578 	ITEM_COMPARE_FIELD_B_CLASS_ID,
579 	ITEM_COMPARE_FIELD_B_OFFSET,
580 	ITEM_COMPARE_FIELD_B_VALUE,
581 	ITEM_COMPARE_FIELD_B_POINTER,
582 	ITEM_COMPARE_FIELD_WIDTH,
583 
584 	/* Validate/create actions. */
585 	ACTIONS,
586 	ACTION_NEXT,
587 	ACTION_END,
588 	ACTION_VOID,
589 	ACTION_PASSTHRU,
590 	ACTION_SKIP_CMAN,
591 	ACTION_JUMP,
592 	ACTION_JUMP_GROUP,
593 	ACTION_MARK,
594 	ACTION_MARK_ID,
595 	ACTION_FLAG,
596 	ACTION_QUEUE,
597 	ACTION_QUEUE_INDEX,
598 	ACTION_DROP,
599 	ACTION_COUNT,
600 	ACTION_COUNT_ID,
601 	ACTION_RSS,
602 	ACTION_RSS_FUNC,
603 	ACTION_RSS_LEVEL,
604 	ACTION_RSS_FUNC_DEFAULT,
605 	ACTION_RSS_FUNC_TOEPLITZ,
606 	ACTION_RSS_FUNC_SIMPLE_XOR,
607 	ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
608 	ACTION_RSS_TYPES,
609 	ACTION_RSS_TYPE,
610 	ACTION_RSS_KEY,
611 	ACTION_RSS_KEY_LEN,
612 	ACTION_RSS_QUEUES,
613 	ACTION_RSS_QUEUE,
614 	ACTION_PF,
615 	ACTION_VF,
616 	ACTION_VF_ORIGINAL,
617 	ACTION_VF_ID,
618 	ACTION_PORT_ID,
619 	ACTION_PORT_ID_ORIGINAL,
620 	ACTION_PORT_ID_ID,
621 	ACTION_METER,
622 	ACTION_METER_COLOR,
623 	ACTION_METER_COLOR_TYPE,
624 	ACTION_METER_COLOR_GREEN,
625 	ACTION_METER_COLOR_YELLOW,
626 	ACTION_METER_COLOR_RED,
627 	ACTION_METER_ID,
628 	ACTION_METER_MARK,
629 	ACTION_METER_PROFILE,
630 	ACTION_METER_PROFILE_ID2PTR,
631 	ACTION_METER_POLICY,
632 	ACTION_METER_POLICY_ID2PTR,
633 	ACTION_METER_COLOR_MODE,
634 	ACTION_METER_STATE,
635 	ACTION_OF_DEC_NW_TTL,
636 	ACTION_OF_POP_VLAN,
637 	ACTION_OF_PUSH_VLAN,
638 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
639 	ACTION_OF_SET_VLAN_VID,
640 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
641 	ACTION_OF_SET_VLAN_PCP,
642 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
643 	ACTION_OF_POP_MPLS,
644 	ACTION_OF_POP_MPLS_ETHERTYPE,
645 	ACTION_OF_PUSH_MPLS,
646 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
647 	ACTION_VXLAN_ENCAP,
648 	ACTION_VXLAN_DECAP,
649 	ACTION_NVGRE_ENCAP,
650 	ACTION_NVGRE_DECAP,
651 	ACTION_L2_ENCAP,
652 	ACTION_L2_DECAP,
653 	ACTION_MPLSOGRE_ENCAP,
654 	ACTION_MPLSOGRE_DECAP,
655 	ACTION_MPLSOUDP_ENCAP,
656 	ACTION_MPLSOUDP_DECAP,
657 	ACTION_SET_IPV4_SRC,
658 	ACTION_SET_IPV4_SRC_IPV4_SRC,
659 	ACTION_SET_IPV4_DST,
660 	ACTION_SET_IPV4_DST_IPV4_DST,
661 	ACTION_SET_IPV6_SRC,
662 	ACTION_SET_IPV6_SRC_IPV6_SRC,
663 	ACTION_SET_IPV6_DST,
664 	ACTION_SET_IPV6_DST_IPV6_DST,
665 	ACTION_SET_TP_SRC,
666 	ACTION_SET_TP_SRC_TP_SRC,
667 	ACTION_SET_TP_DST,
668 	ACTION_SET_TP_DST_TP_DST,
669 	ACTION_MAC_SWAP,
670 	ACTION_DEC_TTL,
671 	ACTION_SET_TTL,
672 	ACTION_SET_TTL_TTL,
673 	ACTION_SET_MAC_SRC,
674 	ACTION_SET_MAC_SRC_MAC_SRC,
675 	ACTION_SET_MAC_DST,
676 	ACTION_SET_MAC_DST_MAC_DST,
677 	ACTION_INC_TCP_SEQ,
678 	ACTION_INC_TCP_SEQ_VALUE,
679 	ACTION_DEC_TCP_SEQ,
680 	ACTION_DEC_TCP_SEQ_VALUE,
681 	ACTION_INC_TCP_ACK,
682 	ACTION_INC_TCP_ACK_VALUE,
683 	ACTION_DEC_TCP_ACK,
684 	ACTION_DEC_TCP_ACK_VALUE,
685 	ACTION_RAW_ENCAP,
686 	ACTION_RAW_DECAP,
687 	ACTION_RAW_ENCAP_SIZE,
688 	ACTION_RAW_ENCAP_INDEX,
689 	ACTION_RAW_ENCAP_INDEX_VALUE,
690 	ACTION_RAW_DECAP_INDEX,
691 	ACTION_RAW_DECAP_INDEX_VALUE,
692 	ACTION_SET_TAG,
693 	ACTION_SET_TAG_DATA,
694 	ACTION_SET_TAG_INDEX,
695 	ACTION_SET_TAG_MASK,
696 	ACTION_SET_META,
697 	ACTION_SET_META_DATA,
698 	ACTION_SET_META_MASK,
699 	ACTION_SET_IPV4_DSCP,
700 	ACTION_SET_IPV4_DSCP_VALUE,
701 	ACTION_SET_IPV6_DSCP,
702 	ACTION_SET_IPV6_DSCP_VALUE,
703 	ACTION_AGE,
704 	ACTION_AGE_TIMEOUT,
705 	ACTION_AGE_UPDATE,
706 	ACTION_AGE_UPDATE_TIMEOUT,
707 	ACTION_AGE_UPDATE_TOUCH,
708 	ACTION_SAMPLE,
709 	ACTION_SAMPLE_RATIO,
710 	ACTION_SAMPLE_INDEX,
711 	ACTION_SAMPLE_INDEX_VALUE,
712 	ACTION_INDIRECT,
713 	ACTION_INDIRECT_LIST,
714 	ACTION_INDIRECT_LIST_HANDLE,
715 	ACTION_INDIRECT_LIST_CONF,
716 	INDIRECT_LIST_ACTION_ID2PTR_HANDLE,
717 	INDIRECT_LIST_ACTION_ID2PTR_CONF,
718 	ACTION_SHARED_INDIRECT,
719 	INDIRECT_ACTION_PORT,
720 	INDIRECT_ACTION_ID2PTR,
721 	ACTION_MODIFY_FIELD,
722 	ACTION_MODIFY_FIELD_OP,
723 	ACTION_MODIFY_FIELD_OP_VALUE,
724 	ACTION_MODIFY_FIELD_DST_TYPE,
725 	ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
726 	ACTION_MODIFY_FIELD_DST_LEVEL,
727 	ACTION_MODIFY_FIELD_DST_LEVEL_VALUE,
728 	ACTION_MODIFY_FIELD_DST_TAG_INDEX,
729 	ACTION_MODIFY_FIELD_DST_TYPE_ID,
730 	ACTION_MODIFY_FIELD_DST_CLASS_ID,
731 	ACTION_MODIFY_FIELD_DST_OFFSET,
732 	ACTION_MODIFY_FIELD_SRC_TYPE,
733 	ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
734 	ACTION_MODIFY_FIELD_SRC_LEVEL,
735 	ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE,
736 	ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
737 	ACTION_MODIFY_FIELD_SRC_TYPE_ID,
738 	ACTION_MODIFY_FIELD_SRC_CLASS_ID,
739 	ACTION_MODIFY_FIELD_SRC_OFFSET,
740 	ACTION_MODIFY_FIELD_SRC_VALUE,
741 	ACTION_MODIFY_FIELD_SRC_POINTER,
742 	ACTION_MODIFY_FIELD_WIDTH,
743 	ACTION_CONNTRACK,
744 	ACTION_CONNTRACK_UPDATE,
745 	ACTION_CONNTRACK_UPDATE_DIR,
746 	ACTION_CONNTRACK_UPDATE_CTX,
747 	ACTION_POL_G,
748 	ACTION_POL_Y,
749 	ACTION_POL_R,
750 	ACTION_PORT_REPRESENTOR,
751 	ACTION_PORT_REPRESENTOR_PORT_ID,
752 	ACTION_REPRESENTED_PORT,
753 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
754 	ACTION_SEND_TO_KERNEL,
755 	ACTION_QUOTA_CREATE,
756 	ACTION_QUOTA_CREATE_LIMIT,
757 	ACTION_QUOTA_CREATE_MODE,
758 	ACTION_QUOTA_CREATE_MODE_NAME,
759 	ACTION_QUOTA_QU,
760 	ACTION_QUOTA_QU_LIMIT,
761 	ACTION_QUOTA_QU_UPDATE_OP,
762 	ACTION_QUOTA_QU_UPDATE_OP_NAME,
763 	ACTION_IPV6_EXT_REMOVE,
764 	ACTION_IPV6_EXT_REMOVE_INDEX,
765 	ACTION_IPV6_EXT_REMOVE_INDEX_VALUE,
766 	ACTION_IPV6_EXT_PUSH,
767 	ACTION_IPV6_EXT_PUSH_INDEX,
768 	ACTION_IPV6_EXT_PUSH_INDEX_VALUE,
769 	ACTION_NAT64,
770 	ACTION_NAT64_MODE,
771 };
772 
773 /** Maximum size for pattern in struct rte_flow_item_raw. */
774 #define ITEM_RAW_PATTERN_SIZE 512
775 
776 /** Maximum size for GENEVE option data pattern in bytes. */
777 #define ITEM_GENEVE_OPT_DATA_SIZE 124
778 
779 /** Storage size for struct rte_flow_item_raw including pattern. */
780 #define ITEM_RAW_SIZE \
781 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
782 
783 static const char *const compare_ops[] = {
784 	"eq", "ne", "lt", "le", "gt", "ge", NULL
785 };
786 
787 /** Maximum size for external pattern in struct rte_flow_field_data. */
788 #define FLOW_FIELD_PATTERN_SIZE 32
789 
790 /** Storage size for struct rte_flow_action_modify_field including pattern. */
791 #define ACTION_MODIFY_SIZE \
792 	(sizeof(struct rte_flow_action_modify_field) + \
793 	FLOW_FIELD_PATTERN_SIZE)
794 
795 /** Maximum number of queue indices in struct rte_flow_action_rss. */
796 #define ACTION_RSS_QUEUE_NUM 128
797 
798 /** Storage for struct rte_flow_action_rss including external data. */
799 struct action_rss_data {
800 	struct rte_flow_action_rss conf;
801 	uint8_t key[RSS_HASH_KEY_LENGTH];
802 	uint16_t queue[ACTION_RSS_QUEUE_NUM];
803 };
804 
805 /** Maximum data size in struct rte_flow_action_raw_encap. */
806 #define ACTION_RAW_ENCAP_MAX_DATA 512
807 #define RAW_ENCAP_CONFS_MAX_NUM 8
808 
809 /** Storage for struct rte_flow_action_raw_encap. */
810 struct raw_encap_conf {
811 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
812 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
813 	size_t size;
814 };
815 
816 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
817 
818 /** Storage for struct rte_flow_action_raw_encap including external data. */
819 struct action_raw_encap_data {
820 	struct rte_flow_action_raw_encap conf;
821 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
822 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
823 	uint16_t idx;
824 };
825 
826 /** Storage for struct rte_flow_action_raw_decap. */
827 struct raw_decap_conf {
828 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
829 	size_t size;
830 };
831 
832 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
833 
834 /** Storage for struct rte_flow_action_raw_decap including external data. */
835 struct action_raw_decap_data {
836 	struct rte_flow_action_raw_decap conf;
837 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
838 	uint16_t idx;
839 };
840 
841 /** Maximum data size in struct rte_flow_action_ipv6_ext_push. */
842 #define ACTION_IPV6_EXT_PUSH_MAX_DATA 512
843 #define IPV6_EXT_PUSH_CONFS_MAX_NUM 8
844 
845 /** Storage for struct rte_flow_action_ipv6_ext_push. */
846 struct ipv6_ext_push_conf {
847 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
848 	size_t size;
849 	uint8_t type;
850 };
851 
852 struct ipv6_ext_push_conf ipv6_ext_push_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
853 
854 /** Storage for struct rte_flow_action_ipv6_ext_push including external data. */
855 struct action_ipv6_ext_push_data {
856 	struct rte_flow_action_ipv6_ext_push conf;
857 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
858 	uint8_t type;
859 	uint16_t idx;
860 };
861 
862 /** Storage for struct rte_flow_action_ipv6_ext_remove. */
863 struct ipv6_ext_remove_conf {
864 	struct rte_flow_action_ipv6_ext_remove conf;
865 	uint8_t type;
866 };
867 
868 struct ipv6_ext_remove_conf ipv6_ext_remove_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
869 
870 /** Storage for struct rte_flow_action_ipv6_ext_remove including external data. */
871 struct action_ipv6_ext_remove_data {
872 	struct rte_flow_action_ipv6_ext_remove conf;
873 	uint8_t type;
874 	uint16_t idx;
875 };
876 
877 struct vxlan_encap_conf vxlan_encap_conf = {
878 	.select_ipv4 = 1,
879 	.select_vlan = 0,
880 	.select_tos_ttl = 0,
881 	.vni = "\x00\x00\x00",
882 	.udp_src = 0,
883 	.udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
884 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
885 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
886 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
887 		"\x00\x00\x00\x00\x00\x00\x00\x01",
888 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
889 		"\x00\x00\x00\x00\x00\x00\x11\x11",
890 	.vlan_tci = 0,
891 	.ip_tos = 0,
892 	.ip_ttl = 255,
893 	.eth_src = "\x00\x00\x00\x00\x00\x00",
894 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
895 };
896 
897 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
898 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
899 
900 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
901 struct action_vxlan_encap_data {
902 	struct rte_flow_action_vxlan_encap conf;
903 	struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
904 	struct rte_flow_item_eth item_eth;
905 	struct rte_flow_item_vlan item_vlan;
906 	union {
907 		struct rte_flow_item_ipv4 item_ipv4;
908 		struct rte_flow_item_ipv6 item_ipv6;
909 	};
910 	struct rte_flow_item_udp item_udp;
911 	struct rte_flow_item_vxlan item_vxlan;
912 };
913 
914 struct nvgre_encap_conf nvgre_encap_conf = {
915 	.select_ipv4 = 1,
916 	.select_vlan = 0,
917 	.tni = "\x00\x00\x00",
918 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
919 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
920 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
921 		"\x00\x00\x00\x00\x00\x00\x00\x01",
922 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
923 		"\x00\x00\x00\x00\x00\x00\x11\x11",
924 	.vlan_tci = 0,
925 	.eth_src = "\x00\x00\x00\x00\x00\x00",
926 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
927 };
928 
929 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
930 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
931 
932 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
933 struct action_nvgre_encap_data {
934 	struct rte_flow_action_nvgre_encap conf;
935 	struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
936 	struct rte_flow_item_eth item_eth;
937 	struct rte_flow_item_vlan item_vlan;
938 	union {
939 		struct rte_flow_item_ipv4 item_ipv4;
940 		struct rte_flow_item_ipv6 item_ipv6;
941 	};
942 	struct rte_flow_item_nvgre item_nvgre;
943 };
944 
945 struct l2_encap_conf l2_encap_conf;
946 
947 struct l2_decap_conf l2_decap_conf;
948 
949 struct mplsogre_encap_conf mplsogre_encap_conf;
950 
951 struct mplsogre_decap_conf mplsogre_decap_conf;
952 
953 struct mplsoudp_encap_conf mplsoudp_encap_conf;
954 
955 struct mplsoudp_decap_conf mplsoudp_decap_conf;
956 
957 struct rte_flow_action_conntrack conntrack_context;
958 
959 #define ACTION_SAMPLE_ACTIONS_NUM 10
960 #define RAW_SAMPLE_CONFS_MAX_NUM 8
961 /** Storage for struct rte_flow_action_sample including external data. */
962 struct action_sample_data {
963 	struct rte_flow_action_sample conf;
964 	uint32_t idx;
965 };
966 /** Storage for struct rte_flow_action_sample. */
967 struct raw_sample_conf {
968 	struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
969 };
970 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
971 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
972 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
973 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
974 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
975 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
976 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
977 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
978 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
979 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
980 struct rte_flow_action_ethdev sample_port_representor[RAW_SAMPLE_CONFS_MAX_NUM];
981 struct rte_flow_action_ethdev sample_represented_port[RAW_SAMPLE_CONFS_MAX_NUM];
982 
983 static const char *const modify_field_ops[] = {
984 	"set", "add", "sub", NULL
985 };
986 
987 static const char *const flow_field_ids[] = {
988 	"start", "mac_dst", "mac_src",
989 	"vlan_type", "vlan_id", "mac_type",
990 	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
991 	"ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
992 	"tcp_port_src", "tcp_port_dst",
993 	"tcp_seq_num", "tcp_ack_num", "tcp_flags",
994 	"udp_port_src", "udp_port_dst",
995 	"vxlan_vni", "geneve_vni", "gtp_teid",
996 	"tag", "mark", "meta", "pointer", "value",
997 	"ipv4_ecn", "ipv6_ecn", "gtp_psc_qfi", "meter_color",
998 	"ipv6_proto",
999 	"flex_item",
1000 	"hash_result",
1001 	"geneve_opt_type", "geneve_opt_class", "geneve_opt_data", "mpls",
1002 	"tcp_data_off", "ipv4_ihl", "ipv4_total_len", "ipv6_payload_len",
1003 	"random",
1004 	"ipv4_proto",
1005 	"esp_spi", "esp_seq_num", "esp_proto",
1006 	"ipv6_flow_label", "ipv6_traffic_class",
1007 	NULL
1008 };
1009 
1010 static const char *const meter_colors[] = {
1011 	"green", "yellow", "red", "all", NULL
1012 };
1013 
1014 static const char *const table_insertion_types[] = {
1015 	"pattern", "index", NULL
1016 };
1017 
1018 static const char *const table_hash_funcs[] = {
1019 	"default", "linear", "crc32", "crc16", NULL
1020 };
1021 
1022 #define RAW_IPSEC_CONFS_MAX_NUM 8
1023 
1024 /** Maximum number of subsequent tokens and arguments on the stack. */
1025 #define CTX_STACK_SIZE 16
1026 
1027 /** Parser context. */
1028 struct context {
1029 	/** Stack of subsequent token lists to process. */
1030 	const enum index *next[CTX_STACK_SIZE];
1031 	/** Arguments for stacked tokens. */
1032 	const void *args[CTX_STACK_SIZE];
1033 	enum index curr; /**< Current token index. */
1034 	enum index prev; /**< Index of the last token seen. */
1035 	int next_num; /**< Number of entries in next[]. */
1036 	int args_num; /**< Number of entries in args[]. */
1037 	uint32_t eol:1; /**< EOL has been detected. */
1038 	uint32_t last:1; /**< No more arguments. */
1039 	portid_t port; /**< Current port ID (for completions). */
1040 	uint32_t objdata; /**< Object-specific data. */
1041 	void *object; /**< Address of current object for relative offsets. */
1042 	void *objmask; /**< Object a full mask must be written to. */
1043 };
1044 
1045 /** Token argument. */
1046 struct arg {
1047 	uint32_t hton:1; /**< Use network byte ordering. */
1048 	uint32_t sign:1; /**< Value is signed. */
1049 	uint32_t bounded:1; /**< Value is bounded. */
1050 	uintmax_t min; /**< Minimum value if bounded. */
1051 	uintmax_t max; /**< Maximum value if bounded. */
1052 	uint32_t offset; /**< Relative offset from ctx->object. */
1053 	uint32_t size; /**< Field size. */
1054 	const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
1055 };
1056 
1057 /** Parser token definition. */
1058 struct token {
1059 	/** Type displayed during completion (defaults to "TOKEN"). */
1060 	const char *type;
1061 	/** Help displayed during completion (defaults to token name). */
1062 	const char *help;
1063 	/** Private data used by parser functions. */
1064 	const void *priv;
1065 	/**
1066 	 * Lists of subsequent tokens to push on the stack. Each call to the
1067 	 * parser consumes the last entry of that stack.
1068 	 */
1069 	const enum index *const *next;
1070 	/** Arguments stack for subsequent tokens that need them. */
1071 	const struct arg *const *args;
1072 	/**
1073 	 * Token-processing callback, returns -1 in case of error, the
1074 	 * length of the matched string otherwise. If NULL, attempts to
1075 	 * match the token name.
1076 	 *
1077 	 * If buf is not NULL, the result should be stored in it according
1078 	 * to context. An error is returned if not large enough.
1079 	 */
1080 	int (*call)(struct context *ctx, const struct token *token,
1081 		    const char *str, unsigned int len,
1082 		    void *buf, unsigned int size);
1083 	/**
1084 	 * Callback that provides possible values for this token, used for
1085 	 * completion. Returns -1 in case of error, the number of possible
1086 	 * values otherwise. If NULL, the token name is used.
1087 	 *
1088 	 * If buf is not NULL, entry index ent is written to buf and the
1089 	 * full length of the entry is returned (same behavior as
1090 	 * snprintf()).
1091 	 */
1092 	int (*comp)(struct context *ctx, const struct token *token,
1093 		    unsigned int ent, char *buf, unsigned int size);
1094 	/** Mandatory token name, no default value. */
1095 	const char *name;
1096 };
1097 
1098 /** Static initializer for the next field. */
1099 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
1100 
1101 /** Static initializer for a NEXT() entry. */
1102 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
1103 
1104 /** Static initializer for the args field. */
1105 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
1106 
1107 /** Static initializer for ARGS() to target a field. */
1108 #define ARGS_ENTRY(s, f) \
1109 	(&(const struct arg){ \
1110 		.offset = offsetof(s, f), \
1111 		.size = sizeof(((s *)0)->f), \
1112 	})
1113 
1114 /** Static initializer for ARGS() to target a bit-field. */
1115 #define ARGS_ENTRY_BF(s, f, b) \
1116 	(&(const struct arg){ \
1117 		.size = sizeof(s), \
1118 		.mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
1119 	})
1120 
1121 /** Static initializer for ARGS() to target a field with limits. */
1122 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
1123 	(&(const struct arg){ \
1124 		.bounded = 1, \
1125 		.min = (i), \
1126 		.max = (a), \
1127 		.offset = offsetof(s, f), \
1128 		.size = sizeof(((s *)0)->f), \
1129 	})
1130 
1131 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
1132 #define ARGS_ENTRY_MASK(s, f, m) \
1133 	(&(const struct arg){ \
1134 		.offset = offsetof(s, f), \
1135 		.size = sizeof(((s *)0)->f), \
1136 		.mask = (const void *)(m), \
1137 	})
1138 
1139 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
1140 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
1141 	(&(const struct arg){ \
1142 		.hton = 1, \
1143 		.offset = offsetof(s, f), \
1144 		.size = sizeof(((s *)0)->f), \
1145 		.mask = (const void *)(m), \
1146 	})
1147 
1148 /** Static initializer for ARGS() to target a pointer. */
1149 #define ARGS_ENTRY_PTR(s, f) \
1150 	(&(const struct arg){ \
1151 		.size = sizeof(*((s *)0)->f), \
1152 	})
1153 
1154 /** Static initializer for ARGS() with arbitrary offset and size. */
1155 #define ARGS_ENTRY_ARB(o, s) \
1156 	(&(const struct arg){ \
1157 		.offset = (o), \
1158 		.size = (s), \
1159 	})
1160 
1161 /** Same as ARGS_ENTRY_ARB() with bounded values. */
1162 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
1163 	(&(const struct arg){ \
1164 		.bounded = 1, \
1165 		.min = (i), \
1166 		.max = (a), \
1167 		.offset = (o), \
1168 		.size = (s), \
1169 	})
1170 
1171 /** Same as ARGS_ENTRY() using network byte ordering. */
1172 #define ARGS_ENTRY_HTON(s, f) \
1173 	(&(const struct arg){ \
1174 		.hton = 1, \
1175 		.offset = offsetof(s, f), \
1176 		.size = sizeof(((s *)0)->f), \
1177 	})
1178 
1179 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
1180 #define ARG_ENTRY_HTON(s) \
1181 	(&(const struct arg){ \
1182 		.hton = 1, \
1183 		.offset = 0, \
1184 		.size = sizeof(s), \
1185 	})
1186 
1187 /** Parser output buffer layout expected by cmd_flow_parsed(). */
1188 struct buffer {
1189 	enum index command; /**< Flow command. */
1190 	portid_t port; /**< Affected port ID. */
1191 	queueid_t queue; /** Async queue ID. */
1192 	bool postpone; /** Postpone async operation */
1193 	union {
1194 		struct {
1195 			struct rte_flow_port_attr port_attr;
1196 			uint32_t nb_queue;
1197 			struct rte_flow_queue_attr queue_attr;
1198 		} configure; /**< Configuration arguments. */
1199 		struct {
1200 			uint32_t *template_id;
1201 			uint32_t template_id_n;
1202 		} templ_destroy; /**< Template destroy arguments. */
1203 		struct {
1204 			uint32_t id;
1205 			struct rte_flow_template_table_attr attr;
1206 			uint32_t *pat_templ_id;
1207 			uint32_t pat_templ_id_n;
1208 			uint32_t *act_templ_id;
1209 			uint32_t act_templ_id_n;
1210 		} table; /**< Table arguments. */
1211 		struct {
1212 			uint32_t *table_id;
1213 			uint32_t table_id_n;
1214 		} table_destroy; /**< Template destroy arguments. */
1215 		struct {
1216 			uint32_t *action_id;
1217 			uint32_t action_id_n;
1218 		} ia_destroy; /**< Indirect action destroy arguments. */
1219 		struct {
1220 			uint32_t action_id;
1221 			enum rte_flow_query_update_mode qu_mode;
1222 		} ia; /* Indirect action query arguments */
1223 		struct {
1224 			uint32_t table_id;
1225 			uint32_t pat_templ_id;
1226 			uint32_t rule_id;
1227 			uint32_t act_templ_id;
1228 			struct rte_flow_attr attr;
1229 			struct tunnel_ops tunnel_ops;
1230 			uintptr_t user_id;
1231 			struct rte_flow_item *pattern;
1232 			struct rte_flow_action *actions;
1233 			struct rte_flow_action *masks;
1234 			uint32_t pattern_n;
1235 			uint32_t actions_n;
1236 			uint8_t *data;
1237 			enum rte_flow_encap_hash_field field;
1238 			uint8_t encap_hash;
1239 		} vc; /**< Validate/create arguments. */
1240 		struct {
1241 			uint64_t *rule;
1242 			uint64_t rule_n;
1243 			bool is_user_id;
1244 		} destroy; /**< Destroy arguments. */
1245 		struct {
1246 			char file[128];
1247 			bool mode;
1248 			uint64_t rule;
1249 			bool is_user_id;
1250 		} dump; /**< Dump arguments. */
1251 		struct {
1252 			uint64_t rule;
1253 			struct rte_flow_action action;
1254 			bool is_user_id;
1255 		} query; /**< Query arguments. */
1256 		struct {
1257 			uint32_t *group;
1258 			uint32_t group_n;
1259 		} list; /**< List arguments. */
1260 		struct {
1261 			int set;
1262 		} isolate; /**< Isolated mode arguments. */
1263 		struct {
1264 			int destroy;
1265 		} aged; /**< Aged arguments. */
1266 		struct {
1267 			uint32_t policy_id;
1268 		} policy;/**< Policy arguments. */
1269 		struct {
1270 			uint16_t token;
1271 			uintptr_t uintptr;
1272 			char filename[128];
1273 		} flex; /**< Flex arguments*/
1274 	} args; /**< Command arguments. */
1275 };
1276 
1277 /** Private data for pattern items. */
1278 struct parse_item_priv {
1279 	enum rte_flow_item_type type; /**< Item type. */
1280 	uint32_t size; /**< Size of item specification structure. */
1281 };
1282 
1283 #define PRIV_ITEM(t, s) \
1284 	(&(const struct parse_item_priv){ \
1285 		.type = RTE_FLOW_ITEM_TYPE_ ## t, \
1286 		.size = s, \
1287 	})
1288 
1289 /** Private data for actions. */
1290 struct parse_action_priv {
1291 	enum rte_flow_action_type type; /**< Action type. */
1292 	uint32_t size; /**< Size of action configuration structure. */
1293 };
1294 
1295 #define PRIV_ACTION(t, s) \
1296 	(&(const struct parse_action_priv){ \
1297 		.type = RTE_FLOW_ACTION_TYPE_ ## t, \
1298 		.size = s, \
1299 	})
1300 
1301 static const enum index next_flex_item[] = {
1302 	FLEX_ITEM_INIT,
1303 	FLEX_ITEM_CREATE,
1304 	FLEX_ITEM_DESTROY,
1305 	ZERO,
1306 };
1307 
1308 static const enum index next_config_attr[] = {
1309 	CONFIG_QUEUES_NUMBER,
1310 	CONFIG_QUEUES_SIZE,
1311 	CONFIG_COUNTERS_NUMBER,
1312 	CONFIG_AGING_OBJECTS_NUMBER,
1313 	CONFIG_METERS_NUMBER,
1314 	CONFIG_CONN_TRACK_NUMBER,
1315 	CONFIG_QUOTAS_NUMBER,
1316 	CONFIG_FLAGS,
1317 	CONFIG_HOST_PORT,
1318 	END,
1319 	ZERO,
1320 };
1321 
1322 static const enum index next_pt_subcmd[] = {
1323 	PATTERN_TEMPLATE_CREATE,
1324 	PATTERN_TEMPLATE_DESTROY,
1325 	ZERO,
1326 };
1327 
1328 static const enum index next_pt_attr[] = {
1329 	PATTERN_TEMPLATE_CREATE_ID,
1330 	PATTERN_TEMPLATE_RELAXED_MATCHING,
1331 	PATTERN_TEMPLATE_INGRESS,
1332 	PATTERN_TEMPLATE_EGRESS,
1333 	PATTERN_TEMPLATE_TRANSFER,
1334 	PATTERN_TEMPLATE_SPEC,
1335 	ZERO,
1336 };
1337 
1338 static const enum index next_pt_destroy_attr[] = {
1339 	PATTERN_TEMPLATE_DESTROY_ID,
1340 	END,
1341 	ZERO,
1342 };
1343 
1344 static const enum index next_at_subcmd[] = {
1345 	ACTIONS_TEMPLATE_CREATE,
1346 	ACTIONS_TEMPLATE_DESTROY,
1347 	ZERO,
1348 };
1349 
1350 static const enum index next_at_attr[] = {
1351 	ACTIONS_TEMPLATE_CREATE_ID,
1352 	ACTIONS_TEMPLATE_INGRESS,
1353 	ACTIONS_TEMPLATE_EGRESS,
1354 	ACTIONS_TEMPLATE_TRANSFER,
1355 	ACTIONS_TEMPLATE_SPEC,
1356 	ZERO,
1357 };
1358 
1359 static const enum index next_at_destroy_attr[] = {
1360 	ACTIONS_TEMPLATE_DESTROY_ID,
1361 	END,
1362 	ZERO,
1363 };
1364 
1365 static const enum index next_group_attr[] = {
1366 	GROUP_INGRESS,
1367 	GROUP_EGRESS,
1368 	GROUP_TRANSFER,
1369 	GROUP_SET_MISS_ACTIONS,
1370 	ZERO,
1371 };
1372 
1373 static const enum index next_table_subcmd[] = {
1374 	TABLE_CREATE,
1375 	TABLE_DESTROY,
1376 	TABLE_RESIZE,
1377 	TABLE_RESIZE_COMPLETE,
1378 	ZERO,
1379 };
1380 
1381 static const enum index next_table_attr[] = {
1382 	TABLE_CREATE_ID,
1383 	TABLE_GROUP,
1384 	TABLE_INSERTION_TYPE,
1385 	TABLE_HASH_FUNC,
1386 	TABLE_PRIORITY,
1387 	TABLE_INGRESS,
1388 	TABLE_EGRESS,
1389 	TABLE_TRANSFER,
1390 	TABLE_TRANSFER_WIRE_ORIG,
1391 	TABLE_TRANSFER_VPORT_ORIG,
1392 	TABLE_RESIZABLE,
1393 	TABLE_RULES_NUMBER,
1394 	TABLE_PATTERN_TEMPLATE,
1395 	TABLE_ACTIONS_TEMPLATE,
1396 	END,
1397 	ZERO,
1398 };
1399 
1400 static const enum index next_table_destroy_attr[] = {
1401 	TABLE_DESTROY_ID,
1402 	END,
1403 	ZERO,
1404 };
1405 
1406 static const enum index next_queue_subcmd[] = {
1407 	QUEUE_CREATE,
1408 	QUEUE_DESTROY,
1409 	QUEUE_FLOW_UPDATE_RESIZED,
1410 	QUEUE_UPDATE,
1411 	QUEUE_AGED,
1412 	QUEUE_INDIRECT_ACTION,
1413 	ZERO,
1414 };
1415 
1416 static const enum index next_queue_destroy_attr[] = {
1417 	QUEUE_DESTROY_ID,
1418 	END,
1419 	ZERO,
1420 };
1421 
1422 static const enum index next_qia_subcmd[] = {
1423 	QUEUE_INDIRECT_ACTION_CREATE,
1424 	QUEUE_INDIRECT_ACTION_UPDATE,
1425 	QUEUE_INDIRECT_ACTION_DESTROY,
1426 	QUEUE_INDIRECT_ACTION_QUERY,
1427 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
1428 	ZERO,
1429 };
1430 
1431 static const enum index next_qia_create_attr[] = {
1432 	QUEUE_INDIRECT_ACTION_CREATE_ID,
1433 	QUEUE_INDIRECT_ACTION_INGRESS,
1434 	QUEUE_INDIRECT_ACTION_EGRESS,
1435 	QUEUE_INDIRECT_ACTION_TRANSFER,
1436 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
1437 	QUEUE_INDIRECT_ACTION_SPEC,
1438 	QUEUE_INDIRECT_ACTION_LIST,
1439 	ZERO,
1440 };
1441 
1442 static const enum index next_qia_update_attr[] = {
1443 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1444 	QUEUE_INDIRECT_ACTION_SPEC,
1445 	ZERO,
1446 };
1447 
1448 static const enum index next_qia_destroy_attr[] = {
1449 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
1450 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
1451 	END,
1452 	ZERO,
1453 };
1454 
1455 static const enum index next_qia_query_attr[] = {
1456 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
1457 	END,
1458 	ZERO,
1459 };
1460 
1461 static const enum index next_ia_create_attr[] = {
1462 	INDIRECT_ACTION_CREATE_ID,
1463 	INDIRECT_ACTION_INGRESS,
1464 	INDIRECT_ACTION_EGRESS,
1465 	INDIRECT_ACTION_TRANSFER,
1466 	INDIRECT_ACTION_SPEC,
1467 	INDIRECT_ACTION_LIST,
1468 	INDIRECT_ACTION_FLOW_CONF,
1469 	ZERO,
1470 };
1471 
1472 static const enum index next_ia[] = {
1473 	INDIRECT_ACTION_ID2PTR,
1474 	ACTION_NEXT,
1475 	ZERO
1476 };
1477 
1478 static const enum index next_ial[] = {
1479 	ACTION_INDIRECT_LIST_HANDLE,
1480 	ACTION_INDIRECT_LIST_CONF,
1481 	ACTION_NEXT,
1482 	ZERO
1483 };
1484 
1485 static const enum index next_qia_qu_attr[] = {
1486 	QUEUE_INDIRECT_ACTION_QU_MODE,
1487 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1488 	INDIRECT_ACTION_SPEC,
1489 	ZERO
1490 };
1491 
1492 static const enum index next_ia_qu_attr[] = {
1493 	INDIRECT_ACTION_QU_MODE,
1494 	INDIRECT_ACTION_SPEC,
1495 	ZERO
1496 };
1497 
1498 static const enum index next_dump_subcmd[] = {
1499 	DUMP_ALL,
1500 	DUMP_ONE,
1501 	DUMP_IS_USER_ID,
1502 	ZERO,
1503 };
1504 
1505 static const enum index next_ia_subcmd[] = {
1506 	INDIRECT_ACTION_CREATE,
1507 	INDIRECT_ACTION_UPDATE,
1508 	INDIRECT_ACTION_DESTROY,
1509 	INDIRECT_ACTION_QUERY,
1510 	INDIRECT_ACTION_QUERY_UPDATE,
1511 	ZERO,
1512 };
1513 
1514 static const enum index next_vc_attr[] = {
1515 	VC_GROUP,
1516 	VC_PRIORITY,
1517 	VC_INGRESS,
1518 	VC_EGRESS,
1519 	VC_TRANSFER,
1520 	VC_TUNNEL_SET,
1521 	VC_TUNNEL_MATCH,
1522 	VC_USER_ID,
1523 	ITEM_PATTERN,
1524 	ZERO,
1525 };
1526 
1527 static const enum index next_destroy_attr[] = {
1528 	DESTROY_RULE,
1529 	DESTROY_IS_USER_ID,
1530 	END,
1531 	ZERO,
1532 };
1533 
1534 static const enum index next_dump_attr[] = {
1535 	COMMON_FILE_PATH,
1536 	END,
1537 	ZERO,
1538 };
1539 
1540 static const enum index next_query_attr[] = {
1541 	QUERY_IS_USER_ID,
1542 	END,
1543 	ZERO,
1544 };
1545 
1546 static const enum index next_list_attr[] = {
1547 	LIST_GROUP,
1548 	END,
1549 	ZERO,
1550 };
1551 
1552 static const enum index next_aged_attr[] = {
1553 	AGED_DESTROY,
1554 	END,
1555 	ZERO,
1556 };
1557 
1558 static const enum index next_ia_destroy_attr[] = {
1559 	INDIRECT_ACTION_DESTROY_ID,
1560 	END,
1561 	ZERO,
1562 };
1563 
1564 static const enum index next_async_insert_subcmd[] = {
1565 	QUEUE_PATTERN_TEMPLATE,
1566 	QUEUE_RULE_ID,
1567 	ZERO,
1568 };
1569 
1570 static const enum index item_param[] = {
1571 	ITEM_PARAM_IS,
1572 	ITEM_PARAM_SPEC,
1573 	ITEM_PARAM_LAST,
1574 	ITEM_PARAM_MASK,
1575 	ITEM_PARAM_PREFIX,
1576 	ZERO,
1577 };
1578 
1579 static const enum index next_item[] = {
1580 	ITEM_END,
1581 	ITEM_VOID,
1582 	ITEM_INVERT,
1583 	ITEM_ANY,
1584 	ITEM_PORT_ID,
1585 	ITEM_MARK,
1586 	ITEM_RAW,
1587 	ITEM_ETH,
1588 	ITEM_VLAN,
1589 	ITEM_IPV4,
1590 	ITEM_IPV6,
1591 	ITEM_ICMP,
1592 	ITEM_UDP,
1593 	ITEM_TCP,
1594 	ITEM_SCTP,
1595 	ITEM_VXLAN,
1596 	ITEM_E_TAG,
1597 	ITEM_NVGRE,
1598 	ITEM_MPLS,
1599 	ITEM_GRE,
1600 	ITEM_FUZZY,
1601 	ITEM_GTP,
1602 	ITEM_GTPC,
1603 	ITEM_GTPU,
1604 	ITEM_GENEVE,
1605 	ITEM_VXLAN_GPE,
1606 	ITEM_ARP_ETH_IPV4,
1607 	ITEM_IPV6_EXT,
1608 	ITEM_IPV6_FRAG_EXT,
1609 	ITEM_IPV6_ROUTING_EXT,
1610 	ITEM_ICMP6,
1611 	ITEM_ICMP6_ECHO_REQUEST,
1612 	ITEM_ICMP6_ECHO_REPLY,
1613 	ITEM_ICMP6_ND_NS,
1614 	ITEM_ICMP6_ND_NA,
1615 	ITEM_ICMP6_ND_OPT,
1616 	ITEM_ICMP6_ND_OPT_SLA_ETH,
1617 	ITEM_ICMP6_ND_OPT_TLA_ETH,
1618 	ITEM_META,
1619 	ITEM_RANDOM,
1620 	ITEM_GRE_KEY,
1621 	ITEM_GRE_OPTION,
1622 	ITEM_GTP_PSC,
1623 	ITEM_PPPOES,
1624 	ITEM_PPPOED,
1625 	ITEM_PPPOE_PROTO_ID,
1626 	ITEM_HIGIG2,
1627 	ITEM_TAG,
1628 	ITEM_L2TPV3OIP,
1629 	ITEM_ESP,
1630 	ITEM_AH,
1631 	ITEM_PFCP,
1632 	ITEM_ECPRI,
1633 	ITEM_GENEVE_OPT,
1634 	ITEM_INTEGRITY,
1635 	ITEM_CONNTRACK,
1636 	ITEM_PORT_REPRESENTOR,
1637 	ITEM_REPRESENTED_PORT,
1638 	ITEM_FLEX,
1639 	ITEM_L2TPV2,
1640 	ITEM_PPP,
1641 	ITEM_METER,
1642 	ITEM_QUOTA,
1643 	ITEM_AGGR_AFFINITY,
1644 	ITEM_TX_QUEUE,
1645 	ITEM_IB_BTH,
1646 	ITEM_PTYPE,
1647 	ITEM_NSH,
1648 	ITEM_COMPARE,
1649 	END_SET,
1650 	ZERO,
1651 };
1652 
1653 static const enum index item_fuzzy[] = {
1654 	ITEM_FUZZY_THRESH,
1655 	ITEM_NEXT,
1656 	ZERO,
1657 };
1658 
1659 static const enum index item_any[] = {
1660 	ITEM_ANY_NUM,
1661 	ITEM_NEXT,
1662 	ZERO,
1663 };
1664 
1665 static const enum index item_port_id[] = {
1666 	ITEM_PORT_ID_ID,
1667 	ITEM_NEXT,
1668 	ZERO,
1669 };
1670 
1671 static const enum index item_mark[] = {
1672 	ITEM_MARK_ID,
1673 	ITEM_NEXT,
1674 	ZERO,
1675 };
1676 
1677 static const enum index item_raw[] = {
1678 	ITEM_RAW_RELATIVE,
1679 	ITEM_RAW_SEARCH,
1680 	ITEM_RAW_OFFSET,
1681 	ITEM_RAW_LIMIT,
1682 	ITEM_RAW_PATTERN,
1683 	ITEM_RAW_PATTERN_HEX,
1684 	ITEM_NEXT,
1685 	ZERO,
1686 };
1687 
1688 static const enum index item_eth[] = {
1689 	ITEM_ETH_DST,
1690 	ITEM_ETH_SRC,
1691 	ITEM_ETH_TYPE,
1692 	ITEM_ETH_HAS_VLAN,
1693 	ITEM_NEXT,
1694 	ZERO,
1695 };
1696 
1697 static const enum index item_vlan[] = {
1698 	ITEM_VLAN_TCI,
1699 	ITEM_VLAN_PCP,
1700 	ITEM_VLAN_DEI,
1701 	ITEM_VLAN_VID,
1702 	ITEM_VLAN_INNER_TYPE,
1703 	ITEM_VLAN_HAS_MORE_VLAN,
1704 	ITEM_NEXT,
1705 	ZERO,
1706 };
1707 
1708 static const enum index item_ipv4[] = {
1709 	ITEM_IPV4_VER_IHL,
1710 	ITEM_IPV4_TOS,
1711 	ITEM_IPV4_LENGTH,
1712 	ITEM_IPV4_ID,
1713 	ITEM_IPV4_FRAGMENT_OFFSET,
1714 	ITEM_IPV4_TTL,
1715 	ITEM_IPV4_PROTO,
1716 	ITEM_IPV4_SRC,
1717 	ITEM_IPV4_DST,
1718 	ITEM_NEXT,
1719 	ZERO,
1720 };
1721 
1722 static const enum index item_ipv6[] = {
1723 	ITEM_IPV6_TC,
1724 	ITEM_IPV6_FLOW,
1725 	ITEM_IPV6_LEN,
1726 	ITEM_IPV6_PROTO,
1727 	ITEM_IPV6_HOP,
1728 	ITEM_IPV6_SRC,
1729 	ITEM_IPV6_DST,
1730 	ITEM_IPV6_HAS_FRAG_EXT,
1731 	ITEM_IPV6_ROUTING_EXT,
1732 	ITEM_NEXT,
1733 	ZERO,
1734 };
1735 
1736 static const enum index item_ipv6_routing_ext[] = {
1737 	ITEM_IPV6_ROUTING_EXT_TYPE,
1738 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
1739 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
1740 	ITEM_NEXT,
1741 	ZERO,
1742 };
1743 
1744 static const enum index item_icmp[] = {
1745 	ITEM_ICMP_TYPE,
1746 	ITEM_ICMP_CODE,
1747 	ITEM_ICMP_IDENT,
1748 	ITEM_ICMP_SEQ,
1749 	ITEM_NEXT,
1750 	ZERO,
1751 };
1752 
1753 static const enum index item_udp[] = {
1754 	ITEM_UDP_SRC,
1755 	ITEM_UDP_DST,
1756 	ITEM_NEXT,
1757 	ZERO,
1758 };
1759 
1760 static const enum index item_tcp[] = {
1761 	ITEM_TCP_SRC,
1762 	ITEM_TCP_DST,
1763 	ITEM_TCP_FLAGS,
1764 	ITEM_NEXT,
1765 	ZERO,
1766 };
1767 
1768 static const enum index item_sctp[] = {
1769 	ITEM_SCTP_SRC,
1770 	ITEM_SCTP_DST,
1771 	ITEM_SCTP_TAG,
1772 	ITEM_SCTP_CKSUM,
1773 	ITEM_NEXT,
1774 	ZERO,
1775 };
1776 
1777 static const enum index item_vxlan[] = {
1778 	ITEM_VXLAN_VNI,
1779 	ITEM_VXLAN_LAST_RSVD,
1780 	ITEM_NEXT,
1781 	ZERO,
1782 };
1783 
1784 static const enum index item_e_tag[] = {
1785 	ITEM_E_TAG_GRP_ECID_B,
1786 	ITEM_NEXT,
1787 	ZERO,
1788 };
1789 
1790 static const enum index item_nvgre[] = {
1791 	ITEM_NVGRE_TNI,
1792 	ITEM_NEXT,
1793 	ZERO,
1794 };
1795 
1796 static const enum index item_mpls[] = {
1797 	ITEM_MPLS_LABEL,
1798 	ITEM_MPLS_TC,
1799 	ITEM_MPLS_S,
1800 	ITEM_MPLS_TTL,
1801 	ITEM_NEXT,
1802 	ZERO,
1803 };
1804 
1805 static const enum index item_gre[] = {
1806 	ITEM_GRE_PROTO,
1807 	ITEM_GRE_C_RSVD0_VER,
1808 	ITEM_GRE_C_BIT,
1809 	ITEM_GRE_K_BIT,
1810 	ITEM_GRE_S_BIT,
1811 	ITEM_NEXT,
1812 	ZERO,
1813 };
1814 
1815 static const enum index item_gre_key[] = {
1816 	ITEM_GRE_KEY_VALUE,
1817 	ITEM_NEXT,
1818 	ZERO,
1819 };
1820 
1821 static const enum index item_gre_option[] = {
1822 	ITEM_GRE_OPTION_CHECKSUM,
1823 	ITEM_GRE_OPTION_KEY,
1824 	ITEM_GRE_OPTION_SEQUENCE,
1825 	ITEM_NEXT,
1826 	ZERO,
1827 };
1828 
1829 static const enum index item_gtp[] = {
1830 	ITEM_GTP_FLAGS,
1831 	ITEM_GTP_MSG_TYPE,
1832 	ITEM_GTP_TEID,
1833 	ITEM_NEXT,
1834 	ZERO,
1835 };
1836 
1837 static const enum index item_geneve[] = {
1838 	ITEM_GENEVE_VNI,
1839 	ITEM_GENEVE_PROTO,
1840 	ITEM_GENEVE_OPTLEN,
1841 	ITEM_NEXT,
1842 	ZERO,
1843 };
1844 
1845 static const enum index item_vxlan_gpe[] = {
1846 	ITEM_VXLAN_GPE_VNI,
1847 	ITEM_VXLAN_GPE_PROTO,
1848 	ITEM_VXLAN_GPE_FLAGS,
1849 	ITEM_VXLAN_GPE_RSVD0,
1850 	ITEM_VXLAN_GPE_RSVD1,
1851 	ITEM_NEXT,
1852 	ZERO,
1853 };
1854 
1855 static const enum index item_arp_eth_ipv4[] = {
1856 	ITEM_ARP_ETH_IPV4_SHA,
1857 	ITEM_ARP_ETH_IPV4_SPA,
1858 	ITEM_ARP_ETH_IPV4_THA,
1859 	ITEM_ARP_ETH_IPV4_TPA,
1860 	ITEM_NEXT,
1861 	ZERO,
1862 };
1863 
1864 static const enum index item_ipv6_ext[] = {
1865 	ITEM_IPV6_EXT_NEXT_HDR,
1866 	ITEM_NEXT,
1867 	ZERO,
1868 };
1869 
1870 static const enum index item_ipv6_frag_ext[] = {
1871 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1872 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1873 	ITEM_IPV6_FRAG_EXT_ID,
1874 	ITEM_NEXT,
1875 	ZERO,
1876 };
1877 
1878 static const enum index item_icmp6[] = {
1879 	ITEM_ICMP6_TYPE,
1880 	ITEM_ICMP6_CODE,
1881 	ITEM_NEXT,
1882 	ZERO,
1883 };
1884 
1885 static const enum index item_icmp6_echo_request[] = {
1886 	ITEM_ICMP6_ECHO_REQUEST_ID,
1887 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
1888 	ITEM_NEXT,
1889 	ZERO,
1890 };
1891 
1892 static const enum index item_icmp6_echo_reply[] = {
1893 	ITEM_ICMP6_ECHO_REPLY_ID,
1894 	ITEM_ICMP6_ECHO_REPLY_SEQ,
1895 	ITEM_NEXT,
1896 	ZERO,
1897 };
1898 
1899 static const enum index item_icmp6_nd_ns[] = {
1900 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
1901 	ITEM_NEXT,
1902 	ZERO,
1903 };
1904 
1905 static const enum index item_icmp6_nd_na[] = {
1906 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
1907 	ITEM_NEXT,
1908 	ZERO,
1909 };
1910 
1911 static const enum index item_icmp6_nd_opt[] = {
1912 	ITEM_ICMP6_ND_OPT_TYPE,
1913 	ITEM_NEXT,
1914 	ZERO,
1915 };
1916 
1917 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1918 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1919 	ITEM_NEXT,
1920 	ZERO,
1921 };
1922 
1923 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1924 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1925 	ITEM_NEXT,
1926 	ZERO,
1927 };
1928 
1929 static const enum index item_meta[] = {
1930 	ITEM_META_DATA,
1931 	ITEM_NEXT,
1932 	ZERO,
1933 };
1934 
1935 static const enum index item_random[] = {
1936 	ITEM_RANDOM_VALUE,
1937 	ITEM_NEXT,
1938 	ZERO,
1939 };
1940 
1941 static const enum index item_gtp_psc[] = {
1942 	ITEM_GTP_PSC_QFI,
1943 	ITEM_GTP_PSC_PDU_T,
1944 	ITEM_NEXT,
1945 	ZERO,
1946 };
1947 
1948 static const enum index item_pppoed[] = {
1949 	ITEM_PPPOE_SEID,
1950 	ITEM_NEXT,
1951 	ZERO,
1952 };
1953 
1954 static const enum index item_pppoes[] = {
1955 	ITEM_PPPOE_SEID,
1956 	ITEM_NEXT,
1957 	ZERO,
1958 };
1959 
1960 static const enum index item_pppoe_proto_id[] = {
1961 	ITEM_NEXT,
1962 	ZERO,
1963 };
1964 
1965 static const enum index item_higig2[] = {
1966 	ITEM_HIGIG2_CLASSIFICATION,
1967 	ITEM_HIGIG2_VID,
1968 	ITEM_NEXT,
1969 	ZERO,
1970 };
1971 
1972 static const enum index item_esp[] = {
1973 	ITEM_ESP_SPI,
1974 	ITEM_NEXT,
1975 	ZERO,
1976 };
1977 
1978 static const enum index item_ah[] = {
1979 	ITEM_AH_SPI,
1980 	ITEM_NEXT,
1981 	ZERO,
1982 };
1983 
1984 static const enum index item_pfcp[] = {
1985 	ITEM_PFCP_S_FIELD,
1986 	ITEM_PFCP_SEID,
1987 	ITEM_NEXT,
1988 	ZERO,
1989 };
1990 
1991 static const enum index next_set_raw[] = {
1992 	SET_RAW_INDEX,
1993 	ITEM_ETH,
1994 	ZERO,
1995 };
1996 
1997 static const enum index item_tag[] = {
1998 	ITEM_TAG_DATA,
1999 	ITEM_TAG_INDEX,
2000 	ITEM_NEXT,
2001 	ZERO,
2002 };
2003 
2004 static const enum index item_l2tpv3oip[] = {
2005 	ITEM_L2TPV3OIP_SESSION_ID,
2006 	ITEM_NEXT,
2007 	ZERO,
2008 };
2009 
2010 static const enum index item_ecpri[] = {
2011 	ITEM_ECPRI_COMMON,
2012 	ITEM_NEXT,
2013 	ZERO,
2014 };
2015 
2016 static const enum index item_ecpri_common[] = {
2017 	ITEM_ECPRI_COMMON_TYPE,
2018 	ZERO,
2019 };
2020 
2021 static const enum index item_ecpri_common_type[] = {
2022 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
2023 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
2024 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
2025 	ZERO,
2026 };
2027 
2028 static const enum index item_geneve_opt[] = {
2029 	ITEM_GENEVE_OPT_CLASS,
2030 	ITEM_GENEVE_OPT_TYPE,
2031 	ITEM_GENEVE_OPT_LENGTH,
2032 	ITEM_GENEVE_OPT_DATA,
2033 	ITEM_NEXT,
2034 	ZERO,
2035 };
2036 
2037 static const enum index item_integrity[] = {
2038 	ITEM_INTEGRITY_LEVEL,
2039 	ITEM_INTEGRITY_VALUE,
2040 	ZERO,
2041 };
2042 
2043 static const enum index item_integrity_lv[] = {
2044 	ITEM_INTEGRITY_LEVEL,
2045 	ITEM_INTEGRITY_VALUE,
2046 	ITEM_NEXT,
2047 	ZERO,
2048 };
2049 
2050 static const enum index item_port_representor[] = {
2051 	ITEM_PORT_REPRESENTOR_PORT_ID,
2052 	ITEM_NEXT,
2053 	ZERO,
2054 };
2055 
2056 static const enum index item_represented_port[] = {
2057 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
2058 	ITEM_NEXT,
2059 	ZERO,
2060 };
2061 
2062 static const enum index item_flex[] = {
2063 	ITEM_FLEX_PATTERN_HANDLE,
2064 	ITEM_FLEX_ITEM_HANDLE,
2065 	ITEM_NEXT,
2066 	ZERO,
2067 };
2068 
2069 static const enum index item_l2tpv2[] = {
2070 	ITEM_L2TPV2_TYPE,
2071 	ITEM_NEXT,
2072 	ZERO,
2073 };
2074 
2075 static const enum index item_l2tpv2_type[] = {
2076 	ITEM_L2TPV2_TYPE_DATA,
2077 	ITEM_L2TPV2_TYPE_DATA_L,
2078 	ITEM_L2TPV2_TYPE_DATA_S,
2079 	ITEM_L2TPV2_TYPE_DATA_O,
2080 	ITEM_L2TPV2_TYPE_DATA_L_S,
2081 	ITEM_L2TPV2_TYPE_CTRL,
2082 	ZERO,
2083 };
2084 
2085 static const enum index item_l2tpv2_type_data[] = {
2086 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
2087 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
2088 	ITEM_NEXT,
2089 	ZERO,
2090 };
2091 
2092 static const enum index item_l2tpv2_type_data_l[] = {
2093 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
2094 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
2095 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
2096 	ITEM_NEXT,
2097 	ZERO,
2098 };
2099 
2100 static const enum index item_l2tpv2_type_data_s[] = {
2101 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
2102 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
2103 	ITEM_L2TPV2_MSG_DATA_S_NS,
2104 	ITEM_L2TPV2_MSG_DATA_S_NR,
2105 	ITEM_NEXT,
2106 	ZERO,
2107 };
2108 
2109 static const enum index item_l2tpv2_type_data_o[] = {
2110 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
2111 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
2112 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
2113 	ITEM_NEXT,
2114 	ZERO,
2115 };
2116 
2117 static const enum index item_l2tpv2_type_data_l_s[] = {
2118 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
2119 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
2120 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
2121 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
2122 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
2123 	ITEM_NEXT,
2124 	ZERO,
2125 };
2126 
2127 static const enum index item_l2tpv2_type_ctrl[] = {
2128 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
2129 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
2130 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
2131 	ITEM_L2TPV2_MSG_CTRL_NS,
2132 	ITEM_L2TPV2_MSG_CTRL_NR,
2133 	ITEM_NEXT,
2134 	ZERO,
2135 };
2136 
2137 static const enum index item_ppp[] = {
2138 	ITEM_PPP_ADDR,
2139 	ITEM_PPP_CTRL,
2140 	ITEM_PPP_PROTO_ID,
2141 	ITEM_NEXT,
2142 	ZERO,
2143 };
2144 
2145 static const enum index item_meter[] = {
2146 	ITEM_METER_COLOR,
2147 	ITEM_NEXT,
2148 	ZERO,
2149 };
2150 
2151 static const enum index item_quota[] = {
2152 	ITEM_QUOTA_STATE,
2153 	ITEM_NEXT,
2154 	ZERO,
2155 };
2156 
2157 static const enum index item_aggr_affinity[] = {
2158 	ITEM_AGGR_AFFINITY_VALUE,
2159 	ITEM_NEXT,
2160 	ZERO,
2161 };
2162 
2163 static const enum index item_tx_queue[] = {
2164 	ITEM_TX_QUEUE_VALUE,
2165 	ITEM_NEXT,
2166 	ZERO,
2167 };
2168 
2169 static const enum index item_ib_bth[] = {
2170 	ITEM_IB_BTH_OPCODE,
2171 	ITEM_IB_BTH_PKEY,
2172 	ITEM_IB_BTH_DST_QPN,
2173 	ITEM_IB_BTH_PSN,
2174 	ITEM_NEXT,
2175 	ZERO,
2176 };
2177 
2178 static const enum index item_ptype[] = {
2179 	ITEM_PTYPE_VALUE,
2180 	ITEM_NEXT,
2181 	ZERO,
2182 };
2183 
2184 static const enum index item_nsh[] = {
2185 	ITEM_NEXT,
2186 	ZERO,
2187 };
2188 
2189 static const enum index item_compare_field[] = {
2190 	ITEM_COMPARE_OP,
2191 	ITEM_COMPARE_FIELD_A_TYPE,
2192 	ITEM_COMPARE_FIELD_B_TYPE,
2193 	ITEM_NEXT,
2194 	ZERO,
2195 };
2196 
2197 static const enum index compare_field_a[] = {
2198 	ITEM_COMPARE_FIELD_A_TYPE,
2199 	ITEM_COMPARE_FIELD_A_LEVEL,
2200 	ITEM_COMPARE_FIELD_A_TAG_INDEX,
2201 	ITEM_COMPARE_FIELD_A_TYPE_ID,
2202 	ITEM_COMPARE_FIELD_A_CLASS_ID,
2203 	ITEM_COMPARE_FIELD_A_OFFSET,
2204 	ITEM_COMPARE_FIELD_B_TYPE,
2205 	ZERO,
2206 };
2207 
2208 static const enum index compare_field_b[] = {
2209 	ITEM_COMPARE_FIELD_B_TYPE,
2210 	ITEM_COMPARE_FIELD_B_LEVEL,
2211 	ITEM_COMPARE_FIELD_B_TAG_INDEX,
2212 	ITEM_COMPARE_FIELD_B_TYPE_ID,
2213 	ITEM_COMPARE_FIELD_B_CLASS_ID,
2214 	ITEM_COMPARE_FIELD_B_OFFSET,
2215 	ITEM_COMPARE_FIELD_B_VALUE,
2216 	ITEM_COMPARE_FIELD_B_POINTER,
2217 	ITEM_COMPARE_FIELD_WIDTH,
2218 	ZERO,
2219 };
2220 
2221 static const enum index next_action[] = {
2222 	ACTION_END,
2223 	ACTION_VOID,
2224 	ACTION_PASSTHRU,
2225 	ACTION_SKIP_CMAN,
2226 	ACTION_JUMP,
2227 	ACTION_MARK,
2228 	ACTION_FLAG,
2229 	ACTION_QUEUE,
2230 	ACTION_DROP,
2231 	ACTION_COUNT,
2232 	ACTION_RSS,
2233 	ACTION_PF,
2234 	ACTION_VF,
2235 	ACTION_PORT_ID,
2236 	ACTION_METER,
2237 	ACTION_METER_COLOR,
2238 	ACTION_METER_MARK,
2239 	ACTION_OF_DEC_NW_TTL,
2240 	ACTION_OF_POP_VLAN,
2241 	ACTION_OF_PUSH_VLAN,
2242 	ACTION_OF_SET_VLAN_VID,
2243 	ACTION_OF_SET_VLAN_PCP,
2244 	ACTION_OF_POP_MPLS,
2245 	ACTION_OF_PUSH_MPLS,
2246 	ACTION_VXLAN_ENCAP,
2247 	ACTION_VXLAN_DECAP,
2248 	ACTION_NVGRE_ENCAP,
2249 	ACTION_NVGRE_DECAP,
2250 	ACTION_L2_ENCAP,
2251 	ACTION_L2_DECAP,
2252 	ACTION_MPLSOGRE_ENCAP,
2253 	ACTION_MPLSOGRE_DECAP,
2254 	ACTION_MPLSOUDP_ENCAP,
2255 	ACTION_MPLSOUDP_DECAP,
2256 	ACTION_SET_IPV4_SRC,
2257 	ACTION_SET_IPV4_DST,
2258 	ACTION_SET_IPV6_SRC,
2259 	ACTION_SET_IPV6_DST,
2260 	ACTION_SET_TP_SRC,
2261 	ACTION_SET_TP_DST,
2262 	ACTION_MAC_SWAP,
2263 	ACTION_DEC_TTL,
2264 	ACTION_SET_TTL,
2265 	ACTION_SET_MAC_SRC,
2266 	ACTION_SET_MAC_DST,
2267 	ACTION_INC_TCP_SEQ,
2268 	ACTION_DEC_TCP_SEQ,
2269 	ACTION_INC_TCP_ACK,
2270 	ACTION_DEC_TCP_ACK,
2271 	ACTION_RAW_ENCAP,
2272 	ACTION_RAW_DECAP,
2273 	ACTION_SET_TAG,
2274 	ACTION_SET_META,
2275 	ACTION_SET_IPV4_DSCP,
2276 	ACTION_SET_IPV6_DSCP,
2277 	ACTION_AGE,
2278 	ACTION_AGE_UPDATE,
2279 	ACTION_SAMPLE,
2280 	ACTION_INDIRECT,
2281 	ACTION_INDIRECT_LIST,
2282 	ACTION_SHARED_INDIRECT,
2283 	ACTION_MODIFY_FIELD,
2284 	ACTION_CONNTRACK,
2285 	ACTION_CONNTRACK_UPDATE,
2286 	ACTION_PORT_REPRESENTOR,
2287 	ACTION_REPRESENTED_PORT,
2288 	ACTION_SEND_TO_KERNEL,
2289 	ACTION_QUOTA_CREATE,
2290 	ACTION_QUOTA_QU,
2291 	ACTION_IPV6_EXT_REMOVE,
2292 	ACTION_IPV6_EXT_PUSH,
2293 	ACTION_NAT64,
2294 	ZERO,
2295 };
2296 
2297 static const enum index action_quota_create[] = {
2298 	ACTION_QUOTA_CREATE_LIMIT,
2299 	ACTION_QUOTA_CREATE_MODE,
2300 	ACTION_NEXT,
2301 	ZERO
2302 };
2303 
2304 static const enum index action_quota_update[] = {
2305 	ACTION_QUOTA_QU_LIMIT,
2306 	ACTION_QUOTA_QU_UPDATE_OP,
2307 	ACTION_NEXT,
2308 	ZERO
2309 };
2310 
2311 static const enum index action_mark[] = {
2312 	ACTION_MARK_ID,
2313 	ACTION_NEXT,
2314 	ZERO,
2315 };
2316 
2317 static const enum index action_queue[] = {
2318 	ACTION_QUEUE_INDEX,
2319 	ACTION_NEXT,
2320 	ZERO,
2321 };
2322 
2323 static const enum index action_count[] = {
2324 	ACTION_COUNT_ID,
2325 	ACTION_NEXT,
2326 	ZERO,
2327 };
2328 
2329 static const enum index action_rss[] = {
2330 	ACTION_RSS_FUNC,
2331 	ACTION_RSS_LEVEL,
2332 	ACTION_RSS_TYPES,
2333 	ACTION_RSS_KEY,
2334 	ACTION_RSS_KEY_LEN,
2335 	ACTION_RSS_QUEUES,
2336 	ACTION_NEXT,
2337 	ZERO,
2338 };
2339 
2340 static const enum index action_vf[] = {
2341 	ACTION_VF_ORIGINAL,
2342 	ACTION_VF_ID,
2343 	ACTION_NEXT,
2344 	ZERO,
2345 };
2346 
2347 static const enum index action_port_id[] = {
2348 	ACTION_PORT_ID_ORIGINAL,
2349 	ACTION_PORT_ID_ID,
2350 	ACTION_NEXT,
2351 	ZERO,
2352 };
2353 
2354 static const enum index action_meter[] = {
2355 	ACTION_METER_ID,
2356 	ACTION_NEXT,
2357 	ZERO,
2358 };
2359 
2360 static const enum index action_meter_color[] = {
2361 	ACTION_METER_COLOR_TYPE,
2362 	ACTION_NEXT,
2363 	ZERO,
2364 };
2365 
2366 static const enum index action_meter_mark[] = {
2367 	ACTION_METER_PROFILE,
2368 	ACTION_METER_POLICY,
2369 	ACTION_METER_COLOR_MODE,
2370 	ACTION_METER_STATE,
2371 	ACTION_NEXT,
2372 	ZERO,
2373 };
2374 
2375 static const enum index action_of_push_vlan[] = {
2376 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
2377 	ACTION_NEXT,
2378 	ZERO,
2379 };
2380 
2381 static const enum index action_of_set_vlan_vid[] = {
2382 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
2383 	ACTION_NEXT,
2384 	ZERO,
2385 };
2386 
2387 static const enum index action_of_set_vlan_pcp[] = {
2388 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
2389 	ACTION_NEXT,
2390 	ZERO,
2391 };
2392 
2393 static const enum index action_of_pop_mpls[] = {
2394 	ACTION_OF_POP_MPLS_ETHERTYPE,
2395 	ACTION_NEXT,
2396 	ZERO,
2397 };
2398 
2399 static const enum index action_of_push_mpls[] = {
2400 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
2401 	ACTION_NEXT,
2402 	ZERO,
2403 };
2404 
2405 static const enum index action_set_ipv4_src[] = {
2406 	ACTION_SET_IPV4_SRC_IPV4_SRC,
2407 	ACTION_NEXT,
2408 	ZERO,
2409 };
2410 
2411 static const enum index action_set_mac_src[] = {
2412 	ACTION_SET_MAC_SRC_MAC_SRC,
2413 	ACTION_NEXT,
2414 	ZERO,
2415 };
2416 
2417 static const enum index action_set_ipv4_dst[] = {
2418 	ACTION_SET_IPV4_DST_IPV4_DST,
2419 	ACTION_NEXT,
2420 	ZERO,
2421 };
2422 
2423 static const enum index action_set_ipv6_src[] = {
2424 	ACTION_SET_IPV6_SRC_IPV6_SRC,
2425 	ACTION_NEXT,
2426 	ZERO,
2427 };
2428 
2429 static const enum index action_set_ipv6_dst[] = {
2430 	ACTION_SET_IPV6_DST_IPV6_DST,
2431 	ACTION_NEXT,
2432 	ZERO,
2433 };
2434 
2435 static const enum index action_set_tp_src[] = {
2436 	ACTION_SET_TP_SRC_TP_SRC,
2437 	ACTION_NEXT,
2438 	ZERO,
2439 };
2440 
2441 static const enum index action_set_tp_dst[] = {
2442 	ACTION_SET_TP_DST_TP_DST,
2443 	ACTION_NEXT,
2444 	ZERO,
2445 };
2446 
2447 static const enum index action_set_ttl[] = {
2448 	ACTION_SET_TTL_TTL,
2449 	ACTION_NEXT,
2450 	ZERO,
2451 };
2452 
2453 static const enum index action_jump[] = {
2454 	ACTION_JUMP_GROUP,
2455 	ACTION_NEXT,
2456 	ZERO,
2457 };
2458 
2459 static const enum index action_set_mac_dst[] = {
2460 	ACTION_SET_MAC_DST_MAC_DST,
2461 	ACTION_NEXT,
2462 	ZERO,
2463 };
2464 
2465 static const enum index action_inc_tcp_seq[] = {
2466 	ACTION_INC_TCP_SEQ_VALUE,
2467 	ACTION_NEXT,
2468 	ZERO,
2469 };
2470 
2471 static const enum index action_dec_tcp_seq[] = {
2472 	ACTION_DEC_TCP_SEQ_VALUE,
2473 	ACTION_NEXT,
2474 	ZERO,
2475 };
2476 
2477 static const enum index action_inc_tcp_ack[] = {
2478 	ACTION_INC_TCP_ACK_VALUE,
2479 	ACTION_NEXT,
2480 	ZERO,
2481 };
2482 
2483 static const enum index action_dec_tcp_ack[] = {
2484 	ACTION_DEC_TCP_ACK_VALUE,
2485 	ACTION_NEXT,
2486 	ZERO,
2487 };
2488 
2489 static const enum index action_raw_encap[] = {
2490 	ACTION_RAW_ENCAP_SIZE,
2491 	ACTION_RAW_ENCAP_INDEX,
2492 	ACTION_NEXT,
2493 	ZERO,
2494 };
2495 
2496 static const enum index action_raw_decap[] = {
2497 	ACTION_RAW_DECAP_INDEX,
2498 	ACTION_NEXT,
2499 	ZERO,
2500 };
2501 
2502 static const enum index action_ipv6_ext_remove[] = {
2503 	ACTION_IPV6_EXT_REMOVE_INDEX,
2504 	ACTION_NEXT,
2505 	ZERO,
2506 };
2507 
2508 static const enum index action_ipv6_ext_push[] = {
2509 	ACTION_IPV6_EXT_PUSH_INDEX,
2510 	ACTION_NEXT,
2511 	ZERO,
2512 };
2513 
2514 static const enum index action_set_tag[] = {
2515 	ACTION_SET_TAG_DATA,
2516 	ACTION_SET_TAG_INDEX,
2517 	ACTION_SET_TAG_MASK,
2518 	ACTION_NEXT,
2519 	ZERO,
2520 };
2521 
2522 static const enum index action_set_meta[] = {
2523 	ACTION_SET_META_DATA,
2524 	ACTION_SET_META_MASK,
2525 	ACTION_NEXT,
2526 	ZERO,
2527 };
2528 
2529 static const enum index action_set_ipv4_dscp[] = {
2530 	ACTION_SET_IPV4_DSCP_VALUE,
2531 	ACTION_NEXT,
2532 	ZERO,
2533 };
2534 
2535 static const enum index action_set_ipv6_dscp[] = {
2536 	ACTION_SET_IPV6_DSCP_VALUE,
2537 	ACTION_NEXT,
2538 	ZERO,
2539 };
2540 
2541 static const enum index action_age[] = {
2542 	ACTION_AGE,
2543 	ACTION_AGE_TIMEOUT,
2544 	ACTION_NEXT,
2545 	ZERO,
2546 };
2547 
2548 static const enum index action_age_update[] = {
2549 	ACTION_AGE_UPDATE,
2550 	ACTION_AGE_UPDATE_TIMEOUT,
2551 	ACTION_AGE_UPDATE_TOUCH,
2552 	ACTION_NEXT,
2553 	ZERO,
2554 };
2555 
2556 static const enum index action_sample[] = {
2557 	ACTION_SAMPLE,
2558 	ACTION_SAMPLE_RATIO,
2559 	ACTION_SAMPLE_INDEX,
2560 	ACTION_NEXT,
2561 	ZERO,
2562 };
2563 
2564 static const enum index next_action_sample[] = {
2565 	ACTION_QUEUE,
2566 	ACTION_RSS,
2567 	ACTION_MARK,
2568 	ACTION_COUNT,
2569 	ACTION_PORT_ID,
2570 	ACTION_RAW_ENCAP,
2571 	ACTION_VXLAN_ENCAP,
2572 	ACTION_NVGRE_ENCAP,
2573 	ACTION_REPRESENTED_PORT,
2574 	ACTION_PORT_REPRESENTOR,
2575 	ACTION_NEXT,
2576 	ZERO,
2577 };
2578 
2579 static const enum index item_ipv6_push_ext[] = {
2580 	ITEM_IPV6_PUSH_REMOVE_EXT,
2581 	ZERO,
2582 };
2583 
2584 static const enum index item_ipv6_push_ext_type[] = {
2585 	ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
2586 	ZERO,
2587 };
2588 
2589 static const enum index item_ipv6_push_ext_header[] = {
2590 	ITEM_IPV6_ROUTING_EXT,
2591 	ITEM_NEXT,
2592 	ZERO,
2593 };
2594 
2595 static const enum index action_modify_field_dst[] = {
2596 	ACTION_MODIFY_FIELD_DST_LEVEL,
2597 	ACTION_MODIFY_FIELD_DST_TAG_INDEX,
2598 	ACTION_MODIFY_FIELD_DST_TYPE_ID,
2599 	ACTION_MODIFY_FIELD_DST_CLASS_ID,
2600 	ACTION_MODIFY_FIELD_DST_OFFSET,
2601 	ACTION_MODIFY_FIELD_SRC_TYPE,
2602 	ZERO,
2603 };
2604 
2605 static const enum index action_modify_field_src[] = {
2606 	ACTION_MODIFY_FIELD_SRC_LEVEL,
2607 	ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
2608 	ACTION_MODIFY_FIELD_SRC_TYPE_ID,
2609 	ACTION_MODIFY_FIELD_SRC_CLASS_ID,
2610 	ACTION_MODIFY_FIELD_SRC_OFFSET,
2611 	ACTION_MODIFY_FIELD_SRC_VALUE,
2612 	ACTION_MODIFY_FIELD_SRC_POINTER,
2613 	ACTION_MODIFY_FIELD_WIDTH,
2614 	ZERO,
2615 };
2616 
2617 static const enum index action_update_conntrack[] = {
2618 	ACTION_CONNTRACK_UPDATE_DIR,
2619 	ACTION_CONNTRACK_UPDATE_CTX,
2620 	ACTION_NEXT,
2621 	ZERO,
2622 };
2623 
2624 static const enum index action_port_representor[] = {
2625 	ACTION_PORT_REPRESENTOR_PORT_ID,
2626 	ACTION_NEXT,
2627 	ZERO,
2628 };
2629 
2630 static const enum index action_represented_port[] = {
2631 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
2632 	ACTION_NEXT,
2633 	ZERO,
2634 };
2635 
2636 static const enum index action_nat64[] = {
2637 	ACTION_NAT64_MODE,
2638 	ACTION_NEXT,
2639 	ZERO,
2640 };
2641 
2642 static const enum index next_hash_subcmd[] = {
2643 	HASH_CALC_TABLE,
2644 	HASH_CALC_ENCAP,
2645 	ZERO,
2646 };
2647 
2648 static const enum index next_hash_encap_dest_subcmd[] = {
2649 	ENCAP_HASH_FIELD_SRC_PORT,
2650 	ENCAP_HASH_FIELD_GRE_FLOW_ID,
2651 	ZERO,
2652 };
2653 
2654 static int parse_set_raw_encap_decap(struct context *, const struct token *,
2655 				     const char *, unsigned int,
2656 				     void *, unsigned int);
2657 static int parse_set_sample_action(struct context *, const struct token *,
2658 				   const char *, unsigned int,
2659 				   void *, unsigned int);
2660 static int parse_set_ipv6_ext_action(struct context *, const struct token *,
2661 				     const char *, unsigned int,
2662 				     void *, unsigned int);
2663 static int parse_set_init(struct context *, const struct token *,
2664 			  const char *, unsigned int,
2665 			  void *, unsigned int);
2666 static int
2667 parse_flex_handle(struct context *, const struct token *,
2668 		  const char *, unsigned int, void *, unsigned int);
2669 static int parse_init(struct context *, const struct token *,
2670 		      const char *, unsigned int,
2671 		      void *, unsigned int);
2672 static int parse_vc(struct context *, const struct token *,
2673 		    const char *, unsigned int,
2674 		    void *, unsigned int);
2675 static int parse_vc_spec(struct context *, const struct token *,
2676 			 const char *, unsigned int, void *, unsigned int);
2677 static int parse_vc_conf(struct context *, const struct token *,
2678 			 const char *, unsigned int, void *, unsigned int);
2679 static int parse_vc_conf_timeout(struct context *, const struct token *,
2680 				 const char *, unsigned int, void *,
2681 				 unsigned int);
2682 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
2683 				    const char *, unsigned int,
2684 				    void *, unsigned int);
2685 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *,
2686 				    const char *, unsigned int,
2687 				    void *, unsigned int);
2688 static int parse_vc_action_meter_color_type(struct context *,
2689 					const struct token *,
2690 					const char *, unsigned int, void *,
2691 					unsigned int);
2692 static int parse_vc_action_rss(struct context *, const struct token *,
2693 			       const char *, unsigned int, void *,
2694 			       unsigned int);
2695 static int parse_vc_action_rss_func(struct context *, const struct token *,
2696 				    const char *, unsigned int, void *,
2697 				    unsigned int);
2698 static int parse_vc_action_rss_type(struct context *, const struct token *,
2699 				    const char *, unsigned int, void *,
2700 				    unsigned int);
2701 static int parse_vc_action_rss_queue(struct context *, const struct token *,
2702 				     const char *, unsigned int, void *,
2703 				     unsigned int);
2704 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
2705 				       const char *, unsigned int, void *,
2706 				       unsigned int);
2707 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
2708 				       const char *, unsigned int, void *,
2709 				       unsigned int);
2710 static int parse_vc_action_l2_encap(struct context *, const struct token *,
2711 				    const char *, unsigned int, void *,
2712 				    unsigned int);
2713 static int parse_vc_action_l2_decap(struct context *, const struct token *,
2714 				    const char *, unsigned int, void *,
2715 				    unsigned int);
2716 static int parse_vc_action_mplsogre_encap(struct context *,
2717 					  const struct token *, const char *,
2718 					  unsigned int, void *, unsigned int);
2719 static int parse_vc_action_mplsogre_decap(struct context *,
2720 					  const struct token *, const char *,
2721 					  unsigned int, void *, unsigned int);
2722 static int parse_vc_action_mplsoudp_encap(struct context *,
2723 					  const struct token *, const char *,
2724 					  unsigned int, void *, unsigned int);
2725 static int parse_vc_action_mplsoudp_decap(struct context *,
2726 					  const struct token *, const char *,
2727 					  unsigned int, void *, unsigned int);
2728 static int parse_vc_action_raw_encap(struct context *,
2729 				     const struct token *, const char *,
2730 				     unsigned int, void *, unsigned int);
2731 static int parse_vc_action_raw_decap(struct context *,
2732 				     const struct token *, const char *,
2733 				     unsigned int, void *, unsigned int);
2734 static int parse_vc_action_raw_encap_index(struct context *,
2735 					   const struct token *, const char *,
2736 					   unsigned int, void *, unsigned int);
2737 static int parse_vc_action_raw_decap_index(struct context *,
2738 					   const struct token *, const char *,
2739 					   unsigned int, void *, unsigned int);
2740 static int parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
2741 					   const char *str, unsigned int len, void *buf,
2742 					   unsigned int size);
2743 static int parse_vc_action_ipv6_ext_remove_index(struct context *ctx,
2744 						 const struct token *token,
2745 						 const char *str, unsigned int len,
2746 						 void *buf,
2747 						 unsigned int size);
2748 static int parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
2749 					 const char *str, unsigned int len, void *buf,
2750 					 unsigned int size);
2751 static int parse_vc_action_ipv6_ext_push_index(struct context *ctx,
2752 					       const struct token *token,
2753 					       const char *str, unsigned int len,
2754 					       void *buf,
2755 					       unsigned int size);
2756 static int parse_vc_action_set_meta(struct context *ctx,
2757 				    const struct token *token, const char *str,
2758 				    unsigned int len, void *buf,
2759 					unsigned int size);
2760 static int parse_vc_action_sample(struct context *ctx,
2761 				    const struct token *token, const char *str,
2762 				    unsigned int len, void *buf,
2763 				    unsigned int size);
2764 static int
2765 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
2766 				const char *str, unsigned int len, void *buf,
2767 				unsigned int size);
2768 static int
2769 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
2770 				const char *str, unsigned int len, void *buf,
2771 				unsigned int size);
2772 static int
2773 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
2774 				const char *str, unsigned int len, void *buf,
2775 				unsigned int size);
2776 static int
2777 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
2778 				const char *str, unsigned int len, void *buf,
2779 				unsigned int size);
2780 static int
2781 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
2782 			 const char *str, unsigned int len, void *buf,
2783 			 unsigned int size);
2784 static int parse_destroy(struct context *, const struct token *,
2785 			 const char *, unsigned int,
2786 			 void *, unsigned int);
2787 static int parse_flush(struct context *, const struct token *,
2788 		       const char *, unsigned int,
2789 		       void *, unsigned int);
2790 static int parse_dump(struct context *, const struct token *,
2791 		      const char *, unsigned int,
2792 		      void *, unsigned int);
2793 static int parse_query(struct context *, const struct token *,
2794 		       const char *, unsigned int,
2795 		       void *, unsigned int);
2796 static int parse_action(struct context *, const struct token *,
2797 			const char *, unsigned int,
2798 			void *, unsigned int);
2799 static int parse_list(struct context *, const struct token *,
2800 		      const char *, unsigned int,
2801 		      void *, unsigned int);
2802 static int parse_aged(struct context *, const struct token *,
2803 		      const char *, unsigned int,
2804 		      void *, unsigned int);
2805 static int parse_isolate(struct context *, const struct token *,
2806 			 const char *, unsigned int,
2807 			 void *, unsigned int);
2808 static int parse_configure(struct context *, const struct token *,
2809 			   const char *, unsigned int,
2810 			   void *, unsigned int);
2811 static int parse_template(struct context *, const struct token *,
2812 			  const char *, unsigned int,
2813 			  void *, unsigned int);
2814 static int parse_template_destroy(struct context *, const struct token *,
2815 				  const char *, unsigned int,
2816 				  void *, unsigned int);
2817 static int parse_table(struct context *, const struct token *,
2818 		       const char *, unsigned int, void *, unsigned int);
2819 static int parse_table_destroy(struct context *, const struct token *,
2820 			       const char *, unsigned int,
2821 			       void *, unsigned int);
2822 static int parse_qo(struct context *, const struct token *,
2823 		    const char *, unsigned int,
2824 		    void *, unsigned int);
2825 static int parse_qo_destroy(struct context *, const struct token *,
2826 			    const char *, unsigned int,
2827 			    void *, unsigned int);
2828 static int parse_qia(struct context *, const struct token *,
2829 		     const char *, unsigned int,
2830 		     void *, unsigned int);
2831 static int parse_qia_destroy(struct context *, const struct token *,
2832 			     const char *, unsigned int,
2833 			     void *, unsigned int);
2834 static int parse_push(struct context *, const struct token *,
2835 		      const char *, unsigned int,
2836 		      void *, unsigned int);
2837 static int parse_pull(struct context *, const struct token *,
2838 		      const char *, unsigned int,
2839 		      void *, unsigned int);
2840 static int parse_group(struct context *, const struct token *,
2841 		       const char *, unsigned int,
2842 		       void *, unsigned int);
2843 static int parse_hash(struct context *, const struct token *,
2844 		      const char *, unsigned int,
2845 		      void *, unsigned int);
2846 static int parse_tunnel(struct context *, const struct token *,
2847 			const char *, unsigned int,
2848 			void *, unsigned int);
2849 static int parse_flex(struct context *, const struct token *,
2850 		      const char *, unsigned int, void *, unsigned int);
2851 static int parse_int(struct context *, const struct token *,
2852 		     const char *, unsigned int,
2853 		     void *, unsigned int);
2854 static int parse_prefix(struct context *, const struct token *,
2855 			const char *, unsigned int,
2856 			void *, unsigned int);
2857 static int parse_boolean(struct context *, const struct token *,
2858 			 const char *, unsigned int,
2859 			 void *, unsigned int);
2860 static int parse_string(struct context *, const struct token *,
2861 			const char *, unsigned int,
2862 			void *, unsigned int);
2863 static int parse_hex(struct context *ctx, const struct token *token,
2864 			const char *str, unsigned int len,
2865 			void *buf, unsigned int size);
2866 static int parse_string0(struct context *, const struct token *,
2867 			const char *, unsigned int,
2868 			void *, unsigned int);
2869 static int parse_mac_addr(struct context *, const struct token *,
2870 			  const char *, unsigned int,
2871 			  void *, unsigned int);
2872 static int parse_ipv4_addr(struct context *, const struct token *,
2873 			   const char *, unsigned int,
2874 			   void *, unsigned int);
2875 static int parse_ipv6_addr(struct context *, const struct token *,
2876 			   const char *, unsigned int,
2877 			   void *, unsigned int);
2878 static int parse_port(struct context *, const struct token *,
2879 		      const char *, unsigned int,
2880 		      void *, unsigned int);
2881 static int parse_ia(struct context *, const struct token *,
2882 		    const char *, unsigned int,
2883 		    void *, unsigned int);
2884 static int parse_ia_destroy(struct context *ctx, const struct token *token,
2885 			    const char *str, unsigned int len,
2886 			    void *buf, unsigned int size);
2887 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
2888 			   const char *str, unsigned int len, void *buf,
2889 			   unsigned int size);
2890 
2891 static int parse_indlst_id2ptr(struct context *ctx, const struct token *token,
2892 			       const char *str, unsigned int len, void *buf,
2893 			       unsigned int size);
2894 static int parse_ia_port(struct context *ctx, const struct token *token,
2895 			 const char *str, unsigned int len, void *buf,
2896 			 unsigned int size);
2897 static int parse_mp(struct context *, const struct token *,
2898 		    const char *, unsigned int,
2899 		    void *, unsigned int);
2900 static int parse_meter_profile_id2ptr(struct context *ctx,
2901 				      const struct token *token,
2902 				      const char *str, unsigned int len,
2903 				      void *buf, unsigned int size);
2904 static int parse_meter_policy_id2ptr(struct context *ctx,
2905 				     const struct token *token,
2906 				     const char *str, unsigned int len,
2907 				     void *buf, unsigned int size);
2908 static int parse_meter_color(struct context *ctx, const struct token *token,
2909 			     const char *str, unsigned int len, void *buf,
2910 			     unsigned int size);
2911 static int parse_insertion_table_type(struct context *ctx, const struct token *token,
2912 				      const char *str, unsigned int len, void *buf,
2913 				      unsigned int size);
2914 static int parse_hash_table_type(struct context *ctx, const struct token *token,
2915 				 const char *str, unsigned int len, void *buf,
2916 				 unsigned int size);
2917 static int
2918 parse_quota_state_name(struct context *ctx, const struct token *token,
2919 		       const char *str, unsigned int len, void *buf,
2920 		       unsigned int size);
2921 static int
2922 parse_quota_mode_name(struct context *ctx, const struct token *token,
2923 		      const char *str, unsigned int len, void *buf,
2924 		      unsigned int size);
2925 static int
2926 parse_quota_update_name(struct context *ctx, const struct token *token,
2927 			const char *str, unsigned int len, void *buf,
2928 			unsigned int size);
2929 static int
2930 parse_qu_mode_name(struct context *ctx, const struct token *token,
2931 		   const char *str, unsigned int len, void *buf,
2932 		   unsigned int size);
2933 static int comp_none(struct context *, const struct token *,
2934 		     unsigned int, char *, unsigned int);
2935 static int comp_boolean(struct context *, const struct token *,
2936 			unsigned int, char *, unsigned int);
2937 static int comp_action(struct context *, const struct token *,
2938 		       unsigned int, char *, unsigned int);
2939 static int comp_port(struct context *, const struct token *,
2940 		     unsigned int, char *, unsigned int);
2941 static int comp_rule_id(struct context *, const struct token *,
2942 			unsigned int, char *, unsigned int);
2943 static int comp_vc_action_rss_type(struct context *, const struct token *,
2944 				   unsigned int, char *, unsigned int);
2945 static int comp_vc_action_rss_queue(struct context *, const struct token *,
2946 				    unsigned int, char *, unsigned int);
2947 static int comp_set_raw_index(struct context *, const struct token *,
2948 			      unsigned int, char *, unsigned int);
2949 static int comp_set_sample_index(struct context *, const struct token *,
2950 			      unsigned int, char *, unsigned int);
2951 static int comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
2952 				   unsigned int ent, char *buf, unsigned int size);
2953 static int comp_set_modify_field_op(struct context *, const struct token *,
2954 			      unsigned int, char *, unsigned int);
2955 static int comp_set_modify_field_id(struct context *, const struct token *,
2956 			      unsigned int, char *, unsigned int);
2957 static int comp_pattern_template_id(struct context *, const struct token *,
2958 				    unsigned int, char *, unsigned int);
2959 static int comp_actions_template_id(struct context *, const struct token *,
2960 				    unsigned int, char *, unsigned int);
2961 static int comp_table_id(struct context *, const struct token *,
2962 			 unsigned int, char *, unsigned int);
2963 static int comp_queue_id(struct context *, const struct token *,
2964 			 unsigned int, char *, unsigned int);
2965 static int comp_meter_color(struct context *, const struct token *,
2966 			    unsigned int, char *, unsigned int);
2967 static int comp_insertion_table_type(struct context *, const struct token *,
2968 				     unsigned int, char *, unsigned int);
2969 static int comp_hash_table_type(struct context *, const struct token *,
2970 				unsigned int, char *, unsigned int);
2971 static int
2972 comp_quota_state_name(struct context *ctx, const struct token *token,
2973 		      unsigned int ent, char *buf, unsigned int size);
2974 static int
2975 comp_quota_mode_name(struct context *ctx, const struct token *token,
2976 		     unsigned int ent, char *buf, unsigned int size);
2977 static int
2978 comp_quota_update_name(struct context *ctx, const struct token *token,
2979 		       unsigned int ent, char *buf, unsigned int size);
2980 static int
2981 comp_qu_mode_name(struct context *ctx, const struct token *token,
2982 		  unsigned int ent, char *buf, unsigned int size);
2983 static int
2984 comp_set_compare_field_id(struct context *ctx, const struct token *token,
2985 			  unsigned int ent, char *buf, unsigned int size);
2986 static int
2987 comp_set_compare_op(struct context *ctx, const struct token *token,
2988 		    unsigned int ent, char *buf, unsigned int size);
2989 static int
2990 parse_vc_compare_op(struct context *ctx, const struct token *token,
2991 			 const char *str, unsigned int len, void *buf,
2992 			 unsigned int size);
2993 static int
2994 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
2995 			  const char *str, unsigned int len, void *buf,
2996 			  unsigned int size);
2997 static int
2998 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
2999 			     const char *str, unsigned int len, void *buf,
3000 			     unsigned int size);
3001 
3002 struct indlst_conf {
3003 	uint32_t id;
3004 	uint32_t conf_num;
3005 	struct rte_flow_action *actions;
3006 	const void **conf;
3007 	SLIST_ENTRY(indlst_conf) next;
3008 };
3009 
3010 static const struct indlst_conf *indirect_action_list_conf_get(uint32_t conf_id);
3011 
3012 /** Token definitions. */
3013 static const struct token token_list[] = {
3014 	/* Special tokens. */
3015 	[ZERO] = {
3016 		.name = "ZERO",
3017 		.help = "null entry, abused as the entry point",
3018 		.next = NEXT(NEXT_ENTRY(FLOW, ADD)),
3019 	},
3020 	[END] = {
3021 		.name = "",
3022 		.type = "RETURN",
3023 		.help = "command may end here",
3024 	},
3025 	[START_SET] = {
3026 		.name = "START_SET",
3027 		.help = "null entry, abused as the entry point for set",
3028 		.next = NEXT(NEXT_ENTRY(SET)),
3029 	},
3030 	[END_SET] = {
3031 		.name = "end_set",
3032 		.type = "RETURN",
3033 		.help = "set command may end here",
3034 	},
3035 	/* Common tokens. */
3036 	[COMMON_INTEGER] = {
3037 		.name = "{int}",
3038 		.type = "INTEGER",
3039 		.help = "integer value",
3040 		.call = parse_int,
3041 		.comp = comp_none,
3042 	},
3043 	[COMMON_UNSIGNED] = {
3044 		.name = "{unsigned}",
3045 		.type = "UNSIGNED",
3046 		.help = "unsigned integer value",
3047 		.call = parse_int,
3048 		.comp = comp_none,
3049 	},
3050 	[COMMON_PREFIX] = {
3051 		.name = "{prefix}",
3052 		.type = "PREFIX",
3053 		.help = "prefix length for bit-mask",
3054 		.call = parse_prefix,
3055 		.comp = comp_none,
3056 	},
3057 	[COMMON_BOOLEAN] = {
3058 		.name = "{boolean}",
3059 		.type = "BOOLEAN",
3060 		.help = "any boolean value",
3061 		.call = parse_boolean,
3062 		.comp = comp_boolean,
3063 	},
3064 	[COMMON_STRING] = {
3065 		.name = "{string}",
3066 		.type = "STRING",
3067 		.help = "fixed string",
3068 		.call = parse_string,
3069 		.comp = comp_none,
3070 	},
3071 	[COMMON_HEX] = {
3072 		.name = "{hex}",
3073 		.type = "HEX",
3074 		.help = "fixed string",
3075 		.call = parse_hex,
3076 	},
3077 	[COMMON_FILE_PATH] = {
3078 		.name = "{file path}",
3079 		.type = "STRING",
3080 		.help = "file path",
3081 		.call = parse_string0,
3082 		.comp = comp_none,
3083 	},
3084 	[COMMON_MAC_ADDR] = {
3085 		.name = "{MAC address}",
3086 		.type = "MAC-48",
3087 		.help = "standard MAC address notation",
3088 		.call = parse_mac_addr,
3089 		.comp = comp_none,
3090 	},
3091 	[COMMON_IPV4_ADDR] = {
3092 		.name = "{IPv4 address}",
3093 		.type = "IPV4 ADDRESS",
3094 		.help = "standard IPv4 address notation",
3095 		.call = parse_ipv4_addr,
3096 		.comp = comp_none,
3097 	},
3098 	[COMMON_IPV6_ADDR] = {
3099 		.name = "{IPv6 address}",
3100 		.type = "IPV6 ADDRESS",
3101 		.help = "standard IPv6 address notation",
3102 		.call = parse_ipv6_addr,
3103 		.comp = comp_none,
3104 	},
3105 	[COMMON_RULE_ID] = {
3106 		.name = "{rule id}",
3107 		.type = "RULE ID",
3108 		.help = "rule identifier",
3109 		.call = parse_int,
3110 		.comp = comp_rule_id,
3111 	},
3112 	[COMMON_PORT_ID] = {
3113 		.name = "{port_id}",
3114 		.type = "PORT ID",
3115 		.help = "port identifier",
3116 		.call = parse_port,
3117 		.comp = comp_port,
3118 	},
3119 	[COMMON_GROUP_ID] = {
3120 		.name = "{group_id}",
3121 		.type = "GROUP ID",
3122 		.help = "group identifier",
3123 		.call = parse_int,
3124 		.comp = comp_none,
3125 	},
3126 	[COMMON_PRIORITY_LEVEL] = {
3127 		.name = "{level}",
3128 		.type = "PRIORITY",
3129 		.help = "priority level",
3130 		.call = parse_int,
3131 		.comp = comp_none,
3132 	},
3133 	[COMMON_INDIRECT_ACTION_ID] = {
3134 		.name = "{indirect_action_id}",
3135 		.type = "INDIRECT_ACTION_ID",
3136 		.help = "indirect action id",
3137 		.call = parse_int,
3138 		.comp = comp_none,
3139 	},
3140 	[COMMON_PROFILE_ID] = {
3141 		.name = "{profile_id}",
3142 		.type = "PROFILE_ID",
3143 		.help = "profile id",
3144 		.call = parse_int,
3145 		.comp = comp_none,
3146 	},
3147 	[COMMON_POLICY_ID] = {
3148 		.name = "{policy_id}",
3149 		.type = "POLICY_ID",
3150 		.help = "policy id",
3151 		.call = parse_int,
3152 		.comp = comp_none,
3153 	},
3154 	[COMMON_FLEX_TOKEN] = {
3155 		.name = "{flex token}",
3156 		.type = "flex token",
3157 		.help = "flex token",
3158 		.call = parse_int,
3159 		.comp = comp_none,
3160 	},
3161 	[COMMON_FLEX_HANDLE] = {
3162 		.name = "{flex handle}",
3163 		.type = "FLEX HANDLE",
3164 		.help = "fill flex item data",
3165 		.call = parse_flex_handle,
3166 		.comp = comp_none,
3167 	},
3168 	[COMMON_PATTERN_TEMPLATE_ID] = {
3169 		.name = "{pattern_template_id}",
3170 		.type = "PATTERN_TEMPLATE_ID",
3171 		.help = "pattern template id",
3172 		.call = parse_int,
3173 		.comp = comp_pattern_template_id,
3174 	},
3175 	[COMMON_ACTIONS_TEMPLATE_ID] = {
3176 		.name = "{actions_template_id}",
3177 		.type = "ACTIONS_TEMPLATE_ID",
3178 		.help = "actions template id",
3179 		.call = parse_int,
3180 		.comp = comp_actions_template_id,
3181 	},
3182 	[COMMON_TABLE_ID] = {
3183 		.name = "{table_id}",
3184 		.type = "TABLE_ID",
3185 		.help = "table id",
3186 		.call = parse_int,
3187 		.comp = comp_table_id,
3188 	},
3189 	[COMMON_QUEUE_ID] = {
3190 		.name = "{queue_id}",
3191 		.type = "QUEUE_ID",
3192 		.help = "queue id",
3193 		.call = parse_int,
3194 		.comp = comp_queue_id,
3195 	},
3196 	/* Top-level command. */
3197 	[FLOW] = {
3198 		.name = "flow",
3199 		.type = "{command} {port_id} [{arg} [...]]",
3200 		.help = "manage ingress/egress flow rules",
3201 		.next = NEXT(NEXT_ENTRY
3202 			     (INFO,
3203 			      CONFIGURE,
3204 			      PATTERN_TEMPLATE,
3205 			      ACTIONS_TEMPLATE,
3206 			      TABLE,
3207 			      FLOW_GROUP,
3208 			      INDIRECT_ACTION,
3209 			      VALIDATE,
3210 			      CREATE,
3211 			      DESTROY,
3212 			      FLUSH,
3213 			      DUMP,
3214 			      LIST,
3215 			      AGED,
3216 			      QUERY,
3217 			      ISOLATE,
3218 			      TUNNEL,
3219 			      FLEX,
3220 			      QUEUE,
3221 			      PUSH,
3222 			      PULL,
3223 			      HASH)),
3224 		.call = parse_init,
3225 	},
3226 	/* Top-level command. */
3227 	[INFO] = {
3228 		.name = "info",
3229 		.help = "get information about flow engine",
3230 		.next = NEXT(NEXT_ENTRY(END),
3231 			     NEXT_ENTRY(COMMON_PORT_ID)),
3232 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3233 		.call = parse_configure,
3234 	},
3235 	/* Top-level command. */
3236 	[CONFIGURE] = {
3237 		.name = "configure",
3238 		.help = "configure flow engine",
3239 		.next = NEXT(next_config_attr,
3240 			     NEXT_ENTRY(COMMON_PORT_ID)),
3241 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3242 		.call = parse_configure,
3243 	},
3244 	/* Configure arguments. */
3245 	[CONFIG_QUEUES_NUMBER] = {
3246 		.name = "queues_number",
3247 		.help = "number of queues",
3248 		.next = NEXT(next_config_attr,
3249 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3250 		.args = ARGS(ARGS_ENTRY(struct buffer,
3251 					args.configure.nb_queue)),
3252 	},
3253 	[CONFIG_QUEUES_SIZE] = {
3254 		.name = "queues_size",
3255 		.help = "number of elements in queues",
3256 		.next = NEXT(next_config_attr,
3257 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3258 		.args = ARGS(ARGS_ENTRY(struct buffer,
3259 					args.configure.queue_attr.size)),
3260 	},
3261 	[CONFIG_COUNTERS_NUMBER] = {
3262 		.name = "counters_number",
3263 		.help = "number of counters",
3264 		.next = NEXT(next_config_attr,
3265 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3266 		.args = ARGS(ARGS_ENTRY(struct buffer,
3267 					args.configure.port_attr.nb_counters)),
3268 	},
3269 	[CONFIG_AGING_OBJECTS_NUMBER] = {
3270 		.name = "aging_counters_number",
3271 		.help = "number of aging objects",
3272 		.next = NEXT(next_config_attr,
3273 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3274 		.args = ARGS(ARGS_ENTRY(struct buffer,
3275 					args.configure.port_attr.nb_aging_objects)),
3276 	},
3277 	[CONFIG_QUOTAS_NUMBER] = {
3278 		.name = "quotas_number",
3279 		.help = "number of quotas",
3280 		.next = NEXT(next_config_attr,
3281 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3282 		.args = ARGS(ARGS_ENTRY(struct buffer,
3283 				     args.configure.port_attr.nb_quotas)),
3284 	},
3285 	[CONFIG_METERS_NUMBER] = {
3286 		.name = "meters_number",
3287 		.help = "number of meters",
3288 		.next = NEXT(next_config_attr,
3289 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3290 		.args = ARGS(ARGS_ENTRY(struct buffer,
3291 					args.configure.port_attr.nb_meters)),
3292 	},
3293 	[CONFIG_CONN_TRACK_NUMBER] = {
3294 		.name = "conn_tracks_number",
3295 		.help = "number of connection trackings",
3296 		.next = NEXT(next_config_attr,
3297 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3298 		.args = ARGS(ARGS_ENTRY(struct buffer,
3299 					args.configure.port_attr.nb_conn_tracks)),
3300 	},
3301 	[CONFIG_FLAGS] = {
3302 		.name = "flags",
3303 		.help = "configuration flags",
3304 		.next = NEXT(next_config_attr,
3305 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3306 		.args = ARGS(ARGS_ENTRY(struct buffer,
3307 					args.configure.port_attr.flags)),
3308 	},
3309 	[CONFIG_HOST_PORT] = {
3310 		.name = "host_port",
3311 		.help = "host port for shared objects",
3312 		.next = NEXT(next_config_attr,
3313 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3314 		.args = ARGS(ARGS_ENTRY(struct buffer,
3315 					args.configure.port_attr.host_port_id)),
3316 	},
3317 	/* Top-level command. */
3318 	[PATTERN_TEMPLATE] = {
3319 		.name = "pattern_template",
3320 		.type = "{command} {port_id} [{arg} [...]]",
3321 		.help = "manage pattern templates",
3322 		.next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3323 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3324 		.call = parse_template,
3325 	},
3326 	/* Sub-level commands. */
3327 	[PATTERN_TEMPLATE_CREATE] = {
3328 		.name = "create",
3329 		.help = "create pattern template",
3330 		.next = NEXT(next_pt_attr),
3331 		.call = parse_template,
3332 	},
3333 	[PATTERN_TEMPLATE_DESTROY] = {
3334 		.name = "destroy",
3335 		.help = "destroy pattern template",
3336 		.next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)),
3337 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3338 		.call = parse_template_destroy,
3339 	},
3340 	/* Pattern template arguments. */
3341 	[PATTERN_TEMPLATE_CREATE_ID] = {
3342 		.name = "pattern_template_id",
3343 		.help = "specify a pattern template id to create",
3344 		.next = NEXT(next_pt_attr,
3345 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3346 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)),
3347 	},
3348 	[PATTERN_TEMPLATE_DESTROY_ID] = {
3349 		.name = "pattern_template",
3350 		.help = "specify a pattern template id to destroy",
3351 		.next = NEXT(next_pt_destroy_attr,
3352 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3353 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3354 					    args.templ_destroy.template_id)),
3355 		.call = parse_template_destroy,
3356 	},
3357 	[PATTERN_TEMPLATE_RELAXED_MATCHING] = {
3358 		.name = "relaxed",
3359 		.help = "is matching relaxed",
3360 		.next = NEXT(next_pt_attr,
3361 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3362 		.args = ARGS(ARGS_ENTRY_BF(struct buffer,
3363 			     args.vc.attr.reserved, 1)),
3364 	},
3365 	[PATTERN_TEMPLATE_INGRESS] = {
3366 		.name = "ingress",
3367 		.help = "attribute pattern to ingress",
3368 		.next = NEXT(next_pt_attr),
3369 		.call = parse_template,
3370 	},
3371 	[PATTERN_TEMPLATE_EGRESS] = {
3372 		.name = "egress",
3373 		.help = "attribute pattern to egress",
3374 		.next = NEXT(next_pt_attr),
3375 		.call = parse_template,
3376 	},
3377 	[PATTERN_TEMPLATE_TRANSFER] = {
3378 		.name = "transfer",
3379 		.help = "attribute pattern to transfer",
3380 		.next = NEXT(next_pt_attr),
3381 		.call = parse_template,
3382 	},
3383 	[PATTERN_TEMPLATE_SPEC] = {
3384 		.name = "template",
3385 		.help = "specify item to create pattern template",
3386 		.next = NEXT(next_item),
3387 	},
3388 	/* Top-level command. */
3389 	[ACTIONS_TEMPLATE] = {
3390 		.name = "actions_template",
3391 		.type = "{command} {port_id} [{arg} [...]]",
3392 		.help = "manage actions templates",
3393 		.next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3394 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3395 		.call = parse_template,
3396 	},
3397 	/* Sub-level commands. */
3398 	[ACTIONS_TEMPLATE_CREATE] = {
3399 		.name = "create",
3400 		.help = "create actions template",
3401 		.next = NEXT(next_at_attr),
3402 		.call = parse_template,
3403 	},
3404 	[ACTIONS_TEMPLATE_DESTROY] = {
3405 		.name = "destroy",
3406 		.help = "destroy actions template",
3407 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)),
3408 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3409 		.call = parse_template_destroy,
3410 	},
3411 	/* Actions template arguments. */
3412 	[ACTIONS_TEMPLATE_CREATE_ID] = {
3413 		.name = "actions_template_id",
3414 		.help = "specify an actions template id to create",
3415 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK),
3416 			     NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC),
3417 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3418 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)),
3419 	},
3420 	[ACTIONS_TEMPLATE_DESTROY_ID] = {
3421 		.name = "actions_template",
3422 		.help = "specify an actions template id to destroy",
3423 		.next = NEXT(next_at_destroy_attr,
3424 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3425 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3426 					    args.templ_destroy.template_id)),
3427 		.call = parse_template_destroy,
3428 	},
3429 	[ACTIONS_TEMPLATE_INGRESS] = {
3430 		.name = "ingress",
3431 		.help = "attribute actions to ingress",
3432 		.next = NEXT(next_at_attr),
3433 		.call = parse_template,
3434 	},
3435 	[ACTIONS_TEMPLATE_EGRESS] = {
3436 		.name = "egress",
3437 		.help = "attribute actions to egress",
3438 		.next = NEXT(next_at_attr),
3439 		.call = parse_template,
3440 	},
3441 	[ACTIONS_TEMPLATE_TRANSFER] = {
3442 		.name = "transfer",
3443 		.help = "attribute actions to transfer",
3444 		.next = NEXT(next_at_attr),
3445 		.call = parse_template,
3446 	},
3447 	[ACTIONS_TEMPLATE_SPEC] = {
3448 		.name = "template",
3449 		.help = "specify action to create actions template",
3450 		.next = NEXT(next_action),
3451 		.call = parse_template,
3452 	},
3453 	[ACTIONS_TEMPLATE_MASK] = {
3454 		.name = "mask",
3455 		.help = "specify action mask to create actions template",
3456 		.next = NEXT(next_action),
3457 		.call = parse_template,
3458 	},
3459 	/* Top-level command. */
3460 	[TABLE] = {
3461 		.name = "template_table",
3462 		.type = "{command} {port_id} [{arg} [...]]",
3463 		.help = "manage template tables",
3464 		.next = NEXT(next_table_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3465 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3466 		.call = parse_table,
3467 	},
3468 	/* Sub-level commands. */
3469 	[TABLE_CREATE] = {
3470 		.name = "create",
3471 		.help = "create template table",
3472 		.next = NEXT(next_table_attr),
3473 		.call = parse_table,
3474 	},
3475 	[TABLE_DESTROY] = {
3476 		.name = "destroy",
3477 		.help = "destroy template table",
3478 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3479 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3480 		.call = parse_table_destroy,
3481 	},
3482 	[TABLE_RESIZE] = {
3483 		.name = "resize",
3484 		.help = "resize template table",
3485 		.next = NEXT(NEXT_ENTRY(TABLE_RESIZE_ID)),
3486 		.call = parse_table
3487 	},
3488 	[TABLE_RESIZE_COMPLETE] = {
3489 		.name = "resize_complete",
3490 		.help = "complete table resize",
3491 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3492 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3493 		.call = parse_table_destroy,
3494 	},
3495 	/* Table  arguments. */
3496 	[TABLE_CREATE_ID] = {
3497 		.name = "table_id",
3498 		.help = "specify table id to create",
3499 		.next = NEXT(next_table_attr,
3500 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3501 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3502 	},
3503 	[TABLE_DESTROY_ID] = {
3504 		.name = "table",
3505 		.help = "table id",
3506 		.next = NEXT(next_table_destroy_attr,
3507 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3508 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3509 					    args.table_destroy.table_id)),
3510 		.call = parse_table_destroy,
3511 	},
3512 	[TABLE_RESIZE_ID] = {
3513 		.name = "table_resize_id",
3514 		.help = "table resize id",
3515 		.next = NEXT(NEXT_ENTRY(TABLE_RESIZE_RULES_NUMBER),
3516 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3517 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3518 		.call = parse_table
3519 	},
3520 	[TABLE_RESIZE_RULES_NUMBER] = {
3521 		.name = "table_resize_rules_num",
3522 		.help = "table resize rules number",
3523 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_UNSIGNED)),
3524 		.args = ARGS(ARGS_ENTRY(struct buffer,
3525 					args.table.attr.nb_flows)),
3526 		.call = parse_table
3527 	},
3528 	[TABLE_INSERTION_TYPE] = {
3529 		.name = "insertion_type",
3530 		.help = "specify insertion type",
3531 		.next = NEXT(next_table_attr,
3532 			     NEXT_ENTRY(TABLE_INSERTION_TYPE_NAME)),
3533 		.args = ARGS(ARGS_ENTRY(struct buffer,
3534 					args.table.attr.insertion_type)),
3535 	},
3536 	[TABLE_INSERTION_TYPE_NAME] = {
3537 		.name = "insertion_type_name",
3538 		.help = "insertion type name",
3539 		.call = parse_insertion_table_type,
3540 		.comp = comp_insertion_table_type,
3541 	},
3542 	[TABLE_HASH_FUNC] = {
3543 		.name = "hash_func",
3544 		.help = "specify hash calculation function",
3545 		.next = NEXT(next_table_attr,
3546 			     NEXT_ENTRY(TABLE_HASH_FUNC_NAME)),
3547 		.args = ARGS(ARGS_ENTRY(struct buffer,
3548 					args.table.attr.hash_func)),
3549 	},
3550 	[TABLE_HASH_FUNC_NAME] = {
3551 		.name = "hash_func_name",
3552 		.help = "hash calculation function name",
3553 		.call = parse_hash_table_type,
3554 		.comp = comp_hash_table_type,
3555 	},
3556 	[TABLE_GROUP] = {
3557 		.name = "group",
3558 		.help = "specify a group",
3559 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3560 		.args = ARGS(ARGS_ENTRY(struct buffer,
3561 					args.table.attr.flow_attr.group)),
3562 	},
3563 	[TABLE_PRIORITY] = {
3564 		.name = "priority",
3565 		.help = "specify a priority level",
3566 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
3567 		.args = ARGS(ARGS_ENTRY(struct buffer,
3568 					args.table.attr.flow_attr.priority)),
3569 	},
3570 	[TABLE_EGRESS] = {
3571 		.name = "egress",
3572 		.help = "affect rule to egress",
3573 		.next = NEXT(next_table_attr),
3574 		.call = parse_table,
3575 	},
3576 	[TABLE_INGRESS] = {
3577 		.name = "ingress",
3578 		.help = "affect rule to ingress",
3579 		.next = NEXT(next_table_attr),
3580 		.call = parse_table,
3581 	},
3582 	[TABLE_TRANSFER] = {
3583 		.name = "transfer",
3584 		.help = "affect rule to transfer",
3585 		.next = NEXT(next_table_attr),
3586 		.call = parse_table,
3587 	},
3588 	[TABLE_TRANSFER_WIRE_ORIG] = {
3589 		.name = "wire_orig",
3590 		.help = "affect rule direction to transfer",
3591 		.next = NEXT(next_table_attr),
3592 		.call = parse_table,
3593 	},
3594 	[TABLE_TRANSFER_VPORT_ORIG] = {
3595 		.name = "vport_orig",
3596 		.help = "affect rule direction to transfer",
3597 		.next = NEXT(next_table_attr),
3598 		.call = parse_table,
3599 	},
3600 	[TABLE_RESIZABLE] = {
3601 		.name = "resizable",
3602 		.help = "set resizable attribute",
3603 		.next = NEXT(next_table_attr),
3604 		.call = parse_table,
3605 	},
3606 	[TABLE_RULES_NUMBER] = {
3607 		.name = "rules_number",
3608 		.help = "number of rules in table",
3609 		.next = NEXT(next_table_attr,
3610 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3611 		.args = ARGS(ARGS_ENTRY(struct buffer,
3612 					args.table.attr.nb_flows)),
3613 		.call = parse_table,
3614 	},
3615 	[TABLE_PATTERN_TEMPLATE] = {
3616 		.name = "pattern_template",
3617 		.help = "specify pattern template id",
3618 		.next = NEXT(next_table_attr,
3619 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3620 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3621 					    args.table.pat_templ_id)),
3622 		.call = parse_table,
3623 	},
3624 	[TABLE_ACTIONS_TEMPLATE] = {
3625 		.name = "actions_template",
3626 		.help = "specify actions template id",
3627 		.next = NEXT(next_table_attr,
3628 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3629 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3630 					    args.table.act_templ_id)),
3631 		.call = parse_table,
3632 	},
3633 	/* Top-level command. */
3634 	[FLOW_GROUP] = {
3635 		.name = "group",
3636 		.help = "manage flow groups",
3637 		.next = NEXT(NEXT_ENTRY(GROUP_ID), NEXT_ENTRY(COMMON_PORT_ID)),
3638 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3639 		.call = parse_group,
3640 	},
3641 	/* Sub-level commands. */
3642 	[GROUP_SET_MISS_ACTIONS] = {
3643 		.name = "set_miss_actions",
3644 		.help = "set group miss actions",
3645 		.next = NEXT(next_action),
3646 		.call = parse_group,
3647 	},
3648 	/* Group arguments */
3649 	[GROUP_ID]	= {
3650 		.name = "group_id",
3651 		.help = "group id",
3652 		.next = NEXT(next_group_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3653 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3654 	},
3655 	[GROUP_INGRESS] = {
3656 		.name = "ingress",
3657 		.help = "group ingress attr",
3658 		.next = NEXT(next_group_attr),
3659 		.call = parse_group,
3660 	},
3661 	[GROUP_EGRESS] = {
3662 		.name = "egress",
3663 		.help = "group egress attr",
3664 		.next = NEXT(next_group_attr),
3665 		.call = parse_group,
3666 	},
3667 	[GROUP_TRANSFER] = {
3668 		.name = "transfer",
3669 		.help = "group transfer attr",
3670 		.next = NEXT(next_group_attr),
3671 		.call = parse_group,
3672 	},
3673 	/* Top-level command. */
3674 	[QUEUE] = {
3675 		.name = "queue",
3676 		.help = "queue a flow rule operation",
3677 		.next = NEXT(next_queue_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3678 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3679 		.call = parse_qo,
3680 	},
3681 	/* Sub-level commands. */
3682 	[QUEUE_CREATE] = {
3683 		.name = "create",
3684 		.help = "create a flow rule",
3685 		.next = NEXT(NEXT_ENTRY(QUEUE_TEMPLATE_TABLE),
3686 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3687 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3688 		.call = parse_qo,
3689 	},
3690 	[QUEUE_DESTROY] = {
3691 		.name = "destroy",
3692 		.help = "destroy a flow rule",
3693 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3694 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3695 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3696 		.call = parse_qo_destroy,
3697 	},
3698 	[QUEUE_FLOW_UPDATE_RESIZED] = {
3699 		.name = "update_resized",
3700 		.help = "update a flow after table resize",
3701 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3702 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3703 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3704 		.call = parse_qo_destroy,
3705 	},
3706 	[QUEUE_UPDATE] = {
3707 		.name = "update",
3708 		.help = "update a flow rule",
3709 		.next = NEXT(NEXT_ENTRY(QUEUE_UPDATE_ID),
3710 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3711 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3712 		.call = parse_qo,
3713 	},
3714 	[QUEUE_AGED] = {
3715 		.name = "aged",
3716 		.help = "list and destroy aged flows",
3717 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_QUEUE_ID)),
3718 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3719 		.call = parse_aged,
3720 	},
3721 	[QUEUE_INDIRECT_ACTION] = {
3722 		.name = "indirect_action",
3723 		.help = "queue indirect actions",
3724 		.next = NEXT(next_qia_subcmd, NEXT_ENTRY(COMMON_QUEUE_ID)),
3725 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3726 		.call = parse_qia,
3727 	},
3728 	/* Queue  arguments. */
3729 	[QUEUE_TEMPLATE_TABLE] = {
3730 		.name = "template_table",
3731 		.help = "specify table id",
3732 		.next = NEXT(next_async_insert_subcmd,
3733 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3734 		.args = ARGS(ARGS_ENTRY(struct buffer,
3735 					args.vc.table_id)),
3736 		.call = parse_qo,
3737 	},
3738 	[QUEUE_PATTERN_TEMPLATE] = {
3739 		.name = "pattern_template",
3740 		.help = "specify pattern template index",
3741 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3742 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3743 		.args = ARGS(ARGS_ENTRY(struct buffer,
3744 					args.vc.pat_templ_id)),
3745 		.call = parse_qo,
3746 	},
3747 	[QUEUE_ACTIONS_TEMPLATE] = {
3748 		.name = "actions_template",
3749 		.help = "specify actions template index",
3750 		.next = NEXT(NEXT_ENTRY(QUEUE_CREATE_POSTPONE),
3751 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3752 		.args = ARGS(ARGS_ENTRY(struct buffer,
3753 					args.vc.act_templ_id)),
3754 		.call = parse_qo,
3755 	},
3756 	[QUEUE_RULE_ID] = {
3757 		.name = "rule_index",
3758 		.help = "specify flow rule index",
3759 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3760 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3761 		.args = ARGS(ARGS_ENTRY(struct buffer,
3762 					args.vc.rule_id)),
3763 		.call = parse_qo,
3764 	},
3765 	[QUEUE_CREATE_POSTPONE] = {
3766 		.name = "postpone",
3767 		.help = "postpone create operation",
3768 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
3769 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3770 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3771 		.call = parse_qo,
3772 	},
3773 	[QUEUE_DESTROY_POSTPONE] = {
3774 		.name = "postpone",
3775 		.help = "postpone destroy operation",
3776 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3777 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3778 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3779 		.call = parse_qo_destroy,
3780 	},
3781 	[QUEUE_DESTROY_ID] = {
3782 		.name = "rule",
3783 		.help = "specify rule id to destroy",
3784 		.next = NEXT(next_queue_destroy_attr,
3785 			NEXT_ENTRY(COMMON_UNSIGNED)),
3786 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3787 					    args.destroy.rule)),
3788 		.call = parse_qo_destroy,
3789 	},
3790 	[QUEUE_UPDATE_ID] = {
3791 		.name = "rule",
3792 		.help = "specify rule id to update",
3793 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3794 			NEXT_ENTRY(COMMON_UNSIGNED)),
3795 		.args = ARGS(ARGS_ENTRY(struct buffer,
3796 				     args.vc.rule_id)),
3797 		.call = parse_qo,
3798 	},
3799 	/* Queue indirect action arguments */
3800 	[QUEUE_INDIRECT_ACTION_CREATE] = {
3801 		.name = "create",
3802 		.help = "create indirect action",
3803 		.next = NEXT(next_qia_create_attr),
3804 		.call = parse_qia,
3805 	},
3806 	[QUEUE_INDIRECT_ACTION_UPDATE] = {
3807 		.name = "update",
3808 		.help = "update indirect action",
3809 		.next = NEXT(next_qia_update_attr,
3810 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3811 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3812 		.call = parse_qia,
3813 	},
3814 	[QUEUE_INDIRECT_ACTION_DESTROY] = {
3815 		.name = "destroy",
3816 		.help = "destroy indirect action",
3817 		.next = NEXT(next_qia_destroy_attr),
3818 		.call = parse_qia_destroy,
3819 	},
3820 	[QUEUE_INDIRECT_ACTION_QUERY] = {
3821 		.name = "query",
3822 		.help = "query indirect action",
3823 		.next = NEXT(next_qia_query_attr,
3824 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3825 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3826 		.call = parse_qia,
3827 	},
3828 	/* Indirect action destroy arguments. */
3829 	[QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE] = {
3830 		.name = "postpone",
3831 		.help = "postpone destroy operation",
3832 		.next = NEXT(next_qia_destroy_attr,
3833 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3834 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3835 	},
3836 	[QUEUE_INDIRECT_ACTION_DESTROY_ID] = {
3837 		.name = "action_id",
3838 		.help = "specify a indirect action id to destroy",
3839 		.next = NEXT(next_qia_destroy_attr,
3840 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3841 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3842 					    args.ia_destroy.action_id)),
3843 		.call = parse_qia_destroy,
3844 	},
3845 	[QUEUE_INDIRECT_ACTION_QUERY_UPDATE] = {
3846 		.name = "query_update",
3847 		.help = "indirect query [and|or] update action",
3848 		.next = NEXT(next_qia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3849 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3850 		.call = parse_qia
3851 	},
3852 	[QUEUE_INDIRECT_ACTION_QU_MODE] = {
3853 		.name = "mode",
3854 		.help = "indirect query [and|or] update action",
3855 		.next = NEXT(next_qia_qu_attr,
3856 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
3857 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
3858 		.call = parse_qia
3859 	},
3860 	/* Indirect action update arguments. */
3861 	[QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE] = {
3862 		.name = "postpone",
3863 		.help = "postpone update operation",
3864 		.next = NEXT(next_qia_update_attr,
3865 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3866 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3867 	},
3868 	/* Indirect action update arguments. */
3869 	[QUEUE_INDIRECT_ACTION_QUERY_POSTPONE] = {
3870 		.name = "postpone",
3871 		.help = "postpone query operation",
3872 		.next = NEXT(next_qia_query_attr,
3873 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3874 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3875 	},
3876 	/* Indirect action create arguments. */
3877 	[QUEUE_INDIRECT_ACTION_CREATE_ID] = {
3878 		.name = "action_id",
3879 		.help = "specify a indirect action id to create",
3880 		.next = NEXT(next_qia_create_attr,
3881 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3882 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3883 	},
3884 	[QUEUE_INDIRECT_ACTION_INGRESS] = {
3885 		.name = "ingress",
3886 		.help = "affect rule to ingress",
3887 		.next = NEXT(next_qia_create_attr),
3888 		.call = parse_qia,
3889 	},
3890 	[QUEUE_INDIRECT_ACTION_EGRESS] = {
3891 		.name = "egress",
3892 		.help = "affect rule to egress",
3893 		.next = NEXT(next_qia_create_attr),
3894 		.call = parse_qia,
3895 	},
3896 	[QUEUE_INDIRECT_ACTION_TRANSFER] = {
3897 		.name = "transfer",
3898 		.help = "affect rule to transfer",
3899 		.next = NEXT(next_qia_create_attr),
3900 		.call = parse_qia,
3901 	},
3902 	[QUEUE_INDIRECT_ACTION_CREATE_POSTPONE] = {
3903 		.name = "postpone",
3904 		.help = "postpone create operation",
3905 		.next = NEXT(next_qia_create_attr,
3906 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3907 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3908 	},
3909 	[QUEUE_INDIRECT_ACTION_SPEC] = {
3910 		.name = "action",
3911 		.help = "specify action to create indirect handle",
3912 		.next = NEXT(next_action),
3913 	},
3914 	[QUEUE_INDIRECT_ACTION_LIST] = {
3915 		.name = "list",
3916 		.help = "specify actions for indirect handle list",
3917 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
3918 		.call = parse_qia,
3919 	},
3920 	/* Top-level command. */
3921 	[PUSH] = {
3922 		.name = "push",
3923 		.help = "push enqueued operations",
3924 		.next = NEXT(NEXT_ENTRY(PUSH_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3925 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3926 		.call = parse_push,
3927 	},
3928 	/* Sub-level commands. */
3929 	[PUSH_QUEUE] = {
3930 		.name = "queue",
3931 		.help = "specify queue id",
3932 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3933 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3934 	},
3935 	/* Top-level command. */
3936 	[PULL] = {
3937 		.name = "pull",
3938 		.help = "pull flow operations results",
3939 		.next = NEXT(NEXT_ENTRY(PULL_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3940 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3941 		.call = parse_pull,
3942 	},
3943 	/* Sub-level commands. */
3944 	[PULL_QUEUE] = {
3945 		.name = "queue",
3946 		.help = "specify queue id",
3947 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3948 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3949 	},
3950 	/* Top-level command. */
3951 	[HASH] = {
3952 		.name = "hash",
3953 		.help = "calculate hash for a given pattern in a given template table",
3954 		.next = NEXT(next_hash_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3955 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3956 		.call = parse_hash,
3957 	},
3958 	/* Sub-level commands. */
3959 	[HASH_CALC_TABLE] = {
3960 		.name = "template_table",
3961 		.help = "specify table id",
3962 		.next = NEXT(NEXT_ENTRY(HASH_CALC_PATTERN_INDEX),
3963 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3964 		.args = ARGS(ARGS_ENTRY(struct buffer,
3965 					args.vc.table_id)),
3966 		.call = parse_hash,
3967 	},
3968 	[HASH_CALC_ENCAP] = {
3969 		.name = "encap",
3970 		.help = "calculates encap hash",
3971 		.next = NEXT(next_hash_encap_dest_subcmd),
3972 		.call = parse_hash,
3973 	},
3974 	[HASH_CALC_PATTERN_INDEX] = {
3975 		.name = "pattern_template",
3976 		.help = "specify pattern template id",
3977 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
3978 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3979 		.args = ARGS(ARGS_ENTRY(struct buffer,
3980 					args.vc.pat_templ_id)),
3981 		.call = parse_hash,
3982 	},
3983 	[ENCAP_HASH_FIELD_SRC_PORT] = {
3984 		.name = "hash_field_sport",
3985 		.help = "the encap hash field is src port",
3986 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
3987 		.call = parse_hash,
3988 	},
3989 	[ENCAP_HASH_FIELD_GRE_FLOW_ID] = {
3990 		.name = "hash_field_flow_id",
3991 		.help = "the encap hash field is NVGRE flow id",
3992 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
3993 		.call = parse_hash,
3994 	},
3995 	/* Top-level command. */
3996 	[INDIRECT_ACTION] = {
3997 		.name = "indirect_action",
3998 		.type = "{command} {port_id} [{arg} [...]]",
3999 		.help = "manage indirect actions",
4000 		.next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
4001 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4002 		.call = parse_ia,
4003 	},
4004 	/* Sub-level commands. */
4005 	[INDIRECT_ACTION_CREATE] = {
4006 		.name = "create",
4007 		.help = "create indirect action",
4008 		.next = NEXT(next_ia_create_attr),
4009 		.call = parse_ia,
4010 	},
4011 	[INDIRECT_ACTION_UPDATE] = {
4012 		.name = "update",
4013 		.help = "update indirect action",
4014 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
4015 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4016 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
4017 		.call = parse_ia,
4018 	},
4019 	[INDIRECT_ACTION_DESTROY] = {
4020 		.name = "destroy",
4021 		.help = "destroy indirect action",
4022 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
4023 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4024 		.call = parse_ia_destroy,
4025 	},
4026 	[INDIRECT_ACTION_QUERY] = {
4027 		.name = "query",
4028 		.help = "query indirect action",
4029 		.next = NEXT(NEXT_ENTRY(END),
4030 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4031 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
4032 		.call = parse_ia,
4033 	},
4034 	[INDIRECT_ACTION_QUERY_UPDATE] = {
4035 		.name = "query_update",
4036 		.help = "query [and|or] update",
4037 		.next = NEXT(next_ia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4038 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
4039 		.call = parse_ia
4040 	},
4041 	[INDIRECT_ACTION_QU_MODE] = {
4042 		.name = "mode",
4043 		.help = "query_update mode",
4044 		.next = NEXT(next_ia_qu_attr,
4045 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
4046 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
4047 		.call = parse_ia,
4048 	},
4049 	[INDIRECT_ACTION_QU_MODE_NAME] = {
4050 		.name = "mode_name",
4051 		.help = "query-update mode name",
4052 		.call = parse_qu_mode_name,
4053 		.comp = comp_qu_mode_name,
4054 	},
4055 	[VALIDATE] = {
4056 		.name = "validate",
4057 		.help = "check whether a flow rule can be created",
4058 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4059 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4060 		.call = parse_vc,
4061 	},
4062 	[CREATE] = {
4063 		.name = "create",
4064 		.help = "create a flow rule",
4065 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4066 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4067 		.call = parse_vc,
4068 	},
4069 	[DESTROY] = {
4070 		.name = "destroy",
4071 		.help = "destroy specific flow rules",
4072 		.next = NEXT(next_destroy_attr,
4073 			     NEXT_ENTRY(COMMON_PORT_ID)),
4074 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4075 		.call = parse_destroy,
4076 	},
4077 	[FLUSH] = {
4078 		.name = "flush",
4079 		.help = "destroy all flow rules",
4080 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4081 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4082 		.call = parse_flush,
4083 	},
4084 	[DUMP] = {
4085 		.name = "dump",
4086 		.help = "dump single/all flow rules to file",
4087 		.next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
4088 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4089 		.call = parse_dump,
4090 	},
4091 	[QUERY] = {
4092 		.name = "query",
4093 		.help = "query an existing flow rule",
4094 		.next = NEXT(next_query_attr, NEXT_ENTRY(QUERY_ACTION),
4095 			     NEXT_ENTRY(COMMON_RULE_ID),
4096 			     NEXT_ENTRY(COMMON_PORT_ID)),
4097 		.args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
4098 			     ARGS_ENTRY(struct buffer, args.query.rule),
4099 			     ARGS_ENTRY(struct buffer, port)),
4100 		.call = parse_query,
4101 	},
4102 	[LIST] = {
4103 		.name = "list",
4104 		.help = "list existing flow rules",
4105 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4106 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4107 		.call = parse_list,
4108 	},
4109 	[AGED] = {
4110 		.name = "aged",
4111 		.help = "list and destroy aged flows",
4112 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4113 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4114 		.call = parse_aged,
4115 	},
4116 	[ISOLATE] = {
4117 		.name = "isolate",
4118 		.help = "restrict ingress traffic to the defined flow rules",
4119 		.next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
4120 			     NEXT_ENTRY(COMMON_PORT_ID)),
4121 		.args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
4122 			     ARGS_ENTRY(struct buffer, port)),
4123 		.call = parse_isolate,
4124 	},
4125 	[FLEX] = {
4126 		.name = "flex_item",
4127 		.help = "flex item API",
4128 		.next = NEXT(next_flex_item),
4129 		.call = parse_flex,
4130 	},
4131 	[FLEX_ITEM_INIT] = {
4132 		.name = "init",
4133 		.help = "flex item init",
4134 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
4135 			     ARGS_ENTRY(struct buffer, port)),
4136 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
4137 			     NEXT_ENTRY(COMMON_PORT_ID)),
4138 		.call = parse_flex
4139 	},
4140 	[FLEX_ITEM_CREATE] = {
4141 		.name = "create",
4142 		.help = "flex item create",
4143 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename),
4144 			     ARGS_ENTRY(struct buffer, args.flex.token),
4145 			     ARGS_ENTRY(struct buffer, port)),
4146 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH),
4147 			     NEXT_ENTRY(COMMON_FLEX_TOKEN),
4148 			     NEXT_ENTRY(COMMON_PORT_ID)),
4149 		.call = parse_flex
4150 	},
4151 	[FLEX_ITEM_DESTROY] = {
4152 		.name = "destroy",
4153 		.help = "flex item destroy",
4154 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
4155 			     ARGS_ENTRY(struct buffer, port)),
4156 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
4157 			     NEXT_ENTRY(COMMON_PORT_ID)),
4158 		.call = parse_flex
4159 	},
4160 	[TUNNEL] = {
4161 		.name = "tunnel",
4162 		.help = "new tunnel API",
4163 		.next = NEXT(NEXT_ENTRY
4164 			     (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
4165 		.call = parse_tunnel,
4166 	},
4167 	/* Tunnel arguments. */
4168 	[TUNNEL_CREATE] = {
4169 		.name = "create",
4170 		.help = "create new tunnel object",
4171 		.next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
4172 			     NEXT_ENTRY(COMMON_PORT_ID)),
4173 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4174 		.call = parse_tunnel,
4175 	},
4176 	[TUNNEL_CREATE_TYPE] = {
4177 		.name = "type",
4178 		.help = "create new tunnel",
4179 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
4180 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
4181 		.call = parse_tunnel,
4182 	},
4183 	[TUNNEL_DESTROY] = {
4184 		.name = "destroy",
4185 		.help = "destroy tunnel",
4186 		.next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
4187 			     NEXT_ENTRY(COMMON_PORT_ID)),
4188 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4189 		.call = parse_tunnel,
4190 	},
4191 	[TUNNEL_DESTROY_ID] = {
4192 		.name = "id",
4193 		.help = "tunnel identifier to destroy",
4194 		.next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
4195 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4196 		.call = parse_tunnel,
4197 	},
4198 	[TUNNEL_LIST] = {
4199 		.name = "list",
4200 		.help = "list existing tunnels",
4201 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4202 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4203 		.call = parse_tunnel,
4204 	},
4205 	/* Destroy arguments. */
4206 	[DESTROY_RULE] = {
4207 		.name = "rule",
4208 		.help = "specify a rule identifier",
4209 		.next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4210 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
4211 		.call = parse_destroy,
4212 	},
4213 	[DESTROY_IS_USER_ID] = {
4214 		.name = "user_id",
4215 		.help = "rule identifier is user-id",
4216 		.next = NEXT(next_destroy_attr),
4217 		.call = parse_destroy,
4218 	},
4219 	/* Dump arguments. */
4220 	[DUMP_ALL] = {
4221 		.name = "all",
4222 		.help = "dump all",
4223 		.next = NEXT(next_dump_attr),
4224 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
4225 		.call = parse_dump,
4226 	},
4227 	[DUMP_ONE] = {
4228 		.name = "rule",
4229 		.help = "dump one rule",
4230 		.next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4231 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
4232 				ARGS_ENTRY(struct buffer, args.dump.rule)),
4233 		.call = parse_dump,
4234 	},
4235 	[DUMP_IS_USER_ID] = {
4236 		.name = "user_id",
4237 		.help = "rule identifier is user-id",
4238 		.next = NEXT(next_dump_subcmd),
4239 		.call = parse_dump,
4240 	},
4241 	/* Query arguments. */
4242 	[QUERY_ACTION] = {
4243 		.name = "{action}",
4244 		.type = "ACTION",
4245 		.help = "action to query, must be part of the rule",
4246 		.call = parse_action,
4247 		.comp = comp_action,
4248 	},
4249 	[QUERY_IS_USER_ID] = {
4250 		.name = "user_id",
4251 		.help = "rule identifier is user-id",
4252 		.next = NEXT(next_query_attr),
4253 		.call = parse_query,
4254 	},
4255 	/* List arguments. */
4256 	[LIST_GROUP] = {
4257 		.name = "group",
4258 		.help = "specify a group",
4259 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4260 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
4261 		.call = parse_list,
4262 	},
4263 	[AGED_DESTROY] = {
4264 		.name = "destroy",
4265 		.help = "specify aged flows need be destroyed",
4266 		.call = parse_aged,
4267 		.comp = comp_none,
4268 	},
4269 	/* Validate/create attributes. */
4270 	[VC_GROUP] = {
4271 		.name = "group",
4272 		.help = "specify a group",
4273 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4274 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
4275 		.call = parse_vc,
4276 	},
4277 	[VC_PRIORITY] = {
4278 		.name = "priority",
4279 		.help = "specify a priority level",
4280 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
4281 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
4282 		.call = parse_vc,
4283 	},
4284 	[VC_INGRESS] = {
4285 		.name = "ingress",
4286 		.help = "affect rule to ingress",
4287 		.next = NEXT(next_vc_attr),
4288 		.call = parse_vc,
4289 	},
4290 	[VC_EGRESS] = {
4291 		.name = "egress",
4292 		.help = "affect rule to egress",
4293 		.next = NEXT(next_vc_attr),
4294 		.call = parse_vc,
4295 	},
4296 	[VC_TRANSFER] = {
4297 		.name = "transfer",
4298 		.help = "apply rule directly to endpoints found in pattern",
4299 		.next = NEXT(next_vc_attr),
4300 		.call = parse_vc,
4301 	},
4302 	[VC_TUNNEL_SET] = {
4303 		.name = "tunnel_set",
4304 		.help = "tunnel steer rule",
4305 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4306 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4307 		.call = parse_vc,
4308 	},
4309 	[VC_TUNNEL_MATCH] = {
4310 		.name = "tunnel_match",
4311 		.help = "tunnel match rule",
4312 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4313 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4314 		.call = parse_vc,
4315 	},
4316 	[VC_USER_ID] = {
4317 		.name = "user_id",
4318 		.help = "specify a user id to create",
4319 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4320 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.user_id)),
4321 		.call = parse_vc,
4322 	},
4323 	/* Validate/create pattern. */
4324 	[ITEM_PATTERN] = {
4325 		.name = "pattern",
4326 		.help = "submit a list of pattern items",
4327 		.next = NEXT(next_item),
4328 		.call = parse_vc,
4329 	},
4330 	[ITEM_PARAM_IS] = {
4331 		.name = "is",
4332 		.help = "match value perfectly (with full bit-mask)",
4333 		.call = parse_vc_spec,
4334 	},
4335 	[ITEM_PARAM_SPEC] = {
4336 		.name = "spec",
4337 		.help = "match value according to configured bit-mask",
4338 		.call = parse_vc_spec,
4339 	},
4340 	[ITEM_PARAM_LAST] = {
4341 		.name = "last",
4342 		.help = "specify upper bound to establish a range",
4343 		.call = parse_vc_spec,
4344 	},
4345 	[ITEM_PARAM_MASK] = {
4346 		.name = "mask",
4347 		.help = "specify bit-mask with relevant bits set to one",
4348 		.call = parse_vc_spec,
4349 	},
4350 	[ITEM_PARAM_PREFIX] = {
4351 		.name = "prefix",
4352 		.help = "generate bit-mask from a prefix length",
4353 		.call = parse_vc_spec,
4354 	},
4355 	[ITEM_NEXT] = {
4356 		.name = "/",
4357 		.help = "specify next pattern item",
4358 		.next = NEXT(next_item),
4359 	},
4360 	[ITEM_END] = {
4361 		.name = "end",
4362 		.help = "end list of pattern items",
4363 		.priv = PRIV_ITEM(END, 0),
4364 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
4365 		.call = parse_vc,
4366 	},
4367 	[ITEM_VOID] = {
4368 		.name = "void",
4369 		.help = "no-op pattern item",
4370 		.priv = PRIV_ITEM(VOID, 0),
4371 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4372 		.call = parse_vc,
4373 	},
4374 	[ITEM_INVERT] = {
4375 		.name = "invert",
4376 		.help = "perform actions when pattern does not match",
4377 		.priv = PRIV_ITEM(INVERT, 0),
4378 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4379 		.call = parse_vc,
4380 	},
4381 	[ITEM_ANY] = {
4382 		.name = "any",
4383 		.help = "match any protocol for the current layer",
4384 		.priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
4385 		.next = NEXT(item_any),
4386 		.call = parse_vc,
4387 	},
4388 	[ITEM_ANY_NUM] = {
4389 		.name = "num",
4390 		.help = "number of layers covered",
4391 		.next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4392 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
4393 	},
4394 	[ITEM_PORT_ID] = {
4395 		.name = "port_id",
4396 		.help = "match traffic from/to a given DPDK port ID",
4397 		.priv = PRIV_ITEM(PORT_ID,
4398 				  sizeof(struct rte_flow_item_port_id)),
4399 		.next = NEXT(item_port_id),
4400 		.call = parse_vc,
4401 	},
4402 	[ITEM_PORT_ID_ID] = {
4403 		.name = "id",
4404 		.help = "DPDK port ID",
4405 		.next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
4406 			     item_param),
4407 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
4408 	},
4409 	[ITEM_MARK] = {
4410 		.name = "mark",
4411 		.help = "match traffic against value set in previously matched rule",
4412 		.priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
4413 		.next = NEXT(item_mark),
4414 		.call = parse_vc,
4415 	},
4416 	[ITEM_MARK_ID] = {
4417 		.name = "id",
4418 		.help = "Integer value to match against",
4419 		.next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
4420 			     item_param),
4421 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
4422 	},
4423 	[ITEM_RAW] = {
4424 		.name = "raw",
4425 		.help = "match an arbitrary byte string",
4426 		.priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
4427 		.next = NEXT(item_raw),
4428 		.call = parse_vc,
4429 	},
4430 	[ITEM_RAW_RELATIVE] = {
4431 		.name = "relative",
4432 		.help = "look for pattern after the previous item",
4433 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4434 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4435 					   relative, 1)),
4436 	},
4437 	[ITEM_RAW_SEARCH] = {
4438 		.name = "search",
4439 		.help = "search pattern from offset (see also limit)",
4440 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4441 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4442 					   search, 1)),
4443 	},
4444 	[ITEM_RAW_OFFSET] = {
4445 		.name = "offset",
4446 		.help = "absolute or relative offset for pattern",
4447 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
4448 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
4449 	},
4450 	[ITEM_RAW_LIMIT] = {
4451 		.name = "limit",
4452 		.help = "search area limit for start of pattern",
4453 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4454 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
4455 	},
4456 	[ITEM_RAW_PATTERN] = {
4457 		.name = "pattern",
4458 		.help = "byte string to look for",
4459 		.next = NEXT(item_raw,
4460 			     NEXT_ENTRY(COMMON_STRING),
4461 			     NEXT_ENTRY(ITEM_PARAM_IS,
4462 					ITEM_PARAM_SPEC,
4463 					ITEM_PARAM_MASK)),
4464 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4465 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4466 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4467 					    ITEM_RAW_PATTERN_SIZE)),
4468 	},
4469 	[ITEM_RAW_PATTERN_HEX] = {
4470 		.name = "pattern_hex",
4471 		.help = "hex string to look for",
4472 		.next = NEXT(item_raw,
4473 			     NEXT_ENTRY(COMMON_HEX),
4474 			     NEXT_ENTRY(ITEM_PARAM_IS,
4475 					ITEM_PARAM_SPEC,
4476 					ITEM_PARAM_MASK)),
4477 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4478 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4479 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4480 					    ITEM_RAW_PATTERN_SIZE)),
4481 	},
4482 	[ITEM_ETH] = {
4483 		.name = "eth",
4484 		.help = "match Ethernet header",
4485 		.priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
4486 		.next = NEXT(item_eth),
4487 		.call = parse_vc,
4488 	},
4489 	[ITEM_ETH_DST] = {
4490 		.name = "dst",
4491 		.help = "destination MAC",
4492 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4493 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.dst_addr)),
4494 	},
4495 	[ITEM_ETH_SRC] = {
4496 		.name = "src",
4497 		.help = "source MAC",
4498 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4499 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.src_addr)),
4500 	},
4501 	[ITEM_ETH_TYPE] = {
4502 		.name = "type",
4503 		.help = "EtherType",
4504 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4505 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.ether_type)),
4506 	},
4507 	[ITEM_ETH_HAS_VLAN] = {
4508 		.name = "has_vlan",
4509 		.help = "packet header contains VLAN",
4510 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4511 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
4512 					   has_vlan, 1)),
4513 	},
4514 	[ITEM_VLAN] = {
4515 		.name = "vlan",
4516 		.help = "match 802.1Q/ad VLAN tag",
4517 		.priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
4518 		.next = NEXT(item_vlan),
4519 		.call = parse_vc,
4520 	},
4521 	[ITEM_VLAN_TCI] = {
4522 		.name = "tci",
4523 		.help = "tag control information",
4524 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4525 			     item_param),
4526 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, hdr.vlan_tci)),
4527 	},
4528 	[ITEM_VLAN_PCP] = {
4529 		.name = "pcp",
4530 		.help = "priority code point",
4531 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4532 			     item_param),
4533 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4534 						  hdr.vlan_tci, "\xe0\x00")),
4535 	},
4536 	[ITEM_VLAN_DEI] = {
4537 		.name = "dei",
4538 		.help = "drop eligible indicator",
4539 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4540 			     item_param),
4541 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4542 						  hdr.vlan_tci, "\x10\x00")),
4543 	},
4544 	[ITEM_VLAN_VID] = {
4545 		.name = "vid",
4546 		.help = "VLAN identifier",
4547 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4548 			     item_param),
4549 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4550 						  hdr.vlan_tci, "\x0f\xff")),
4551 	},
4552 	[ITEM_VLAN_INNER_TYPE] = {
4553 		.name = "inner_type",
4554 		.help = "inner EtherType",
4555 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4556 			     item_param),
4557 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
4558 					     hdr.eth_proto)),
4559 	},
4560 	[ITEM_VLAN_HAS_MORE_VLAN] = {
4561 		.name = "has_more_vlan",
4562 		.help = "packet header contains another VLAN",
4563 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4564 			     item_param),
4565 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
4566 					   has_more_vlan, 1)),
4567 	},
4568 	[ITEM_IPV4] = {
4569 		.name = "ipv4",
4570 		.help = "match IPv4 header",
4571 		.priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
4572 		.next = NEXT(item_ipv4),
4573 		.call = parse_vc,
4574 	},
4575 	[ITEM_IPV4_VER_IHL] = {
4576 		.name = "version_ihl",
4577 		.help = "match header length",
4578 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4579 			     item_param),
4580 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
4581 				     hdr.version_ihl)),
4582 	},
4583 	[ITEM_IPV4_TOS] = {
4584 		.name = "tos",
4585 		.help = "type of service",
4586 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4587 			     item_param),
4588 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4589 					     hdr.type_of_service)),
4590 	},
4591 	[ITEM_IPV4_LENGTH] = {
4592 		.name = "length",
4593 		.help = "total length",
4594 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4595 			     item_param),
4596 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4597 					     hdr.total_length)),
4598 	},
4599 	[ITEM_IPV4_ID] = {
4600 		.name = "packet_id",
4601 		.help = "fragment packet id",
4602 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4603 			     item_param),
4604 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4605 					     hdr.packet_id)),
4606 	},
4607 	[ITEM_IPV4_FRAGMENT_OFFSET] = {
4608 		.name = "fragment_offset",
4609 		.help = "fragmentation flags and fragment offset",
4610 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4611 			     item_param),
4612 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4613 					     hdr.fragment_offset)),
4614 	},
4615 	[ITEM_IPV4_TTL] = {
4616 		.name = "ttl",
4617 		.help = "time to live",
4618 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4619 			     item_param),
4620 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4621 					     hdr.time_to_live)),
4622 	},
4623 	[ITEM_IPV4_PROTO] = {
4624 		.name = "proto",
4625 		.help = "next protocol ID",
4626 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4627 			     item_param),
4628 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4629 					     hdr.next_proto_id)),
4630 	},
4631 	[ITEM_IPV4_SRC] = {
4632 		.name = "src",
4633 		.help = "source address",
4634 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4635 			     item_param),
4636 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4637 					     hdr.src_addr)),
4638 	},
4639 	[ITEM_IPV4_DST] = {
4640 		.name = "dst",
4641 		.help = "destination address",
4642 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4643 			     item_param),
4644 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4645 					     hdr.dst_addr)),
4646 	},
4647 	[ITEM_IPV6] = {
4648 		.name = "ipv6",
4649 		.help = "match IPv6 header",
4650 		.priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
4651 		.next = NEXT(item_ipv6),
4652 		.call = parse_vc,
4653 	},
4654 	[ITEM_IPV6_TC] = {
4655 		.name = "tc",
4656 		.help = "traffic class",
4657 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4658 			     item_param),
4659 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4660 						  hdr.vtc_flow,
4661 						  "\x0f\xf0\x00\x00")),
4662 	},
4663 	[ITEM_IPV6_FLOW] = {
4664 		.name = "flow",
4665 		.help = "flow label",
4666 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4667 			     item_param),
4668 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4669 						  hdr.vtc_flow,
4670 						  "\x00\x0f\xff\xff")),
4671 	},
4672 	[ITEM_IPV6_LEN] = {
4673 		.name = "length",
4674 		.help = "payload length",
4675 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4676 			     item_param),
4677 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4678 					     hdr.payload_len)),
4679 	},
4680 	[ITEM_IPV6_PROTO] = {
4681 		.name = "proto",
4682 		.help = "protocol (next header)",
4683 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4684 			     item_param),
4685 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4686 					     hdr.proto)),
4687 	},
4688 	[ITEM_IPV6_HOP] = {
4689 		.name = "hop",
4690 		.help = "hop limit",
4691 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4692 			     item_param),
4693 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4694 					     hdr.hop_limits)),
4695 	},
4696 	[ITEM_IPV6_SRC] = {
4697 		.name = "src",
4698 		.help = "source address",
4699 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4700 			     item_param),
4701 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4702 					     hdr.src_addr)),
4703 	},
4704 	[ITEM_IPV6_DST] = {
4705 		.name = "dst",
4706 		.help = "destination address",
4707 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4708 			     item_param),
4709 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4710 					     hdr.dst_addr)),
4711 	},
4712 	[ITEM_IPV6_HAS_FRAG_EXT] = {
4713 		.name = "has_frag_ext",
4714 		.help = "fragment packet attribute",
4715 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4716 			     item_param),
4717 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
4718 					   has_frag_ext, 1)),
4719 	},
4720 	[ITEM_IPV6_ROUTING_EXT] = {
4721 		.name = "ipv6_routing_ext",
4722 		.help = "match IPv6 routing extension header",
4723 		.priv = PRIV_ITEM(IPV6_ROUTING_EXT,
4724 				  sizeof(struct rte_flow_item_ipv6_routing_ext)),
4725 		.next = NEXT(item_ipv6_routing_ext),
4726 		.call = parse_vc,
4727 	},
4728 	[ITEM_IPV6_ROUTING_EXT_TYPE] = {
4729 		.name = "ext_type",
4730 		.help = "match IPv6 routing extension header type",
4731 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4732 			     item_param),
4733 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4734 					     hdr.type)),
4735 	},
4736 	[ITEM_IPV6_ROUTING_EXT_NEXT_HDR] = {
4737 		.name = "ext_next_hdr",
4738 		.help = "match IPv6 routing extension header next header type",
4739 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4740 			     item_param),
4741 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4742 					     hdr.next_hdr)),
4743 	},
4744 	[ITEM_IPV6_ROUTING_EXT_SEG_LEFT] = {
4745 		.name = "ext_seg_left",
4746 		.help = "match IPv6 routing extension header segment left",
4747 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4748 			     item_param),
4749 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4750 					     hdr.segments_left)),
4751 	},
4752 	[ITEM_ICMP] = {
4753 		.name = "icmp",
4754 		.help = "match ICMP header",
4755 		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
4756 		.next = NEXT(item_icmp),
4757 		.call = parse_vc,
4758 	},
4759 	[ITEM_ICMP_TYPE] = {
4760 		.name = "type",
4761 		.help = "ICMP packet type",
4762 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4763 			     item_param),
4764 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4765 					     hdr.icmp_type)),
4766 	},
4767 	[ITEM_ICMP_CODE] = {
4768 		.name = "code",
4769 		.help = "ICMP packet code",
4770 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4771 			     item_param),
4772 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4773 					     hdr.icmp_code)),
4774 	},
4775 	[ITEM_ICMP_IDENT] = {
4776 		.name = "ident",
4777 		.help = "ICMP packet identifier",
4778 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4779 			     item_param),
4780 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4781 					     hdr.icmp_ident)),
4782 	},
4783 	[ITEM_ICMP_SEQ] = {
4784 		.name = "seq",
4785 		.help = "ICMP packet sequence number",
4786 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4787 			     item_param),
4788 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4789 					     hdr.icmp_seq_nb)),
4790 	},
4791 	[ITEM_UDP] = {
4792 		.name = "udp",
4793 		.help = "match UDP header",
4794 		.priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
4795 		.next = NEXT(item_udp),
4796 		.call = parse_vc,
4797 	},
4798 	[ITEM_UDP_SRC] = {
4799 		.name = "src",
4800 		.help = "UDP source port",
4801 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
4802 			     item_param),
4803 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4804 					     hdr.src_port)),
4805 	},
4806 	[ITEM_UDP_DST] = {
4807 		.name = "dst",
4808 		.help = "UDP destination port",
4809 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4810 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4811 					     hdr.dst_port)),
4812 	},
4813 	[ITEM_TCP] = {
4814 		.name = "tcp",
4815 		.help = "match TCP header",
4816 		.priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
4817 		.next = NEXT(item_tcp),
4818 		.call = parse_vc,
4819 	},
4820 	[ITEM_TCP_SRC] = {
4821 		.name = "src",
4822 		.help = "TCP source port",
4823 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4824 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4825 					     hdr.src_port)),
4826 	},
4827 	[ITEM_TCP_DST] = {
4828 		.name = "dst",
4829 		.help = "TCP destination port",
4830 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4831 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4832 					     hdr.dst_port)),
4833 	},
4834 	[ITEM_TCP_FLAGS] = {
4835 		.name = "flags",
4836 		.help = "TCP flags",
4837 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4838 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4839 					     hdr.tcp_flags)),
4840 	},
4841 	[ITEM_SCTP] = {
4842 		.name = "sctp",
4843 		.help = "match SCTP header",
4844 		.priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
4845 		.next = NEXT(item_sctp),
4846 		.call = parse_vc,
4847 	},
4848 	[ITEM_SCTP_SRC] = {
4849 		.name = "src",
4850 		.help = "SCTP source port",
4851 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4852 			     item_param),
4853 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4854 					     hdr.src_port)),
4855 	},
4856 	[ITEM_SCTP_DST] = {
4857 		.name = "dst",
4858 		.help = "SCTP destination port",
4859 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4860 			     item_param),
4861 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4862 					     hdr.dst_port)),
4863 	},
4864 	[ITEM_SCTP_TAG] = {
4865 		.name = "tag",
4866 		.help = "validation tag",
4867 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4868 			     item_param),
4869 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4870 					     hdr.tag)),
4871 	},
4872 	[ITEM_SCTP_CKSUM] = {
4873 		.name = "cksum",
4874 		.help = "checksum",
4875 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4876 			     item_param),
4877 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4878 					     hdr.cksum)),
4879 	},
4880 	[ITEM_VXLAN] = {
4881 		.name = "vxlan",
4882 		.help = "match VXLAN header",
4883 		.priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
4884 		.next = NEXT(item_vxlan),
4885 		.call = parse_vc,
4886 	},
4887 	[ITEM_VXLAN_VNI] = {
4888 		.name = "vni",
4889 		.help = "VXLAN identifier",
4890 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4891 			     item_param),
4892 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, hdr.vni)),
4893 	},
4894 	[ITEM_VXLAN_LAST_RSVD] = {
4895 		.name = "last_rsvd",
4896 		.help = "VXLAN last reserved bits",
4897 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4898 			     item_param),
4899 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
4900 					     hdr.rsvd1)),
4901 	},
4902 	[ITEM_E_TAG] = {
4903 		.name = "e_tag",
4904 		.help = "match E-Tag header",
4905 		.priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
4906 		.next = NEXT(item_e_tag),
4907 		.call = parse_vc,
4908 	},
4909 	[ITEM_E_TAG_GRP_ECID_B] = {
4910 		.name = "grp_ecid_b",
4911 		.help = "GRP and E-CID base",
4912 		.next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
4913 			     item_param),
4914 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
4915 						  rsvd_grp_ecid_b,
4916 						  "\x3f\xff")),
4917 	},
4918 	[ITEM_NVGRE] = {
4919 		.name = "nvgre",
4920 		.help = "match NVGRE header",
4921 		.priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
4922 		.next = NEXT(item_nvgre),
4923 		.call = parse_vc,
4924 	},
4925 	[ITEM_NVGRE_TNI] = {
4926 		.name = "tni",
4927 		.help = "virtual subnet ID",
4928 		.next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
4929 			     item_param),
4930 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
4931 	},
4932 	[ITEM_MPLS] = {
4933 		.name = "mpls",
4934 		.help = "match MPLS header",
4935 		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
4936 		.next = NEXT(item_mpls),
4937 		.call = parse_vc,
4938 	},
4939 	[ITEM_MPLS_LABEL] = {
4940 		.name = "label",
4941 		.help = "MPLS label",
4942 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4943 			     item_param),
4944 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4945 						  label_tc_s,
4946 						  "\xff\xff\xf0")),
4947 	},
4948 	[ITEM_MPLS_TC] = {
4949 		.name = "tc",
4950 		.help = "MPLS Traffic Class",
4951 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4952 			     item_param),
4953 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4954 						  label_tc_s,
4955 						  "\x00\x00\x0e")),
4956 	},
4957 	[ITEM_MPLS_S] = {
4958 		.name = "s",
4959 		.help = "MPLS Bottom-of-Stack",
4960 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4961 			     item_param),
4962 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4963 						  label_tc_s,
4964 						  "\x00\x00\x01")),
4965 	},
4966 	[ITEM_MPLS_TTL] = {
4967 		.name = "ttl",
4968 		.help = "MPLS Time-to-Live",
4969 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4970 			     item_param),
4971 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_mpls, ttl)),
4972 	},
4973 	[ITEM_GRE] = {
4974 		.name = "gre",
4975 		.help = "match GRE header",
4976 		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
4977 		.next = NEXT(item_gre),
4978 		.call = parse_vc,
4979 	},
4980 	[ITEM_GRE_PROTO] = {
4981 		.name = "protocol",
4982 		.help = "GRE protocol type",
4983 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
4984 			     item_param),
4985 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
4986 					     protocol)),
4987 	},
4988 	[ITEM_GRE_C_RSVD0_VER] = {
4989 		.name = "c_rsvd0_ver",
4990 		.help =
4991 			"checksum (1b), undefined (1b), key bit (1b),"
4992 			" sequence number (1b), reserved 0 (9b),"
4993 			" version (3b)",
4994 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
4995 			     item_param),
4996 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
4997 					     c_rsvd0_ver)),
4998 	},
4999 	[ITEM_GRE_C_BIT] = {
5000 		.name = "c_bit",
5001 		.help = "checksum bit (C)",
5002 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
5003 			     item_param),
5004 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5005 						  c_rsvd0_ver,
5006 						  "\x80\x00\x00\x00")),
5007 	},
5008 	[ITEM_GRE_S_BIT] = {
5009 		.name = "s_bit",
5010 		.help = "sequence number bit (S)",
5011 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
5012 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5013 						  c_rsvd0_ver,
5014 						  "\x10\x00\x00\x00")),
5015 	},
5016 	[ITEM_GRE_K_BIT] = {
5017 		.name = "k_bit",
5018 		.help = "key bit (K)",
5019 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
5020 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5021 						  c_rsvd0_ver,
5022 						  "\x20\x00\x00\x00")),
5023 	},
5024 	[ITEM_FUZZY] = {
5025 		.name = "fuzzy",
5026 		.help = "fuzzy pattern match, expect faster than default",
5027 		.priv = PRIV_ITEM(FUZZY,
5028 				sizeof(struct rte_flow_item_fuzzy)),
5029 		.next = NEXT(item_fuzzy),
5030 		.call = parse_vc,
5031 	},
5032 	[ITEM_FUZZY_THRESH] = {
5033 		.name = "thresh",
5034 		.help = "match accuracy threshold",
5035 		.next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
5036 			     item_param),
5037 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
5038 					thresh)),
5039 	},
5040 	[ITEM_GTP] = {
5041 		.name = "gtp",
5042 		.help = "match GTP header",
5043 		.priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
5044 		.next = NEXT(item_gtp),
5045 		.call = parse_vc,
5046 	},
5047 	[ITEM_GTP_FLAGS] = {
5048 		.name = "v_pt_rsv_flags",
5049 		.help = "GTP flags",
5050 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5051 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
5052 					hdr.gtp_hdr_info)),
5053 	},
5054 	[ITEM_GTP_MSG_TYPE] = {
5055 		.name = "msg_type",
5056 		.help = "GTP message type",
5057 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5058 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, hdr.msg_type)),
5059 	},
5060 	[ITEM_GTP_TEID] = {
5061 		.name = "teid",
5062 		.help = "tunnel endpoint identifier",
5063 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5064 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, hdr.teid)),
5065 	},
5066 	[ITEM_GTPC] = {
5067 		.name = "gtpc",
5068 		.help = "match GTP header",
5069 		.priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
5070 		.next = NEXT(item_gtp),
5071 		.call = parse_vc,
5072 	},
5073 	[ITEM_GTPU] = {
5074 		.name = "gtpu",
5075 		.help = "match GTP header",
5076 		.priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
5077 		.next = NEXT(item_gtp),
5078 		.call = parse_vc,
5079 	},
5080 	[ITEM_GENEVE] = {
5081 		.name = "geneve",
5082 		.help = "match GENEVE header",
5083 		.priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
5084 		.next = NEXT(item_geneve),
5085 		.call = parse_vc,
5086 	},
5087 	[ITEM_GENEVE_VNI] = {
5088 		.name = "vni",
5089 		.help = "virtual network identifier",
5090 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5091 			     item_param),
5092 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
5093 	},
5094 	[ITEM_GENEVE_PROTO] = {
5095 		.name = "protocol",
5096 		.help = "GENEVE protocol type",
5097 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5098 			     item_param),
5099 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
5100 					     protocol)),
5101 	},
5102 	[ITEM_GENEVE_OPTLEN] = {
5103 		.name = "optlen",
5104 		.help = "GENEVE options length in dwords",
5105 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5106 			     item_param),
5107 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
5108 						  ver_opt_len_o_c_rsvd0,
5109 						  "\x3f\x00")),
5110 	},
5111 	[ITEM_VXLAN_GPE] = {
5112 		.name = "vxlan-gpe",
5113 		.help = "match VXLAN-GPE header",
5114 		.priv = PRIV_ITEM(VXLAN_GPE,
5115 				  sizeof(struct rte_flow_item_vxlan_gpe)),
5116 		.next = NEXT(item_vxlan_gpe),
5117 		.call = parse_vc,
5118 	},
5119 	[ITEM_VXLAN_GPE_VNI] = {
5120 		.name = "vni",
5121 		.help = "VXLAN-GPE identifier",
5122 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5123 			     item_param),
5124 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5125 					     hdr.vni)),
5126 	},
5127 	[ITEM_VXLAN_GPE_PROTO] = {
5128 		.name = "protocol",
5129 		.help = "VXLAN-GPE next protocol",
5130 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5131 			     item_param),
5132 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5133 					     protocol)),
5134 	},
5135 	[ITEM_VXLAN_GPE_FLAGS] = {
5136 		.name = "flags",
5137 		.help = "VXLAN-GPE flags",
5138 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5139 			     item_param),
5140 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5141 					     flags)),
5142 	},
5143 	[ITEM_VXLAN_GPE_RSVD0] = {
5144 		.name = "rsvd0",
5145 		.help = "VXLAN-GPE rsvd0",
5146 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5147 			     item_param),
5148 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5149 					     rsvd0)),
5150 	},
5151 	[ITEM_VXLAN_GPE_RSVD1] = {
5152 		.name = "rsvd1",
5153 		.help = "VXLAN-GPE rsvd1",
5154 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5155 			     item_param),
5156 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5157 					     rsvd1)),
5158 	},
5159 	[ITEM_ARP_ETH_IPV4] = {
5160 		.name = "arp_eth_ipv4",
5161 		.help = "match ARP header for Ethernet/IPv4",
5162 		.priv = PRIV_ITEM(ARP_ETH_IPV4,
5163 				  sizeof(struct rte_flow_item_arp_eth_ipv4)),
5164 		.next = NEXT(item_arp_eth_ipv4),
5165 		.call = parse_vc,
5166 	},
5167 	[ITEM_ARP_ETH_IPV4_SHA] = {
5168 		.name = "sha",
5169 		.help = "sender hardware address",
5170 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5171 			     item_param),
5172 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5173 					     hdr.arp_data.arp_sha)),
5174 	},
5175 	[ITEM_ARP_ETH_IPV4_SPA] = {
5176 		.name = "spa",
5177 		.help = "sender IPv4 address",
5178 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5179 			     item_param),
5180 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5181 					     hdr.arp_data.arp_sip)),
5182 	},
5183 	[ITEM_ARP_ETH_IPV4_THA] = {
5184 		.name = "tha",
5185 		.help = "target hardware address",
5186 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5187 			     item_param),
5188 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5189 					     hdr.arp_data.arp_tha)),
5190 	},
5191 	[ITEM_ARP_ETH_IPV4_TPA] = {
5192 		.name = "tpa",
5193 		.help = "target IPv4 address",
5194 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5195 			     item_param),
5196 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5197 					     hdr.arp_data.arp_tip)),
5198 	},
5199 	[ITEM_IPV6_EXT] = {
5200 		.name = "ipv6_ext",
5201 		.help = "match presence of any IPv6 extension header",
5202 		.priv = PRIV_ITEM(IPV6_EXT,
5203 				  sizeof(struct rte_flow_item_ipv6_ext)),
5204 		.next = NEXT(item_ipv6_ext),
5205 		.call = parse_vc,
5206 	},
5207 	[ITEM_IPV6_EXT_NEXT_HDR] = {
5208 		.name = "next_hdr",
5209 		.help = "next header",
5210 		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5211 			     item_param),
5212 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
5213 					     next_hdr)),
5214 	},
5215 	[ITEM_IPV6_FRAG_EXT] = {
5216 		.name = "ipv6_frag_ext",
5217 		.help = "match presence of IPv6 fragment extension header",
5218 		.priv = PRIV_ITEM(IPV6_FRAG_EXT,
5219 				sizeof(struct rte_flow_item_ipv6_frag_ext)),
5220 		.next = NEXT(item_ipv6_frag_ext),
5221 		.call = parse_vc,
5222 	},
5223 	[ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
5224 		.name = "next_hdr",
5225 		.help = "next header",
5226 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5227 			     item_param),
5228 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
5229 					hdr.next_header)),
5230 	},
5231 	[ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
5232 		.name = "frag_data",
5233 		.help = "fragment flags and offset",
5234 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5235 			     item_param),
5236 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5237 					     hdr.frag_data)),
5238 	},
5239 	[ITEM_IPV6_FRAG_EXT_ID] = {
5240 		.name = "packet_id",
5241 		.help = "fragment packet id",
5242 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5243 			     item_param),
5244 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5245 					     hdr.id)),
5246 	},
5247 	[ITEM_ICMP6] = {
5248 		.name = "icmp6",
5249 		.help = "match any ICMPv6 header",
5250 		.priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
5251 		.next = NEXT(item_icmp6),
5252 		.call = parse_vc,
5253 	},
5254 	[ITEM_ICMP6_TYPE] = {
5255 		.name = "type",
5256 		.help = "ICMPv6 type",
5257 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5258 			     item_param),
5259 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5260 					     type)),
5261 	},
5262 	[ITEM_ICMP6_CODE] = {
5263 		.name = "code",
5264 		.help = "ICMPv6 code",
5265 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5266 			     item_param),
5267 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5268 					     code)),
5269 	},
5270 	[ITEM_ICMP6_ECHO_REQUEST] = {
5271 		.name = "icmp6_echo_request",
5272 		.help = "match ICMPv6 echo request",
5273 		.priv = PRIV_ITEM(ICMP6_ECHO_REQUEST,
5274 				  sizeof(struct rte_flow_item_icmp6_echo)),
5275 		.next = NEXT(item_icmp6_echo_request),
5276 		.call = parse_vc,
5277 	},
5278 	[ITEM_ICMP6_ECHO_REQUEST_ID] = {
5279 		.name = "ident",
5280 		.help = "ICMPv6 echo request identifier",
5281 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5282 			     item_param),
5283 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5284 					     hdr.identifier)),
5285 	},
5286 	[ITEM_ICMP6_ECHO_REQUEST_SEQ] = {
5287 		.name = "seq",
5288 		.help = "ICMPv6 echo request sequence",
5289 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5290 			     item_param),
5291 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5292 					     hdr.sequence)),
5293 	},
5294 	[ITEM_ICMP6_ECHO_REPLY] = {
5295 		.name = "icmp6_echo_reply",
5296 		.help = "match ICMPv6 echo reply",
5297 		.priv = PRIV_ITEM(ICMP6_ECHO_REPLY,
5298 				  sizeof(struct rte_flow_item_icmp6_echo)),
5299 		.next = NEXT(item_icmp6_echo_reply),
5300 		.call = parse_vc,
5301 	},
5302 	[ITEM_ICMP6_ECHO_REPLY_ID] = {
5303 		.name = "ident",
5304 		.help = "ICMPv6 echo reply identifier",
5305 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5306 			     item_param),
5307 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5308 					     hdr.identifier)),
5309 	},
5310 	[ITEM_ICMP6_ECHO_REPLY_SEQ] = {
5311 		.name = "seq",
5312 		.help = "ICMPv6 echo reply sequence",
5313 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5314 			     item_param),
5315 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5316 					     hdr.sequence)),
5317 	},
5318 	[ITEM_ICMP6_ND_NS] = {
5319 		.name = "icmp6_nd_ns",
5320 		.help = "match ICMPv6 neighbor discovery solicitation",
5321 		.priv = PRIV_ITEM(ICMP6_ND_NS,
5322 				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
5323 		.next = NEXT(item_icmp6_nd_ns),
5324 		.call = parse_vc,
5325 	},
5326 	[ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
5327 		.name = "target_addr",
5328 		.help = "target address",
5329 		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
5330 			     item_param),
5331 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
5332 					     target_addr)),
5333 	},
5334 	[ITEM_ICMP6_ND_NA] = {
5335 		.name = "icmp6_nd_na",
5336 		.help = "match ICMPv6 neighbor discovery advertisement",
5337 		.priv = PRIV_ITEM(ICMP6_ND_NA,
5338 				  sizeof(struct rte_flow_item_icmp6_nd_na)),
5339 		.next = NEXT(item_icmp6_nd_na),
5340 		.call = parse_vc,
5341 	},
5342 	[ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
5343 		.name = "target_addr",
5344 		.help = "target address",
5345 		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
5346 			     item_param),
5347 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
5348 					     target_addr)),
5349 	},
5350 	[ITEM_ICMP6_ND_OPT] = {
5351 		.name = "icmp6_nd_opt",
5352 		.help = "match presence of any ICMPv6 neighbor discovery"
5353 			" option",
5354 		.priv = PRIV_ITEM(ICMP6_ND_OPT,
5355 				  sizeof(struct rte_flow_item_icmp6_nd_opt)),
5356 		.next = NEXT(item_icmp6_nd_opt),
5357 		.call = parse_vc,
5358 	},
5359 	[ITEM_ICMP6_ND_OPT_TYPE] = {
5360 		.name = "type",
5361 		.help = "ND option type",
5362 		.next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5363 			     item_param),
5364 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
5365 					     type)),
5366 	},
5367 	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
5368 		.name = "icmp6_nd_opt_sla_eth",
5369 		.help = "match ICMPv6 neighbor discovery source Ethernet"
5370 			" link-layer address option",
5371 		.priv = PRIV_ITEM
5372 			(ICMP6_ND_OPT_SLA_ETH,
5373 			 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
5374 		.next = NEXT(item_icmp6_nd_opt_sla_eth),
5375 		.call = parse_vc,
5376 	},
5377 	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
5378 		.name = "sla",
5379 		.help = "source Ethernet LLA",
5380 		.next = NEXT(item_icmp6_nd_opt_sla_eth,
5381 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5382 		.args = ARGS(ARGS_ENTRY_HTON
5383 			     (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
5384 	},
5385 	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
5386 		.name = "icmp6_nd_opt_tla_eth",
5387 		.help = "match ICMPv6 neighbor discovery target Ethernet"
5388 			" link-layer address option",
5389 		.priv = PRIV_ITEM
5390 			(ICMP6_ND_OPT_TLA_ETH,
5391 			 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
5392 		.next = NEXT(item_icmp6_nd_opt_tla_eth),
5393 		.call = parse_vc,
5394 	},
5395 	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
5396 		.name = "tla",
5397 		.help = "target Ethernet LLA",
5398 		.next = NEXT(item_icmp6_nd_opt_tla_eth,
5399 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5400 		.args = ARGS(ARGS_ENTRY_HTON
5401 			     (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
5402 	},
5403 	[ITEM_META] = {
5404 		.name = "meta",
5405 		.help = "match metadata header",
5406 		.priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
5407 		.next = NEXT(item_meta),
5408 		.call = parse_vc,
5409 	},
5410 	[ITEM_META_DATA] = {
5411 		.name = "data",
5412 		.help = "metadata value",
5413 		.next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
5414 			     item_param),
5415 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
5416 					     data, "\xff\xff\xff\xff")),
5417 	},
5418 	[ITEM_RANDOM] = {
5419 		.name = "random",
5420 		.help = "match random value",
5421 		.priv = PRIV_ITEM(RANDOM, sizeof(struct rte_flow_item_random)),
5422 		.next = NEXT(item_random),
5423 		.call = parse_vc,
5424 	},
5425 	[ITEM_RANDOM_VALUE] = {
5426 		.name = "value",
5427 		.help = "random value",
5428 		.next = NEXT(item_random, NEXT_ENTRY(COMMON_UNSIGNED),
5429 			     item_param),
5430 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_random,
5431 					     value, "\xff\xff")),
5432 	},
5433 	[ITEM_GRE_KEY] = {
5434 		.name = "gre_key",
5435 		.help = "match GRE key",
5436 		.priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
5437 		.next = NEXT(item_gre_key),
5438 		.call = parse_vc,
5439 	},
5440 	[ITEM_GRE_KEY_VALUE] = {
5441 		.name = "value",
5442 		.help = "key value",
5443 		.next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
5444 			     item_param),
5445 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5446 	},
5447 	[ITEM_GRE_OPTION] = {
5448 		.name = "gre_option",
5449 		.help = "match GRE optional fields",
5450 		.priv = PRIV_ITEM(GRE_OPTION,
5451 				  sizeof(struct rte_flow_item_gre_opt)),
5452 		.next = NEXT(item_gre_option),
5453 		.call = parse_vc,
5454 	},
5455 	[ITEM_GRE_OPTION_CHECKSUM] = {
5456 		.name = "checksum",
5457 		.help = "match GRE checksum",
5458 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5459 			     item_param),
5460 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5461 					     checksum_rsvd.checksum)),
5462 	},
5463 	[ITEM_GRE_OPTION_KEY] = {
5464 		.name = "key",
5465 		.help = "match GRE key",
5466 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5467 			     item_param),
5468 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5469 					     key.key)),
5470 	},
5471 	[ITEM_GRE_OPTION_SEQUENCE] = {
5472 		.name = "sequence",
5473 		.help = "match GRE sequence",
5474 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5475 			     item_param),
5476 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5477 					     sequence.sequence)),
5478 	},
5479 	[ITEM_GTP_PSC] = {
5480 		.name = "gtp_psc",
5481 		.help = "match GTP extension header with type 0x85",
5482 		.priv = PRIV_ITEM(GTP_PSC,
5483 				sizeof(struct rte_flow_item_gtp_psc)),
5484 		.next = NEXT(item_gtp_psc),
5485 		.call = parse_vc,
5486 	},
5487 	[ITEM_GTP_PSC_QFI] = {
5488 		.name = "qfi",
5489 		.help = "QoS flow identifier",
5490 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5491 			     item_param),
5492 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5493 					hdr.qfi, 6)),
5494 	},
5495 	[ITEM_GTP_PSC_PDU_T] = {
5496 		.name = "pdu_t",
5497 		.help = "PDU type",
5498 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5499 			     item_param),
5500 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5501 					hdr.type, 4)),
5502 	},
5503 	[ITEM_PPPOES] = {
5504 		.name = "pppoes",
5505 		.help = "match PPPoE session header",
5506 		.priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
5507 		.next = NEXT(item_pppoes),
5508 		.call = parse_vc,
5509 	},
5510 	[ITEM_PPPOED] = {
5511 		.name = "pppoed",
5512 		.help = "match PPPoE discovery header",
5513 		.priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
5514 		.next = NEXT(item_pppoed),
5515 		.call = parse_vc,
5516 	},
5517 	[ITEM_PPPOE_SEID] = {
5518 		.name = "seid",
5519 		.help = "session identifier",
5520 		.next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
5521 			     item_param),
5522 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
5523 					session_id)),
5524 	},
5525 	[ITEM_PPPOE_PROTO_ID] = {
5526 		.name = "pppoe_proto_id",
5527 		.help = "match PPPoE session protocol identifier",
5528 		.priv = PRIV_ITEM(PPPOE_PROTO_ID,
5529 				sizeof(struct rte_flow_item_pppoe_proto_id)),
5530 		.next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
5531 			     item_param),
5532 		.args = ARGS(ARGS_ENTRY_HTON
5533 			     (struct rte_flow_item_pppoe_proto_id, proto_id)),
5534 		.call = parse_vc,
5535 	},
5536 	[ITEM_HIGIG2] = {
5537 		.name = "higig2",
5538 		.help = "matches higig2 header",
5539 		.priv = PRIV_ITEM(HIGIG2,
5540 				sizeof(struct rte_flow_item_higig2_hdr)),
5541 		.next = NEXT(item_higig2),
5542 		.call = parse_vc,
5543 	},
5544 	[ITEM_HIGIG2_CLASSIFICATION] = {
5545 		.name = "classification",
5546 		.help = "matches classification of higig2 header",
5547 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5548 			     item_param),
5549 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5550 					hdr.ppt1.classification)),
5551 	},
5552 	[ITEM_HIGIG2_VID] = {
5553 		.name = "vid",
5554 		.help = "matches vid of higig2 header",
5555 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5556 			     item_param),
5557 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5558 					hdr.ppt1.vid)),
5559 	},
5560 	[ITEM_TAG] = {
5561 		.name = "tag",
5562 		.help = "match tag value",
5563 		.priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
5564 		.next = NEXT(item_tag),
5565 		.call = parse_vc,
5566 	},
5567 	[ITEM_TAG_DATA] = {
5568 		.name = "data",
5569 		.help = "tag value to match",
5570 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5571 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
5572 	},
5573 	[ITEM_TAG_INDEX] = {
5574 		.name = "index",
5575 		.help = "index of tag array to match",
5576 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
5577 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5578 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
5579 	},
5580 	[ITEM_L2TPV3OIP] = {
5581 		.name = "l2tpv3oip",
5582 		.help = "match L2TPv3 over IP header",
5583 		.priv = PRIV_ITEM(L2TPV3OIP,
5584 				  sizeof(struct rte_flow_item_l2tpv3oip)),
5585 		.next = NEXT(item_l2tpv3oip),
5586 		.call = parse_vc,
5587 	},
5588 	[ITEM_L2TPV3OIP_SESSION_ID] = {
5589 		.name = "session_id",
5590 		.help = "session identifier",
5591 		.next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
5592 			     item_param),
5593 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
5594 					     session_id)),
5595 	},
5596 	[ITEM_ESP] = {
5597 		.name = "esp",
5598 		.help = "match ESP header",
5599 		.priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
5600 		.next = NEXT(item_esp),
5601 		.call = parse_vc,
5602 	},
5603 	[ITEM_ESP_SPI] = {
5604 		.name = "spi",
5605 		.help = "security policy index",
5606 		.next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5607 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
5608 				hdr.spi)),
5609 	},
5610 	[ITEM_AH] = {
5611 		.name = "ah",
5612 		.help = "match AH header",
5613 		.priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
5614 		.next = NEXT(item_ah),
5615 		.call = parse_vc,
5616 	},
5617 	[ITEM_AH_SPI] = {
5618 		.name = "spi",
5619 		.help = "security parameters index",
5620 		.next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5621 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
5622 	},
5623 	[ITEM_PFCP] = {
5624 		.name = "pfcp",
5625 		.help = "match pfcp header",
5626 		.priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
5627 		.next = NEXT(item_pfcp),
5628 		.call = parse_vc,
5629 	},
5630 	[ITEM_PFCP_S_FIELD] = {
5631 		.name = "s_field",
5632 		.help = "S field",
5633 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5634 			     item_param),
5635 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
5636 				s_field)),
5637 	},
5638 	[ITEM_PFCP_SEID] = {
5639 		.name = "seid",
5640 		.help = "session endpoint identifier",
5641 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5642 			     item_param),
5643 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
5644 	},
5645 	[ITEM_ECPRI] = {
5646 		.name = "ecpri",
5647 		.help = "match eCPRI header",
5648 		.priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
5649 		.next = NEXT(item_ecpri),
5650 		.call = parse_vc,
5651 	},
5652 	[ITEM_ECPRI_COMMON] = {
5653 		.name = "common",
5654 		.help = "eCPRI common header",
5655 		.next = NEXT(item_ecpri_common),
5656 	},
5657 	[ITEM_ECPRI_COMMON_TYPE] = {
5658 		.name = "type",
5659 		.help = "type of common header",
5660 		.next = NEXT(item_ecpri_common_type),
5661 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
5662 	},
5663 	[ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
5664 		.name = "iq_data",
5665 		.help = "Type #0: IQ Data",
5666 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5667 					ITEM_NEXT)),
5668 		.call = parse_vc_item_ecpri_type,
5669 	},
5670 	[ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
5671 		.name = "pc_id",
5672 		.help = "Physical Channel ID",
5673 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5674 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5675 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5676 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5677 				hdr.type0.pc_id)),
5678 	},
5679 	[ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
5680 		.name = "rtc_ctrl",
5681 		.help = "Type #2: Real-Time Control Data",
5682 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5683 					ITEM_NEXT)),
5684 		.call = parse_vc_item_ecpri_type,
5685 	},
5686 	[ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
5687 		.name = "rtc_id",
5688 		.help = "Real-Time Control Data ID",
5689 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5690 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5691 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5692 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5693 				hdr.type2.rtc_id)),
5694 	},
5695 	[ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
5696 		.name = "delay_measure",
5697 		.help = "Type #5: One-Way Delay Measurement",
5698 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5699 					ITEM_NEXT)),
5700 		.call = parse_vc_item_ecpri_type,
5701 	},
5702 	[ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
5703 		.name = "msr_id",
5704 		.help = "Measurement ID",
5705 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5706 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5707 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5708 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5709 				hdr.type5.msr_id)),
5710 	},
5711 	[ITEM_GENEVE_OPT] = {
5712 		.name = "geneve-opt",
5713 		.help = "GENEVE header option",
5714 		.priv = PRIV_ITEM(GENEVE_OPT,
5715 				  sizeof(struct rte_flow_item_geneve_opt) +
5716 				  ITEM_GENEVE_OPT_DATA_SIZE),
5717 		.next = NEXT(item_geneve_opt),
5718 		.call = parse_vc,
5719 	},
5720 	[ITEM_GENEVE_OPT_CLASS]	= {
5721 		.name = "class",
5722 		.help = "GENEVE option class",
5723 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5724 			     item_param),
5725 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
5726 					     option_class)),
5727 	},
5728 	[ITEM_GENEVE_OPT_TYPE] = {
5729 		.name = "type",
5730 		.help = "GENEVE option type",
5731 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5732 			     item_param),
5733 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
5734 					option_type)),
5735 	},
5736 	[ITEM_GENEVE_OPT_LENGTH] = {
5737 		.name = "length",
5738 		.help = "GENEVE option data length (in 32b words)",
5739 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5740 			     item_param),
5741 		.args = ARGS(ARGS_ENTRY_BOUNDED(
5742 				struct rte_flow_item_geneve_opt, option_len,
5743 				0, 31)),
5744 	},
5745 	[ITEM_GENEVE_OPT_DATA] = {
5746 		.name = "data",
5747 		.help = "GENEVE option data pattern",
5748 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
5749 			     item_param),
5750 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
5751 			     ARGS_ENTRY_ARB(0, 0),
5752 			     ARGS_ENTRY_ARB
5753 				(sizeof(struct rte_flow_item_geneve_opt),
5754 				ITEM_GENEVE_OPT_DATA_SIZE)),
5755 	},
5756 	[ITEM_INTEGRITY] = {
5757 		.name = "integrity",
5758 		.help = "match packet integrity",
5759 		.priv = PRIV_ITEM(INTEGRITY,
5760 				  sizeof(struct rte_flow_item_integrity)),
5761 		.next = NEXT(item_integrity),
5762 		.call = parse_vc,
5763 	},
5764 	[ITEM_INTEGRITY_LEVEL] = {
5765 		.name = "level",
5766 		.help = "integrity level",
5767 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5768 			     item_param),
5769 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
5770 	},
5771 	[ITEM_INTEGRITY_VALUE] = {
5772 		.name = "value",
5773 		.help = "integrity value",
5774 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5775 			     item_param),
5776 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
5777 	},
5778 	[ITEM_CONNTRACK] = {
5779 		.name = "conntrack",
5780 		.help = "conntrack state",
5781 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
5782 			     item_param),
5783 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
5784 	},
5785 	[ITEM_PORT_REPRESENTOR] = {
5786 		.name = "port_representor",
5787 		.help = "match traffic entering the embedded switch from the given ethdev",
5788 		.priv = PRIV_ITEM(PORT_REPRESENTOR,
5789 				  sizeof(struct rte_flow_item_ethdev)),
5790 		.next = NEXT(item_port_representor),
5791 		.call = parse_vc,
5792 	},
5793 	[ITEM_PORT_REPRESENTOR_PORT_ID] = {
5794 		.name = "port_id",
5795 		.help = "ethdev port ID",
5796 		.next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
5797 			     item_param),
5798 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5799 	},
5800 	[ITEM_REPRESENTED_PORT] = {
5801 		.name = "represented_port",
5802 		.help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
5803 		.priv = PRIV_ITEM(REPRESENTED_PORT,
5804 				  sizeof(struct rte_flow_item_ethdev)),
5805 		.next = NEXT(item_represented_port),
5806 		.call = parse_vc,
5807 	},
5808 	[ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
5809 		.name = "ethdev_port_id",
5810 		.help = "ethdev port ID",
5811 		.next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
5812 			     item_param),
5813 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5814 	},
5815 	[ITEM_FLEX] = {
5816 		.name = "flex",
5817 		.help = "match flex header",
5818 		.priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
5819 		.next = NEXT(item_flex),
5820 		.call = parse_vc,
5821 	},
5822 	[ITEM_FLEX_ITEM_HANDLE] = {
5823 		.name = "item",
5824 		.help = "flex item handle",
5825 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5826 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5827 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
5828 	},
5829 	[ITEM_FLEX_PATTERN_HANDLE] = {
5830 		.name = "pattern",
5831 		.help = "flex pattern handle",
5832 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5833 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5834 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
5835 	},
5836 	[ITEM_L2TPV2] = {
5837 		.name = "l2tpv2",
5838 		.help = "match L2TPv2 header",
5839 		.priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
5840 		.next = NEXT(item_l2tpv2),
5841 		.call = parse_vc,
5842 	},
5843 	[ITEM_L2TPV2_TYPE] = {
5844 		.name = "type",
5845 		.help = "type of l2tpv2",
5846 		.next = NEXT(item_l2tpv2_type),
5847 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
5848 	},
5849 	[ITEM_L2TPV2_TYPE_DATA] = {
5850 		.name = "data",
5851 		.help = "Type #7: data message without any options",
5852 		.next = NEXT(item_l2tpv2_type_data),
5853 		.call = parse_vc_item_l2tpv2_type,
5854 	},
5855 	[ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
5856 		.name = "tunnel_id",
5857 		.help = "tunnel identifier",
5858 		.next = NEXT(item_l2tpv2_type_data,
5859 			     NEXT_ENTRY(COMMON_UNSIGNED),
5860 			     item_param),
5861 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5862 					     hdr.type7.tunnel_id)),
5863 	},
5864 	[ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
5865 		.name = "session_id",
5866 		.help = "session identifier",
5867 		.next = NEXT(item_l2tpv2_type_data,
5868 			     NEXT_ENTRY(COMMON_UNSIGNED),
5869 			     item_param),
5870 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5871 					     hdr.type7.session_id)),
5872 	},
5873 	[ITEM_L2TPV2_TYPE_DATA_L] = {
5874 		.name = "data_l",
5875 		.help = "Type #6: data message with length option",
5876 		.next = NEXT(item_l2tpv2_type_data_l),
5877 		.call = parse_vc_item_l2tpv2_type,
5878 	},
5879 	[ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
5880 		.name = "length",
5881 		.help = "message length",
5882 		.next = NEXT(item_l2tpv2_type_data_l,
5883 			     NEXT_ENTRY(COMMON_UNSIGNED),
5884 			     item_param),
5885 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5886 					     hdr.type6.length)),
5887 	},
5888 	[ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
5889 		.name = "tunnel_id",
5890 		.help = "tunnel identifier",
5891 		.next = NEXT(item_l2tpv2_type_data_l,
5892 			     NEXT_ENTRY(COMMON_UNSIGNED),
5893 			     item_param),
5894 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5895 					     hdr.type6.tunnel_id)),
5896 	},
5897 	[ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
5898 		.name = "session_id",
5899 		.help = "session identifier",
5900 		.next = NEXT(item_l2tpv2_type_data_l,
5901 			     NEXT_ENTRY(COMMON_UNSIGNED),
5902 			     item_param),
5903 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5904 					     hdr.type6.session_id)),
5905 	},
5906 	[ITEM_L2TPV2_TYPE_DATA_S] = {
5907 		.name = "data_s",
5908 		.help = "Type #5: data message with ns, nr option",
5909 		.next = NEXT(item_l2tpv2_type_data_s),
5910 		.call = parse_vc_item_l2tpv2_type,
5911 	},
5912 	[ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
5913 		.name = "tunnel_id",
5914 		.help = "tunnel identifier",
5915 		.next = NEXT(item_l2tpv2_type_data_s,
5916 			     NEXT_ENTRY(COMMON_UNSIGNED),
5917 			     item_param),
5918 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5919 					     hdr.type5.tunnel_id)),
5920 	},
5921 	[ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
5922 		.name = "session_id",
5923 		.help = "session identifier",
5924 		.next = NEXT(item_l2tpv2_type_data_s,
5925 			     NEXT_ENTRY(COMMON_UNSIGNED),
5926 			     item_param),
5927 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5928 					     hdr.type5.session_id)),
5929 	},
5930 	[ITEM_L2TPV2_MSG_DATA_S_NS] = {
5931 		.name = "ns",
5932 		.help = "sequence number for message",
5933 		.next = NEXT(item_l2tpv2_type_data_s,
5934 			     NEXT_ENTRY(COMMON_UNSIGNED),
5935 			     item_param),
5936 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5937 					     hdr.type5.ns)),
5938 	},
5939 	[ITEM_L2TPV2_MSG_DATA_S_NR] = {
5940 		.name = "nr",
5941 		.help = "sequence number for next receive message",
5942 		.next = NEXT(item_l2tpv2_type_data_s,
5943 			     NEXT_ENTRY(COMMON_UNSIGNED),
5944 			     item_param),
5945 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5946 					     hdr.type5.nr)),
5947 	},
5948 	[ITEM_L2TPV2_TYPE_DATA_O] = {
5949 		.name = "data_o",
5950 		.help = "Type #4: data message with offset option",
5951 		.next = NEXT(item_l2tpv2_type_data_o),
5952 		.call = parse_vc_item_l2tpv2_type,
5953 	},
5954 	[ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
5955 		.name = "tunnel_id",
5956 		.help = "tunnel identifier",
5957 		.next = NEXT(item_l2tpv2_type_data_o,
5958 			     NEXT_ENTRY(COMMON_UNSIGNED),
5959 			     item_param),
5960 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5961 					     hdr.type4.tunnel_id)),
5962 	},
5963 	[ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
5964 		.name = "session_id",
5965 		.help = "session identifier",
5966 		.next = NEXT(item_l2tpv2_type_data_o,
5967 			     NEXT_ENTRY(COMMON_UNSIGNED),
5968 			     item_param),
5969 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5970 					     hdr.type5.session_id)),
5971 	},
5972 	[ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
5973 		.name = "offset_size",
5974 		.help = "the size of offset padding",
5975 		.next = NEXT(item_l2tpv2_type_data_o,
5976 			     NEXT_ENTRY(COMMON_UNSIGNED),
5977 			     item_param),
5978 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5979 					     hdr.type4.offset_size)),
5980 	},
5981 	[ITEM_L2TPV2_TYPE_DATA_L_S] = {
5982 		.name = "data_l_s",
5983 		.help = "Type #3: data message contains length, ns, nr "
5984 			"options",
5985 		.next = NEXT(item_l2tpv2_type_data_l_s),
5986 		.call = parse_vc_item_l2tpv2_type,
5987 	},
5988 	[ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
5989 		.name = "length",
5990 		.help = "message length",
5991 		.next = NEXT(item_l2tpv2_type_data_l_s,
5992 			     NEXT_ENTRY(COMMON_UNSIGNED),
5993 			     item_param),
5994 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5995 					     hdr.type3.length)),
5996 	},
5997 	[ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
5998 		.name = "tunnel_id",
5999 		.help = "tunnel identifier",
6000 		.next = NEXT(item_l2tpv2_type_data_l_s,
6001 			     NEXT_ENTRY(COMMON_UNSIGNED),
6002 			     item_param),
6003 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6004 					     hdr.type3.tunnel_id)),
6005 	},
6006 	[ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
6007 		.name = "session_id",
6008 		.help = "session identifier",
6009 		.next = NEXT(item_l2tpv2_type_data_l_s,
6010 			     NEXT_ENTRY(COMMON_UNSIGNED),
6011 			     item_param),
6012 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6013 					     hdr.type3.session_id)),
6014 	},
6015 	[ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
6016 		.name = "ns",
6017 		.help = "sequence number for message",
6018 		.next = NEXT(item_l2tpv2_type_data_l_s,
6019 			     NEXT_ENTRY(COMMON_UNSIGNED),
6020 			     item_param),
6021 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6022 					     hdr.type3.ns)),
6023 	},
6024 	[ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
6025 		.name = "nr",
6026 		.help = "sequence number for next receive message",
6027 		.next = NEXT(item_l2tpv2_type_data_l_s,
6028 			     NEXT_ENTRY(COMMON_UNSIGNED),
6029 			     item_param),
6030 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6031 					     hdr.type3.nr)),
6032 	},
6033 	[ITEM_L2TPV2_TYPE_CTRL] = {
6034 		.name = "control",
6035 		.help = "Type #3: conrtol message contains length, ns, nr "
6036 			"options",
6037 		.next = NEXT(item_l2tpv2_type_ctrl),
6038 		.call = parse_vc_item_l2tpv2_type,
6039 	},
6040 	[ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
6041 		.name = "length",
6042 		.help = "message length",
6043 		.next = NEXT(item_l2tpv2_type_ctrl,
6044 			     NEXT_ENTRY(COMMON_UNSIGNED),
6045 			     item_param),
6046 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6047 					     hdr.type3.length)),
6048 	},
6049 	[ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
6050 		.name = "tunnel_id",
6051 		.help = "tunnel identifier",
6052 		.next = NEXT(item_l2tpv2_type_ctrl,
6053 			     NEXT_ENTRY(COMMON_UNSIGNED),
6054 			     item_param),
6055 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6056 					     hdr.type3.tunnel_id)),
6057 	},
6058 	[ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
6059 		.name = "session_id",
6060 		.help = "session identifier",
6061 		.next = NEXT(item_l2tpv2_type_ctrl,
6062 			     NEXT_ENTRY(COMMON_UNSIGNED),
6063 			     item_param),
6064 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6065 					     hdr.type3.session_id)),
6066 	},
6067 	[ITEM_L2TPV2_MSG_CTRL_NS] = {
6068 		.name = "ns",
6069 		.help = "sequence number for message",
6070 		.next = NEXT(item_l2tpv2_type_ctrl,
6071 			     NEXT_ENTRY(COMMON_UNSIGNED),
6072 			     item_param),
6073 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6074 					     hdr.type3.ns)),
6075 	},
6076 	[ITEM_L2TPV2_MSG_CTRL_NR] = {
6077 		.name = "nr",
6078 		.help = "sequence number for next receive message",
6079 		.next = NEXT(item_l2tpv2_type_ctrl,
6080 			     NEXT_ENTRY(COMMON_UNSIGNED),
6081 			     item_param),
6082 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6083 					     hdr.type3.nr)),
6084 	},
6085 	[ITEM_PPP] = {
6086 		.name = "ppp",
6087 		.help = "match PPP header",
6088 		.priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
6089 		.next = NEXT(item_ppp),
6090 		.call = parse_vc,
6091 	},
6092 	[ITEM_PPP_ADDR] = {
6093 		.name = "addr",
6094 		.help = "PPP address",
6095 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6096 			     item_param),
6097 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
6098 	},
6099 	[ITEM_PPP_CTRL] = {
6100 		.name = "ctrl",
6101 		.help = "PPP control",
6102 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6103 			     item_param),
6104 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
6105 	},
6106 	[ITEM_PPP_PROTO_ID] = {
6107 		.name = "proto_id",
6108 		.help = "PPP protocol identifier",
6109 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6110 			     item_param),
6111 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
6112 					hdr.proto_id)),
6113 	},
6114 	[ITEM_METER] = {
6115 		.name = "meter",
6116 		.help = "match meter color",
6117 		.priv = PRIV_ITEM(METER_COLOR,
6118 				  sizeof(struct rte_flow_item_meter_color)),
6119 		.next = NEXT(item_meter),
6120 		.call = parse_vc,
6121 	},
6122 	[ITEM_METER_COLOR] = {
6123 		.name = "color",
6124 		.help = "meter color",
6125 		.next = NEXT(item_meter,
6126 			     NEXT_ENTRY(ITEM_METER_COLOR_NAME),
6127 			     item_param),
6128 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_meter_color,
6129 					color)),
6130 	},
6131 	[ITEM_METER_COLOR_NAME] = {
6132 		.name = "color_name",
6133 		.help = "meter color name",
6134 		.call = parse_meter_color,
6135 		.comp = comp_meter_color,
6136 	},
6137 	[ITEM_QUOTA] = {
6138 		.name = "quota",
6139 		.help = "match quota",
6140 		.priv = PRIV_ITEM(QUOTA, sizeof(struct rte_flow_item_quota)),
6141 		.next = NEXT(item_quota),
6142 		.call = parse_vc
6143 	},
6144 	[ITEM_QUOTA_STATE] = {
6145 		.name = "quota_state",
6146 		.help = "quota state",
6147 		.next = NEXT(item_quota, NEXT_ENTRY(ITEM_QUOTA_STATE_NAME),
6148 			     NEXT_ENTRY(ITEM_PARAM_SPEC, ITEM_PARAM_MASK)),
6149 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_quota, state))
6150 	},
6151 	[ITEM_QUOTA_STATE_NAME] = {
6152 		.name = "state_name",
6153 		.help = "quota state name",
6154 		.call = parse_quota_state_name,
6155 		.comp = comp_quota_state_name
6156 	},
6157 	[ITEM_IB_BTH] = {
6158 		.name = "ib_bth",
6159 		.help = "match ib bth fields",
6160 		.priv = PRIV_ITEM(IB_BTH,
6161 				  sizeof(struct rte_flow_item_ib_bth)),
6162 		.next = NEXT(item_ib_bth),
6163 		.call = parse_vc,
6164 	},
6165 	[ITEM_IB_BTH_OPCODE] = {
6166 		.name = "opcode",
6167 		.help = "match ib bth opcode",
6168 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6169 				 item_param),
6170 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6171 						 hdr.opcode)),
6172 	},
6173 	[ITEM_IB_BTH_PKEY] = {
6174 		.name = "pkey",
6175 		.help = "partition key",
6176 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6177 				 item_param),
6178 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6179 						 hdr.pkey)),
6180 	},
6181 	[ITEM_IB_BTH_DST_QPN] = {
6182 		.name = "dst_qp",
6183 		.help = "destination qp",
6184 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6185 				 item_param),
6186 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6187 						 hdr.dst_qp)),
6188 	},
6189 	[ITEM_IB_BTH_PSN] = {
6190 		.name = "psn",
6191 		.help = "packet sequence number",
6192 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6193 				 item_param),
6194 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6195 						 hdr.psn)),
6196 	},
6197 	[ITEM_PTYPE] = {
6198 		.name = "ptype",
6199 		.help = "match L2/L3/L4 and tunnel information",
6200 		.priv = PRIV_ITEM(PTYPE,
6201 				  sizeof(struct rte_flow_item_ptype)),
6202 		.next = NEXT(item_ptype),
6203 		.call = parse_vc,
6204 	},
6205 	[ITEM_PTYPE_VALUE] = {
6206 		.name = "packet_type",
6207 		.help = "packet type as defined in rte_mbuf_ptype",
6208 		.next = NEXT(item_ptype, NEXT_ENTRY(COMMON_UNSIGNED),
6209 			     item_param),
6210 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ptype, packet_type)),
6211 	},
6212 	[ITEM_NSH] = {
6213 		.name = "nsh",
6214 		.help = "match NSH header",
6215 		.priv = PRIV_ITEM(NSH,
6216 				  sizeof(struct rte_flow_item_nsh)),
6217 		.next = NEXT(item_nsh),
6218 		.call = parse_vc,
6219 	},
6220 	[ITEM_COMPARE] = {
6221 		.name = "compare",
6222 		.help = "match with the comparison result",
6223 		.priv = PRIV_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
6224 		.next = NEXT(NEXT_ENTRY(ITEM_COMPARE_OP)),
6225 		.call = parse_vc,
6226 	},
6227 	[ITEM_COMPARE_OP] = {
6228 		.name = "op",
6229 		.help = "operation type",
6230 		.next = NEXT(item_compare_field,
6231 			NEXT_ENTRY(ITEM_COMPARE_OP_VALUE), item_param),
6232 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, operation)),
6233 	},
6234 	[ITEM_COMPARE_OP_VALUE] = {
6235 		.name = "{operation}",
6236 		.help = "operation type value",
6237 		.call = parse_vc_compare_op,
6238 		.comp = comp_set_compare_op,
6239 	},
6240 	[ITEM_COMPARE_FIELD_A_TYPE] = {
6241 		.name = "a_type",
6242 		.help = "compared field type",
6243 		.next = NEXT(compare_field_a,
6244 			NEXT_ENTRY(ITEM_COMPARE_FIELD_A_TYPE_VALUE), item_param),
6245 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.field)),
6246 	},
6247 	[ITEM_COMPARE_FIELD_A_TYPE_VALUE] = {
6248 		.name = "{a_type}",
6249 		.help = "compared field type value",
6250 		.call = parse_vc_compare_field_id,
6251 		.comp = comp_set_compare_field_id,
6252 	},
6253 	[ITEM_COMPARE_FIELD_A_LEVEL] = {
6254 		.name = "a_level",
6255 		.help = "compared field level",
6256 		.next = NEXT(compare_field_a,
6257 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_A_LEVEL_VALUE), item_param),
6258 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.level)),
6259 	},
6260 	[ITEM_COMPARE_FIELD_A_LEVEL_VALUE] = {
6261 		.name = "{a_level}",
6262 		.help = "compared field level value",
6263 		.call = parse_vc_compare_field_level,
6264 		.comp = comp_none,
6265 	},
6266 	[ITEM_COMPARE_FIELD_A_TAG_INDEX] = {
6267 		.name = "a_tag_index",
6268 		.help = "compared field tag array",
6269 		.next = NEXT(compare_field_a,
6270 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6271 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6272 					a.tag_index)),
6273 	},
6274 	[ITEM_COMPARE_FIELD_A_TYPE_ID] = {
6275 		.name = "a_type_id",
6276 		.help = "compared field type ID",
6277 		.next = NEXT(compare_field_a,
6278 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6279 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6280 					a.type)),
6281 	},
6282 	[ITEM_COMPARE_FIELD_A_CLASS_ID] = {
6283 		.name = "a_class",
6284 		.help = "compared field class ID",
6285 		.next = NEXT(compare_field_a,
6286 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6287 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6288 					     a.class_id)),
6289 	},
6290 	[ITEM_COMPARE_FIELD_A_OFFSET] = {
6291 		.name = "a_offset",
6292 		.help = "compared field bit offset",
6293 		.next = NEXT(compare_field_a,
6294 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6295 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6296 					a.offset)),
6297 	},
6298 	[ITEM_COMPARE_FIELD_B_TYPE] = {
6299 		.name = "b_type",
6300 		.help = "comparator field type",
6301 		.next = NEXT(compare_field_b,
6302 			NEXT_ENTRY(ITEM_COMPARE_FIELD_B_TYPE_VALUE), item_param),
6303 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6304 					b.field)),
6305 	},
6306 	[ITEM_COMPARE_FIELD_B_TYPE_VALUE] = {
6307 		.name = "{b_type}",
6308 		.help = "comparator field type value",
6309 		.call = parse_vc_compare_field_id,
6310 		.comp = comp_set_compare_field_id,
6311 	},
6312 	[ITEM_COMPARE_FIELD_B_LEVEL] = {
6313 		.name = "b_level",
6314 		.help = "comparator field level",
6315 		.next = NEXT(compare_field_b,
6316 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_B_LEVEL_VALUE), item_param),
6317 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6318 					b.level)),
6319 	},
6320 	[ITEM_COMPARE_FIELD_B_LEVEL_VALUE] = {
6321 		.name = "{b_level}",
6322 		.help = "comparator field level value",
6323 		.call = parse_vc_compare_field_level,
6324 		.comp = comp_none,
6325 	},
6326 	[ITEM_COMPARE_FIELD_B_TAG_INDEX] = {
6327 		.name = "b_tag_index",
6328 		.help = "comparator field tag array",
6329 		.next = NEXT(compare_field_b,
6330 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6331 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6332 					b.tag_index)),
6333 	},
6334 	[ITEM_COMPARE_FIELD_B_TYPE_ID] = {
6335 		.name = "b_type_id",
6336 		.help = "comparator field type ID",
6337 		.next = NEXT(compare_field_b,
6338 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6339 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6340 					b.type)),
6341 	},
6342 	[ITEM_COMPARE_FIELD_B_CLASS_ID] = {
6343 		.name = "b_class",
6344 		.help = "comparator field class ID",
6345 		.next = NEXT(compare_field_b,
6346 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6347 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6348 					     b.class_id)),
6349 	},
6350 	[ITEM_COMPARE_FIELD_B_OFFSET] = {
6351 		.name = "b_offset",
6352 		.help = "comparator field bit offset",
6353 		.next = NEXT(compare_field_b,
6354 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6355 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6356 					b.offset)),
6357 	},
6358 	[ITEM_COMPARE_FIELD_B_VALUE] = {
6359 		.name = "b_value",
6360 		.help = "comparator immediate value",
6361 		.next = NEXT(compare_field_b,
6362 			     NEXT_ENTRY(COMMON_HEX), item_param),
6363 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
6364 			     ARGS_ENTRY_ARB(0, 0),
6365 			     ARGS_ENTRY(struct rte_flow_item_compare,
6366 					b.value)),
6367 	},
6368 	[ITEM_COMPARE_FIELD_B_POINTER] = {
6369 		.name = "b_ptr",
6370 		.help = "pointer to comparator immediate value",
6371 		.next = NEXT(compare_field_b,
6372 			     NEXT_ENTRY(COMMON_HEX), item_param),
6373 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6374 					b.pvalue),
6375 			     ARGS_ENTRY_ARB(0, 0),
6376 			     ARGS_ENTRY_ARB
6377 				(sizeof(struct rte_flow_item_compare),
6378 				 FLOW_FIELD_PATTERN_SIZE)),
6379 	},
6380 	[ITEM_COMPARE_FIELD_WIDTH] = {
6381 		.name = "width",
6382 		.help = "number of bits to compare",
6383 		.next = NEXT(item_compare_field,
6384 			NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6385 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6386 					width)),
6387 	},
6388 
6389 	/* Validate/create actions. */
6390 	[ACTIONS] = {
6391 		.name = "actions",
6392 		.help = "submit a list of associated actions",
6393 		.next = NEXT(next_action),
6394 		.call = parse_vc,
6395 	},
6396 	[ACTION_NEXT] = {
6397 		.name = "/",
6398 		.help = "specify next action",
6399 		.next = NEXT(next_action),
6400 	},
6401 	[ACTION_END] = {
6402 		.name = "end",
6403 		.help = "end list of actions",
6404 		.priv = PRIV_ACTION(END, 0),
6405 		.call = parse_vc,
6406 	},
6407 	[ACTION_VOID] = {
6408 		.name = "void",
6409 		.help = "no-op action",
6410 		.priv = PRIV_ACTION(VOID, 0),
6411 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6412 		.call = parse_vc,
6413 	},
6414 	[ACTION_PASSTHRU] = {
6415 		.name = "passthru",
6416 		.help = "let subsequent rule process matched packets",
6417 		.priv = PRIV_ACTION(PASSTHRU, 0),
6418 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6419 		.call = parse_vc,
6420 	},
6421 	[ACTION_SKIP_CMAN] = {
6422 		.name = "skip_cman",
6423 		.help = "bypass cman on received packets",
6424 		.priv = PRIV_ACTION(SKIP_CMAN, 0),
6425 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6426 		.call = parse_vc,
6427 	},
6428 	[ACTION_JUMP] = {
6429 		.name = "jump",
6430 		.help = "redirect traffic to a given group",
6431 		.priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
6432 		.next = NEXT(action_jump),
6433 		.call = parse_vc,
6434 	},
6435 	[ACTION_JUMP_GROUP] = {
6436 		.name = "group",
6437 		.help = "group to redirect traffic to",
6438 		.next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
6439 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
6440 		.call = parse_vc_conf,
6441 	},
6442 	[ACTION_MARK] = {
6443 		.name = "mark",
6444 		.help = "attach 32 bit value to packets",
6445 		.priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
6446 		.next = NEXT(action_mark),
6447 		.call = parse_vc,
6448 	},
6449 	[ACTION_MARK_ID] = {
6450 		.name = "id",
6451 		.help = "32 bit value to return with packets",
6452 		.next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6453 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
6454 		.call = parse_vc_conf,
6455 	},
6456 	[ACTION_FLAG] = {
6457 		.name = "flag",
6458 		.help = "flag packets",
6459 		.priv = PRIV_ACTION(FLAG, 0),
6460 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6461 		.call = parse_vc,
6462 	},
6463 	[ACTION_QUEUE] = {
6464 		.name = "queue",
6465 		.help = "assign packets to a given queue index",
6466 		.priv = PRIV_ACTION(QUEUE,
6467 				    sizeof(struct rte_flow_action_queue)),
6468 		.next = NEXT(action_queue),
6469 		.call = parse_vc,
6470 	},
6471 	[ACTION_QUEUE_INDEX] = {
6472 		.name = "index",
6473 		.help = "queue index to use",
6474 		.next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
6475 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
6476 		.call = parse_vc_conf,
6477 	},
6478 	[ACTION_DROP] = {
6479 		.name = "drop",
6480 		.help = "drop packets (note: passthru has priority)",
6481 		.priv = PRIV_ACTION(DROP, 0),
6482 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6483 		.call = parse_vc,
6484 	},
6485 	[ACTION_COUNT] = {
6486 		.name = "count",
6487 		.help = "enable counters for this rule",
6488 		.priv = PRIV_ACTION(COUNT,
6489 				    sizeof(struct rte_flow_action_count)),
6490 		.next = NEXT(action_count),
6491 		.call = parse_vc,
6492 	},
6493 	[ACTION_COUNT_ID] = {
6494 		.name = "identifier",
6495 		.help = "counter identifier to use",
6496 		.next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
6497 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
6498 		.call = parse_vc_conf,
6499 	},
6500 	[ACTION_RSS] = {
6501 		.name = "rss",
6502 		.help = "spread packets among several queues",
6503 		.priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
6504 		.next = NEXT(action_rss),
6505 		.call = parse_vc_action_rss,
6506 	},
6507 	[ACTION_RSS_FUNC] = {
6508 		.name = "func",
6509 		.help = "RSS hash function to apply",
6510 		.next = NEXT(action_rss,
6511 			     NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
6512 					ACTION_RSS_FUNC_TOEPLITZ,
6513 					ACTION_RSS_FUNC_SIMPLE_XOR,
6514 					ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
6515 	},
6516 	[ACTION_RSS_FUNC_DEFAULT] = {
6517 		.name = "default",
6518 		.help = "default hash function",
6519 		.call = parse_vc_action_rss_func,
6520 	},
6521 	[ACTION_RSS_FUNC_TOEPLITZ] = {
6522 		.name = "toeplitz",
6523 		.help = "Toeplitz hash function",
6524 		.call = parse_vc_action_rss_func,
6525 	},
6526 	[ACTION_RSS_FUNC_SIMPLE_XOR] = {
6527 		.name = "simple_xor",
6528 		.help = "simple XOR hash function",
6529 		.call = parse_vc_action_rss_func,
6530 	},
6531 	[ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
6532 		.name = "symmetric_toeplitz",
6533 		.help = "Symmetric Toeplitz hash function",
6534 		.call = parse_vc_action_rss_func,
6535 	},
6536 	[ACTION_RSS_LEVEL] = {
6537 		.name = "level",
6538 		.help = "encapsulation level for \"types\"",
6539 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6540 		.args = ARGS(ARGS_ENTRY_ARB
6541 			     (offsetof(struct action_rss_data, conf) +
6542 			      offsetof(struct rte_flow_action_rss, level),
6543 			      sizeof(((struct rte_flow_action_rss *)0)->
6544 				     level))),
6545 	},
6546 	[ACTION_RSS_TYPES] = {
6547 		.name = "types",
6548 		.help = "specific RSS hash types",
6549 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
6550 	},
6551 	[ACTION_RSS_TYPE] = {
6552 		.name = "{type}",
6553 		.help = "RSS hash type",
6554 		.call = parse_vc_action_rss_type,
6555 		.comp = comp_vc_action_rss_type,
6556 	},
6557 	[ACTION_RSS_KEY] = {
6558 		.name = "key",
6559 		.help = "RSS hash key",
6560 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
6561 		.args = ARGS(ARGS_ENTRY_ARB
6562 			     (offsetof(struct action_rss_data, conf) +
6563 			      offsetof(struct rte_flow_action_rss, key),
6564 			      sizeof(((struct rte_flow_action_rss *)0)->key)),
6565 			     ARGS_ENTRY_ARB
6566 			     (offsetof(struct action_rss_data, conf) +
6567 			      offsetof(struct rte_flow_action_rss, key_len),
6568 			      sizeof(((struct rte_flow_action_rss *)0)->
6569 				     key_len)),
6570 			     ARGS_ENTRY(struct action_rss_data, key)),
6571 	},
6572 	[ACTION_RSS_KEY_LEN] = {
6573 		.name = "key_len",
6574 		.help = "RSS hash key length in bytes",
6575 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6576 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
6577 			     (offsetof(struct action_rss_data, conf) +
6578 			      offsetof(struct rte_flow_action_rss, key_len),
6579 			      sizeof(((struct rte_flow_action_rss *)0)->
6580 				     key_len),
6581 			      0,
6582 			      RSS_HASH_KEY_LENGTH)),
6583 	},
6584 	[ACTION_RSS_QUEUES] = {
6585 		.name = "queues",
6586 		.help = "queue indices to use",
6587 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
6588 		.call = parse_vc_conf,
6589 	},
6590 	[ACTION_RSS_QUEUE] = {
6591 		.name = "{queue}",
6592 		.help = "queue index",
6593 		.call = parse_vc_action_rss_queue,
6594 		.comp = comp_vc_action_rss_queue,
6595 	},
6596 	[ACTION_PF] = {
6597 		.name = "pf",
6598 		.help = "direct traffic to physical function",
6599 		.priv = PRIV_ACTION(PF, 0),
6600 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6601 		.call = parse_vc,
6602 	},
6603 	[ACTION_VF] = {
6604 		.name = "vf",
6605 		.help = "direct traffic to a virtual function ID",
6606 		.priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
6607 		.next = NEXT(action_vf),
6608 		.call = parse_vc,
6609 	},
6610 	[ACTION_VF_ORIGINAL] = {
6611 		.name = "original",
6612 		.help = "use original VF ID if possible",
6613 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
6614 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
6615 					   original, 1)),
6616 		.call = parse_vc_conf,
6617 	},
6618 	[ACTION_VF_ID] = {
6619 		.name = "id",
6620 		.help = "VF ID",
6621 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
6622 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
6623 		.call = parse_vc_conf,
6624 	},
6625 	[ACTION_PORT_ID] = {
6626 		.name = "port_id",
6627 		.help = "direct matching traffic to a given DPDK port ID",
6628 		.priv = PRIV_ACTION(PORT_ID,
6629 				    sizeof(struct rte_flow_action_port_id)),
6630 		.next = NEXT(action_port_id),
6631 		.call = parse_vc,
6632 	},
6633 	[ACTION_PORT_ID_ORIGINAL] = {
6634 		.name = "original",
6635 		.help = "use original DPDK port ID if possible",
6636 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
6637 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
6638 					   original, 1)),
6639 		.call = parse_vc_conf,
6640 	},
6641 	[ACTION_PORT_ID_ID] = {
6642 		.name = "id",
6643 		.help = "DPDK port ID",
6644 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
6645 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
6646 		.call = parse_vc_conf,
6647 	},
6648 	[ACTION_METER] = {
6649 		.name = "meter",
6650 		.help = "meter the directed packets at given id",
6651 		.priv = PRIV_ACTION(METER,
6652 				    sizeof(struct rte_flow_action_meter)),
6653 		.next = NEXT(action_meter),
6654 		.call = parse_vc,
6655 	},
6656 	[ACTION_METER_COLOR] = {
6657 		.name = "color",
6658 		.help = "meter color for the packets",
6659 		.priv = PRIV_ACTION(METER_COLOR,
6660 				sizeof(struct rte_flow_action_meter_color)),
6661 		.next = NEXT(action_meter_color),
6662 		.call = parse_vc,
6663 	},
6664 	[ACTION_METER_COLOR_TYPE] = {
6665 		.name = "type",
6666 		.help = "specific meter color",
6667 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
6668 				NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
6669 					ACTION_METER_COLOR_YELLOW,
6670 					ACTION_METER_COLOR_RED)),
6671 	},
6672 	[ACTION_METER_COLOR_GREEN] = {
6673 		.name = "green",
6674 		.help = "meter color green",
6675 		.call = parse_vc_action_meter_color_type,
6676 	},
6677 	[ACTION_METER_COLOR_YELLOW] = {
6678 		.name = "yellow",
6679 		.help = "meter color yellow",
6680 		.call = parse_vc_action_meter_color_type,
6681 	},
6682 	[ACTION_METER_COLOR_RED] = {
6683 		.name = "red",
6684 		.help = "meter color red",
6685 		.call = parse_vc_action_meter_color_type,
6686 	},
6687 	[ACTION_METER_ID] = {
6688 		.name = "mtr_id",
6689 		.help = "meter id to use",
6690 		.next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
6691 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
6692 		.call = parse_vc_conf,
6693 	},
6694 	[ACTION_METER_MARK] = {
6695 		.name = "meter_mark",
6696 		.help = "meter the directed packets using profile and policy",
6697 		.priv = PRIV_ACTION(METER_MARK,
6698 				    sizeof(struct rte_flow_action_meter_mark)),
6699 		.next = NEXT(action_meter_mark),
6700 		.call = parse_vc,
6701 	},
6702 	[ACTION_METER_PROFILE] = {
6703 		.name = "mtr_profile",
6704 		.help = "meter profile id to use",
6705 		.next = NEXT(NEXT_ENTRY(ACTION_METER_PROFILE_ID2PTR)),
6706 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6707 	},
6708 	[ACTION_METER_PROFILE_ID2PTR] = {
6709 		.name = "{mtr_profile_id}",
6710 		.type = "PROFILE_ID",
6711 		.help = "meter profile id",
6712 		.next = NEXT(action_meter_mark),
6713 		.call = parse_meter_profile_id2ptr,
6714 		.comp = comp_none,
6715 	},
6716 	[ACTION_METER_POLICY] = {
6717 		.name = "mtr_policy",
6718 		.help = "meter policy id to use",
6719 		.next = NEXT(NEXT_ENTRY(ACTION_METER_POLICY_ID2PTR)),
6720 		ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6721 	},
6722 	[ACTION_METER_POLICY_ID2PTR] = {
6723 		.name = "{mtr_policy_id}",
6724 		.type = "POLICY_ID",
6725 		.help = "meter policy id",
6726 		.next = NEXT(action_meter_mark),
6727 		.call = parse_meter_policy_id2ptr,
6728 		.comp = comp_none,
6729 	},
6730 	[ACTION_METER_COLOR_MODE] = {
6731 		.name = "mtr_color_mode",
6732 		.help = "meter color awareness mode",
6733 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6734 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, color_mode)),
6735 		.call = parse_vc_conf,
6736 	},
6737 	[ACTION_METER_STATE] = {
6738 		.name = "mtr_state",
6739 		.help = "meter state",
6740 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6741 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, state)),
6742 		.call = parse_vc_conf,
6743 	},
6744 	[ACTION_OF_DEC_NW_TTL] = {
6745 		.name = "of_dec_nw_ttl",
6746 		.help = "OpenFlow's OFPAT_DEC_NW_TTL",
6747 		.priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
6748 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6749 		.call = parse_vc,
6750 	},
6751 	[ACTION_OF_POP_VLAN] = {
6752 		.name = "of_pop_vlan",
6753 		.help = "OpenFlow's OFPAT_POP_VLAN",
6754 		.priv = PRIV_ACTION(OF_POP_VLAN, 0),
6755 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6756 		.call = parse_vc,
6757 	},
6758 	[ACTION_OF_PUSH_VLAN] = {
6759 		.name = "of_push_vlan",
6760 		.help = "OpenFlow's OFPAT_PUSH_VLAN",
6761 		.priv = PRIV_ACTION
6762 			(OF_PUSH_VLAN,
6763 			 sizeof(struct rte_flow_action_of_push_vlan)),
6764 		.next = NEXT(action_of_push_vlan),
6765 		.call = parse_vc,
6766 	},
6767 	[ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
6768 		.name = "ethertype",
6769 		.help = "EtherType",
6770 		.next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
6771 		.args = ARGS(ARGS_ENTRY_HTON
6772 			     (struct rte_flow_action_of_push_vlan,
6773 			      ethertype)),
6774 		.call = parse_vc_conf,
6775 	},
6776 	[ACTION_OF_SET_VLAN_VID] = {
6777 		.name = "of_set_vlan_vid",
6778 		.help = "OpenFlow's OFPAT_SET_VLAN_VID",
6779 		.priv = PRIV_ACTION
6780 			(OF_SET_VLAN_VID,
6781 			 sizeof(struct rte_flow_action_of_set_vlan_vid)),
6782 		.next = NEXT(action_of_set_vlan_vid),
6783 		.call = parse_vc,
6784 	},
6785 	[ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
6786 		.name = "vlan_vid",
6787 		.help = "VLAN id",
6788 		.next = NEXT(action_of_set_vlan_vid,
6789 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6790 		.args = ARGS(ARGS_ENTRY_HTON
6791 			     (struct rte_flow_action_of_set_vlan_vid,
6792 			      vlan_vid)),
6793 		.call = parse_vc_conf,
6794 	},
6795 	[ACTION_OF_SET_VLAN_PCP] = {
6796 		.name = "of_set_vlan_pcp",
6797 		.help = "OpenFlow's OFPAT_SET_VLAN_PCP",
6798 		.priv = PRIV_ACTION
6799 			(OF_SET_VLAN_PCP,
6800 			 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
6801 		.next = NEXT(action_of_set_vlan_pcp),
6802 		.call = parse_vc,
6803 	},
6804 	[ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
6805 		.name = "vlan_pcp",
6806 		.help = "VLAN priority",
6807 		.next = NEXT(action_of_set_vlan_pcp,
6808 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6809 		.args = ARGS(ARGS_ENTRY_HTON
6810 			     (struct rte_flow_action_of_set_vlan_pcp,
6811 			      vlan_pcp)),
6812 		.call = parse_vc_conf,
6813 	},
6814 	[ACTION_OF_POP_MPLS] = {
6815 		.name = "of_pop_mpls",
6816 		.help = "OpenFlow's OFPAT_POP_MPLS",
6817 		.priv = PRIV_ACTION(OF_POP_MPLS,
6818 				    sizeof(struct rte_flow_action_of_pop_mpls)),
6819 		.next = NEXT(action_of_pop_mpls),
6820 		.call = parse_vc,
6821 	},
6822 	[ACTION_OF_POP_MPLS_ETHERTYPE] = {
6823 		.name = "ethertype",
6824 		.help = "EtherType",
6825 		.next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6826 		.args = ARGS(ARGS_ENTRY_HTON
6827 			     (struct rte_flow_action_of_pop_mpls,
6828 			      ethertype)),
6829 		.call = parse_vc_conf,
6830 	},
6831 	[ACTION_OF_PUSH_MPLS] = {
6832 		.name = "of_push_mpls",
6833 		.help = "OpenFlow's OFPAT_PUSH_MPLS",
6834 		.priv = PRIV_ACTION
6835 			(OF_PUSH_MPLS,
6836 			 sizeof(struct rte_flow_action_of_push_mpls)),
6837 		.next = NEXT(action_of_push_mpls),
6838 		.call = parse_vc,
6839 	},
6840 	[ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
6841 		.name = "ethertype",
6842 		.help = "EtherType",
6843 		.next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6844 		.args = ARGS(ARGS_ENTRY_HTON
6845 			     (struct rte_flow_action_of_push_mpls,
6846 			      ethertype)),
6847 		.call = parse_vc_conf,
6848 	},
6849 	[ACTION_VXLAN_ENCAP] = {
6850 		.name = "vxlan_encap",
6851 		.help = "VXLAN encapsulation, uses configuration set by \"set"
6852 			" vxlan\"",
6853 		.priv = PRIV_ACTION(VXLAN_ENCAP,
6854 				    sizeof(struct action_vxlan_encap_data)),
6855 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6856 		.call = parse_vc_action_vxlan_encap,
6857 	},
6858 	[ACTION_VXLAN_DECAP] = {
6859 		.name = "vxlan_decap",
6860 		.help = "Performs a decapsulation action by stripping all"
6861 			" headers of the VXLAN tunnel network overlay from the"
6862 			" matched flow.",
6863 		.priv = PRIV_ACTION(VXLAN_DECAP, 0),
6864 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6865 		.call = parse_vc,
6866 	},
6867 	[ACTION_NVGRE_ENCAP] = {
6868 		.name = "nvgre_encap",
6869 		.help = "NVGRE encapsulation, uses configuration set by \"set"
6870 			" nvgre\"",
6871 		.priv = PRIV_ACTION(NVGRE_ENCAP,
6872 				    sizeof(struct action_nvgre_encap_data)),
6873 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6874 		.call = parse_vc_action_nvgre_encap,
6875 	},
6876 	[ACTION_NVGRE_DECAP] = {
6877 		.name = "nvgre_decap",
6878 		.help = "Performs a decapsulation action by stripping all"
6879 			" headers of the NVGRE tunnel network overlay from the"
6880 			" matched flow.",
6881 		.priv = PRIV_ACTION(NVGRE_DECAP, 0),
6882 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6883 		.call = parse_vc,
6884 	},
6885 	[ACTION_L2_ENCAP] = {
6886 		.name = "l2_encap",
6887 		.help = "l2 encap, uses configuration set by"
6888 			" \"set l2_encap\"",
6889 		.priv = PRIV_ACTION(RAW_ENCAP,
6890 				    sizeof(struct action_raw_encap_data)),
6891 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6892 		.call = parse_vc_action_l2_encap,
6893 	},
6894 	[ACTION_L2_DECAP] = {
6895 		.name = "l2_decap",
6896 		.help = "l2 decap, uses configuration set by"
6897 			" \"set l2_decap\"",
6898 		.priv = PRIV_ACTION(RAW_DECAP,
6899 				    sizeof(struct action_raw_decap_data)),
6900 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6901 		.call = parse_vc_action_l2_decap,
6902 	},
6903 	[ACTION_MPLSOGRE_ENCAP] = {
6904 		.name = "mplsogre_encap",
6905 		.help = "mplsogre encapsulation, uses configuration set by"
6906 			" \"set mplsogre_encap\"",
6907 		.priv = PRIV_ACTION(RAW_ENCAP,
6908 				    sizeof(struct action_raw_encap_data)),
6909 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6910 		.call = parse_vc_action_mplsogre_encap,
6911 	},
6912 	[ACTION_MPLSOGRE_DECAP] = {
6913 		.name = "mplsogre_decap",
6914 		.help = "mplsogre decapsulation, uses configuration set by"
6915 			" \"set mplsogre_decap\"",
6916 		.priv = PRIV_ACTION(RAW_DECAP,
6917 				    sizeof(struct action_raw_decap_data)),
6918 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6919 		.call = parse_vc_action_mplsogre_decap,
6920 	},
6921 	[ACTION_MPLSOUDP_ENCAP] = {
6922 		.name = "mplsoudp_encap",
6923 		.help = "mplsoudp encapsulation, uses configuration set by"
6924 			" \"set mplsoudp_encap\"",
6925 		.priv = PRIV_ACTION(RAW_ENCAP,
6926 				    sizeof(struct action_raw_encap_data)),
6927 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6928 		.call = parse_vc_action_mplsoudp_encap,
6929 	},
6930 	[ACTION_MPLSOUDP_DECAP] = {
6931 		.name = "mplsoudp_decap",
6932 		.help = "mplsoudp decapsulation, uses configuration set by"
6933 			" \"set mplsoudp_decap\"",
6934 		.priv = PRIV_ACTION(RAW_DECAP,
6935 				    sizeof(struct action_raw_decap_data)),
6936 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6937 		.call = parse_vc_action_mplsoudp_decap,
6938 	},
6939 	[ACTION_SET_IPV4_SRC] = {
6940 		.name = "set_ipv4_src",
6941 		.help = "Set a new IPv4 source address in the outermost"
6942 			" IPv4 header",
6943 		.priv = PRIV_ACTION(SET_IPV4_SRC,
6944 			sizeof(struct rte_flow_action_set_ipv4)),
6945 		.next = NEXT(action_set_ipv4_src),
6946 		.call = parse_vc,
6947 	},
6948 	[ACTION_SET_IPV4_SRC_IPV4_SRC] = {
6949 		.name = "ipv4_addr",
6950 		.help = "new IPv4 source address to set",
6951 		.next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
6952 		.args = ARGS(ARGS_ENTRY_HTON
6953 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
6954 		.call = parse_vc_conf,
6955 	},
6956 	[ACTION_SET_IPV4_DST] = {
6957 		.name = "set_ipv4_dst",
6958 		.help = "Set a new IPv4 destination address in the outermost"
6959 			" IPv4 header",
6960 		.priv = PRIV_ACTION(SET_IPV4_DST,
6961 			sizeof(struct rte_flow_action_set_ipv4)),
6962 		.next = NEXT(action_set_ipv4_dst),
6963 		.call = parse_vc,
6964 	},
6965 	[ACTION_SET_IPV4_DST_IPV4_DST] = {
6966 		.name = "ipv4_addr",
6967 		.help = "new IPv4 destination address to set",
6968 		.next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
6969 		.args = ARGS(ARGS_ENTRY_HTON
6970 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
6971 		.call = parse_vc_conf,
6972 	},
6973 	[ACTION_SET_IPV6_SRC] = {
6974 		.name = "set_ipv6_src",
6975 		.help = "Set a new IPv6 source address in the outermost"
6976 			" IPv6 header",
6977 		.priv = PRIV_ACTION(SET_IPV6_SRC,
6978 			sizeof(struct rte_flow_action_set_ipv6)),
6979 		.next = NEXT(action_set_ipv6_src),
6980 		.call = parse_vc,
6981 	},
6982 	[ACTION_SET_IPV6_SRC_IPV6_SRC] = {
6983 		.name = "ipv6_addr",
6984 		.help = "new IPv6 source address to set",
6985 		.next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
6986 		.args = ARGS(ARGS_ENTRY_HTON
6987 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
6988 		.call = parse_vc_conf,
6989 	},
6990 	[ACTION_SET_IPV6_DST] = {
6991 		.name = "set_ipv6_dst",
6992 		.help = "Set a new IPv6 destination address in the outermost"
6993 			" IPv6 header",
6994 		.priv = PRIV_ACTION(SET_IPV6_DST,
6995 			sizeof(struct rte_flow_action_set_ipv6)),
6996 		.next = NEXT(action_set_ipv6_dst),
6997 		.call = parse_vc,
6998 	},
6999 	[ACTION_SET_IPV6_DST_IPV6_DST] = {
7000 		.name = "ipv6_addr",
7001 		.help = "new IPv6 destination address to set",
7002 		.next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
7003 		.args = ARGS(ARGS_ENTRY_HTON
7004 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
7005 		.call = parse_vc_conf,
7006 	},
7007 	[ACTION_SET_TP_SRC] = {
7008 		.name = "set_tp_src",
7009 		.help = "set a new source port number in the outermost"
7010 			" TCP/UDP header",
7011 		.priv = PRIV_ACTION(SET_TP_SRC,
7012 			sizeof(struct rte_flow_action_set_tp)),
7013 		.next = NEXT(action_set_tp_src),
7014 		.call = parse_vc,
7015 	},
7016 	[ACTION_SET_TP_SRC_TP_SRC] = {
7017 		.name = "port",
7018 		.help = "new source port number to set",
7019 		.next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
7020 		.args = ARGS(ARGS_ENTRY_HTON
7021 			     (struct rte_flow_action_set_tp, port)),
7022 		.call = parse_vc_conf,
7023 	},
7024 	[ACTION_SET_TP_DST] = {
7025 		.name = "set_tp_dst",
7026 		.help = "set a new destination port number in the outermost"
7027 			" TCP/UDP header",
7028 		.priv = PRIV_ACTION(SET_TP_DST,
7029 			sizeof(struct rte_flow_action_set_tp)),
7030 		.next = NEXT(action_set_tp_dst),
7031 		.call = parse_vc,
7032 	},
7033 	[ACTION_SET_TP_DST_TP_DST] = {
7034 		.name = "port",
7035 		.help = "new destination port number to set",
7036 		.next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
7037 		.args = ARGS(ARGS_ENTRY_HTON
7038 			     (struct rte_flow_action_set_tp, port)),
7039 		.call = parse_vc_conf,
7040 	},
7041 	[ACTION_MAC_SWAP] = {
7042 		.name = "mac_swap",
7043 		.help = "Swap the source and destination MAC addresses"
7044 			" in the outermost Ethernet header",
7045 		.priv = PRIV_ACTION(MAC_SWAP, 0),
7046 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7047 		.call = parse_vc,
7048 	},
7049 	[ACTION_DEC_TTL] = {
7050 		.name = "dec_ttl",
7051 		.help = "decrease network TTL if available",
7052 		.priv = PRIV_ACTION(DEC_TTL, 0),
7053 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7054 		.call = parse_vc,
7055 	},
7056 	[ACTION_SET_TTL] = {
7057 		.name = "set_ttl",
7058 		.help = "set ttl value",
7059 		.priv = PRIV_ACTION(SET_TTL,
7060 			sizeof(struct rte_flow_action_set_ttl)),
7061 		.next = NEXT(action_set_ttl),
7062 		.call = parse_vc,
7063 	},
7064 	[ACTION_SET_TTL_TTL] = {
7065 		.name = "ttl_value",
7066 		.help = "new ttl value to set",
7067 		.next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
7068 		.args = ARGS(ARGS_ENTRY_HTON
7069 			     (struct rte_flow_action_set_ttl, ttl_value)),
7070 		.call = parse_vc_conf,
7071 	},
7072 	[ACTION_SET_MAC_SRC] = {
7073 		.name = "set_mac_src",
7074 		.help = "set source mac address",
7075 		.priv = PRIV_ACTION(SET_MAC_SRC,
7076 			sizeof(struct rte_flow_action_set_mac)),
7077 		.next = NEXT(action_set_mac_src),
7078 		.call = parse_vc,
7079 	},
7080 	[ACTION_SET_MAC_SRC_MAC_SRC] = {
7081 		.name = "mac_addr",
7082 		.help = "new source mac address",
7083 		.next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
7084 		.args = ARGS(ARGS_ENTRY_HTON
7085 			     (struct rte_flow_action_set_mac, mac_addr)),
7086 		.call = parse_vc_conf,
7087 	},
7088 	[ACTION_SET_MAC_DST] = {
7089 		.name = "set_mac_dst",
7090 		.help = "set destination mac address",
7091 		.priv = PRIV_ACTION(SET_MAC_DST,
7092 			sizeof(struct rte_flow_action_set_mac)),
7093 		.next = NEXT(action_set_mac_dst),
7094 		.call = parse_vc,
7095 	},
7096 	[ACTION_SET_MAC_DST_MAC_DST] = {
7097 		.name = "mac_addr",
7098 		.help = "new destination mac address to set",
7099 		.next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
7100 		.args = ARGS(ARGS_ENTRY_HTON
7101 			     (struct rte_flow_action_set_mac, mac_addr)),
7102 		.call = parse_vc_conf,
7103 	},
7104 	[ACTION_INC_TCP_SEQ] = {
7105 		.name = "inc_tcp_seq",
7106 		.help = "increase TCP sequence number",
7107 		.priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
7108 		.next = NEXT(action_inc_tcp_seq),
7109 		.call = parse_vc,
7110 	},
7111 	[ACTION_INC_TCP_SEQ_VALUE] = {
7112 		.name = "value",
7113 		.help = "the value to increase TCP sequence number by",
7114 		.next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7115 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7116 		.call = parse_vc_conf,
7117 	},
7118 	[ACTION_DEC_TCP_SEQ] = {
7119 		.name = "dec_tcp_seq",
7120 		.help = "decrease TCP sequence number",
7121 		.priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
7122 		.next = NEXT(action_dec_tcp_seq),
7123 		.call = parse_vc,
7124 	},
7125 	[ACTION_DEC_TCP_SEQ_VALUE] = {
7126 		.name = "value",
7127 		.help = "the value to decrease TCP sequence number by",
7128 		.next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7129 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7130 		.call = parse_vc_conf,
7131 	},
7132 	[ACTION_INC_TCP_ACK] = {
7133 		.name = "inc_tcp_ack",
7134 		.help = "increase TCP acknowledgment number",
7135 		.priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
7136 		.next = NEXT(action_inc_tcp_ack),
7137 		.call = parse_vc,
7138 	},
7139 	[ACTION_INC_TCP_ACK_VALUE] = {
7140 		.name = "value",
7141 		.help = "the value to increase TCP acknowledgment number by",
7142 		.next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7143 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7144 		.call = parse_vc_conf,
7145 	},
7146 	[ACTION_DEC_TCP_ACK] = {
7147 		.name = "dec_tcp_ack",
7148 		.help = "decrease TCP acknowledgment number",
7149 		.priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
7150 		.next = NEXT(action_dec_tcp_ack),
7151 		.call = parse_vc,
7152 	},
7153 	[ACTION_DEC_TCP_ACK_VALUE] = {
7154 		.name = "value",
7155 		.help = "the value to decrease TCP acknowledgment number by",
7156 		.next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7157 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7158 		.call = parse_vc_conf,
7159 	},
7160 	[ACTION_RAW_ENCAP] = {
7161 		.name = "raw_encap",
7162 		.help = "encapsulation data, defined by set raw_encap",
7163 		.priv = PRIV_ACTION(RAW_ENCAP,
7164 			sizeof(struct action_raw_encap_data)),
7165 		.next = NEXT(action_raw_encap),
7166 		.call = parse_vc_action_raw_encap,
7167 	},
7168 	[ACTION_RAW_ENCAP_SIZE] = {
7169 		.name = "size",
7170 		.help = "raw encap size",
7171 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7172 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7173 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_raw_encap, size)),
7174 		.call = parse_vc_conf,
7175 	},
7176 	[ACTION_RAW_ENCAP_INDEX] = {
7177 		.name = "index",
7178 		.help = "the index of raw_encap_confs",
7179 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
7180 	},
7181 	[ACTION_RAW_ENCAP_INDEX_VALUE] = {
7182 		.name = "{index}",
7183 		.type = "UNSIGNED",
7184 		.help = "unsigned integer value",
7185 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7186 		.call = parse_vc_action_raw_encap_index,
7187 		.comp = comp_set_raw_index,
7188 	},
7189 	[ACTION_RAW_DECAP] = {
7190 		.name = "raw_decap",
7191 		.help = "decapsulation data, defined by set raw_encap",
7192 		.priv = PRIV_ACTION(RAW_DECAP,
7193 			sizeof(struct action_raw_decap_data)),
7194 		.next = NEXT(action_raw_decap),
7195 		.call = parse_vc_action_raw_decap,
7196 	},
7197 	[ACTION_RAW_DECAP_INDEX] = {
7198 		.name = "index",
7199 		.help = "the index of raw_encap_confs",
7200 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
7201 	},
7202 	[ACTION_RAW_DECAP_INDEX_VALUE] = {
7203 		.name = "{index}",
7204 		.type = "UNSIGNED",
7205 		.help = "unsigned integer value",
7206 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7207 		.call = parse_vc_action_raw_decap_index,
7208 		.comp = comp_set_raw_index,
7209 	},
7210 	[ACTION_MODIFY_FIELD] = {
7211 		.name = "modify_field",
7212 		.help = "modify destination field with data from source field",
7213 		.priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
7214 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
7215 		.call = parse_vc,
7216 	},
7217 	[ACTION_MODIFY_FIELD_OP] = {
7218 		.name = "op",
7219 		.help = "operation type",
7220 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
7221 			NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
7222 		.call = parse_vc_conf,
7223 	},
7224 	[ACTION_MODIFY_FIELD_OP_VALUE] = {
7225 		.name = "{operation}",
7226 		.help = "operation type value",
7227 		.call = parse_vc_modify_field_op,
7228 		.comp = comp_set_modify_field_op,
7229 	},
7230 	[ACTION_MODIFY_FIELD_DST_TYPE] = {
7231 		.name = "dst_type",
7232 		.help = "destination field type",
7233 		.next = NEXT(action_modify_field_dst,
7234 			NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
7235 		.call = parse_vc_conf,
7236 	},
7237 	[ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
7238 		.name = "{dst_type}",
7239 		.help = "destination field type value",
7240 		.call = parse_vc_modify_field_id,
7241 		.comp = comp_set_modify_field_id,
7242 	},
7243 	[ACTION_MODIFY_FIELD_DST_LEVEL] = {
7244 		.name = "dst_level",
7245 		.help = "destination field level",
7246 		.next = NEXT(action_modify_field_dst,
7247 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)),
7248 		.call = parse_vc_conf,
7249 	},
7250 	[ACTION_MODIFY_FIELD_DST_LEVEL_VALUE] = {
7251 		.name = "{dst_level}",
7252 		.help = "destination field level value",
7253 		.call = parse_vc_modify_field_level,
7254 		.comp = comp_none,
7255 	},
7256 	[ACTION_MODIFY_FIELD_DST_TAG_INDEX] = {
7257 		.name = "dst_tag_index",
7258 		.help = "destination field tag array",
7259 		.next = NEXT(action_modify_field_dst,
7260 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7261 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7262 					dst.tag_index)),
7263 		.call = parse_vc_conf,
7264 	},
7265 	[ACTION_MODIFY_FIELD_DST_TYPE_ID] = {
7266 		.name = "dst_type_id",
7267 		.help = "destination field type ID",
7268 		.next = NEXT(action_modify_field_dst,
7269 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7270 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7271 					dst.type)),
7272 		.call = parse_vc_conf,
7273 	},
7274 	[ACTION_MODIFY_FIELD_DST_CLASS_ID] = {
7275 		.name = "dst_class",
7276 		.help = "destination field class ID",
7277 		.next = NEXT(action_modify_field_dst,
7278 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7279 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7280 					     dst.class_id)),
7281 		.call = parse_vc_conf,
7282 	},
7283 	[ACTION_MODIFY_FIELD_DST_OFFSET] = {
7284 		.name = "dst_offset",
7285 		.help = "destination field bit offset",
7286 		.next = NEXT(action_modify_field_dst,
7287 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7288 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7289 					dst.offset)),
7290 		.call = parse_vc_conf,
7291 	},
7292 	[ACTION_MODIFY_FIELD_SRC_TYPE] = {
7293 		.name = "src_type",
7294 		.help = "source field type",
7295 		.next = NEXT(action_modify_field_src,
7296 			NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
7297 		.call = parse_vc_conf,
7298 	},
7299 	[ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
7300 		.name = "{src_type}",
7301 		.help = "source field type value",
7302 		.call = parse_vc_modify_field_id,
7303 		.comp = comp_set_modify_field_id,
7304 	},
7305 	[ACTION_MODIFY_FIELD_SRC_LEVEL] = {
7306 		.name = "src_level",
7307 		.help = "source field level",
7308 		.next = NEXT(action_modify_field_src,
7309 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)),
7310 		.call = parse_vc_conf,
7311 	},
7312 	[ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE] = {
7313 		.name = "{src_level}",
7314 		.help = "source field level value",
7315 		.call = parse_vc_modify_field_level,
7316 		.comp = comp_none,
7317 	},
7318 	[ACTION_MODIFY_FIELD_SRC_TAG_INDEX] = {
7319 		.name = "stc_tag_index",
7320 		.help = "source field tag array",
7321 		.next = NEXT(action_modify_field_src,
7322 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7323 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7324 					src.tag_index)),
7325 		.call = parse_vc_conf,
7326 	},
7327 	[ACTION_MODIFY_FIELD_SRC_TYPE_ID] = {
7328 		.name = "src_type_id",
7329 		.help = "source field type ID",
7330 		.next = NEXT(action_modify_field_src,
7331 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7332 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7333 					src.type)),
7334 		.call = parse_vc_conf,
7335 	},
7336 	[ACTION_MODIFY_FIELD_SRC_CLASS_ID] = {
7337 		.name = "src_class",
7338 		.help = "source field class ID",
7339 		.next = NEXT(action_modify_field_src,
7340 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7341 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7342 					     src.class_id)),
7343 		.call = parse_vc_conf,
7344 	},
7345 	[ACTION_MODIFY_FIELD_SRC_OFFSET] = {
7346 		.name = "src_offset",
7347 		.help = "source field bit offset",
7348 		.next = NEXT(action_modify_field_src,
7349 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7350 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7351 					src.offset)),
7352 		.call = parse_vc_conf,
7353 	},
7354 	[ACTION_MODIFY_FIELD_SRC_VALUE] = {
7355 		.name = "src_value",
7356 		.help = "source immediate value",
7357 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7358 			     NEXT_ENTRY(COMMON_HEX)),
7359 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
7360 			     ARGS_ENTRY_ARB(0, 0),
7361 			     ARGS_ENTRY(struct rte_flow_action_modify_field,
7362 					src.value)),
7363 		.call = parse_vc_conf,
7364 	},
7365 	[ACTION_MODIFY_FIELD_SRC_POINTER] = {
7366 		.name = "src_ptr",
7367 		.help = "pointer to source immediate value",
7368 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7369 			     NEXT_ENTRY(COMMON_HEX)),
7370 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7371 					src.pvalue),
7372 			     ARGS_ENTRY_ARB(0, 0),
7373 			     ARGS_ENTRY_ARB
7374 				(sizeof(struct rte_flow_action_modify_field),
7375 				 FLOW_FIELD_PATTERN_SIZE)),
7376 		.call = parse_vc_conf,
7377 	},
7378 	[ACTION_MODIFY_FIELD_WIDTH] = {
7379 		.name = "width",
7380 		.help = "number of bits to copy",
7381 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7382 			NEXT_ENTRY(COMMON_UNSIGNED)),
7383 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7384 					width)),
7385 		.call = parse_vc_conf,
7386 	},
7387 	[ACTION_SEND_TO_KERNEL] = {
7388 		.name = "send_to_kernel",
7389 		.help = "send packets to kernel",
7390 		.priv = PRIV_ACTION(SEND_TO_KERNEL, 0),
7391 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7392 		.call = parse_vc,
7393 	},
7394 	[ACTION_IPV6_EXT_REMOVE] = {
7395 		.name = "ipv6_ext_remove",
7396 		.help = "IPv6 extension type, defined by set ipv6_ext_remove",
7397 		.priv = PRIV_ACTION(IPV6_EXT_REMOVE,
7398 			sizeof(struct action_ipv6_ext_remove_data)),
7399 		.next = NEXT(action_ipv6_ext_remove),
7400 		.call = parse_vc_action_ipv6_ext_remove,
7401 	},
7402 	[ACTION_IPV6_EXT_REMOVE_INDEX] = {
7403 		.name = "index",
7404 		.help = "the index of ipv6_ext_remove",
7405 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_REMOVE_INDEX_VALUE)),
7406 	},
7407 	[ACTION_IPV6_EXT_REMOVE_INDEX_VALUE] = {
7408 		.name = "{index}",
7409 		.type = "UNSIGNED",
7410 		.help = "unsigned integer value",
7411 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7412 		.call = parse_vc_action_ipv6_ext_remove_index,
7413 		.comp = comp_set_ipv6_ext_index,
7414 	},
7415 	[ACTION_IPV6_EXT_PUSH] = {
7416 		.name = "ipv6_ext_push",
7417 		.help = "IPv6 extension data, defined by set ipv6_ext_push",
7418 		.priv = PRIV_ACTION(IPV6_EXT_PUSH,
7419 			sizeof(struct action_ipv6_ext_push_data)),
7420 		.next = NEXT(action_ipv6_ext_push),
7421 		.call = parse_vc_action_ipv6_ext_push,
7422 	},
7423 	[ACTION_IPV6_EXT_PUSH_INDEX] = {
7424 		.name = "index",
7425 		.help = "the index of ipv6_ext_push",
7426 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_PUSH_INDEX_VALUE)),
7427 	},
7428 	[ACTION_IPV6_EXT_PUSH_INDEX_VALUE] = {
7429 		.name = "{index}",
7430 		.type = "UNSIGNED",
7431 		.help = "unsigned integer value",
7432 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7433 		.call = parse_vc_action_ipv6_ext_push_index,
7434 		.comp = comp_set_ipv6_ext_index,
7435 	},
7436 	[ACTION_NAT64] = {
7437 		.name = "nat64",
7438 		.help = "NAT64 IP headers translation",
7439 		.priv = PRIV_ACTION(NAT64, sizeof(struct rte_flow_action_nat64)),
7440 		.next = NEXT(action_nat64),
7441 		.call = parse_vc,
7442 	},
7443 	[ACTION_NAT64_MODE] = {
7444 		.name = "type",
7445 		.help = "NAT64 translation type",
7446 		.next = NEXT(action_nat64, NEXT_ENTRY(COMMON_UNSIGNED)),
7447 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_nat64, type)),
7448 		.call = parse_vc_conf,
7449 	},
7450 	/* Top level command. */
7451 	[SET] = {
7452 		.name = "set",
7453 		.help = "set raw encap/decap/sample data",
7454 		.type = "set raw_encap|raw_decap <index> <pattern>"
7455 				" or set sample_actions <index> <action>",
7456 		.next = NEXT(NEXT_ENTRY
7457 			     (SET_RAW_ENCAP,
7458 			      SET_RAW_DECAP,
7459 			      SET_SAMPLE_ACTIONS,
7460 			      SET_IPV6_EXT_REMOVE,
7461 			      SET_IPV6_EXT_PUSH)),
7462 		.call = parse_set_init,
7463 	},
7464 	/* Sub-level commands. */
7465 	[SET_RAW_ENCAP] = {
7466 		.name = "raw_encap",
7467 		.help = "set raw encap data",
7468 		.next = NEXT(next_set_raw),
7469 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7470 				(offsetof(struct buffer, port),
7471 				 sizeof(((struct buffer *)0)->port),
7472 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7473 		.call = parse_set_raw_encap_decap,
7474 	},
7475 	[SET_RAW_DECAP] = {
7476 		.name = "raw_decap",
7477 		.help = "set raw decap data",
7478 		.next = NEXT(next_set_raw),
7479 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7480 				(offsetof(struct buffer, port),
7481 				 sizeof(((struct buffer *)0)->port),
7482 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7483 		.call = parse_set_raw_encap_decap,
7484 	},
7485 	[SET_RAW_INDEX] = {
7486 		.name = "{index}",
7487 		.type = "COMMON_UNSIGNED",
7488 		.help = "index of raw_encap/raw_decap data",
7489 		.next = NEXT(next_item),
7490 		.call = parse_port,
7491 	},
7492 	[SET_SAMPLE_INDEX] = {
7493 		.name = "{index}",
7494 		.type = "UNSIGNED",
7495 		.help = "index of sample actions",
7496 		.next = NEXT(next_action_sample),
7497 		.call = parse_port,
7498 	},
7499 	[SET_SAMPLE_ACTIONS] = {
7500 		.name = "sample_actions",
7501 		.help = "set sample actions list",
7502 		.next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
7503 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7504 				(offsetof(struct buffer, port),
7505 				 sizeof(((struct buffer *)0)->port),
7506 				 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
7507 		.call = parse_set_sample_action,
7508 	},
7509 	[SET_IPV6_EXT_PUSH] = {
7510 		.name = "ipv6_ext_push",
7511 		.help = "set IPv6 extension header",
7512 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7513 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7514 				(offsetof(struct buffer, port),
7515 				 sizeof(((struct buffer *)0)->port),
7516 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7517 		.call = parse_set_ipv6_ext_action,
7518 	},
7519 	[SET_IPV6_EXT_REMOVE] = {
7520 		.name = "ipv6_ext_remove",
7521 		.help = "set IPv6 extension header",
7522 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7523 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7524 				(offsetof(struct buffer, port),
7525 				 sizeof(((struct buffer *)0)->port),
7526 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7527 		.call = parse_set_ipv6_ext_action,
7528 	},
7529 	[SET_IPV6_EXT_INDEX] = {
7530 		.name = "{index}",
7531 		.type = "UNSIGNED",
7532 		.help = "index of ipv6 extension push/remove actions",
7533 		.next = NEXT(item_ipv6_push_ext),
7534 		.call = parse_port,
7535 	},
7536 	[ITEM_IPV6_PUSH_REMOVE_EXT] = {
7537 		.name = "ipv6_ext",
7538 		.help = "set IPv6 extension header",
7539 		.priv = PRIV_ITEM(IPV6_EXT,
7540 				  sizeof(struct rte_flow_item_ipv6_ext)),
7541 		.next = NEXT(item_ipv6_push_ext_type),
7542 		.call = parse_vc,
7543 	},
7544 	[ITEM_IPV6_PUSH_REMOVE_EXT_TYPE] = {
7545 		.name = "type",
7546 		.help = "set IPv6 extension type",
7547 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
7548 					     next_hdr)),
7549 		.next = NEXT(item_ipv6_push_ext_header, NEXT_ENTRY(COMMON_UNSIGNED),
7550 			     item_param),
7551 	},
7552 	[ACTION_SET_TAG] = {
7553 		.name = "set_tag",
7554 		.help = "set tag",
7555 		.priv = PRIV_ACTION(SET_TAG,
7556 			sizeof(struct rte_flow_action_set_tag)),
7557 		.next = NEXT(action_set_tag),
7558 		.call = parse_vc,
7559 	},
7560 	[ACTION_SET_TAG_INDEX] = {
7561 		.name = "index",
7562 		.help = "index of tag array",
7563 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7564 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
7565 		.call = parse_vc_conf,
7566 	},
7567 	[ACTION_SET_TAG_DATA] = {
7568 		.name = "data",
7569 		.help = "tag value",
7570 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7571 		.args = ARGS(ARGS_ENTRY
7572 			     (struct rte_flow_action_set_tag, data)),
7573 		.call = parse_vc_conf,
7574 	},
7575 	[ACTION_SET_TAG_MASK] = {
7576 		.name = "mask",
7577 		.help = "mask for tag value",
7578 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7579 		.args = ARGS(ARGS_ENTRY
7580 			     (struct rte_flow_action_set_tag, mask)),
7581 		.call = parse_vc_conf,
7582 	},
7583 	[ACTION_SET_META] = {
7584 		.name = "set_meta",
7585 		.help = "set metadata",
7586 		.priv = PRIV_ACTION(SET_META,
7587 			sizeof(struct rte_flow_action_set_meta)),
7588 		.next = NEXT(action_set_meta),
7589 		.call = parse_vc_action_set_meta,
7590 	},
7591 	[ACTION_SET_META_DATA] = {
7592 		.name = "data",
7593 		.help = "metadata value",
7594 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7595 		.args = ARGS(ARGS_ENTRY
7596 			     (struct rte_flow_action_set_meta, data)),
7597 		.call = parse_vc_conf,
7598 	},
7599 	[ACTION_SET_META_MASK] = {
7600 		.name = "mask",
7601 		.help = "mask for metadata value",
7602 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7603 		.args = ARGS(ARGS_ENTRY
7604 			     (struct rte_flow_action_set_meta, mask)),
7605 		.call = parse_vc_conf,
7606 	},
7607 	[ACTION_SET_IPV4_DSCP] = {
7608 		.name = "set_ipv4_dscp",
7609 		.help = "set DSCP value",
7610 		.priv = PRIV_ACTION(SET_IPV4_DSCP,
7611 			sizeof(struct rte_flow_action_set_dscp)),
7612 		.next = NEXT(action_set_ipv4_dscp),
7613 		.call = parse_vc,
7614 	},
7615 	[ACTION_SET_IPV4_DSCP_VALUE] = {
7616 		.name = "dscp_value",
7617 		.help = "new IPv4 DSCP value to set",
7618 		.next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7619 		.args = ARGS(ARGS_ENTRY
7620 			     (struct rte_flow_action_set_dscp, dscp)),
7621 		.call = parse_vc_conf,
7622 	},
7623 	[ACTION_SET_IPV6_DSCP] = {
7624 		.name = "set_ipv6_dscp",
7625 		.help = "set DSCP value",
7626 		.priv = PRIV_ACTION(SET_IPV6_DSCP,
7627 			sizeof(struct rte_flow_action_set_dscp)),
7628 		.next = NEXT(action_set_ipv6_dscp),
7629 		.call = parse_vc,
7630 	},
7631 	[ACTION_SET_IPV6_DSCP_VALUE] = {
7632 		.name = "dscp_value",
7633 		.help = "new IPv6 DSCP value to set",
7634 		.next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7635 		.args = ARGS(ARGS_ENTRY
7636 			     (struct rte_flow_action_set_dscp, dscp)),
7637 		.call = parse_vc_conf,
7638 	},
7639 	[ACTION_AGE] = {
7640 		.name = "age",
7641 		.help = "set a specific metadata header",
7642 		.next = NEXT(action_age),
7643 		.priv = PRIV_ACTION(AGE,
7644 			sizeof(struct rte_flow_action_age)),
7645 		.call = parse_vc,
7646 	},
7647 	[ACTION_AGE_TIMEOUT] = {
7648 		.name = "timeout",
7649 		.help = "flow age timeout value",
7650 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
7651 					   timeout, 24)),
7652 		.next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
7653 		.call = parse_vc_conf,
7654 	},
7655 	[ACTION_AGE_UPDATE] = {
7656 		.name = "age_update",
7657 		.help = "update aging parameter",
7658 		.next = NEXT(action_age_update),
7659 		.priv = PRIV_ACTION(AGE,
7660 				    sizeof(struct rte_flow_update_age)),
7661 		.call = parse_vc,
7662 	},
7663 	[ACTION_AGE_UPDATE_TIMEOUT] = {
7664 		.name = "timeout",
7665 		.help = "age timeout update value",
7666 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7667 					   timeout, 24)),
7668 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_UNSIGNED)),
7669 		.call = parse_vc_conf_timeout,
7670 	},
7671 	[ACTION_AGE_UPDATE_TOUCH] = {
7672 		.name = "touch",
7673 		.help = "this flow is touched",
7674 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_BOOLEAN)),
7675 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7676 					   touch, 1)),
7677 		.call = parse_vc_conf,
7678 	},
7679 	[ACTION_SAMPLE] = {
7680 		.name = "sample",
7681 		.help = "set a sample action",
7682 		.next = NEXT(action_sample),
7683 		.priv = PRIV_ACTION(SAMPLE,
7684 			sizeof(struct action_sample_data)),
7685 		.call = parse_vc_action_sample,
7686 	},
7687 	[ACTION_SAMPLE_RATIO] = {
7688 		.name = "ratio",
7689 		.help = "flow sample ratio value",
7690 		.next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
7691 		.args = ARGS(ARGS_ENTRY_ARB
7692 			     (offsetof(struct action_sample_data, conf) +
7693 			      offsetof(struct rte_flow_action_sample, ratio),
7694 			      sizeof(((struct rte_flow_action_sample *)0)->
7695 				     ratio))),
7696 	},
7697 	[ACTION_SAMPLE_INDEX] = {
7698 		.name = "index",
7699 		.help = "the index of sample actions list",
7700 		.next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
7701 	},
7702 	[ACTION_SAMPLE_INDEX_VALUE] = {
7703 		.name = "{index}",
7704 		.type = "COMMON_UNSIGNED",
7705 		.help = "unsigned integer value",
7706 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7707 		.call = parse_vc_action_sample_index,
7708 		.comp = comp_set_sample_index,
7709 	},
7710 	[ACTION_CONNTRACK] = {
7711 		.name = "conntrack",
7712 		.help = "create a conntrack object",
7713 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7714 		.priv = PRIV_ACTION(CONNTRACK,
7715 				    sizeof(struct rte_flow_action_conntrack)),
7716 		.call = parse_vc,
7717 	},
7718 	[ACTION_CONNTRACK_UPDATE] = {
7719 		.name = "conntrack_update",
7720 		.help = "update a conntrack object",
7721 		.next = NEXT(action_update_conntrack),
7722 		.priv = PRIV_ACTION(CONNTRACK,
7723 				    sizeof(struct rte_flow_modify_conntrack)),
7724 		.call = parse_vc,
7725 	},
7726 	[ACTION_CONNTRACK_UPDATE_DIR] = {
7727 		.name = "dir",
7728 		.help = "update a conntrack object direction",
7729 		.next = NEXT(action_update_conntrack),
7730 		.call = parse_vc_action_conntrack_update,
7731 	},
7732 	[ACTION_CONNTRACK_UPDATE_CTX] = {
7733 		.name = "ctx",
7734 		.help = "update a conntrack object context",
7735 		.next = NEXT(action_update_conntrack),
7736 		.call = parse_vc_action_conntrack_update,
7737 	},
7738 	[ACTION_PORT_REPRESENTOR] = {
7739 		.name = "port_representor",
7740 		.help = "at embedded switch level, send matching traffic to the given ethdev",
7741 		.priv = PRIV_ACTION(PORT_REPRESENTOR,
7742 				    sizeof(struct rte_flow_action_ethdev)),
7743 		.next = NEXT(action_port_representor),
7744 		.call = parse_vc,
7745 	},
7746 	[ACTION_PORT_REPRESENTOR_PORT_ID] = {
7747 		.name = "port_id",
7748 		.help = "ethdev port ID",
7749 		.next = NEXT(action_port_representor,
7750 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7751 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7752 					port_id)),
7753 		.call = parse_vc_conf,
7754 	},
7755 	[ACTION_REPRESENTED_PORT] = {
7756 		.name = "represented_port",
7757 		.help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
7758 		.priv = PRIV_ACTION(REPRESENTED_PORT,
7759 				sizeof(struct rte_flow_action_ethdev)),
7760 		.next = NEXT(action_represented_port),
7761 		.call = parse_vc,
7762 	},
7763 	[ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
7764 		.name = "ethdev_port_id",
7765 		.help = "ethdev port ID",
7766 		.next = NEXT(action_represented_port,
7767 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7768 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7769 					port_id)),
7770 		.call = parse_vc_conf,
7771 	},
7772 	/* Indirect action destroy arguments. */
7773 	[INDIRECT_ACTION_DESTROY_ID] = {
7774 		.name = "action_id",
7775 		.help = "specify a indirect action id to destroy",
7776 		.next = NEXT(next_ia_destroy_attr,
7777 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7778 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
7779 					    args.ia_destroy.action_id)),
7780 		.call = parse_ia_destroy,
7781 	},
7782 	/* Indirect action create arguments. */
7783 	[INDIRECT_ACTION_CREATE_ID] = {
7784 		.name = "action_id",
7785 		.help = "specify a indirect action id to create",
7786 		.next = NEXT(next_ia_create_attr,
7787 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7788 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
7789 	},
7790 	[ACTION_INDIRECT] = {
7791 		.name = "indirect",
7792 		.help = "apply indirect action by id",
7793 		.priv = PRIV_ACTION(INDIRECT, 0),
7794 		.next = NEXT(next_ia),
7795 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7796 		.call = parse_vc,
7797 	},
7798 	[ACTION_INDIRECT_LIST] = {
7799 		.name = "indirect_list",
7800 		.help = "apply indirect list action by id",
7801 		.priv = PRIV_ACTION(INDIRECT_LIST,
7802 				    sizeof(struct
7803 					   rte_flow_action_indirect_list)),
7804 		.next = NEXT(next_ial),
7805 		.call = parse_vc,
7806 	},
7807 	[ACTION_INDIRECT_LIST_HANDLE] = {
7808 		.name = "handle",
7809 		.help = "indirect list handle",
7810 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_HANDLE)),
7811 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7812 	},
7813 	[ACTION_INDIRECT_LIST_CONF] = {
7814 		.name = "conf",
7815 		.help = "indirect list configuration",
7816 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_CONF)),
7817 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7818 	},
7819 	[INDIRECT_LIST_ACTION_ID2PTR_HANDLE] = {
7820 		.type = "UNSIGNED",
7821 		.help = "unsigned integer value",
7822 		.call = parse_indlst_id2ptr,
7823 	},
7824 	[INDIRECT_LIST_ACTION_ID2PTR_CONF] = {
7825 		.type = "UNSIGNED",
7826 		.help = "unsigned integer value",
7827 		.call = parse_indlst_id2ptr,
7828 	},
7829 	[ACTION_SHARED_INDIRECT] = {
7830 		.name = "shared_indirect",
7831 		.help = "apply indirect action by id and port",
7832 		.priv = PRIV_ACTION(INDIRECT, 0),
7833 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_PORT)),
7834 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t)),
7835 			     ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7836 		.call = parse_vc,
7837 	},
7838 	[INDIRECT_ACTION_PORT] = {
7839 		.name = "{indirect_action_port}",
7840 		.type = "INDIRECT_ACTION_PORT",
7841 		.help = "indirect action port",
7842 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
7843 		.call = parse_ia_port,
7844 		.comp = comp_none,
7845 	},
7846 	[INDIRECT_ACTION_ID2PTR] = {
7847 		.name = "{action_id}",
7848 		.type = "INDIRECT_ACTION_ID",
7849 		.help = "indirect action id",
7850 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7851 		.call = parse_ia_id2ptr,
7852 		.comp = comp_none,
7853 	},
7854 	[INDIRECT_ACTION_INGRESS] = {
7855 		.name = "ingress",
7856 		.help = "affect rule to ingress",
7857 		.next = NEXT(next_ia_create_attr),
7858 		.call = parse_ia,
7859 	},
7860 	[INDIRECT_ACTION_EGRESS] = {
7861 		.name = "egress",
7862 		.help = "affect rule to egress",
7863 		.next = NEXT(next_ia_create_attr),
7864 		.call = parse_ia,
7865 	},
7866 	[INDIRECT_ACTION_TRANSFER] = {
7867 		.name = "transfer",
7868 		.help = "affect rule to transfer",
7869 		.next = NEXT(next_ia_create_attr),
7870 		.call = parse_ia,
7871 	},
7872 	[INDIRECT_ACTION_SPEC] = {
7873 		.name = "action",
7874 		.help = "specify action to create indirect handle",
7875 		.next = NEXT(next_action),
7876 	},
7877 	[INDIRECT_ACTION_LIST] = {
7878 		.name = "list",
7879 		.help = "specify actions for indirect handle list",
7880 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
7881 		.call = parse_ia,
7882 	},
7883 	[INDIRECT_ACTION_FLOW_CONF] = {
7884 		.name = "flow_conf",
7885 		.help = "specify actions configuration for indirect handle list",
7886 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
7887 		.call = parse_ia,
7888 	},
7889 	[ACTION_POL_G] = {
7890 		.name = "g_actions",
7891 		.help = "submit a list of associated actions for green",
7892 		.next = NEXT(next_action),
7893 		.call = parse_mp,
7894 	},
7895 	[ACTION_POL_Y] = {
7896 		.name = "y_actions",
7897 		.help = "submit a list of associated actions for yellow",
7898 		.next = NEXT(next_action),
7899 	},
7900 	[ACTION_POL_R] = {
7901 		.name = "r_actions",
7902 		.help = "submit a list of associated actions for red",
7903 		.next = NEXT(next_action),
7904 	},
7905 	[ACTION_QUOTA_CREATE] = {
7906 		.name = "quota_create",
7907 		.help = "create quota action",
7908 		.priv = PRIV_ACTION(QUOTA,
7909 				    sizeof(struct rte_flow_action_quota)),
7910 		.next = NEXT(action_quota_create),
7911 		.call = parse_vc
7912 	},
7913 	[ACTION_QUOTA_CREATE_LIMIT] = {
7914 		.name = "limit",
7915 		.help = "quota limit",
7916 		.next = NEXT(action_quota_create, NEXT_ENTRY(COMMON_UNSIGNED)),
7917 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, quota)),
7918 		.call = parse_vc_conf
7919 	},
7920 	[ACTION_QUOTA_CREATE_MODE] = {
7921 		.name = "mode",
7922 		.help = "quota mode",
7923 		.next = NEXT(action_quota_create,
7924 			     NEXT_ENTRY(ACTION_QUOTA_CREATE_MODE_NAME)),
7925 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, mode)),
7926 		.call = parse_vc_conf
7927 	},
7928 	[ACTION_QUOTA_CREATE_MODE_NAME] = {
7929 		.name = "mode_name",
7930 		.help = "quota mode name",
7931 		.call = parse_quota_mode_name,
7932 		.comp = comp_quota_mode_name
7933 	},
7934 	[ACTION_QUOTA_QU] = {
7935 		.name = "quota_update",
7936 		.help = "update quota action",
7937 		.priv = PRIV_ACTION(QUOTA,
7938 				    sizeof(struct rte_flow_update_quota)),
7939 		.next = NEXT(action_quota_update),
7940 		.call = parse_vc
7941 	},
7942 	[ACTION_QUOTA_QU_LIMIT] = {
7943 		.name = "limit",
7944 		.help = "quota limit",
7945 		.next = NEXT(action_quota_update, NEXT_ENTRY(COMMON_UNSIGNED)),
7946 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, quota)),
7947 		.call = parse_vc_conf
7948 	},
7949 	[ACTION_QUOTA_QU_UPDATE_OP] = {
7950 		.name = "update_op",
7951 		.help = "query update op SET|ADD",
7952 		.next = NEXT(action_quota_update,
7953 			     NEXT_ENTRY(ACTION_QUOTA_QU_UPDATE_OP_NAME)),
7954 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, op)),
7955 		.call = parse_vc_conf
7956 	},
7957 	[ACTION_QUOTA_QU_UPDATE_OP_NAME] = {
7958 		.name = "update_op_name",
7959 		.help = "quota update op name",
7960 		.call = parse_quota_update_name,
7961 		.comp = comp_quota_update_name
7962 	},
7963 
7964 	/* Top-level command. */
7965 	[ADD] = {
7966 		.name = "add",
7967 		.type = "port meter policy {port_id} {arg}",
7968 		.help = "add port meter policy",
7969 		.next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
7970 		.call = parse_init,
7971 	},
7972 	/* Sub-level commands. */
7973 	[ITEM_POL_PORT] = {
7974 		.name = "port",
7975 		.help = "add port meter policy",
7976 		.next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
7977 	},
7978 	[ITEM_POL_METER] = {
7979 		.name = "meter",
7980 		.help = "add port meter policy",
7981 		.next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
7982 	},
7983 	[ITEM_POL_POLICY] = {
7984 		.name = "policy",
7985 		.help = "add port meter policy",
7986 		.next = NEXT(NEXT_ENTRY(ACTION_POL_R),
7987 				NEXT_ENTRY(ACTION_POL_Y),
7988 				NEXT_ENTRY(ACTION_POL_G),
7989 				NEXT_ENTRY(COMMON_POLICY_ID),
7990 				NEXT_ENTRY(COMMON_PORT_ID)),
7991 		.args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
7992 				ARGS_ENTRY(struct buffer, port)),
7993 		.call = parse_mp,
7994 	},
7995 	[ITEM_AGGR_AFFINITY] = {
7996 		.name = "aggr_affinity",
7997 		.help = "match on the aggregated port receiving the packets",
7998 		.priv = PRIV_ITEM(AGGR_AFFINITY,
7999 				  sizeof(struct rte_flow_item_aggr_affinity)),
8000 		.next = NEXT(item_aggr_affinity),
8001 		.call = parse_vc,
8002 	},
8003 	[ITEM_AGGR_AFFINITY_VALUE] = {
8004 		.name = "affinity",
8005 		.help = "aggregated affinity value",
8006 		.next = NEXT(item_aggr_affinity, NEXT_ENTRY(COMMON_UNSIGNED),
8007 			     item_param),
8008 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_aggr_affinity,
8009 					affinity)),
8010 	},
8011 	[ITEM_TX_QUEUE] = {
8012 		.name = "tx_queue",
8013 		.help = "match on the tx queue of send packet",
8014 		.priv = PRIV_ITEM(TX_QUEUE,
8015 				  sizeof(struct rte_flow_item_tx_queue)),
8016 		.next = NEXT(item_tx_queue),
8017 		.call = parse_vc,
8018 	},
8019 	[ITEM_TX_QUEUE_VALUE] = {
8020 		.name = "tx_queue_value",
8021 		.help = "tx queue value",
8022 		.next = NEXT(item_tx_queue, NEXT_ENTRY(COMMON_UNSIGNED),
8023 			     item_param),
8024 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tx_queue,
8025 					tx_queue)),
8026 	},
8027 };
8028 
8029 /** Remove and return last entry from argument stack. */
8030 static const struct arg *
8031 pop_args(struct context *ctx)
8032 {
8033 	return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
8034 }
8035 
8036 /** Add entry on top of the argument stack. */
8037 static int
8038 push_args(struct context *ctx, const struct arg *arg)
8039 {
8040 	if (ctx->args_num == CTX_STACK_SIZE)
8041 		return -1;
8042 	ctx->args[ctx->args_num++] = arg;
8043 	return 0;
8044 }
8045 
8046 /** Spread value into buffer according to bit-mask. */
8047 static size_t
8048 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
8049 {
8050 	uint32_t i = arg->size;
8051 	uint32_t end = 0;
8052 	int sub = 1;
8053 	int add = 0;
8054 	size_t len = 0;
8055 
8056 	if (!arg->mask)
8057 		return 0;
8058 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8059 	if (!arg->hton) {
8060 		i = 0;
8061 		end = arg->size;
8062 		sub = 0;
8063 		add = 1;
8064 	}
8065 #endif
8066 	while (i != end) {
8067 		unsigned int shift = 0;
8068 		uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
8069 
8070 		for (shift = 0; arg->mask[i] >> shift; ++shift) {
8071 			if (!(arg->mask[i] & (1 << shift)))
8072 				continue;
8073 			++len;
8074 			if (!dst)
8075 				continue;
8076 			*buf &= ~(1 << shift);
8077 			*buf |= (val & 1) << shift;
8078 			val >>= 1;
8079 		}
8080 		i += add;
8081 	}
8082 	return len;
8083 }
8084 
8085 /** Compare a string with a partial one of a given length. */
8086 static int
8087 strcmp_partial(const char *full, const char *partial, size_t partial_len)
8088 {
8089 	int r = strncmp(full, partial, partial_len);
8090 
8091 	if (r)
8092 		return r;
8093 	if (strlen(full) <= partial_len)
8094 		return 0;
8095 	return full[partial_len];
8096 }
8097 
8098 /**
8099  * Parse a prefix length and generate a bit-mask.
8100  *
8101  * Last argument (ctx->args) is retrieved to determine mask size, storage
8102  * location and whether the result must use network byte ordering.
8103  */
8104 static int
8105 parse_prefix(struct context *ctx, const struct token *token,
8106 	     const char *str, unsigned int len,
8107 	     void *buf, unsigned int size)
8108 {
8109 	const struct arg *arg = pop_args(ctx);
8110 	static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
8111 	char *end;
8112 	uintmax_t u;
8113 	unsigned int bytes;
8114 	unsigned int extra;
8115 
8116 	(void)token;
8117 	/* Argument is expected. */
8118 	if (!arg)
8119 		return -1;
8120 	errno = 0;
8121 	u = strtoumax(str, &end, 0);
8122 	if (errno || (size_t)(end - str) != len)
8123 		goto error;
8124 	if (arg->mask) {
8125 		uintmax_t v = 0;
8126 
8127 		extra = arg_entry_bf_fill(NULL, 0, arg);
8128 		if (u > extra)
8129 			goto error;
8130 		if (!ctx->object)
8131 			return len;
8132 		extra -= u;
8133 		while (u--)
8134 			(v <<= 1, v |= 1);
8135 		v <<= extra;
8136 		if (!arg_entry_bf_fill(ctx->object, v, arg) ||
8137 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
8138 			goto error;
8139 		return len;
8140 	}
8141 	bytes = u / 8;
8142 	extra = u % 8;
8143 	size = arg->size;
8144 	if (bytes > size || bytes + !!extra > size)
8145 		goto error;
8146 	if (!ctx->object)
8147 		return len;
8148 	buf = (uint8_t *)ctx->object + arg->offset;
8149 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8150 	if (!arg->hton) {
8151 		memset((uint8_t *)buf + size - bytes, 0xff, bytes);
8152 		memset(buf, 0x00, size - bytes);
8153 		if (extra)
8154 			((uint8_t *)buf)[size - bytes - 1] = conv[extra];
8155 	} else
8156 #endif
8157 	{
8158 		memset(buf, 0xff, bytes);
8159 		memset((uint8_t *)buf + bytes, 0x00, size - bytes);
8160 		if (extra)
8161 			((uint8_t *)buf)[bytes] = conv[extra];
8162 	}
8163 	if (ctx->objmask)
8164 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8165 	return len;
8166 error:
8167 	push_args(ctx, arg);
8168 	return -1;
8169 }
8170 
8171 /** Default parsing function for token name matching. */
8172 static int
8173 parse_default(struct context *ctx, const struct token *token,
8174 	      const char *str, unsigned int len,
8175 	      void *buf, unsigned int size)
8176 {
8177 	(void)ctx;
8178 	(void)buf;
8179 	(void)size;
8180 	if (strcmp_partial(token->name, str, len))
8181 		return -1;
8182 	return len;
8183 }
8184 
8185 /** Parse flow command, initialize output buffer for subsequent tokens. */
8186 static int
8187 parse_init(struct context *ctx, const struct token *token,
8188 	   const char *str, unsigned int len,
8189 	   void *buf, unsigned int size)
8190 {
8191 	struct buffer *out = buf;
8192 
8193 	/* Token name must match. */
8194 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8195 		return -1;
8196 	/* Nothing else to do if there is no buffer. */
8197 	if (!out)
8198 		return len;
8199 	/* Make sure buffer is large enough. */
8200 	if (size < sizeof(*out))
8201 		return -1;
8202 	/* Initialize buffer. */
8203 	memset(out, 0x00, sizeof(*out));
8204 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
8205 	ctx->objdata = 0;
8206 	ctx->object = out;
8207 	ctx->objmask = NULL;
8208 	return len;
8209 }
8210 
8211 /** Parse tokens for indirect action commands. */
8212 static int
8213 parse_ia(struct context *ctx, const struct token *token,
8214 	 const char *str, unsigned int len,
8215 	 void *buf, unsigned int size)
8216 {
8217 	struct buffer *out = buf;
8218 
8219 	/* Token name must match. */
8220 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8221 		return -1;
8222 	/* Nothing else to do if there is no buffer. */
8223 	if (!out)
8224 		return len;
8225 	if (!out->command) {
8226 		if (ctx->curr != INDIRECT_ACTION)
8227 			return -1;
8228 		if (sizeof(*out) > size)
8229 			return -1;
8230 		out->command = ctx->curr;
8231 		ctx->objdata = 0;
8232 		ctx->object = out;
8233 		ctx->objmask = NULL;
8234 		out->args.vc.data = (uint8_t *)out + size;
8235 		return len;
8236 	}
8237 	switch (ctx->curr) {
8238 	case INDIRECT_ACTION_CREATE:
8239 	case INDIRECT_ACTION_UPDATE:
8240 	case INDIRECT_ACTION_QUERY_UPDATE:
8241 		out->args.vc.actions =
8242 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8243 					       sizeof(double));
8244 		out->args.vc.attr.group = UINT32_MAX;
8245 		/* fallthrough */
8246 	case INDIRECT_ACTION_QUERY:
8247 		out->command = ctx->curr;
8248 		ctx->objdata = 0;
8249 		ctx->object = out;
8250 		ctx->objmask = NULL;
8251 		return len;
8252 	case INDIRECT_ACTION_EGRESS:
8253 		out->args.vc.attr.egress = 1;
8254 		return len;
8255 	case INDIRECT_ACTION_INGRESS:
8256 		out->args.vc.attr.ingress = 1;
8257 		return len;
8258 	case INDIRECT_ACTION_TRANSFER:
8259 		out->args.vc.attr.transfer = 1;
8260 		return len;
8261 	case INDIRECT_ACTION_QU_MODE:
8262 		return len;
8263 	case INDIRECT_ACTION_LIST:
8264 		out->command = INDIRECT_ACTION_LIST_CREATE;
8265 		return len;
8266 	case INDIRECT_ACTION_FLOW_CONF:
8267 		out->command = INDIRECT_ACTION_FLOW_CONF_CREATE;
8268 		return len;
8269 	default:
8270 		return -1;
8271 	}
8272 }
8273 
8274 
8275 /** Parse tokens for indirect action destroy command. */
8276 static int
8277 parse_ia_destroy(struct context *ctx, const struct token *token,
8278 		 const char *str, unsigned int len,
8279 		 void *buf, unsigned int size)
8280 {
8281 	struct buffer *out = buf;
8282 	uint32_t *action_id;
8283 
8284 	/* Token name must match. */
8285 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8286 		return -1;
8287 	/* Nothing else to do if there is no buffer. */
8288 	if (!out)
8289 		return len;
8290 	if (!out->command || out->command == INDIRECT_ACTION) {
8291 		if (ctx->curr != INDIRECT_ACTION_DESTROY)
8292 			return -1;
8293 		if (sizeof(*out) > size)
8294 			return -1;
8295 		out->command = ctx->curr;
8296 		ctx->objdata = 0;
8297 		ctx->object = out;
8298 		ctx->objmask = NULL;
8299 		out->args.ia_destroy.action_id =
8300 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8301 					       sizeof(double));
8302 		return len;
8303 	}
8304 	action_id = out->args.ia_destroy.action_id
8305 		    + out->args.ia_destroy.action_id_n++;
8306 	if ((uint8_t *)action_id > (uint8_t *)out + size)
8307 		return -1;
8308 	ctx->objdata = 0;
8309 	ctx->object = action_id;
8310 	ctx->objmask = NULL;
8311 	return len;
8312 }
8313 
8314 /** Parse tokens for indirect action commands. */
8315 static int
8316 parse_qia(struct context *ctx, const struct token *token,
8317 	  const char *str, unsigned int len,
8318 	  void *buf, unsigned int size)
8319 {
8320 	struct buffer *out = buf;
8321 
8322 	/* Token name must match. */
8323 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8324 		return -1;
8325 	/* Nothing else to do if there is no buffer. */
8326 	if (!out)
8327 		return len;
8328 	if (!out->command) {
8329 		if (ctx->curr != QUEUE)
8330 			return -1;
8331 		if (sizeof(*out) > size)
8332 			return -1;
8333 		out->args.vc.data = (uint8_t *)out + size;
8334 		return len;
8335 	}
8336 	switch (ctx->curr) {
8337 	case QUEUE_INDIRECT_ACTION:
8338 		return len;
8339 	case QUEUE_INDIRECT_ACTION_CREATE:
8340 	case QUEUE_INDIRECT_ACTION_UPDATE:
8341 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
8342 		out->args.vc.actions =
8343 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8344 					       sizeof(double));
8345 		out->args.vc.attr.group = UINT32_MAX;
8346 		/* fallthrough */
8347 	case QUEUE_INDIRECT_ACTION_QUERY:
8348 		out->command = ctx->curr;
8349 		ctx->objdata = 0;
8350 		ctx->object = out;
8351 		ctx->objmask = NULL;
8352 		return len;
8353 	case QUEUE_INDIRECT_ACTION_EGRESS:
8354 		out->args.vc.attr.egress = 1;
8355 		return len;
8356 	case QUEUE_INDIRECT_ACTION_INGRESS:
8357 		out->args.vc.attr.ingress = 1;
8358 		return len;
8359 	case QUEUE_INDIRECT_ACTION_TRANSFER:
8360 		out->args.vc.attr.transfer = 1;
8361 		return len;
8362 	case QUEUE_INDIRECT_ACTION_CREATE_POSTPONE:
8363 		return len;
8364 	case QUEUE_INDIRECT_ACTION_QU_MODE:
8365 		return len;
8366 	case QUEUE_INDIRECT_ACTION_LIST:
8367 		out->command = QUEUE_INDIRECT_ACTION_LIST_CREATE;
8368 		return len;
8369 	default:
8370 		return -1;
8371 	}
8372 }
8373 
8374 /** Parse tokens for indirect action destroy command. */
8375 static int
8376 parse_qia_destroy(struct context *ctx, const struct token *token,
8377 		  const char *str, unsigned int len,
8378 		  void *buf, unsigned int size)
8379 {
8380 	struct buffer *out = buf;
8381 	uint32_t *action_id;
8382 
8383 	/* Token name must match. */
8384 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8385 		return -1;
8386 	/* Nothing else to do if there is no buffer. */
8387 	if (!out)
8388 		return len;
8389 	if (!out->command || out->command == QUEUE) {
8390 		if (ctx->curr != QUEUE_INDIRECT_ACTION_DESTROY)
8391 			return -1;
8392 		if (sizeof(*out) > size)
8393 			return -1;
8394 		out->command = ctx->curr;
8395 		ctx->objdata = 0;
8396 		ctx->object = out;
8397 		ctx->objmask = NULL;
8398 		out->args.ia_destroy.action_id =
8399 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8400 					       sizeof(double));
8401 		return len;
8402 	}
8403 	switch (ctx->curr) {
8404 	case QUEUE_INDIRECT_ACTION:
8405 		out->command = ctx->curr;
8406 		ctx->objdata = 0;
8407 		ctx->object = out;
8408 		ctx->objmask = NULL;
8409 		return len;
8410 	case QUEUE_INDIRECT_ACTION_DESTROY_ID:
8411 		action_id = out->args.ia_destroy.action_id
8412 				+ out->args.ia_destroy.action_id_n++;
8413 		if ((uint8_t *)action_id > (uint8_t *)out + size)
8414 			return -1;
8415 		ctx->objdata = 0;
8416 		ctx->object = action_id;
8417 		ctx->objmask = NULL;
8418 		return len;
8419 	case QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE:
8420 		return len;
8421 	default:
8422 		return -1;
8423 	}
8424 }
8425 
8426 /** Parse tokens for meter policy action commands. */
8427 static int
8428 parse_mp(struct context *ctx, const struct token *token,
8429 	const char *str, unsigned int len,
8430 	void *buf, unsigned int size)
8431 {
8432 	struct buffer *out = buf;
8433 
8434 	/* Token name must match. */
8435 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8436 		return -1;
8437 	/* Nothing else to do if there is no buffer. */
8438 	if (!out)
8439 		return len;
8440 	if (!out->command) {
8441 		if (ctx->curr != ITEM_POL_POLICY)
8442 			return -1;
8443 		if (sizeof(*out) > size)
8444 			return -1;
8445 		out->command = ctx->curr;
8446 		ctx->objdata = 0;
8447 		ctx->object = out;
8448 		ctx->objmask = NULL;
8449 		out->args.vc.data = (uint8_t *)out + size;
8450 		return len;
8451 	}
8452 	switch (ctx->curr) {
8453 	case ACTION_POL_G:
8454 		out->args.vc.actions =
8455 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8456 					sizeof(double));
8457 		out->command = ctx->curr;
8458 		ctx->objdata = 0;
8459 		ctx->object = out;
8460 		ctx->objmask = NULL;
8461 		return len;
8462 	default:
8463 		return -1;
8464 	}
8465 }
8466 
8467 /** Parse tokens for validate/create commands. */
8468 static int
8469 parse_vc(struct context *ctx, const struct token *token,
8470 	 const char *str, unsigned int len,
8471 	 void *buf, unsigned int size)
8472 {
8473 	struct buffer *out = buf;
8474 	uint8_t *data;
8475 	uint32_t data_size;
8476 
8477 	/* Token name must match. */
8478 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8479 		return -1;
8480 	/* Nothing else to do if there is no buffer. */
8481 	if (!out)
8482 		return len;
8483 	if (!out->command) {
8484 		if (ctx->curr != VALIDATE && ctx->curr != CREATE &&
8485 		    ctx->curr != PATTERN_TEMPLATE_CREATE &&
8486 		    ctx->curr != ACTIONS_TEMPLATE_CREATE)
8487 			return -1;
8488 		if (sizeof(*out) > size)
8489 			return -1;
8490 		out->command = ctx->curr;
8491 		ctx->objdata = 0;
8492 		ctx->object = out;
8493 		ctx->objmask = NULL;
8494 		out->args.vc.data = (uint8_t *)out + size;
8495 		return len;
8496 	}
8497 	ctx->objdata = 0;
8498 	switch (ctx->curr) {
8499 	default:
8500 		ctx->object = &out->args.vc.attr;
8501 		break;
8502 	case VC_TUNNEL_SET:
8503 	case VC_TUNNEL_MATCH:
8504 		ctx->object = &out->args.vc.tunnel_ops;
8505 		break;
8506 	case VC_USER_ID:
8507 		ctx->object = out;
8508 		break;
8509 	}
8510 	ctx->objmask = NULL;
8511 	switch (ctx->curr) {
8512 	case VC_GROUP:
8513 	case VC_PRIORITY:
8514 	case VC_USER_ID:
8515 		return len;
8516 	case VC_TUNNEL_SET:
8517 		out->args.vc.tunnel_ops.enabled = 1;
8518 		out->args.vc.tunnel_ops.actions = 1;
8519 		return len;
8520 	case VC_TUNNEL_MATCH:
8521 		out->args.vc.tunnel_ops.enabled = 1;
8522 		out->args.vc.tunnel_ops.items = 1;
8523 		return len;
8524 	case VC_INGRESS:
8525 		out->args.vc.attr.ingress = 1;
8526 		return len;
8527 	case VC_EGRESS:
8528 		out->args.vc.attr.egress = 1;
8529 		return len;
8530 	case VC_TRANSFER:
8531 		out->args.vc.attr.transfer = 1;
8532 		return len;
8533 	case ITEM_PATTERN:
8534 		out->args.vc.pattern =
8535 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8536 					       sizeof(double));
8537 		ctx->object = out->args.vc.pattern;
8538 		ctx->objmask = NULL;
8539 		return len;
8540 	case ITEM_END:
8541 		if ((out->command == VALIDATE || out->command == CREATE) &&
8542 		    ctx->last)
8543 			return -1;
8544 		if (out->command == PATTERN_TEMPLATE_CREATE &&
8545 		    !ctx->last)
8546 			return -1;
8547 		break;
8548 	case ACTIONS:
8549 		out->args.vc.actions = out->args.vc.pattern ?
8550 			(void *)RTE_ALIGN_CEIL((uintptr_t)
8551 					       (out->args.vc.pattern +
8552 						out->args.vc.pattern_n),
8553 					       sizeof(double)) :
8554 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8555 					       sizeof(double));
8556 		ctx->object = out->args.vc.actions;
8557 		ctx->objmask = NULL;
8558 		return len;
8559 	default:
8560 		if (!token->priv)
8561 			return -1;
8562 		break;
8563 	}
8564 	if (!out->args.vc.actions) {
8565 		const struct parse_item_priv *priv = token->priv;
8566 		struct rte_flow_item *item =
8567 			out->args.vc.pattern + out->args.vc.pattern_n;
8568 
8569 		data_size = priv->size * 3; /* spec, last, mask */
8570 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8571 					       (out->args.vc.data - data_size),
8572 					       sizeof(double));
8573 		if ((uint8_t *)item + sizeof(*item) > data)
8574 			return -1;
8575 		*item = (struct rte_flow_item){
8576 			.type = priv->type,
8577 		};
8578 		++out->args.vc.pattern_n;
8579 		ctx->object = item;
8580 		ctx->objmask = NULL;
8581 	} else {
8582 		const struct parse_action_priv *priv = token->priv;
8583 		struct rte_flow_action *action =
8584 			out->args.vc.actions + out->args.vc.actions_n;
8585 
8586 		data_size = priv->size; /* configuration */
8587 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8588 					       (out->args.vc.data - data_size),
8589 					       sizeof(double));
8590 		if ((uint8_t *)action + sizeof(*action) > data)
8591 			return -1;
8592 		*action = (struct rte_flow_action){
8593 			.type = priv->type,
8594 			.conf = data_size ? data : NULL,
8595 		};
8596 		++out->args.vc.actions_n;
8597 		ctx->object = action;
8598 		ctx->objmask = NULL;
8599 	}
8600 	memset(data, 0, data_size);
8601 	out->args.vc.data = data;
8602 	ctx->objdata = data_size;
8603 	return len;
8604 }
8605 
8606 /** Parse pattern item parameter type. */
8607 static int
8608 parse_vc_spec(struct context *ctx, const struct token *token,
8609 	      const char *str, unsigned int len,
8610 	      void *buf, unsigned int size)
8611 {
8612 	struct buffer *out = buf;
8613 	struct rte_flow_item *item;
8614 	uint32_t data_size;
8615 	int index;
8616 	int objmask = 0;
8617 
8618 	(void)size;
8619 	/* Token name must match. */
8620 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8621 		return -1;
8622 	/* Parse parameter types. */
8623 	switch (ctx->curr) {
8624 		static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
8625 
8626 	case ITEM_PARAM_IS:
8627 		index = 0;
8628 		objmask = 1;
8629 		break;
8630 	case ITEM_PARAM_SPEC:
8631 		index = 0;
8632 		break;
8633 	case ITEM_PARAM_LAST:
8634 		index = 1;
8635 		break;
8636 	case ITEM_PARAM_PREFIX:
8637 		/* Modify next token to expect a prefix. */
8638 		if (ctx->next_num < 2)
8639 			return -1;
8640 		ctx->next[ctx->next_num - 2] = prefix;
8641 		/* Fall through. */
8642 	case ITEM_PARAM_MASK:
8643 		index = 2;
8644 		break;
8645 	default:
8646 		return -1;
8647 	}
8648 	/* Nothing else to do if there is no buffer. */
8649 	if (!out)
8650 		return len;
8651 	if (!out->args.vc.pattern_n)
8652 		return -1;
8653 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8654 	data_size = ctx->objdata / 3; /* spec, last, mask */
8655 	/* Point to selected object. */
8656 	ctx->object = out->args.vc.data + (data_size * index);
8657 	if (objmask) {
8658 		ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
8659 		item->mask = ctx->objmask;
8660 	} else
8661 		ctx->objmask = NULL;
8662 	/* Update relevant item pointer. */
8663 	*((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
8664 		ctx->object;
8665 	return len;
8666 }
8667 
8668 /** Parse action configuration field. */
8669 static int
8670 parse_vc_conf(struct context *ctx, const struct token *token,
8671 	      const char *str, unsigned int len,
8672 	      void *buf, unsigned int size)
8673 {
8674 	struct buffer *out = buf;
8675 
8676 	(void)size;
8677 	/* Token name must match. */
8678 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8679 		return -1;
8680 	/* Nothing else to do if there is no buffer. */
8681 	if (!out)
8682 		return len;
8683 	/* Point to selected object. */
8684 	ctx->object = out->args.vc.data;
8685 	ctx->objmask = NULL;
8686 	return len;
8687 }
8688 
8689 /** Parse action configuration field. */
8690 static int
8691 parse_vc_conf_timeout(struct context *ctx, const struct token *token,
8692 		      const char *str, unsigned int len,
8693 		      void *buf, unsigned int size)
8694 {
8695 	struct buffer *out = buf;
8696 	struct rte_flow_update_age *update;
8697 
8698 	(void)size;
8699 	if (ctx->curr != ACTION_AGE_UPDATE_TIMEOUT)
8700 		return -1;
8701 	/* Token name must match. */
8702 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8703 		return -1;
8704 	/* Nothing else to do if there is no buffer. */
8705 	if (!out)
8706 		return len;
8707 	/* Point to selected object. */
8708 	ctx->object = out->args.vc.data;
8709 	ctx->objmask = NULL;
8710 	/* Update the timeout is valid. */
8711 	update = (struct rte_flow_update_age *)out->args.vc.data;
8712 	update->timeout_valid = 1;
8713 	return len;
8714 }
8715 
8716 /** Parse eCPRI common header type field. */
8717 static int
8718 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
8719 			 const char *str, unsigned int len,
8720 			 void *buf, unsigned int size)
8721 {
8722 	struct rte_flow_item_ecpri *ecpri;
8723 	struct rte_flow_item_ecpri *ecpri_mask;
8724 	struct rte_flow_item *item;
8725 	uint32_t data_size;
8726 	uint8_t msg_type;
8727 	struct buffer *out = buf;
8728 	const struct arg *arg;
8729 
8730 	(void)size;
8731 	/* Token name must match. */
8732 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8733 		return -1;
8734 	switch (ctx->curr) {
8735 	case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
8736 		msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
8737 		break;
8738 	case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
8739 		msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
8740 		break;
8741 	case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
8742 		msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
8743 		break;
8744 	default:
8745 		return -1;
8746 	}
8747 	if (!ctx->object)
8748 		return len;
8749 	arg = pop_args(ctx);
8750 	if (!arg)
8751 		return -1;
8752 	ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
8753 	ecpri->hdr.common.type = msg_type;
8754 	data_size = ctx->objdata / 3; /* spec, last, mask */
8755 	ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
8756 						    (data_size * 2));
8757 	ecpri_mask->hdr.common.type = 0xFF;
8758 	if (arg->hton) {
8759 		ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
8760 		ecpri_mask->hdr.common.u32 =
8761 				rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
8762 	}
8763 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8764 	item->spec = ecpri;
8765 	item->mask = ecpri_mask;
8766 	return len;
8767 }
8768 
8769 /** Parse L2TPv2 common header type field. */
8770 static int
8771 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
8772 			 const char *str, unsigned int len,
8773 			 void *buf, unsigned int size)
8774 {
8775 	struct rte_flow_item_l2tpv2 *l2tpv2;
8776 	struct rte_flow_item_l2tpv2 *l2tpv2_mask;
8777 	struct rte_flow_item *item;
8778 	uint32_t data_size;
8779 	uint16_t msg_type = 0;
8780 	struct buffer *out = buf;
8781 	const struct arg *arg;
8782 
8783 	(void)size;
8784 	/* Token name must match. */
8785 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8786 		return -1;
8787 	switch (ctx->curr) {
8788 	case ITEM_L2TPV2_TYPE_DATA:
8789 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
8790 		break;
8791 	case ITEM_L2TPV2_TYPE_DATA_L:
8792 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
8793 		break;
8794 	case ITEM_L2TPV2_TYPE_DATA_S:
8795 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
8796 		break;
8797 	case ITEM_L2TPV2_TYPE_DATA_O:
8798 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
8799 		break;
8800 	case ITEM_L2TPV2_TYPE_DATA_L_S:
8801 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
8802 		break;
8803 	case ITEM_L2TPV2_TYPE_CTRL:
8804 		msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
8805 		break;
8806 	default:
8807 		return -1;
8808 	}
8809 	if (!ctx->object)
8810 		return len;
8811 	arg = pop_args(ctx);
8812 	if (!arg)
8813 		return -1;
8814 	l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
8815 	l2tpv2->hdr.common.flags_version |= msg_type;
8816 	data_size = ctx->objdata / 3; /* spec, last, mask */
8817 	l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
8818 						    (data_size * 2));
8819 	l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
8820 	if (arg->hton) {
8821 		l2tpv2->hdr.common.flags_version =
8822 			rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
8823 		l2tpv2_mask->hdr.common.flags_version =
8824 		    rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
8825 	}
8826 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8827 	item->spec = l2tpv2;
8828 	item->mask = l2tpv2_mask;
8829 	return len;
8830 }
8831 
8832 /** Parse operation for compare match item. */
8833 static int
8834 parse_vc_compare_op(struct context *ctx, const struct token *token,
8835 			 const char *str, unsigned int len, void *buf,
8836 			 unsigned int size)
8837 {
8838 	struct rte_flow_item_compare *compare_item;
8839 	unsigned int i;
8840 
8841 	(void)token;
8842 	(void)buf;
8843 	(void)size;
8844 	if (ctx->curr != ITEM_COMPARE_OP_VALUE)
8845 		return -1;
8846 	for (i = 0; compare_ops[i]; ++i)
8847 		if (!strcmp_partial(compare_ops[i], str, len))
8848 			break;
8849 	if (!compare_ops[i])
8850 		return -1;
8851 	if (!ctx->object)
8852 		return len;
8853 	compare_item = ctx->object;
8854 	compare_item->operation = (enum rte_flow_item_compare_op)i;
8855 	return len;
8856 }
8857 
8858 /** Parse id for compare match item. */
8859 static int
8860 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
8861 			  const char *str, unsigned int len, void *buf,
8862 			  unsigned int size)
8863 {
8864 	struct rte_flow_item_compare *compare_item;
8865 	unsigned int i;
8866 
8867 	(void)token;
8868 	(void)buf;
8869 	(void)size;
8870 	if (ctx->curr != ITEM_COMPARE_FIELD_A_TYPE_VALUE &&
8871 		ctx->curr != ITEM_COMPARE_FIELD_B_TYPE_VALUE)
8872 		return -1;
8873 	for (i = 0; flow_field_ids[i]; ++i)
8874 		if (!strcmp_partial(flow_field_ids[i], str, len))
8875 			break;
8876 	if (!flow_field_ids[i])
8877 		return -1;
8878 	if (!ctx->object)
8879 		return len;
8880 	compare_item = ctx->object;
8881 	if (ctx->curr == ITEM_COMPARE_FIELD_A_TYPE_VALUE)
8882 		compare_item->a.field = (enum rte_flow_field_id)i;
8883 	else
8884 		compare_item->b.field = (enum rte_flow_field_id)i;
8885 	return len;
8886 }
8887 
8888 /** Parse level for compare match item. */
8889 static int
8890 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
8891 			     const char *str, unsigned int len, void *buf,
8892 			     unsigned int size)
8893 {
8894 	struct rte_flow_item_compare *compare_item;
8895 	struct flex_item *fp = NULL;
8896 	uint32_t val;
8897 	struct buffer *out = buf;
8898 	char *end;
8899 
8900 	(void)token;
8901 	(void)size;
8902 	if (ctx->curr != ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
8903 		ctx->curr != ITEM_COMPARE_FIELD_B_LEVEL_VALUE)
8904 		return -1;
8905 	if (!ctx->object)
8906 		return len;
8907 	compare_item = ctx->object;
8908 	errno = 0;
8909 	val = strtoumax(str, &end, 0);
8910 	if (errno || (size_t)(end - str) != len)
8911 		return -1;
8912 	/* No need to validate action template mask value */
8913 	if (out->args.vc.masks) {
8914 		if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE)
8915 			compare_item->a.level = val;
8916 		else
8917 			compare_item->b.level = val;
8918 		return len;
8919 	}
8920 	if ((ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
8921 		compare_item->a.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
8922 		(ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE &&
8923 		compare_item->b.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
8924 		if (val >= FLEX_MAX_PARSERS_NUM) {
8925 			printf("Bad flex item handle\n");
8926 			return -1;
8927 		}
8928 		fp = flex_items[ctx->port][val];
8929 		if (!fp) {
8930 			printf("Bad flex item handle\n");
8931 			return -1;
8932 		}
8933 	}
8934 	if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE) {
8935 		if (compare_item->a.field != RTE_FLOW_FIELD_FLEX_ITEM)
8936 			compare_item->a.level = val;
8937 		else
8938 			compare_item->a.flex_handle = fp->flex_handle;
8939 	} else if (ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE) {
8940 		if (compare_item->b.field != RTE_FLOW_FIELD_FLEX_ITEM)
8941 			compare_item->b.level = val;
8942 		else
8943 			compare_item->b.flex_handle = fp->flex_handle;
8944 	}
8945 	return len;
8946 }
8947 
8948 /** Parse meter color action type. */
8949 static int
8950 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
8951 				const char *str, unsigned int len,
8952 				void *buf, unsigned int size)
8953 {
8954 	struct rte_flow_action *action_data;
8955 	struct rte_flow_action_meter_color *conf;
8956 	enum rte_color color;
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_METER_COLOR_GREEN:
8965 		color = RTE_COLOR_GREEN;
8966 	break;
8967 	case ACTION_METER_COLOR_YELLOW:
8968 		color = RTE_COLOR_YELLOW;
8969 	break;
8970 	case ACTION_METER_COLOR_RED:
8971 		color = RTE_COLOR_RED;
8972 	break;
8973 	default:
8974 		return -1;
8975 	}
8976 
8977 	if (!ctx->object)
8978 		return len;
8979 	action_data = ctx->object;
8980 	conf = (struct rte_flow_action_meter_color *)
8981 					(uintptr_t)(action_data->conf);
8982 	conf->color = color;
8983 	return len;
8984 }
8985 
8986 /** Parse RSS action. */
8987 static int
8988 parse_vc_action_rss(struct context *ctx, const struct token *token,
8989 		    const char *str, unsigned int len,
8990 		    void *buf, unsigned int size)
8991 {
8992 	struct buffer *out = buf;
8993 	struct rte_flow_action *action;
8994 	struct action_rss_data *action_rss_data;
8995 	unsigned int i;
8996 	int ret;
8997 
8998 	ret = parse_vc(ctx, token, str, len, buf, size);
8999 	if (ret < 0)
9000 		return ret;
9001 	/* Nothing else to do if there is no buffer. */
9002 	if (!out)
9003 		return ret;
9004 	if (!out->args.vc.actions_n)
9005 		return -1;
9006 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9007 	/* Point to selected object. */
9008 	ctx->object = out->args.vc.data;
9009 	ctx->objmask = NULL;
9010 	/* Set up default configuration. */
9011 	action_rss_data = ctx->object;
9012 	*action_rss_data = (struct action_rss_data){
9013 		.conf = (struct rte_flow_action_rss){
9014 			.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
9015 			.level = 0,
9016 			.types = rss_hf,
9017 			.key_len = 0,
9018 			.queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
9019 			.key = NULL,
9020 			.queue = action_rss_data->queue,
9021 		},
9022 		.queue = { 0 },
9023 	};
9024 	for (i = 0; i < action_rss_data->conf.queue_num; ++i)
9025 		action_rss_data->queue[i] = i;
9026 	action->conf = &action_rss_data->conf;
9027 	return ret;
9028 }
9029 
9030 /**
9031  * Parse func field for RSS action.
9032  *
9033  * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
9034  * ACTION_RSS_FUNC_* index that called this function.
9035  */
9036 static int
9037 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
9038 			 const char *str, unsigned int len,
9039 			 void *buf, unsigned int size)
9040 {
9041 	struct action_rss_data *action_rss_data;
9042 	enum rte_eth_hash_function func;
9043 
9044 	(void)buf;
9045 	(void)size;
9046 	/* Token name must match. */
9047 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9048 		return -1;
9049 	switch (ctx->curr) {
9050 	case ACTION_RSS_FUNC_DEFAULT:
9051 		func = RTE_ETH_HASH_FUNCTION_DEFAULT;
9052 		break;
9053 	case ACTION_RSS_FUNC_TOEPLITZ:
9054 		func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
9055 		break;
9056 	case ACTION_RSS_FUNC_SIMPLE_XOR:
9057 		func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
9058 		break;
9059 	case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
9060 		func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
9061 		break;
9062 	default:
9063 		return -1;
9064 	}
9065 	if (!ctx->object)
9066 		return len;
9067 	action_rss_data = ctx->object;
9068 	action_rss_data->conf.func = func;
9069 	return len;
9070 }
9071 
9072 /**
9073  * Parse type field for RSS action.
9074  *
9075  * Valid tokens are type field names and the "end" token.
9076  */
9077 static int
9078 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
9079 			  const char *str, unsigned int len,
9080 			  void *buf, unsigned int size)
9081 {
9082 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
9083 	struct action_rss_data *action_rss_data;
9084 	unsigned int i;
9085 
9086 	(void)token;
9087 	(void)buf;
9088 	(void)size;
9089 	if (ctx->curr != ACTION_RSS_TYPE)
9090 		return -1;
9091 	if (!(ctx->objdata >> 16) && ctx->object) {
9092 		action_rss_data = ctx->object;
9093 		action_rss_data->conf.types = 0;
9094 	}
9095 	if (!strcmp_partial("end", str, len)) {
9096 		ctx->objdata &= 0xffff;
9097 		return len;
9098 	}
9099 	for (i = 0; rss_type_table[i].str; ++i)
9100 		if (!strcmp_partial(rss_type_table[i].str, str, len))
9101 			break;
9102 	if (!rss_type_table[i].str)
9103 		return -1;
9104 	ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
9105 	/* Repeat token. */
9106 	if (ctx->next_num == RTE_DIM(ctx->next))
9107 		return -1;
9108 	ctx->next[ctx->next_num++] = next;
9109 	if (!ctx->object)
9110 		return len;
9111 	action_rss_data = ctx->object;
9112 	action_rss_data->conf.types |= rss_type_table[i].rss_type;
9113 	return len;
9114 }
9115 
9116 /**
9117  * Parse queue field for RSS action.
9118  *
9119  * Valid tokens are queue indices and the "end" token.
9120  */
9121 static int
9122 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
9123 			  const char *str, unsigned int len,
9124 			  void *buf, unsigned int size)
9125 {
9126 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
9127 	struct action_rss_data *action_rss_data;
9128 	const struct arg *arg;
9129 	int ret;
9130 	int i;
9131 
9132 	(void)token;
9133 	(void)buf;
9134 	(void)size;
9135 	if (ctx->curr != ACTION_RSS_QUEUE)
9136 		return -1;
9137 	i = ctx->objdata >> 16;
9138 	if (!strcmp_partial("end", str, len)) {
9139 		ctx->objdata &= 0xffff;
9140 		goto end;
9141 	}
9142 	if (i >= ACTION_RSS_QUEUE_NUM)
9143 		return -1;
9144 	arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
9145 			     i * sizeof(action_rss_data->queue[i]),
9146 			     sizeof(action_rss_data->queue[i]));
9147 	if (push_args(ctx, arg))
9148 		return -1;
9149 	ret = parse_int(ctx, token, str, len, NULL, 0);
9150 	if (ret < 0) {
9151 		pop_args(ctx);
9152 		return -1;
9153 	}
9154 	++i;
9155 	ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
9156 	/* Repeat token. */
9157 	if (ctx->next_num == RTE_DIM(ctx->next))
9158 		return -1;
9159 	ctx->next[ctx->next_num++] = next;
9160 end:
9161 	if (!ctx->object)
9162 		return len;
9163 	action_rss_data = ctx->object;
9164 	action_rss_data->conf.queue_num = i;
9165 	action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
9166 	return len;
9167 }
9168 
9169 /** Setup VXLAN encap configuration. */
9170 static int
9171 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
9172 {
9173 	/* Set up default configuration. */
9174 	*action_vxlan_encap_data = (struct action_vxlan_encap_data){
9175 		.conf = (struct rte_flow_action_vxlan_encap){
9176 			.definition = action_vxlan_encap_data->items,
9177 		},
9178 		.items = {
9179 			{
9180 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9181 				.spec = &action_vxlan_encap_data->item_eth,
9182 				.mask = &rte_flow_item_eth_mask,
9183 			},
9184 			{
9185 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9186 				.spec = &action_vxlan_encap_data->item_vlan,
9187 				.mask = &rte_flow_item_vlan_mask,
9188 			},
9189 			{
9190 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9191 				.spec = &action_vxlan_encap_data->item_ipv4,
9192 				.mask = &rte_flow_item_ipv4_mask,
9193 			},
9194 			{
9195 				.type = RTE_FLOW_ITEM_TYPE_UDP,
9196 				.spec = &action_vxlan_encap_data->item_udp,
9197 				.mask = &rte_flow_item_udp_mask,
9198 			},
9199 			{
9200 				.type = RTE_FLOW_ITEM_TYPE_VXLAN,
9201 				.spec = &action_vxlan_encap_data->item_vxlan,
9202 				.mask = &rte_flow_item_vxlan_mask,
9203 			},
9204 			{
9205 				.type = RTE_FLOW_ITEM_TYPE_END,
9206 			},
9207 		},
9208 		.item_eth.hdr.ether_type = 0,
9209 		.item_vlan = {
9210 			.hdr.vlan_tci = vxlan_encap_conf.vlan_tci,
9211 			.hdr.eth_proto = 0,
9212 		},
9213 		.item_ipv4.hdr = {
9214 			.src_addr = vxlan_encap_conf.ipv4_src,
9215 			.dst_addr = vxlan_encap_conf.ipv4_dst,
9216 		},
9217 		.item_udp.hdr = {
9218 			.src_port = vxlan_encap_conf.udp_src,
9219 			.dst_port = vxlan_encap_conf.udp_dst,
9220 		},
9221 		.item_vxlan.hdr.flags = 0,
9222 	};
9223 	memcpy(action_vxlan_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9224 	       vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9225 	memcpy(action_vxlan_encap_data->item_eth.hdr.src_addr.addr_bytes,
9226 	       vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9227 	if (!vxlan_encap_conf.select_ipv4) {
9228 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
9229 		       &vxlan_encap_conf.ipv6_src,
9230 		       sizeof(vxlan_encap_conf.ipv6_src));
9231 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
9232 		       &vxlan_encap_conf.ipv6_dst,
9233 		       sizeof(vxlan_encap_conf.ipv6_dst));
9234 		action_vxlan_encap_data->items[2] = (struct rte_flow_item){
9235 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9236 			.spec = &action_vxlan_encap_data->item_ipv6,
9237 			.mask = &rte_flow_item_ipv6_mask,
9238 		};
9239 	}
9240 	if (!vxlan_encap_conf.select_vlan)
9241 		action_vxlan_encap_data->items[1].type =
9242 			RTE_FLOW_ITEM_TYPE_VOID;
9243 	if (vxlan_encap_conf.select_tos_ttl) {
9244 		if (vxlan_encap_conf.select_ipv4) {
9245 			static struct rte_flow_item_ipv4 ipv4_mask_tos;
9246 
9247 			memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
9248 			       sizeof(ipv4_mask_tos));
9249 			ipv4_mask_tos.hdr.type_of_service = 0xff;
9250 			ipv4_mask_tos.hdr.time_to_live = 0xff;
9251 			action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
9252 					vxlan_encap_conf.ip_tos;
9253 			action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
9254 					vxlan_encap_conf.ip_ttl;
9255 			action_vxlan_encap_data->items[2].mask =
9256 							&ipv4_mask_tos;
9257 		} else {
9258 			static struct rte_flow_item_ipv6 ipv6_mask_tos;
9259 
9260 			memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
9261 			       sizeof(ipv6_mask_tos));
9262 			ipv6_mask_tos.hdr.vtc_flow |=
9263 				RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
9264 			ipv6_mask_tos.hdr.hop_limits = 0xff;
9265 			action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
9266 				rte_cpu_to_be_32
9267 					((uint32_t)vxlan_encap_conf.ip_tos <<
9268 					 RTE_IPV6_HDR_TC_SHIFT);
9269 			action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
9270 					vxlan_encap_conf.ip_ttl;
9271 			action_vxlan_encap_data->items[2].mask =
9272 							&ipv6_mask_tos;
9273 		}
9274 	}
9275 	memcpy(action_vxlan_encap_data->item_vxlan.hdr.vni, vxlan_encap_conf.vni,
9276 	       RTE_DIM(vxlan_encap_conf.vni));
9277 	return 0;
9278 }
9279 
9280 /** Parse VXLAN encap action. */
9281 static int
9282 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
9283 			    const char *str, unsigned int len,
9284 			    void *buf, unsigned int size)
9285 {
9286 	struct buffer *out = buf;
9287 	struct rte_flow_action *action;
9288 	struct action_vxlan_encap_data *action_vxlan_encap_data;
9289 	int ret;
9290 
9291 	ret = parse_vc(ctx, token, str, len, buf, size);
9292 	if (ret < 0)
9293 		return ret;
9294 	/* Nothing else to do if there is no buffer. */
9295 	if (!out)
9296 		return ret;
9297 	if (!out->args.vc.actions_n)
9298 		return -1;
9299 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9300 	/* Point to selected object. */
9301 	ctx->object = out->args.vc.data;
9302 	ctx->objmask = NULL;
9303 	action_vxlan_encap_data = ctx->object;
9304 	parse_setup_vxlan_encap_data(action_vxlan_encap_data);
9305 	action->conf = &action_vxlan_encap_data->conf;
9306 	return ret;
9307 }
9308 
9309 /** Setup NVGRE encap configuration. */
9310 static int
9311 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
9312 {
9313 	/* Set up default configuration. */
9314 	*action_nvgre_encap_data = (struct action_nvgre_encap_data){
9315 		.conf = (struct rte_flow_action_nvgre_encap){
9316 			.definition = action_nvgre_encap_data->items,
9317 		},
9318 		.items = {
9319 			{
9320 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9321 				.spec = &action_nvgre_encap_data->item_eth,
9322 				.mask = &rte_flow_item_eth_mask,
9323 			},
9324 			{
9325 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9326 				.spec = &action_nvgre_encap_data->item_vlan,
9327 				.mask = &rte_flow_item_vlan_mask,
9328 			},
9329 			{
9330 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9331 				.spec = &action_nvgre_encap_data->item_ipv4,
9332 				.mask = &rte_flow_item_ipv4_mask,
9333 			},
9334 			{
9335 				.type = RTE_FLOW_ITEM_TYPE_NVGRE,
9336 				.spec = &action_nvgre_encap_data->item_nvgre,
9337 				.mask = &rte_flow_item_nvgre_mask,
9338 			},
9339 			{
9340 				.type = RTE_FLOW_ITEM_TYPE_END,
9341 			},
9342 		},
9343 		.item_eth.hdr.ether_type = 0,
9344 		.item_vlan = {
9345 			.hdr.vlan_tci = nvgre_encap_conf.vlan_tci,
9346 			.hdr.eth_proto = 0,
9347 		},
9348 		.item_ipv4.hdr = {
9349 		       .src_addr = nvgre_encap_conf.ipv4_src,
9350 		       .dst_addr = nvgre_encap_conf.ipv4_dst,
9351 		},
9352 		.item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
9353 		.item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
9354 		.item_nvgre.flow_id = 0,
9355 	};
9356 	memcpy(action_nvgre_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9357 	       nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9358 	memcpy(action_nvgre_encap_data->item_eth.hdr.src_addr.addr_bytes,
9359 	       nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9360 	if (!nvgre_encap_conf.select_ipv4) {
9361 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
9362 		       &nvgre_encap_conf.ipv6_src,
9363 		       sizeof(nvgre_encap_conf.ipv6_src));
9364 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
9365 		       &nvgre_encap_conf.ipv6_dst,
9366 		       sizeof(nvgre_encap_conf.ipv6_dst));
9367 		action_nvgre_encap_data->items[2] = (struct rte_flow_item){
9368 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9369 			.spec = &action_nvgre_encap_data->item_ipv6,
9370 			.mask = &rte_flow_item_ipv6_mask,
9371 		};
9372 	}
9373 	if (!nvgre_encap_conf.select_vlan)
9374 		action_nvgre_encap_data->items[1].type =
9375 			RTE_FLOW_ITEM_TYPE_VOID;
9376 	memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
9377 	       RTE_DIM(nvgre_encap_conf.tni));
9378 	return 0;
9379 }
9380 
9381 /** Parse NVGRE encap action. */
9382 static int
9383 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
9384 			    const char *str, unsigned int len,
9385 			    void *buf, unsigned int size)
9386 {
9387 	struct buffer *out = buf;
9388 	struct rte_flow_action *action;
9389 	struct action_nvgre_encap_data *action_nvgre_encap_data;
9390 	int ret;
9391 
9392 	ret = parse_vc(ctx, token, str, len, buf, size);
9393 	if (ret < 0)
9394 		return ret;
9395 	/* Nothing else to do if there is no buffer. */
9396 	if (!out)
9397 		return ret;
9398 	if (!out->args.vc.actions_n)
9399 		return -1;
9400 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9401 	/* Point to selected object. */
9402 	ctx->object = out->args.vc.data;
9403 	ctx->objmask = NULL;
9404 	action_nvgre_encap_data = ctx->object;
9405 	parse_setup_nvgre_encap_data(action_nvgre_encap_data);
9406 	action->conf = &action_nvgre_encap_data->conf;
9407 	return ret;
9408 }
9409 
9410 /** Parse l2 encap action. */
9411 static int
9412 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
9413 			 const char *str, unsigned int len,
9414 			 void *buf, unsigned int size)
9415 {
9416 	struct buffer *out = buf;
9417 	struct rte_flow_action *action;
9418 	struct action_raw_encap_data *action_encap_data;
9419 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9420 	struct rte_flow_item_vlan vlan = {
9421 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9422 		.hdr.eth_proto = 0,
9423 	};
9424 	uint8_t *header;
9425 	int ret;
9426 
9427 	ret = parse_vc(ctx, token, str, len, buf, size);
9428 	if (ret < 0)
9429 		return ret;
9430 	/* Nothing else to do if there is no buffer. */
9431 	if (!out)
9432 		return ret;
9433 	if (!out->args.vc.actions_n)
9434 		return -1;
9435 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9436 	/* Point to selected object. */
9437 	ctx->object = out->args.vc.data;
9438 	ctx->objmask = NULL;
9439 	/* Copy the headers to the buffer. */
9440 	action_encap_data = ctx->object;
9441 	*action_encap_data = (struct action_raw_encap_data) {
9442 		.conf = (struct rte_flow_action_raw_encap){
9443 			.data = action_encap_data->data,
9444 		},
9445 		.data = {},
9446 	};
9447 	header = action_encap_data->data;
9448 	if (l2_encap_conf.select_vlan)
9449 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9450 	else if (l2_encap_conf.select_ipv4)
9451 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9452 	else
9453 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9454 	memcpy(eth.hdr.dst_addr.addr_bytes,
9455 	       l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9456 	memcpy(eth.hdr.src_addr.addr_bytes,
9457 	       l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9458 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9459 	header += sizeof(struct rte_ether_hdr);
9460 	if (l2_encap_conf.select_vlan) {
9461 		if (l2_encap_conf.select_ipv4)
9462 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9463 		else
9464 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9465 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9466 		header += sizeof(struct rte_vlan_hdr);
9467 	}
9468 	action_encap_data->conf.size = header -
9469 		action_encap_data->data;
9470 	action->conf = &action_encap_data->conf;
9471 	return ret;
9472 }
9473 
9474 /** Parse l2 decap action. */
9475 static int
9476 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
9477 			 const char *str, unsigned int len,
9478 			 void *buf, unsigned int size)
9479 {
9480 	struct buffer *out = buf;
9481 	struct rte_flow_action *action;
9482 	struct action_raw_decap_data *action_decap_data;
9483 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9484 	struct rte_flow_item_vlan vlan = {
9485 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9486 		.hdr.eth_proto = 0,
9487 	};
9488 	uint8_t *header;
9489 	int ret;
9490 
9491 	ret = parse_vc(ctx, token, str, len, buf, size);
9492 	if (ret < 0)
9493 		return ret;
9494 	/* Nothing else to do if there is no buffer. */
9495 	if (!out)
9496 		return ret;
9497 	if (!out->args.vc.actions_n)
9498 		return -1;
9499 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9500 	/* Point to selected object. */
9501 	ctx->object = out->args.vc.data;
9502 	ctx->objmask = NULL;
9503 	/* Copy the headers to the buffer. */
9504 	action_decap_data = ctx->object;
9505 	*action_decap_data = (struct action_raw_decap_data) {
9506 		.conf = (struct rte_flow_action_raw_decap){
9507 			.data = action_decap_data->data,
9508 		},
9509 		.data = {},
9510 	};
9511 	header = action_decap_data->data;
9512 	if (l2_decap_conf.select_vlan)
9513 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9514 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9515 	header += sizeof(struct rte_ether_hdr);
9516 	if (l2_decap_conf.select_vlan) {
9517 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9518 		header += sizeof(struct rte_vlan_hdr);
9519 	}
9520 	action_decap_data->conf.size = header -
9521 		action_decap_data->data;
9522 	action->conf = &action_decap_data->conf;
9523 	return ret;
9524 }
9525 
9526 #define ETHER_TYPE_MPLS_UNICAST 0x8847
9527 
9528 /** Parse MPLSOGRE encap action. */
9529 static int
9530 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
9531 			       const char *str, unsigned int len,
9532 			       void *buf, unsigned int size)
9533 {
9534 	struct buffer *out = buf;
9535 	struct rte_flow_action *action;
9536 	struct action_raw_encap_data *action_encap_data;
9537 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9538 	struct rte_flow_item_vlan vlan = {
9539 		.hdr.vlan_tci = mplsogre_encap_conf.vlan_tci,
9540 		.hdr.eth_proto = 0,
9541 	};
9542 	struct rte_flow_item_ipv4 ipv4 = {
9543 		.hdr =  {
9544 			.src_addr = mplsogre_encap_conf.ipv4_src,
9545 			.dst_addr = mplsogre_encap_conf.ipv4_dst,
9546 			.next_proto_id = IPPROTO_GRE,
9547 			.version_ihl = RTE_IPV4_VHL_DEF,
9548 			.time_to_live = IPDEFTTL,
9549 		},
9550 	};
9551 	struct rte_flow_item_ipv6 ipv6 = {
9552 		.hdr =  {
9553 			.proto = IPPROTO_GRE,
9554 			.hop_limits = IPDEFTTL,
9555 		},
9556 	};
9557 	struct rte_flow_item_gre gre = {
9558 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9559 	};
9560 	struct rte_flow_item_mpls mpls = {
9561 		.ttl = 0,
9562 	};
9563 	uint8_t *header;
9564 	int ret;
9565 
9566 	ret = parse_vc(ctx, token, str, len, buf, size);
9567 	if (ret < 0)
9568 		return ret;
9569 	/* Nothing else to do if there is no buffer. */
9570 	if (!out)
9571 		return ret;
9572 	if (!out->args.vc.actions_n)
9573 		return -1;
9574 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9575 	/* Point to selected object. */
9576 	ctx->object = out->args.vc.data;
9577 	ctx->objmask = NULL;
9578 	/* Copy the headers to the buffer. */
9579 	action_encap_data = ctx->object;
9580 	*action_encap_data = (struct action_raw_encap_data) {
9581 		.conf = (struct rte_flow_action_raw_encap){
9582 			.data = action_encap_data->data,
9583 		},
9584 		.data = {},
9585 		.preserve = {},
9586 	};
9587 	header = action_encap_data->data;
9588 	if (mplsogre_encap_conf.select_vlan)
9589 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9590 	else if (mplsogre_encap_conf.select_ipv4)
9591 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9592 	else
9593 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9594 	memcpy(eth.hdr.dst_addr.addr_bytes,
9595 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9596 	memcpy(eth.hdr.src_addr.addr_bytes,
9597 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9598 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9599 	header += sizeof(struct rte_ether_hdr);
9600 	if (mplsogre_encap_conf.select_vlan) {
9601 		if (mplsogre_encap_conf.select_ipv4)
9602 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9603 		else
9604 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9605 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9606 		header += sizeof(struct rte_vlan_hdr);
9607 	}
9608 	if (mplsogre_encap_conf.select_ipv4) {
9609 		memcpy(header, &ipv4, sizeof(ipv4));
9610 		header += sizeof(ipv4);
9611 	} else {
9612 		memcpy(&ipv6.hdr.src_addr,
9613 		       &mplsogre_encap_conf.ipv6_src,
9614 		       sizeof(mplsogre_encap_conf.ipv6_src));
9615 		memcpy(&ipv6.hdr.dst_addr,
9616 		       &mplsogre_encap_conf.ipv6_dst,
9617 		       sizeof(mplsogre_encap_conf.ipv6_dst));
9618 		memcpy(header, &ipv6, sizeof(ipv6));
9619 		header += sizeof(ipv6);
9620 	}
9621 	memcpy(header, &gre, sizeof(gre));
9622 	header += sizeof(gre);
9623 	memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
9624 	       RTE_DIM(mplsogre_encap_conf.label));
9625 	mpls.label_tc_s[2] |= 0x1;
9626 	memcpy(header, &mpls, sizeof(mpls));
9627 	header += sizeof(mpls);
9628 	action_encap_data->conf.size = header -
9629 		action_encap_data->data;
9630 	action->conf = &action_encap_data->conf;
9631 	return ret;
9632 }
9633 
9634 /** Parse MPLSOGRE decap action. */
9635 static int
9636 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
9637 			       const char *str, unsigned int len,
9638 			       void *buf, unsigned int size)
9639 {
9640 	struct buffer *out = buf;
9641 	struct rte_flow_action *action;
9642 	struct action_raw_decap_data *action_decap_data;
9643 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9644 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
9645 	struct rte_flow_item_ipv4 ipv4 = {
9646 		.hdr =  {
9647 			.next_proto_id = IPPROTO_GRE,
9648 		},
9649 	};
9650 	struct rte_flow_item_ipv6 ipv6 = {
9651 		.hdr =  {
9652 			.proto = IPPROTO_GRE,
9653 		},
9654 	};
9655 	struct rte_flow_item_gre gre = {
9656 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9657 	};
9658 	struct rte_flow_item_mpls mpls;
9659 	uint8_t *header;
9660 	int ret;
9661 
9662 	ret = parse_vc(ctx, token, str, len, buf, size);
9663 	if (ret < 0)
9664 		return ret;
9665 	/* Nothing else to do if there is no buffer. */
9666 	if (!out)
9667 		return ret;
9668 	if (!out->args.vc.actions_n)
9669 		return -1;
9670 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9671 	/* Point to selected object. */
9672 	ctx->object = out->args.vc.data;
9673 	ctx->objmask = NULL;
9674 	/* Copy the headers to the buffer. */
9675 	action_decap_data = ctx->object;
9676 	*action_decap_data = (struct action_raw_decap_data) {
9677 		.conf = (struct rte_flow_action_raw_decap){
9678 			.data = action_decap_data->data,
9679 		},
9680 		.data = {},
9681 	};
9682 	header = action_decap_data->data;
9683 	if (mplsogre_decap_conf.select_vlan)
9684 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9685 	else if (mplsogre_encap_conf.select_ipv4)
9686 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9687 	else
9688 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9689 	memcpy(eth.hdr.dst_addr.addr_bytes,
9690 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9691 	memcpy(eth.hdr.src_addr.addr_bytes,
9692 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9693 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9694 	header += sizeof(struct rte_ether_hdr);
9695 	if (mplsogre_encap_conf.select_vlan) {
9696 		if (mplsogre_encap_conf.select_ipv4)
9697 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9698 		else
9699 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9700 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9701 		header += sizeof(struct rte_vlan_hdr);
9702 	}
9703 	if (mplsogre_encap_conf.select_ipv4) {
9704 		memcpy(header, &ipv4, sizeof(ipv4));
9705 		header += sizeof(ipv4);
9706 	} else {
9707 		memcpy(header, &ipv6, sizeof(ipv6));
9708 		header += sizeof(ipv6);
9709 	}
9710 	memcpy(header, &gre, sizeof(gre));
9711 	header += sizeof(gre);
9712 	memset(&mpls, 0, sizeof(mpls));
9713 	memcpy(header, &mpls, sizeof(mpls));
9714 	header += sizeof(mpls);
9715 	action_decap_data->conf.size = header -
9716 		action_decap_data->data;
9717 	action->conf = &action_decap_data->conf;
9718 	return ret;
9719 }
9720 
9721 /** Parse MPLSOUDP encap action. */
9722 static int
9723 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
9724 			       const char *str, unsigned int len,
9725 			       void *buf, unsigned int size)
9726 {
9727 	struct buffer *out = buf;
9728 	struct rte_flow_action *action;
9729 	struct action_raw_encap_data *action_encap_data;
9730 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9731 	struct rte_flow_item_vlan vlan = {
9732 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9733 		.hdr.eth_proto = 0,
9734 	};
9735 	struct rte_flow_item_ipv4 ipv4 = {
9736 		.hdr =  {
9737 			.src_addr = mplsoudp_encap_conf.ipv4_src,
9738 			.dst_addr = mplsoudp_encap_conf.ipv4_dst,
9739 			.next_proto_id = IPPROTO_UDP,
9740 			.version_ihl = RTE_IPV4_VHL_DEF,
9741 			.time_to_live = IPDEFTTL,
9742 		},
9743 	};
9744 	struct rte_flow_item_ipv6 ipv6 = {
9745 		.hdr =  {
9746 			.proto = IPPROTO_UDP,
9747 			.hop_limits = IPDEFTTL,
9748 		},
9749 	};
9750 	struct rte_flow_item_udp udp = {
9751 		.hdr = {
9752 			.src_port = mplsoudp_encap_conf.udp_src,
9753 			.dst_port = mplsoudp_encap_conf.udp_dst,
9754 		},
9755 	};
9756 	struct rte_flow_item_mpls mpls;
9757 	uint8_t *header;
9758 	int ret;
9759 
9760 	ret = parse_vc(ctx, token, str, len, buf, size);
9761 	if (ret < 0)
9762 		return ret;
9763 	/* Nothing else to do if there is no buffer. */
9764 	if (!out)
9765 		return ret;
9766 	if (!out->args.vc.actions_n)
9767 		return -1;
9768 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9769 	/* Point to selected object. */
9770 	ctx->object = out->args.vc.data;
9771 	ctx->objmask = NULL;
9772 	/* Copy the headers to the buffer. */
9773 	action_encap_data = ctx->object;
9774 	*action_encap_data = (struct action_raw_encap_data) {
9775 		.conf = (struct rte_flow_action_raw_encap){
9776 			.data = action_encap_data->data,
9777 		},
9778 		.data = {},
9779 		.preserve = {},
9780 	};
9781 	header = action_encap_data->data;
9782 	if (mplsoudp_encap_conf.select_vlan)
9783 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9784 	else if (mplsoudp_encap_conf.select_ipv4)
9785 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9786 	else
9787 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9788 	memcpy(eth.hdr.dst_addr.addr_bytes,
9789 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9790 	memcpy(eth.hdr.src_addr.addr_bytes,
9791 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9792 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9793 	header += sizeof(struct rte_ether_hdr);
9794 	if (mplsoudp_encap_conf.select_vlan) {
9795 		if (mplsoudp_encap_conf.select_ipv4)
9796 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9797 		else
9798 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9799 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9800 		header += sizeof(struct rte_vlan_hdr);
9801 	}
9802 	if (mplsoudp_encap_conf.select_ipv4) {
9803 		memcpy(header, &ipv4, sizeof(ipv4));
9804 		header += sizeof(ipv4);
9805 	} else {
9806 		memcpy(&ipv6.hdr.src_addr,
9807 		       &mplsoudp_encap_conf.ipv6_src,
9808 		       sizeof(mplsoudp_encap_conf.ipv6_src));
9809 		memcpy(&ipv6.hdr.dst_addr,
9810 		       &mplsoudp_encap_conf.ipv6_dst,
9811 		       sizeof(mplsoudp_encap_conf.ipv6_dst));
9812 		memcpy(header, &ipv6, sizeof(ipv6));
9813 		header += sizeof(ipv6);
9814 	}
9815 	memcpy(header, &udp, sizeof(udp));
9816 	header += sizeof(udp);
9817 	memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
9818 	       RTE_DIM(mplsoudp_encap_conf.label));
9819 	mpls.label_tc_s[2] |= 0x1;
9820 	memcpy(header, &mpls, sizeof(mpls));
9821 	header += sizeof(mpls);
9822 	action_encap_data->conf.size = header -
9823 		action_encap_data->data;
9824 	action->conf = &action_encap_data->conf;
9825 	return ret;
9826 }
9827 
9828 /** Parse MPLSOUDP decap action. */
9829 static int
9830 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
9831 			       const char *str, unsigned int len,
9832 			       void *buf, unsigned int size)
9833 {
9834 	struct buffer *out = buf;
9835 	struct rte_flow_action *action;
9836 	struct action_raw_decap_data *action_decap_data;
9837 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9838 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
9839 	struct rte_flow_item_ipv4 ipv4 = {
9840 		.hdr =  {
9841 			.next_proto_id = IPPROTO_UDP,
9842 		},
9843 	};
9844 	struct rte_flow_item_ipv6 ipv6 = {
9845 		.hdr =  {
9846 			.proto = IPPROTO_UDP,
9847 		},
9848 	};
9849 	struct rte_flow_item_udp udp = {
9850 		.hdr = {
9851 			.dst_port = rte_cpu_to_be_16(6635),
9852 		},
9853 	};
9854 	struct rte_flow_item_mpls mpls;
9855 	uint8_t *header;
9856 	int ret;
9857 
9858 	ret = parse_vc(ctx, token, str, len, buf, size);
9859 	if (ret < 0)
9860 		return ret;
9861 	/* Nothing else to do if there is no buffer. */
9862 	if (!out)
9863 		return ret;
9864 	if (!out->args.vc.actions_n)
9865 		return -1;
9866 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9867 	/* Point to selected object. */
9868 	ctx->object = out->args.vc.data;
9869 	ctx->objmask = NULL;
9870 	/* Copy the headers to the buffer. */
9871 	action_decap_data = ctx->object;
9872 	*action_decap_data = (struct action_raw_decap_data) {
9873 		.conf = (struct rte_flow_action_raw_decap){
9874 			.data = action_decap_data->data,
9875 		},
9876 		.data = {},
9877 	};
9878 	header = action_decap_data->data;
9879 	if (mplsoudp_decap_conf.select_vlan)
9880 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9881 	else if (mplsoudp_encap_conf.select_ipv4)
9882 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9883 	else
9884 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9885 	memcpy(eth.hdr.dst_addr.addr_bytes,
9886 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9887 	memcpy(eth.hdr.src_addr.addr_bytes,
9888 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9889 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9890 	header += sizeof(struct rte_ether_hdr);
9891 	if (mplsoudp_encap_conf.select_vlan) {
9892 		if (mplsoudp_encap_conf.select_ipv4)
9893 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9894 		else
9895 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9896 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9897 		header += sizeof(struct rte_vlan_hdr);
9898 	}
9899 	if (mplsoudp_encap_conf.select_ipv4) {
9900 		memcpy(header, &ipv4, sizeof(ipv4));
9901 		header += sizeof(ipv4);
9902 	} else {
9903 		memcpy(header, &ipv6, sizeof(ipv6));
9904 		header += sizeof(ipv6);
9905 	}
9906 	memcpy(header, &udp, sizeof(udp));
9907 	header += sizeof(udp);
9908 	memset(&mpls, 0, sizeof(mpls));
9909 	memcpy(header, &mpls, sizeof(mpls));
9910 	header += sizeof(mpls);
9911 	action_decap_data->conf.size = header -
9912 		action_decap_data->data;
9913 	action->conf = &action_decap_data->conf;
9914 	return ret;
9915 }
9916 
9917 static int
9918 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
9919 				const char *str, unsigned int len, void *buf,
9920 				unsigned int size)
9921 {
9922 	struct action_raw_decap_data *action_raw_decap_data;
9923 	struct rte_flow_action *action;
9924 	const struct arg *arg;
9925 	struct buffer *out = buf;
9926 	int ret;
9927 	uint16_t idx;
9928 
9929 	RTE_SET_USED(token);
9930 	RTE_SET_USED(buf);
9931 	RTE_SET_USED(size);
9932 	arg = ARGS_ENTRY_ARB_BOUNDED
9933 		(offsetof(struct action_raw_decap_data, idx),
9934 		 sizeof(((struct action_raw_decap_data *)0)->idx),
9935 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
9936 	if (push_args(ctx, arg))
9937 		return -1;
9938 	ret = parse_int(ctx, token, str, len, NULL, 0);
9939 	if (ret < 0) {
9940 		pop_args(ctx);
9941 		return -1;
9942 	}
9943 	if (!ctx->object)
9944 		return len;
9945 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9946 	action_raw_decap_data = ctx->object;
9947 	idx = action_raw_decap_data->idx;
9948 	action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
9949 	action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
9950 	action->conf = &action_raw_decap_data->conf;
9951 	return len;
9952 }
9953 
9954 
9955 static int
9956 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
9957 				const char *str, unsigned int len, void *buf,
9958 				unsigned int size)
9959 {
9960 	struct action_raw_encap_data *action_raw_encap_data;
9961 	struct rte_flow_action *action;
9962 	const struct arg *arg;
9963 	struct buffer *out = buf;
9964 	int ret;
9965 	uint16_t idx;
9966 
9967 	RTE_SET_USED(token);
9968 	RTE_SET_USED(buf);
9969 	RTE_SET_USED(size);
9970 	if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
9971 		return -1;
9972 	arg = ARGS_ENTRY_ARB_BOUNDED
9973 		(offsetof(struct action_raw_encap_data, idx),
9974 		 sizeof(((struct action_raw_encap_data *)0)->idx),
9975 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
9976 	if (push_args(ctx, arg))
9977 		return -1;
9978 	ret = parse_int(ctx, token, str, len, NULL, 0);
9979 	if (ret < 0) {
9980 		pop_args(ctx);
9981 		return -1;
9982 	}
9983 	if (!ctx->object)
9984 		return len;
9985 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9986 	action_raw_encap_data = ctx->object;
9987 	idx = action_raw_encap_data->idx;
9988 	action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
9989 	action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
9990 	action_raw_encap_data->conf.preserve = NULL;
9991 	action->conf = &action_raw_encap_data->conf;
9992 	return len;
9993 }
9994 
9995 static int
9996 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
9997 			  const char *str, unsigned int len, void *buf,
9998 			  unsigned int size)
9999 {
10000 	struct buffer *out = buf;
10001 	int ret;
10002 
10003 	ret = parse_vc(ctx, token, str, len, buf, size);
10004 	if (ret < 0)
10005 		return ret;
10006 	/* Nothing else to do if there is no buffer. */
10007 	if (!out)
10008 		return ret;
10009 	if (!out->args.vc.actions_n)
10010 		return -1;
10011 	/* Point to selected object. */
10012 	ctx->object = out->args.vc.data;
10013 	ctx->objmask = NULL;
10014 	return ret;
10015 }
10016 
10017 static int
10018 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
10019 			  const char *str, unsigned int len, void *buf,
10020 			  unsigned int size)
10021 {
10022 	struct buffer *out = buf;
10023 	struct rte_flow_action *action;
10024 	struct action_raw_decap_data *action_raw_decap_data = NULL;
10025 	int ret;
10026 
10027 	ret = parse_vc(ctx, token, str, len, buf, size);
10028 	if (ret < 0)
10029 		return ret;
10030 	/* Nothing else to do if there is no buffer. */
10031 	if (!out)
10032 		return ret;
10033 	if (!out->args.vc.actions_n)
10034 		return -1;
10035 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10036 	/* Point to selected object. */
10037 	ctx->object = out->args.vc.data;
10038 	ctx->objmask = NULL;
10039 	/* Copy the headers to the buffer. */
10040 	action_raw_decap_data = ctx->object;
10041 	action_raw_decap_data->conf.data = raw_decap_confs[0].data;
10042 	action_raw_decap_data->conf.size = raw_decap_confs[0].size;
10043 	action->conf = &action_raw_decap_data->conf;
10044 	return ret;
10045 }
10046 
10047 static int
10048 parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
10049 				const char *str, unsigned int len, void *buf,
10050 				unsigned int size)
10051 {
10052 	struct buffer *out = buf;
10053 	struct rte_flow_action *action;
10054 	struct action_ipv6_ext_remove_data *ipv6_ext_remove_data = NULL;
10055 	int ret;
10056 
10057 	ret = parse_vc(ctx, token, str, len, buf, size);
10058 	if (ret < 0)
10059 		return ret;
10060 	/* Nothing else to do if there is no buffer. */
10061 	if (!out)
10062 		return ret;
10063 	if (!out->args.vc.actions_n)
10064 		return -1;
10065 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10066 	/* Point to selected object. */
10067 	ctx->object = out->args.vc.data;
10068 	ctx->objmask = NULL;
10069 	/* Copy the headers to the buffer. */
10070 	ipv6_ext_remove_data = ctx->object;
10071 	ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[0].type;
10072 	action->conf = &ipv6_ext_remove_data->conf;
10073 	return ret;
10074 }
10075 
10076 static int
10077 parse_vc_action_ipv6_ext_remove_index(struct context *ctx, const struct token *token,
10078 				      const char *str, unsigned int len, void *buf,
10079 				      unsigned int size)
10080 {
10081 	struct action_ipv6_ext_remove_data *action_ipv6_ext_remove_data;
10082 	struct rte_flow_action *action;
10083 	const struct arg *arg;
10084 	struct buffer *out = buf;
10085 	int ret;
10086 	uint16_t idx;
10087 
10088 	RTE_SET_USED(token);
10089 	RTE_SET_USED(buf);
10090 	RTE_SET_USED(size);
10091 	arg = ARGS_ENTRY_ARB_BOUNDED
10092 		(offsetof(struct action_ipv6_ext_remove_data, idx),
10093 		 sizeof(((struct action_ipv6_ext_remove_data *)0)->idx),
10094 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10095 	if (push_args(ctx, arg))
10096 		return -1;
10097 	ret = parse_int(ctx, token, str, len, NULL, 0);
10098 	if (ret < 0) {
10099 		pop_args(ctx);
10100 		return -1;
10101 	}
10102 	if (!ctx->object)
10103 		return len;
10104 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10105 	action_ipv6_ext_remove_data = ctx->object;
10106 	idx = action_ipv6_ext_remove_data->idx;
10107 	action_ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[idx].type;
10108 	action->conf = &action_ipv6_ext_remove_data->conf;
10109 	return len;
10110 }
10111 
10112 static int
10113 parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
10114 			      const char *str, unsigned int len, void *buf,
10115 			      unsigned int size)
10116 {
10117 	struct buffer *out = buf;
10118 	struct rte_flow_action *action;
10119 	struct action_ipv6_ext_push_data *ipv6_ext_push_data = NULL;
10120 	int ret;
10121 
10122 	ret = parse_vc(ctx, token, str, len, buf, size);
10123 	if (ret < 0)
10124 		return ret;
10125 	/* Nothing else to do if there is no buffer. */
10126 	if (!out)
10127 		return ret;
10128 	if (!out->args.vc.actions_n)
10129 		return -1;
10130 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10131 	/* Point to selected object. */
10132 	ctx->object = out->args.vc.data;
10133 	ctx->objmask = NULL;
10134 	/* Copy the headers to the buffer. */
10135 	ipv6_ext_push_data = ctx->object;
10136 	ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[0].type;
10137 	ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[0].data;
10138 	ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[0].size;
10139 	action->conf = &ipv6_ext_push_data->conf;
10140 	return ret;
10141 }
10142 
10143 static int
10144 parse_vc_action_ipv6_ext_push_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_ipv6_ext_push_data *action_ipv6_ext_push_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 	arg = ARGS_ENTRY_ARB_BOUNDED
10159 		(offsetof(struct action_ipv6_ext_push_data, idx),
10160 		 sizeof(((struct action_ipv6_ext_push_data *)0)->idx),
10161 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10162 	if (push_args(ctx, arg))
10163 		return -1;
10164 	ret = parse_int(ctx, token, str, len, NULL, 0);
10165 	if (ret < 0) {
10166 		pop_args(ctx);
10167 		return -1;
10168 	}
10169 	if (!ctx->object)
10170 		return len;
10171 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10172 	action_ipv6_ext_push_data = ctx->object;
10173 	idx = action_ipv6_ext_push_data->idx;
10174 	action_ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[idx].type;
10175 	action_ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[idx].size;
10176 	action_ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[idx].data;
10177 	action->conf = &action_ipv6_ext_push_data->conf;
10178 	return len;
10179 }
10180 
10181 static int
10182 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
10183 			 const char *str, unsigned int len, void *buf,
10184 			 unsigned int size)
10185 {
10186 	int ret;
10187 
10188 	ret = parse_vc(ctx, token, str, len, buf, size);
10189 	if (ret < 0)
10190 		return ret;
10191 	ret = rte_flow_dynf_metadata_register();
10192 	if (ret < 0)
10193 		return -1;
10194 	return len;
10195 }
10196 
10197 static int
10198 parse_vc_action_sample(struct context *ctx, const struct token *token,
10199 			 const char *str, unsigned int len, void *buf,
10200 			 unsigned int size)
10201 {
10202 	struct buffer *out = buf;
10203 	struct rte_flow_action *action;
10204 	struct action_sample_data *action_sample_data = NULL;
10205 	static struct rte_flow_action end_action = {
10206 		RTE_FLOW_ACTION_TYPE_END, 0
10207 	};
10208 	int ret;
10209 
10210 	ret = parse_vc(ctx, token, str, len, buf, size);
10211 	if (ret < 0)
10212 		return ret;
10213 	/* Nothing else to do if there is no buffer. */
10214 	if (!out)
10215 		return ret;
10216 	if (!out->args.vc.actions_n)
10217 		return -1;
10218 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10219 	/* Point to selected object. */
10220 	ctx->object = out->args.vc.data;
10221 	ctx->objmask = NULL;
10222 	/* Copy the headers to the buffer. */
10223 	action_sample_data = ctx->object;
10224 	action_sample_data->conf.actions = &end_action;
10225 	action->conf = &action_sample_data->conf;
10226 	return ret;
10227 }
10228 
10229 static int
10230 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
10231 				const char *str, unsigned int len, void *buf,
10232 				unsigned int size)
10233 {
10234 	struct action_sample_data *action_sample_data;
10235 	struct rte_flow_action *action;
10236 	const struct arg *arg;
10237 	struct buffer *out = buf;
10238 	int ret;
10239 	uint16_t idx;
10240 
10241 	RTE_SET_USED(token);
10242 	RTE_SET_USED(buf);
10243 	RTE_SET_USED(size);
10244 	if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
10245 		return -1;
10246 	arg = ARGS_ENTRY_ARB_BOUNDED
10247 		(offsetof(struct action_sample_data, idx),
10248 		 sizeof(((struct action_sample_data *)0)->idx),
10249 		 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
10250 	if (push_args(ctx, arg))
10251 		return -1;
10252 	ret = parse_int(ctx, token, str, len, NULL, 0);
10253 	if (ret < 0) {
10254 		pop_args(ctx);
10255 		return -1;
10256 	}
10257 	if (!ctx->object)
10258 		return len;
10259 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10260 	action_sample_data = ctx->object;
10261 	idx = action_sample_data->idx;
10262 	action_sample_data->conf.actions = raw_sample_confs[idx].data;
10263 	action->conf = &action_sample_data->conf;
10264 	return len;
10265 }
10266 
10267 /** Parse operation for modify_field command. */
10268 static int
10269 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
10270 			 const char *str, unsigned int len, void *buf,
10271 			 unsigned int size)
10272 {
10273 	struct rte_flow_action_modify_field *action_modify_field;
10274 	unsigned int i;
10275 
10276 	(void)token;
10277 	(void)buf;
10278 	(void)size;
10279 	if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
10280 		return -1;
10281 	for (i = 0; modify_field_ops[i]; ++i)
10282 		if (!strcmp_partial(modify_field_ops[i], str, len))
10283 			break;
10284 	if (!modify_field_ops[i])
10285 		return -1;
10286 	if (!ctx->object)
10287 		return len;
10288 	action_modify_field = ctx->object;
10289 	action_modify_field->operation = (enum rte_flow_modify_op)i;
10290 	return len;
10291 }
10292 
10293 /** Parse id for modify_field command. */
10294 static int
10295 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
10296 			 const char *str, unsigned int len, void *buf,
10297 			 unsigned int size)
10298 {
10299 	struct rte_flow_action_modify_field *action_modify_field;
10300 	unsigned int i;
10301 
10302 	(void)token;
10303 	(void)buf;
10304 	(void)size;
10305 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
10306 		ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
10307 		return -1;
10308 	for (i = 0; flow_field_ids[i]; ++i)
10309 		if (!strcmp_partial(flow_field_ids[i], str, len))
10310 			break;
10311 	if (!flow_field_ids[i])
10312 		return -1;
10313 	if (!ctx->object)
10314 		return len;
10315 	action_modify_field = ctx->object;
10316 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
10317 		action_modify_field->dst.field = (enum rte_flow_field_id)i;
10318 	else
10319 		action_modify_field->src.field = (enum rte_flow_field_id)i;
10320 	return len;
10321 }
10322 
10323 /** Parse level for modify_field command. */
10324 static int
10325 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
10326 			 const char *str, unsigned int len, void *buf,
10327 			 unsigned int size)
10328 {
10329 	struct rte_flow_action_modify_field *action;
10330 	struct flex_item *fp = NULL;
10331 	uint32_t val;
10332 	struct buffer *out = buf;
10333 	char *end;
10334 
10335 	(void)token;
10336 	(void)size;
10337 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10338 		ctx->curr != ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)
10339 		return -1;
10340 	if (!ctx->object)
10341 		return len;
10342 	action = ctx->object;
10343 	errno = 0;
10344 	val = strtoumax(str, &end, 0);
10345 	if (errno || (size_t)(end - str) != len)
10346 		return -1;
10347 	/* No need to validate action template mask value */
10348 	if (out->args.vc.masks) {
10349 		if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)
10350 			action->dst.level = val;
10351 		else
10352 			action->src.level = val;
10353 		return len;
10354 	}
10355 	if ((ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10356 		action->dst.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
10357 		(ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE &&
10358 		action->src.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
10359 		if (val >= FLEX_MAX_PARSERS_NUM) {
10360 			printf("Bad flex item handle\n");
10361 			return -1;
10362 		}
10363 		fp = flex_items[ctx->port][val];
10364 		if (!fp) {
10365 			printf("Bad flex item handle\n");
10366 			return -1;
10367 		}
10368 	}
10369 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE) {
10370 		if (action->dst.field != RTE_FLOW_FIELD_FLEX_ITEM)
10371 			action->dst.level = val;
10372 		else
10373 			action->dst.flex_handle = fp->flex_handle;
10374 	} else if (ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE) {
10375 		if (action->src.field != RTE_FLOW_FIELD_FLEX_ITEM)
10376 			action->src.level = val;
10377 		else
10378 			action->src.flex_handle = fp->flex_handle;
10379 	}
10380 	return len;
10381 }
10382 
10383 /** Parse the conntrack update, not a rte_flow_action. */
10384 static int
10385 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
10386 			 const char *str, unsigned int len, void *buf,
10387 			 unsigned int size)
10388 {
10389 	struct buffer *out = buf;
10390 	struct rte_flow_modify_conntrack *ct_modify = NULL;
10391 
10392 	(void)size;
10393 	if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
10394 	    ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
10395 		return -1;
10396 	/* Token name must match. */
10397 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10398 		return -1;
10399 	/* Nothing else to do if there is no buffer. */
10400 	if (!out)
10401 		return len;
10402 	ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
10403 	if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
10404 		ct_modify->new_ct.is_original_dir =
10405 				conntrack_context.is_original_dir;
10406 		ct_modify->direction = 1;
10407 	} else {
10408 		uint32_t old_dir;
10409 
10410 		old_dir = ct_modify->new_ct.is_original_dir;
10411 		memcpy(&ct_modify->new_ct, &conntrack_context,
10412 		       sizeof(conntrack_context));
10413 		ct_modify->new_ct.is_original_dir = old_dir;
10414 		ct_modify->state = 1;
10415 	}
10416 	return len;
10417 }
10418 
10419 /** Parse tokens for destroy command. */
10420 static int
10421 parse_destroy(struct context *ctx, const struct token *token,
10422 	      const char *str, unsigned int len,
10423 	      void *buf, unsigned int size)
10424 {
10425 	struct buffer *out = buf;
10426 
10427 	/* Token name must match. */
10428 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10429 		return -1;
10430 	/* Nothing else to do if there is no buffer. */
10431 	if (!out)
10432 		return len;
10433 	if (!out->command) {
10434 		if (ctx->curr != DESTROY)
10435 			return -1;
10436 		if (sizeof(*out) > size)
10437 			return -1;
10438 		out->command = ctx->curr;
10439 		ctx->objdata = 0;
10440 		ctx->object = out;
10441 		ctx->objmask = NULL;
10442 		out->args.destroy.rule =
10443 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10444 					       sizeof(double));
10445 		return len;
10446 	}
10447 	if (ctx->curr == DESTROY_IS_USER_ID) {
10448 		out->args.destroy.is_user_id = true;
10449 		return len;
10450 	}
10451 	if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
10452 	     sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
10453 		return -1;
10454 	ctx->objdata = 0;
10455 	ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
10456 	ctx->objmask = NULL;
10457 	return len;
10458 }
10459 
10460 /** Parse tokens for flush command. */
10461 static int
10462 parse_flush(struct context *ctx, const struct token *token,
10463 	    const char *str, unsigned int len,
10464 	    void *buf, unsigned int size)
10465 {
10466 	struct buffer *out = buf;
10467 
10468 	/* Token name must match. */
10469 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10470 		return -1;
10471 	/* Nothing else to do if there is no buffer. */
10472 	if (!out)
10473 		return len;
10474 	if (!out->command) {
10475 		if (ctx->curr != FLUSH)
10476 			return -1;
10477 		if (sizeof(*out) > size)
10478 			return -1;
10479 		out->command = ctx->curr;
10480 		ctx->objdata = 0;
10481 		ctx->object = out;
10482 		ctx->objmask = NULL;
10483 	}
10484 	return len;
10485 }
10486 
10487 /** Parse tokens for dump command. */
10488 static int
10489 parse_dump(struct context *ctx, const struct token *token,
10490 	    const char *str, unsigned int len,
10491 	    void *buf, unsigned int size)
10492 {
10493 	struct buffer *out = buf;
10494 
10495 	/* Token name must match. */
10496 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10497 		return -1;
10498 	/* Nothing else to do if there is no buffer. */
10499 	if (!out)
10500 		return len;
10501 	if (!out->command) {
10502 		if (ctx->curr != DUMP)
10503 			return -1;
10504 		if (sizeof(*out) > size)
10505 			return -1;
10506 		out->command = ctx->curr;
10507 		ctx->objdata = 0;
10508 		ctx->object = out;
10509 		ctx->objmask = NULL;
10510 		return len;
10511 	}
10512 	switch (ctx->curr) {
10513 	case DUMP_ALL:
10514 	case DUMP_ONE:
10515 		out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
10516 		out->command = ctx->curr;
10517 		ctx->objdata = 0;
10518 		ctx->object = out;
10519 		ctx->objmask = NULL;
10520 		return len;
10521 	case DUMP_IS_USER_ID:
10522 		out->args.dump.is_user_id = true;
10523 		return len;
10524 	default:
10525 		return -1;
10526 	}
10527 }
10528 
10529 /** Parse tokens for query command. */
10530 static int
10531 parse_query(struct context *ctx, const struct token *token,
10532 	    const char *str, unsigned int len,
10533 	    void *buf, unsigned int size)
10534 {
10535 	struct buffer *out = buf;
10536 
10537 	/* Token name must match. */
10538 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10539 		return -1;
10540 	/* Nothing else to do if there is no buffer. */
10541 	if (!out)
10542 		return len;
10543 	if (!out->command) {
10544 		if (ctx->curr != QUERY)
10545 			return -1;
10546 		if (sizeof(*out) > size)
10547 			return -1;
10548 		out->command = ctx->curr;
10549 		ctx->objdata = 0;
10550 		ctx->object = out;
10551 		ctx->objmask = NULL;
10552 	}
10553 	if (ctx->curr == QUERY_IS_USER_ID) {
10554 		out->args.query.is_user_id = true;
10555 		return len;
10556 	}
10557 	return len;
10558 }
10559 
10560 /** Parse action names. */
10561 static int
10562 parse_action(struct context *ctx, const struct token *token,
10563 	     const char *str, unsigned int len,
10564 	     void *buf, unsigned int size)
10565 {
10566 	struct buffer *out = buf;
10567 	const struct arg *arg = pop_args(ctx);
10568 	unsigned int i;
10569 
10570 	(void)size;
10571 	/* Argument is expected. */
10572 	if (!arg)
10573 		return -1;
10574 	/* Parse action name. */
10575 	for (i = 0; next_action[i]; ++i) {
10576 		const struct parse_action_priv *priv;
10577 
10578 		token = &token_list[next_action[i]];
10579 		if (strcmp_partial(token->name, str, len))
10580 			continue;
10581 		priv = token->priv;
10582 		if (!priv)
10583 			goto error;
10584 		if (out)
10585 			memcpy((uint8_t *)ctx->object + arg->offset,
10586 			       &priv->type,
10587 			       arg->size);
10588 		return len;
10589 	}
10590 error:
10591 	push_args(ctx, arg);
10592 	return -1;
10593 }
10594 
10595 /** Parse tokens for list command. */
10596 static int
10597 parse_list(struct context *ctx, const struct token *token,
10598 	   const char *str, unsigned int len,
10599 	   void *buf, unsigned int size)
10600 {
10601 	struct buffer *out = buf;
10602 
10603 	/* Token name must match. */
10604 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10605 		return -1;
10606 	/* Nothing else to do if there is no buffer. */
10607 	if (!out)
10608 		return len;
10609 	if (!out->command) {
10610 		if (ctx->curr != LIST)
10611 			return -1;
10612 		if (sizeof(*out) > size)
10613 			return -1;
10614 		out->command = ctx->curr;
10615 		ctx->objdata = 0;
10616 		ctx->object = out;
10617 		ctx->objmask = NULL;
10618 		out->args.list.group =
10619 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10620 					       sizeof(double));
10621 		return len;
10622 	}
10623 	if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
10624 	     sizeof(*out->args.list.group)) > (uint8_t *)out + size)
10625 		return -1;
10626 	ctx->objdata = 0;
10627 	ctx->object = out->args.list.group + out->args.list.group_n++;
10628 	ctx->objmask = NULL;
10629 	return len;
10630 }
10631 
10632 /** Parse tokens for list all aged flows command. */
10633 static int
10634 parse_aged(struct context *ctx, const struct token *token,
10635 	   const char *str, unsigned int len,
10636 	   void *buf, unsigned int size)
10637 {
10638 	struct buffer *out = buf;
10639 
10640 	/* Token name must match. */
10641 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10642 		return -1;
10643 	/* Nothing else to do if there is no buffer. */
10644 	if (!out)
10645 		return len;
10646 	if (!out->command || out->command == QUEUE) {
10647 		if (ctx->curr != AGED && ctx->curr != QUEUE_AGED)
10648 			return -1;
10649 		if (sizeof(*out) > size)
10650 			return -1;
10651 		out->command = ctx->curr;
10652 		ctx->objdata = 0;
10653 		ctx->object = out;
10654 		ctx->objmask = NULL;
10655 	}
10656 	if (ctx->curr == AGED_DESTROY)
10657 		out->args.aged.destroy = 1;
10658 	return len;
10659 }
10660 
10661 /** Parse tokens for isolate command. */
10662 static int
10663 parse_isolate(struct context *ctx, const struct token *token,
10664 	      const char *str, unsigned int len,
10665 	      void *buf, unsigned int size)
10666 {
10667 	struct buffer *out = buf;
10668 
10669 	/* Token name must match. */
10670 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10671 		return -1;
10672 	/* Nothing else to do if there is no buffer. */
10673 	if (!out)
10674 		return len;
10675 	if (!out->command) {
10676 		if (ctx->curr != ISOLATE)
10677 			return -1;
10678 		if (sizeof(*out) > size)
10679 			return -1;
10680 		out->command = ctx->curr;
10681 		ctx->objdata = 0;
10682 		ctx->object = out;
10683 		ctx->objmask = NULL;
10684 	}
10685 	return len;
10686 }
10687 
10688 /** Parse tokens for info/configure command. */
10689 static int
10690 parse_configure(struct context *ctx, const struct token *token,
10691 		const char *str, unsigned int len,
10692 		void *buf, unsigned int size)
10693 {
10694 	struct buffer *out = buf;
10695 
10696 	/* Token name must match. */
10697 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10698 		return -1;
10699 	/* Nothing else to do if there is no buffer. */
10700 	if (!out)
10701 		return len;
10702 	if (!out->command) {
10703 		if (ctx->curr != INFO && ctx->curr != CONFIGURE)
10704 			return -1;
10705 		if (sizeof(*out) > size)
10706 			return -1;
10707 		out->command = ctx->curr;
10708 		ctx->objdata = 0;
10709 		ctx->object = out;
10710 		ctx->objmask = NULL;
10711 	}
10712 	return len;
10713 }
10714 
10715 /** Parse tokens for template create command. */
10716 static int
10717 parse_template(struct context *ctx, const struct token *token,
10718 	       const char *str, unsigned int len,
10719 	       void *buf, unsigned int size)
10720 {
10721 	struct buffer *out = buf;
10722 
10723 	/* Token name must match. */
10724 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10725 		return -1;
10726 	/* Nothing else to do if there is no buffer. */
10727 	if (!out)
10728 		return len;
10729 	if (!out->command) {
10730 		if (ctx->curr != PATTERN_TEMPLATE &&
10731 		    ctx->curr != ACTIONS_TEMPLATE)
10732 			return -1;
10733 		if (sizeof(*out) > size)
10734 			return -1;
10735 		out->command = ctx->curr;
10736 		ctx->objdata = 0;
10737 		ctx->object = out;
10738 		ctx->objmask = NULL;
10739 		out->args.vc.data = (uint8_t *)out + size;
10740 		return len;
10741 	}
10742 	switch (ctx->curr) {
10743 	case PATTERN_TEMPLATE_CREATE:
10744 		out->args.vc.pattern =
10745 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10746 					       sizeof(double));
10747 		out->args.vc.pat_templ_id = UINT32_MAX;
10748 		out->command = ctx->curr;
10749 		ctx->objdata = 0;
10750 		ctx->object = out;
10751 		ctx->objmask = NULL;
10752 		return len;
10753 	case PATTERN_TEMPLATE_EGRESS:
10754 		out->args.vc.attr.egress = 1;
10755 		return len;
10756 	case PATTERN_TEMPLATE_INGRESS:
10757 		out->args.vc.attr.ingress = 1;
10758 		return len;
10759 	case PATTERN_TEMPLATE_TRANSFER:
10760 		out->args.vc.attr.transfer = 1;
10761 		return len;
10762 	case ACTIONS_TEMPLATE_CREATE:
10763 		out->args.vc.act_templ_id = UINT32_MAX;
10764 		out->command = ctx->curr;
10765 		ctx->objdata = 0;
10766 		ctx->object = out;
10767 		ctx->objmask = NULL;
10768 		return len;
10769 	case ACTIONS_TEMPLATE_SPEC:
10770 		out->args.vc.actions =
10771 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10772 					       sizeof(double));
10773 		ctx->object = out->args.vc.actions;
10774 		ctx->objmask = NULL;
10775 		return len;
10776 	case ACTIONS_TEMPLATE_MASK:
10777 		out->args.vc.masks =
10778 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10779 					       (out->args.vc.actions +
10780 						out->args.vc.actions_n),
10781 					       sizeof(double));
10782 		ctx->object = out->args.vc.masks;
10783 		ctx->objmask = NULL;
10784 		return len;
10785 	case ACTIONS_TEMPLATE_EGRESS:
10786 		out->args.vc.attr.egress = 1;
10787 		return len;
10788 	case ACTIONS_TEMPLATE_INGRESS:
10789 		out->args.vc.attr.ingress = 1;
10790 		return len;
10791 	case ACTIONS_TEMPLATE_TRANSFER:
10792 		out->args.vc.attr.transfer = 1;
10793 		return len;
10794 	default:
10795 		return -1;
10796 	}
10797 }
10798 
10799 /** Parse tokens for template destroy command. */
10800 static int
10801 parse_template_destroy(struct context *ctx, const struct token *token,
10802 		       const char *str, unsigned int len,
10803 		       void *buf, unsigned int size)
10804 {
10805 	struct buffer *out = buf;
10806 	uint32_t *template_id;
10807 
10808 	/* Token name must match. */
10809 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10810 		return -1;
10811 	/* Nothing else to do if there is no buffer. */
10812 	if (!out)
10813 		return len;
10814 	if (!out->command ||
10815 		out->command == PATTERN_TEMPLATE ||
10816 		out->command == ACTIONS_TEMPLATE) {
10817 		if (ctx->curr != PATTERN_TEMPLATE_DESTROY &&
10818 			ctx->curr != ACTIONS_TEMPLATE_DESTROY)
10819 			return -1;
10820 		if (sizeof(*out) > size)
10821 			return -1;
10822 		out->command = ctx->curr;
10823 		ctx->objdata = 0;
10824 		ctx->object = out;
10825 		ctx->objmask = NULL;
10826 		out->args.templ_destroy.template_id =
10827 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10828 					       sizeof(double));
10829 		return len;
10830 	}
10831 	template_id = out->args.templ_destroy.template_id
10832 		    + out->args.templ_destroy.template_id_n++;
10833 	if ((uint8_t *)template_id > (uint8_t *)out + size)
10834 		return -1;
10835 	ctx->objdata = 0;
10836 	ctx->object = template_id;
10837 	ctx->objmask = NULL;
10838 	return len;
10839 }
10840 
10841 /** Parse tokens for table create command. */
10842 static int
10843 parse_table(struct context *ctx, const struct token *token,
10844 	    const char *str, unsigned int len,
10845 	    void *buf, unsigned int size)
10846 {
10847 	struct buffer *out = buf;
10848 	uint32_t *template_id;
10849 
10850 	/* Token name must match. */
10851 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10852 		return -1;
10853 	/* Nothing else to do if there is no buffer. */
10854 	if (!out)
10855 		return len;
10856 	if (!out->command) {
10857 		if (ctx->curr != TABLE)
10858 			return -1;
10859 		if (sizeof(*out) > size)
10860 			return -1;
10861 		out->command = ctx->curr;
10862 		ctx->objdata = 0;
10863 		ctx->object = out;
10864 		ctx->objmask = NULL;
10865 		return len;
10866 	}
10867 	switch (ctx->curr) {
10868 	case TABLE_CREATE:
10869 	case TABLE_RESIZE:
10870 		out->command = ctx->curr;
10871 		ctx->objdata = 0;
10872 		ctx->object = out;
10873 		ctx->objmask = NULL;
10874 		out->args.table.id = UINT32_MAX;
10875 		return len;
10876 	case TABLE_PATTERN_TEMPLATE:
10877 		out->args.table.pat_templ_id =
10878 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10879 					       sizeof(double));
10880 		template_id = out->args.table.pat_templ_id
10881 				+ out->args.table.pat_templ_id_n++;
10882 		if ((uint8_t *)template_id > (uint8_t *)out + size)
10883 			return -1;
10884 		ctx->objdata = 0;
10885 		ctx->object = template_id;
10886 		ctx->objmask = NULL;
10887 		return len;
10888 	case TABLE_ACTIONS_TEMPLATE:
10889 		out->args.table.act_templ_id =
10890 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10891 					       (out->args.table.pat_templ_id +
10892 						out->args.table.pat_templ_id_n),
10893 					       sizeof(double));
10894 		template_id = out->args.table.act_templ_id
10895 				+ out->args.table.act_templ_id_n++;
10896 		if ((uint8_t *)template_id > (uint8_t *)out + size)
10897 			return -1;
10898 		ctx->objdata = 0;
10899 		ctx->object = template_id;
10900 		ctx->objmask = NULL;
10901 		return len;
10902 	case TABLE_INGRESS:
10903 		out->args.table.attr.flow_attr.ingress = 1;
10904 		return len;
10905 	case TABLE_EGRESS:
10906 		out->args.table.attr.flow_attr.egress = 1;
10907 		return len;
10908 	case TABLE_TRANSFER:
10909 		out->args.table.attr.flow_attr.transfer = 1;
10910 		return len;
10911 	case TABLE_TRANSFER_WIRE_ORIG:
10912 		if (!out->args.table.attr.flow_attr.transfer)
10913 			return -1;
10914 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_WIRE_ORIG;
10915 		return len;
10916 	case TABLE_TRANSFER_VPORT_ORIG:
10917 		if (!out->args.table.attr.flow_attr.transfer)
10918 			return -1;
10919 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_VPORT_ORIG;
10920 		return len;
10921 	case TABLE_RESIZABLE:
10922 		out->args.table.attr.specialize |=
10923 			RTE_FLOW_TABLE_SPECIALIZE_RESIZABLE;
10924 		return len;
10925 	case TABLE_RULES_NUMBER:
10926 		ctx->objdata = 0;
10927 		ctx->object = out;
10928 		ctx->objmask = NULL;
10929 		return len;
10930 	case TABLE_RESIZE_ID:
10931 	case TABLE_RESIZE_RULES_NUMBER:
10932 		return len;
10933 	default:
10934 		return -1;
10935 	}
10936 }
10937 
10938 /** Parse tokens for table destroy command. */
10939 static int
10940 parse_table_destroy(struct context *ctx, const struct token *token,
10941 		    const char *str, unsigned int len,
10942 		    void *buf, unsigned int size)
10943 {
10944 	struct buffer *out = buf;
10945 	uint32_t *table_id;
10946 
10947 	/* Token name must match. */
10948 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10949 		return -1;
10950 	/* Nothing else to do if there is no buffer. */
10951 	if (!out)
10952 		return len;
10953 	if (!out->command || out->command == TABLE) {
10954 		if (ctx->curr != TABLE_DESTROY &&
10955 		    ctx->curr != TABLE_RESIZE_COMPLETE)
10956 			return -1;
10957 		if (sizeof(*out) > size)
10958 			return -1;
10959 		out->command = ctx->curr;
10960 		ctx->objdata = 0;
10961 		ctx->object = out;
10962 		ctx->objmask = NULL;
10963 		out->args.table_destroy.table_id =
10964 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10965 					       sizeof(double));
10966 		return len;
10967 	}
10968 	table_id = out->args.table_destroy.table_id
10969 		    + out->args.table_destroy.table_id_n++;
10970 	if ((uint8_t *)table_id > (uint8_t *)out + size)
10971 		return -1;
10972 	ctx->objdata = 0;
10973 	ctx->object = table_id;
10974 	ctx->objmask = NULL;
10975 	return len;
10976 }
10977 
10978 /** Parse tokens for queue create commands. */
10979 static int
10980 parse_qo(struct context *ctx, const struct token *token,
10981 	 const char *str, unsigned int len,
10982 	 void *buf, unsigned int size)
10983 {
10984 	struct buffer *out = buf;
10985 
10986 	/* Token name must match. */
10987 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10988 		return -1;
10989 	/* Nothing else to do if there is no buffer. */
10990 	if (!out)
10991 		return len;
10992 	if (!out->command) {
10993 		if (ctx->curr != QUEUE)
10994 			return -1;
10995 		if (sizeof(*out) > size)
10996 			return -1;
10997 		out->command = ctx->curr;
10998 		ctx->objdata = 0;
10999 		ctx->object = out;
11000 		ctx->objmask = NULL;
11001 		out->args.vc.data = (uint8_t *)out + size;
11002 		return len;
11003 	}
11004 	switch (ctx->curr) {
11005 	case QUEUE_CREATE:
11006 	case QUEUE_UPDATE:
11007 		out->command = ctx->curr;
11008 		ctx->objdata = 0;
11009 		ctx->object = out;
11010 		ctx->objmask = NULL;
11011 		out->args.vc.rule_id = UINT32_MAX;
11012 		return len;
11013 	case QUEUE_TEMPLATE_TABLE:
11014 	case QUEUE_PATTERN_TEMPLATE:
11015 	case QUEUE_ACTIONS_TEMPLATE:
11016 	case QUEUE_CREATE_POSTPONE:
11017 	case QUEUE_RULE_ID:
11018 	case QUEUE_UPDATE_ID:
11019 		return len;
11020 	case ITEM_PATTERN:
11021 		out->args.vc.pattern =
11022 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11023 					       sizeof(double));
11024 		ctx->object = out->args.vc.pattern;
11025 		ctx->objmask = NULL;
11026 		return len;
11027 	case ACTIONS:
11028 		out->args.vc.actions =
11029 			(void *)RTE_ALIGN_CEIL((uintptr_t)
11030 					       (out->args.vc.pattern +
11031 						out->args.vc.pattern_n),
11032 					       sizeof(double));
11033 		ctx->object = out->args.vc.actions;
11034 		ctx->objmask = NULL;
11035 		return len;
11036 	default:
11037 		return -1;
11038 	}
11039 }
11040 
11041 /** Parse tokens for queue destroy command. */
11042 static int
11043 parse_qo_destroy(struct context *ctx, const struct token *token,
11044 		 const char *str, unsigned int len,
11045 		 void *buf, unsigned int size)
11046 {
11047 	struct buffer *out = buf;
11048 	uint64_t *flow_id;
11049 
11050 	/* Token name must match. */
11051 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11052 		return -1;
11053 	/* Nothing else to do if there is no buffer. */
11054 	if (!out)
11055 		return len;
11056 	if (!out->command || out->command == QUEUE) {
11057 		if (ctx->curr != QUEUE_DESTROY &&
11058 		    ctx->curr != QUEUE_FLOW_UPDATE_RESIZED)
11059 			return -1;
11060 		if (sizeof(*out) > size)
11061 			return -1;
11062 		out->command = ctx->curr;
11063 		ctx->objdata = 0;
11064 		ctx->object = out;
11065 		ctx->objmask = NULL;
11066 		out->args.destroy.rule =
11067 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11068 					       sizeof(double));
11069 		return len;
11070 	}
11071 	switch (ctx->curr) {
11072 	case QUEUE_DESTROY_ID:
11073 		flow_id = out->args.destroy.rule
11074 				+ out->args.destroy.rule_n++;
11075 		if ((uint8_t *)flow_id > (uint8_t *)out + size)
11076 			return -1;
11077 		ctx->objdata = 0;
11078 		ctx->object = flow_id;
11079 		ctx->objmask = NULL;
11080 		return len;
11081 	case QUEUE_DESTROY_POSTPONE:
11082 		return len;
11083 	default:
11084 		return -1;
11085 	}
11086 }
11087 
11088 /** Parse tokens for push queue command. */
11089 static int
11090 parse_push(struct context *ctx, const struct token *token,
11091 	   const char *str, unsigned int len,
11092 	   void *buf, unsigned int size)
11093 {
11094 	struct buffer *out = buf;
11095 
11096 	/* Token name must match. */
11097 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11098 		return -1;
11099 	/* Nothing else to do if there is no buffer. */
11100 	if (!out)
11101 		return len;
11102 	if (!out->command) {
11103 		if (ctx->curr != PUSH)
11104 			return -1;
11105 		if (sizeof(*out) > size)
11106 			return -1;
11107 		out->command = ctx->curr;
11108 		ctx->objdata = 0;
11109 		ctx->object = out;
11110 		ctx->objmask = NULL;
11111 		out->args.vc.data = (uint8_t *)out + size;
11112 	}
11113 	return len;
11114 }
11115 
11116 /** Parse tokens for pull command. */
11117 static int
11118 parse_pull(struct context *ctx, const struct token *token,
11119 	   const char *str, unsigned int len,
11120 	   void *buf, unsigned int size)
11121 {
11122 	struct buffer *out = buf;
11123 
11124 	/* Token name must match. */
11125 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11126 		return -1;
11127 	/* Nothing else to do if there is no buffer. */
11128 	if (!out)
11129 		return len;
11130 	if (!out->command) {
11131 		if (ctx->curr != PULL)
11132 			return -1;
11133 		if (sizeof(*out) > size)
11134 			return -1;
11135 		out->command = ctx->curr;
11136 		ctx->objdata = 0;
11137 		ctx->object = out;
11138 		ctx->objmask = NULL;
11139 		out->args.vc.data = (uint8_t *)out + size;
11140 	}
11141 	return len;
11142 }
11143 
11144 /** Parse tokens for hash calculation commands. */
11145 static int
11146 parse_hash(struct context *ctx, const struct token *token,
11147 	 const char *str, unsigned int len,
11148 	 void *buf, unsigned int size)
11149 {
11150 	struct buffer *out = buf;
11151 
11152 	/* Token name must match. */
11153 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11154 		return -1;
11155 	/* Nothing else to do if there is no buffer. */
11156 	if (!out)
11157 		return len;
11158 	if (!out->command) {
11159 		if (ctx->curr != HASH)
11160 			return -1;
11161 		if (sizeof(*out) > size)
11162 			return -1;
11163 		out->command = ctx->curr;
11164 		ctx->objdata = 0;
11165 		ctx->object = out;
11166 		ctx->objmask = NULL;
11167 		out->args.vc.data = (uint8_t *)out + size;
11168 		return len;
11169 	}
11170 	switch (ctx->curr) {
11171 	case HASH_CALC_TABLE:
11172 	case HASH_CALC_PATTERN_INDEX:
11173 		return len;
11174 	case ITEM_PATTERN:
11175 		out->args.vc.pattern =
11176 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11177 					       sizeof(double));
11178 		ctx->object = out->args.vc.pattern;
11179 		ctx->objmask = NULL;
11180 		return len;
11181 	case HASH_CALC_ENCAP:
11182 		out->args.vc.encap_hash = 1;
11183 		return len;
11184 	case ENCAP_HASH_FIELD_SRC_PORT:
11185 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_SRC_PORT;
11186 		return len;
11187 	case ENCAP_HASH_FIELD_GRE_FLOW_ID:
11188 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_NVGRE_FLOW_ID;
11189 		return len;
11190 	default:
11191 		return -1;
11192 	}
11193 }
11194 
11195 static int
11196 parse_group(struct context *ctx, const struct token *token,
11197 	    const char *str, unsigned int len,
11198 	    void *buf, unsigned int size)
11199 {
11200 	struct buffer *out = buf;
11201 
11202 	/* Token name must match. */
11203 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11204 		return -1;
11205 	/* Nothing else to do if there is no buffer. */
11206 	if (!out)
11207 		return len;
11208 	if (!out->command) {
11209 		if (ctx->curr != FLOW_GROUP)
11210 			return -1;
11211 		if (sizeof(*out) > size)
11212 			return -1;
11213 		out->command = ctx->curr;
11214 		ctx->objdata = 0;
11215 		ctx->object = out;
11216 		ctx->objmask = NULL;
11217 		out->args.vc.data = (uint8_t *)out + size;
11218 		return len;
11219 	}
11220 	switch (ctx->curr) {
11221 	case GROUP_INGRESS:
11222 		out->args.vc.attr.ingress = 1;
11223 		return len;
11224 	case GROUP_EGRESS:
11225 		out->args.vc.attr.egress = 1;
11226 		return len;
11227 	case GROUP_TRANSFER:
11228 		out->args.vc.attr.transfer = 1;
11229 		return len;
11230 	case GROUP_SET_MISS_ACTIONS:
11231 		out->command = ctx->curr;
11232 		ctx->objdata = 0;
11233 		ctx->object = out;
11234 		ctx->objmask = NULL;
11235 		out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11236 							       sizeof(double));
11237 		return len;
11238 	default:
11239 		return -1;
11240 	}
11241 }
11242 
11243 static int
11244 parse_flex(struct context *ctx, const struct token *token,
11245 	     const char *str, unsigned int len,
11246 	     void *buf, unsigned int size)
11247 {
11248 	struct buffer *out = buf;
11249 
11250 	/* Token name must match. */
11251 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11252 		return -1;
11253 	/* Nothing else to do if there is no buffer. */
11254 	if (!out)
11255 		return len;
11256 	if (out->command == ZERO) {
11257 		if (ctx->curr != FLEX)
11258 			return -1;
11259 		if (sizeof(*out) > size)
11260 			return -1;
11261 		out->command = ctx->curr;
11262 		ctx->objdata = 0;
11263 		ctx->object = out;
11264 		ctx->objmask = NULL;
11265 	} else {
11266 		switch (ctx->curr) {
11267 		default:
11268 			break;
11269 		case FLEX_ITEM_INIT:
11270 		case FLEX_ITEM_CREATE:
11271 		case FLEX_ITEM_DESTROY:
11272 			out->command = ctx->curr;
11273 			break;
11274 		}
11275 	}
11276 
11277 	return len;
11278 }
11279 
11280 static int
11281 parse_tunnel(struct context *ctx, const struct token *token,
11282 	     const char *str, unsigned int len,
11283 	     void *buf, unsigned int size)
11284 {
11285 	struct buffer *out = buf;
11286 
11287 	/* Token name must match. */
11288 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11289 		return -1;
11290 	/* Nothing else to do if there is no buffer. */
11291 	if (!out)
11292 		return len;
11293 	if (!out->command) {
11294 		if (ctx->curr != TUNNEL)
11295 			return -1;
11296 		if (sizeof(*out) > size)
11297 			return -1;
11298 		out->command = ctx->curr;
11299 		ctx->objdata = 0;
11300 		ctx->object = out;
11301 		ctx->objmask = NULL;
11302 	} else {
11303 		switch (ctx->curr) {
11304 		default:
11305 			break;
11306 		case TUNNEL_CREATE:
11307 		case TUNNEL_DESTROY:
11308 		case TUNNEL_LIST:
11309 			out->command = ctx->curr;
11310 			break;
11311 		case TUNNEL_CREATE_TYPE:
11312 		case TUNNEL_DESTROY_ID:
11313 			ctx->object = &out->args.vc.tunnel_ops;
11314 			break;
11315 		}
11316 	}
11317 
11318 	return len;
11319 }
11320 
11321 /**
11322  * Parse signed/unsigned integers 8 to 64-bit long.
11323  *
11324  * Last argument (ctx->args) is retrieved to determine integer type and
11325  * storage location.
11326  */
11327 static int
11328 parse_int(struct context *ctx, const struct token *token,
11329 	  const char *str, unsigned int len,
11330 	  void *buf, unsigned int size)
11331 {
11332 	const struct arg *arg = pop_args(ctx);
11333 	uintmax_t u;
11334 	char *end;
11335 
11336 	(void)token;
11337 	/* Argument is expected. */
11338 	if (!arg)
11339 		return -1;
11340 	errno = 0;
11341 	u = arg->sign ?
11342 		(uintmax_t)strtoimax(str, &end, 0) :
11343 		strtoumax(str, &end, 0);
11344 	if (errno || (size_t)(end - str) != len)
11345 		goto error;
11346 	if (arg->bounded &&
11347 	    ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
11348 			    (intmax_t)u > (intmax_t)arg->max)) ||
11349 	     (!arg->sign && (u < arg->min || u > arg->max))))
11350 		goto error;
11351 	if (!ctx->object)
11352 		return len;
11353 	if (arg->mask) {
11354 		if (!arg_entry_bf_fill(ctx->object, u, arg) ||
11355 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
11356 			goto error;
11357 		return len;
11358 	}
11359 	buf = (uint8_t *)ctx->object + arg->offset;
11360 	size = arg->size;
11361 	if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
11362 		return -1;
11363 objmask:
11364 	switch (size) {
11365 	case sizeof(uint8_t):
11366 		*(uint8_t *)buf = u;
11367 		break;
11368 	case sizeof(uint16_t):
11369 		*(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
11370 		break;
11371 	case sizeof(uint8_t [3]):
11372 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
11373 		if (!arg->hton) {
11374 			((uint8_t *)buf)[0] = u;
11375 			((uint8_t *)buf)[1] = u >> 8;
11376 			((uint8_t *)buf)[2] = u >> 16;
11377 			break;
11378 		}
11379 #endif
11380 		((uint8_t *)buf)[0] = u >> 16;
11381 		((uint8_t *)buf)[1] = u >> 8;
11382 		((uint8_t *)buf)[2] = u;
11383 		break;
11384 	case sizeof(uint32_t):
11385 		*(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
11386 		break;
11387 	case sizeof(uint64_t):
11388 		*(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
11389 		break;
11390 	default:
11391 		goto error;
11392 	}
11393 	if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
11394 		u = -1;
11395 		buf = (uint8_t *)ctx->objmask + arg->offset;
11396 		goto objmask;
11397 	}
11398 	return len;
11399 error:
11400 	push_args(ctx, arg);
11401 	return -1;
11402 }
11403 
11404 /**
11405  * Parse a string.
11406  *
11407  * Three arguments (ctx->args) are retrieved from the stack to store data,
11408  * its actual length and address (in that order).
11409  */
11410 static int
11411 parse_string(struct context *ctx, const struct token *token,
11412 	     const char *str, unsigned int len,
11413 	     void *buf, unsigned int size)
11414 {
11415 	const struct arg *arg_data = pop_args(ctx);
11416 	const struct arg *arg_len = pop_args(ctx);
11417 	const struct arg *arg_addr = pop_args(ctx);
11418 	char tmp[16]; /* Ought to be enough. */
11419 	int ret;
11420 
11421 	/* Arguments are expected. */
11422 	if (!arg_data)
11423 		return -1;
11424 	if (!arg_len) {
11425 		push_args(ctx, arg_data);
11426 		return -1;
11427 	}
11428 	if (!arg_addr) {
11429 		push_args(ctx, arg_len);
11430 		push_args(ctx, arg_data);
11431 		return -1;
11432 	}
11433 	size = arg_data->size;
11434 	/* Bit-mask fill is not supported. */
11435 	if (arg_data->mask || size < len)
11436 		goto error;
11437 	if (!ctx->object)
11438 		return len;
11439 	/* Let parse_int() fill length information first. */
11440 	ret = snprintf(tmp, sizeof(tmp), "%u", len);
11441 	if (ret < 0)
11442 		goto error;
11443 	push_args(ctx, arg_len);
11444 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11445 	if (ret < 0) {
11446 		pop_args(ctx);
11447 		goto error;
11448 	}
11449 	buf = (uint8_t *)ctx->object + arg_data->offset;
11450 	/* Output buffer is not necessarily NUL-terminated. */
11451 	memcpy(buf, str, len);
11452 	memset((uint8_t *)buf + len, 0x00, size - len);
11453 	if (ctx->objmask)
11454 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11455 	/* Save address if requested. */
11456 	if (arg_addr->size) {
11457 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11458 		       (void *[]){
11459 			(uint8_t *)ctx->object + arg_data->offset
11460 		       },
11461 		       arg_addr->size);
11462 		if (ctx->objmask)
11463 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11464 			       (void *[]){
11465 				(uint8_t *)ctx->objmask + arg_data->offset
11466 			       },
11467 			       arg_addr->size);
11468 	}
11469 	return len;
11470 error:
11471 	push_args(ctx, arg_addr);
11472 	push_args(ctx, arg_len);
11473 	push_args(ctx, arg_data);
11474 	return -1;
11475 }
11476 
11477 static int
11478 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
11479 {
11480 	const uint8_t *head = dst;
11481 	uint32_t left;
11482 
11483 	if (*size == 0)
11484 		return -1;
11485 
11486 	left = *size;
11487 
11488 	/* Convert chars to bytes */
11489 	while (left) {
11490 		char tmp[3], *end = tmp;
11491 		uint32_t read_lim = left & 1 ? 1 : 2;
11492 
11493 		snprintf(tmp, read_lim + 1, "%s", src);
11494 		*dst = strtoul(tmp, &end, 16);
11495 		if (*end) {
11496 			*dst = 0;
11497 			*size = (uint32_t)(dst - head);
11498 			return -1;
11499 		}
11500 		left -= read_lim;
11501 		src += read_lim;
11502 		dst++;
11503 	}
11504 	*dst = 0;
11505 	*size = (uint32_t)(dst - head);
11506 	return 0;
11507 }
11508 
11509 static int
11510 parse_hex(struct context *ctx, const struct token *token,
11511 		const char *str, unsigned int len,
11512 		void *buf, unsigned int size)
11513 {
11514 	const struct arg *arg_data = pop_args(ctx);
11515 	const struct arg *arg_len = pop_args(ctx);
11516 	const struct arg *arg_addr = pop_args(ctx);
11517 	char tmp[16]; /* Ought to be enough. */
11518 	int ret;
11519 	unsigned int hexlen = len;
11520 	unsigned int length = 256;
11521 	uint8_t hex_tmp[length];
11522 
11523 	/* Arguments are expected. */
11524 	if (!arg_data)
11525 		return -1;
11526 	if (!arg_len) {
11527 		push_args(ctx, arg_data);
11528 		return -1;
11529 	}
11530 	if (!arg_addr) {
11531 		push_args(ctx, arg_len);
11532 		push_args(ctx, arg_data);
11533 		return -1;
11534 	}
11535 	size = arg_data->size;
11536 	/* Bit-mask fill is not supported. */
11537 	if (arg_data->mask)
11538 		goto error;
11539 	if (!ctx->object)
11540 		return len;
11541 
11542 	/* translate bytes string to array. */
11543 	if (str[0] == '0' && ((str[1] == 'x') ||
11544 			(str[1] == 'X'))) {
11545 		str += 2;
11546 		hexlen -= 2;
11547 	}
11548 	if (hexlen > length)
11549 		goto error;
11550 	ret = parse_hex_string(str, hex_tmp, &hexlen);
11551 	if (ret < 0)
11552 		goto error;
11553 	/* Check the converted binary fits into data buffer. */
11554 	if (hexlen > size)
11555 		goto error;
11556 	/* Let parse_int() fill length information first. */
11557 	ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
11558 	if (ret < 0)
11559 		goto error;
11560 	/* Save length if requested. */
11561 	if (arg_len->size) {
11562 		push_args(ctx, arg_len);
11563 		ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11564 		if (ret < 0) {
11565 			pop_args(ctx);
11566 			goto error;
11567 		}
11568 	}
11569 	buf = (uint8_t *)ctx->object + arg_data->offset;
11570 	/* Output buffer is not necessarily NUL-terminated. */
11571 	memcpy(buf, hex_tmp, hexlen);
11572 	memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
11573 	if (ctx->objmask)
11574 		memset((uint8_t *)ctx->objmask + arg_data->offset,
11575 					0xff, hexlen);
11576 	/* Save address if requested. */
11577 	if (arg_addr->size) {
11578 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11579 		       (void *[]){
11580 			(uint8_t *)ctx->object + arg_data->offset
11581 		       },
11582 		       arg_addr->size);
11583 		if (ctx->objmask)
11584 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11585 			       (void *[]){
11586 				(uint8_t *)ctx->objmask + arg_data->offset
11587 			       },
11588 			       arg_addr->size);
11589 	}
11590 	return len;
11591 error:
11592 	push_args(ctx, arg_addr);
11593 	push_args(ctx, arg_len);
11594 	push_args(ctx, arg_data);
11595 	return -1;
11596 
11597 }
11598 
11599 /**
11600  * Parse a zero-ended string.
11601  */
11602 static int
11603 parse_string0(struct context *ctx, const struct token *token __rte_unused,
11604 	     const char *str, unsigned int len,
11605 	     void *buf, unsigned int size)
11606 {
11607 	const struct arg *arg_data = pop_args(ctx);
11608 
11609 	/* Arguments are expected. */
11610 	if (!arg_data)
11611 		return -1;
11612 	size = arg_data->size;
11613 	/* Bit-mask fill is not supported. */
11614 	if (arg_data->mask || size < len + 1)
11615 		goto error;
11616 	if (!ctx->object)
11617 		return len;
11618 	buf = (uint8_t *)ctx->object + arg_data->offset;
11619 	strncpy(buf, str, len);
11620 	if (ctx->objmask)
11621 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11622 	return len;
11623 error:
11624 	push_args(ctx, arg_data);
11625 	return -1;
11626 }
11627 
11628 /**
11629  * Parse a MAC address.
11630  *
11631  * Last argument (ctx->args) is retrieved to determine storage size and
11632  * location.
11633  */
11634 static int
11635 parse_mac_addr(struct context *ctx, const struct token *token,
11636 	       const char *str, unsigned int len,
11637 	       void *buf, unsigned int size)
11638 {
11639 	const struct arg *arg = pop_args(ctx);
11640 	struct rte_ether_addr tmp;
11641 	int ret;
11642 
11643 	(void)token;
11644 	/* Argument is expected. */
11645 	if (!arg)
11646 		return -1;
11647 	size = arg->size;
11648 	/* Bit-mask fill is not supported. */
11649 	if (arg->mask || size != sizeof(tmp))
11650 		goto error;
11651 	/* Only network endian is supported. */
11652 	if (!arg->hton)
11653 		goto error;
11654 	ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
11655 	if (ret < 0 || (unsigned int)ret != len)
11656 		goto error;
11657 	if (!ctx->object)
11658 		return len;
11659 	buf = (uint8_t *)ctx->object + arg->offset;
11660 	memcpy(buf, &tmp, size);
11661 	if (ctx->objmask)
11662 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11663 	return len;
11664 error:
11665 	push_args(ctx, arg);
11666 	return -1;
11667 }
11668 
11669 /**
11670  * Parse an IPv4 address.
11671  *
11672  * Last argument (ctx->args) is retrieved to determine storage size and
11673  * location.
11674  */
11675 static int
11676 parse_ipv4_addr(struct context *ctx, const struct token *token,
11677 		const char *str, unsigned int len,
11678 		void *buf, unsigned int size)
11679 {
11680 	const struct arg *arg = pop_args(ctx);
11681 	char str2[len + 1];
11682 	struct in_addr tmp;
11683 	int ret;
11684 
11685 	/* Argument is expected. */
11686 	if (!arg)
11687 		return -1;
11688 	size = arg->size;
11689 	/* Bit-mask fill is not supported. */
11690 	if (arg->mask || size != sizeof(tmp))
11691 		goto error;
11692 	/* Only network endian is supported. */
11693 	if (!arg->hton)
11694 		goto error;
11695 	memcpy(str2, str, len);
11696 	str2[len] = '\0';
11697 	ret = inet_pton(AF_INET, str2, &tmp);
11698 	if (ret != 1) {
11699 		/* Attempt integer parsing. */
11700 		push_args(ctx, arg);
11701 		return parse_int(ctx, token, str, len, buf, size);
11702 	}
11703 	if (!ctx->object)
11704 		return len;
11705 	buf = (uint8_t *)ctx->object + arg->offset;
11706 	memcpy(buf, &tmp, size);
11707 	if (ctx->objmask)
11708 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11709 	return len;
11710 error:
11711 	push_args(ctx, arg);
11712 	return -1;
11713 }
11714 
11715 /**
11716  * Parse an IPv6 address.
11717  *
11718  * Last argument (ctx->args) is retrieved to determine storage size and
11719  * location.
11720  */
11721 static int
11722 parse_ipv6_addr(struct context *ctx, const struct token *token,
11723 		const char *str, unsigned int len,
11724 		void *buf, unsigned int size)
11725 {
11726 	const struct arg *arg = pop_args(ctx);
11727 	char str2[len + 1];
11728 	struct in6_addr tmp;
11729 	int ret;
11730 
11731 	(void)token;
11732 	/* Argument is expected. */
11733 	if (!arg)
11734 		return -1;
11735 	size = arg->size;
11736 	/* Bit-mask fill is not supported. */
11737 	if (arg->mask || size != sizeof(tmp))
11738 		goto error;
11739 	/* Only network endian is supported. */
11740 	if (!arg->hton)
11741 		goto error;
11742 	memcpy(str2, str, len);
11743 	str2[len] = '\0';
11744 	ret = inet_pton(AF_INET6, str2, &tmp);
11745 	if (ret != 1)
11746 		goto error;
11747 	if (!ctx->object)
11748 		return len;
11749 	buf = (uint8_t *)ctx->object + arg->offset;
11750 	memcpy(buf, &tmp, size);
11751 	if (ctx->objmask)
11752 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11753 	return len;
11754 error:
11755 	push_args(ctx, arg);
11756 	return -1;
11757 }
11758 
11759 /** Boolean values (even indices stand for false). */
11760 static const char *const boolean_name[] = {
11761 	"0", "1",
11762 	"false", "true",
11763 	"no", "yes",
11764 	"N", "Y",
11765 	"off", "on",
11766 	NULL,
11767 };
11768 
11769 /**
11770  * Parse a boolean value.
11771  *
11772  * Last argument (ctx->args) is retrieved to determine storage size and
11773  * location.
11774  */
11775 static int
11776 parse_boolean(struct context *ctx, const struct token *token,
11777 	      const char *str, unsigned int len,
11778 	      void *buf, unsigned int size)
11779 {
11780 	const struct arg *arg = pop_args(ctx);
11781 	unsigned int i;
11782 	int ret;
11783 
11784 	/* Argument is expected. */
11785 	if (!arg)
11786 		return -1;
11787 	for (i = 0; boolean_name[i]; ++i)
11788 		if (!strcmp_partial(boolean_name[i], str, len))
11789 			break;
11790 	/* Process token as integer. */
11791 	if (boolean_name[i])
11792 		str = i & 1 ? "1" : "0";
11793 	push_args(ctx, arg);
11794 	ret = parse_int(ctx, token, str, strlen(str), buf, size);
11795 	return ret > 0 ? (int)len : ret;
11796 }
11797 
11798 /** Parse port and update context. */
11799 static int
11800 parse_port(struct context *ctx, const struct token *token,
11801 	   const char *str, unsigned int len,
11802 	   void *buf, unsigned int size)
11803 {
11804 	struct buffer *out = &(struct buffer){ .port = 0 };
11805 	int ret;
11806 
11807 	if (buf)
11808 		out = buf;
11809 	else {
11810 		ctx->objdata = 0;
11811 		ctx->object = out;
11812 		ctx->objmask = NULL;
11813 		size = sizeof(*out);
11814 	}
11815 	ret = parse_int(ctx, token, str, len, out, size);
11816 	if (ret >= 0)
11817 		ctx->port = out->port;
11818 	if (!buf)
11819 		ctx->object = NULL;
11820 	return ret;
11821 }
11822 
11823 /** Parse tokens for shared indirect actions. */
11824 static int
11825 parse_ia_port(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 	uint32_t id;
11831 	int ret;
11832 
11833 	(void)buf;
11834 	(void)size;
11835 	ctx->objdata = 0;
11836 	ctx->object = &id;
11837 	ctx->objmask = NULL;
11838 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11839 	ctx->object = action;
11840 	if (ret != (int)len)
11841 		return ret;
11842 	/* set indirect action */
11843 	if (action)
11844 		action->conf = (void *)(uintptr_t)id;
11845 	return ret;
11846 }
11847 
11848 static int
11849 parse_ia_id2ptr(struct context *ctx, const struct token *token,
11850 		const char *str, unsigned int len,
11851 		void *buf, unsigned int size)
11852 {
11853 	struct rte_flow_action *action = ctx->object;
11854 	uint32_t id;
11855 	int ret;
11856 
11857 	(void)buf;
11858 	(void)size;
11859 	ctx->objdata = 0;
11860 	ctx->object = &id;
11861 	ctx->objmask = NULL;
11862 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11863 	ctx->object = action;
11864 	if (ret != (int)len)
11865 		return ret;
11866 	/* set indirect action */
11867 	if (action) {
11868 		portid_t port_id = ctx->port;
11869 		if (ctx->prev == INDIRECT_ACTION_PORT)
11870 			port_id = (portid_t)(uintptr_t)action->conf;
11871 		action->conf = port_action_handle_get_by_id(port_id, id);
11872 		ret = (action->conf) ? ret : -1;
11873 	}
11874 	return ret;
11875 }
11876 
11877 static int
11878 parse_indlst_id2ptr(struct context *ctx, const struct token *token,
11879 		    const char *str, unsigned int len,
11880 		    __rte_unused void *buf, __rte_unused unsigned int size)
11881 {
11882 	struct rte_flow_action *action = ctx->object;
11883 	struct rte_flow_action_indirect_list *action_conf;
11884 	const struct indlst_conf *indlst_conf;
11885 	uint32_t id;
11886 	int ret;
11887 
11888 	if (!action)
11889 		return -1;
11890 	ctx->objdata = 0;
11891 	ctx->object = &id;
11892 	ctx->objmask = NULL;
11893 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11894 	if (ret != (int)len)
11895 		return ret;
11896 	ctx->object = action;
11897 	action_conf = (void *)(uintptr_t)action->conf;
11898 	action_conf->conf = NULL;
11899 	switch (ctx->curr) {
11900 	case INDIRECT_LIST_ACTION_ID2PTR_HANDLE:
11901 	action_conf->handle = (typeof(action_conf->handle))
11902 				port_action_handle_get_by_id(ctx->port, id);
11903 		if (!action_conf->handle) {
11904 			printf("no indirect list handle for id %u\n", id);
11905 			return -1;
11906 		}
11907 		break;
11908 	case INDIRECT_LIST_ACTION_ID2PTR_CONF:
11909 		indlst_conf = indirect_action_list_conf_get(id);
11910 		if (!indlst_conf)
11911 			return -1;
11912 		action_conf->conf = (const void **)indlst_conf->conf;
11913 		break;
11914 	default:
11915 		break;
11916 	}
11917 	return ret;
11918 }
11919 
11920 static int
11921 parse_meter_profile_id2ptr(struct context *ctx, const struct token *token,
11922 		const char *str, unsigned int len,
11923 		void *buf, unsigned int size)
11924 {
11925 	struct rte_flow_action *action = ctx->object;
11926 	struct rte_flow_action_meter_mark *meter;
11927 	struct rte_flow_meter_profile *profile = NULL;
11928 	uint32_t id = 0;
11929 	int ret;
11930 
11931 	(void)buf;
11932 	(void)size;
11933 	ctx->objdata = 0;
11934 	ctx->object = &id;
11935 	ctx->objmask = NULL;
11936 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11937 	ctx->object = action;
11938 	if (ret != (int)len)
11939 		return ret;
11940 	/* set meter profile */
11941 	if (action) {
11942 		meter = (struct rte_flow_action_meter_mark *)
11943 			(uintptr_t)(action->conf);
11944 		profile = port_meter_profile_get_by_id(ctx->port, id);
11945 		meter->profile = profile;
11946 		ret = (profile) ? ret : -1;
11947 	}
11948 	return ret;
11949 }
11950 
11951 static int
11952 parse_meter_policy_id2ptr(struct context *ctx, const struct token *token,
11953 		const char *str, unsigned int len,
11954 		void *buf, unsigned int size)
11955 {
11956 	struct rte_flow_action *action = ctx->object;
11957 	struct rte_flow_action_meter_mark *meter;
11958 	struct rte_flow_meter_policy *policy = NULL;
11959 	uint32_t id = 0;
11960 	int ret;
11961 
11962 	(void)buf;
11963 	(void)size;
11964 	ctx->objdata = 0;
11965 	ctx->object = &id;
11966 	ctx->objmask = NULL;
11967 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11968 	ctx->object = action;
11969 	if (ret != (int)len)
11970 		return ret;
11971 	/* set meter policy */
11972 	if (action) {
11973 		meter = (struct rte_flow_action_meter_mark *)
11974 			(uintptr_t)(action->conf);
11975 		policy = port_meter_policy_get_by_id(ctx->port, id);
11976 		meter->policy = policy;
11977 		ret = (policy) ? ret : -1;
11978 	}
11979 	return ret;
11980 }
11981 
11982 /** Parse set command, initialize output buffer for subsequent tokens. */
11983 static int
11984 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
11985 			  const char *str, unsigned int len,
11986 			  void *buf, unsigned int size)
11987 {
11988 	struct buffer *out = buf;
11989 
11990 	/* Token name must match. */
11991 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11992 		return -1;
11993 	/* Nothing else to do if there is no buffer. */
11994 	if (!out)
11995 		return len;
11996 	/* Make sure buffer is large enough. */
11997 	if (size < sizeof(*out))
11998 		return -1;
11999 	ctx->objdata = 0;
12000 	ctx->objmask = NULL;
12001 	ctx->object = out;
12002 	if (!out->command)
12003 		return -1;
12004 	out->command = ctx->curr;
12005 	/* For encap/decap we need is pattern */
12006 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12007 						       sizeof(double));
12008 	return len;
12009 }
12010 
12011 /** Parse set command, initialize output buffer for subsequent tokens. */
12012 static int
12013 parse_set_sample_action(struct context *ctx, const struct token *token,
12014 			  const char *str, unsigned int len,
12015 			  void *buf, unsigned int size)
12016 {
12017 	struct buffer *out = buf;
12018 
12019 	/* Token name must match. */
12020 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12021 		return -1;
12022 	/* Nothing else to do if there is no buffer. */
12023 	if (!out)
12024 		return len;
12025 	/* Make sure buffer is large enough. */
12026 	if (size < sizeof(*out))
12027 		return -1;
12028 	ctx->objdata = 0;
12029 	ctx->objmask = NULL;
12030 	ctx->object = out;
12031 	if (!out->command)
12032 		return -1;
12033 	out->command = ctx->curr;
12034 	/* For sampler we need is actions */
12035 	out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12036 						       sizeof(double));
12037 	return len;
12038 }
12039 
12040 /** Parse set command, initialize output buffer for subsequent tokens. */
12041 static int
12042 parse_set_ipv6_ext_action(struct context *ctx, const struct token *token,
12043 			  const char *str, unsigned int len,
12044 			  void *buf, unsigned int size)
12045 {
12046 	struct buffer *out = buf;
12047 
12048 	/* Token name must match. */
12049 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12050 		return -1;
12051 	/* Nothing else to do if there is no buffer. */
12052 	if (!out)
12053 		return len;
12054 	/* Make sure buffer is large enough. */
12055 	if (size < sizeof(*out))
12056 		return -1;
12057 	ctx->objdata = 0;
12058 	ctx->objmask = NULL;
12059 	ctx->object = out;
12060 	if (!out->command)
12061 		return -1;
12062 	out->command = ctx->curr;
12063 	/* For ipv6_ext_push/remove we need is pattern */
12064 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12065 						       sizeof(double));
12066 	return len;
12067 }
12068 
12069 /**
12070  * Parse set raw_encap/raw_decap command,
12071  * initialize output buffer for subsequent tokens.
12072  */
12073 static int
12074 parse_set_init(struct context *ctx, const struct token *token,
12075 	       const char *str, unsigned int len,
12076 	       void *buf, unsigned int size)
12077 {
12078 	struct buffer *out = buf;
12079 
12080 	/* Token name must match. */
12081 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12082 		return -1;
12083 	/* Nothing else to do if there is no buffer. */
12084 	if (!out)
12085 		return len;
12086 	/* Make sure buffer is large enough. */
12087 	if (size < sizeof(*out))
12088 		return -1;
12089 	/* Initialize buffer. */
12090 	memset(out, 0x00, sizeof(*out));
12091 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
12092 	ctx->objdata = 0;
12093 	ctx->object = out;
12094 	ctx->objmask = NULL;
12095 	if (!out->command) {
12096 		if (ctx->curr != SET)
12097 			return -1;
12098 		if (sizeof(*out) > size)
12099 			return -1;
12100 		out->command = ctx->curr;
12101 		out->args.vc.data = (uint8_t *)out + size;
12102 		ctx->object  = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12103 						       sizeof(double));
12104 	}
12105 	return len;
12106 }
12107 
12108 /*
12109  * Replace testpmd handles in a flex flow item with real values.
12110  */
12111 static int
12112 parse_flex_handle(struct context *ctx, const struct token *token,
12113 		  const char *str, unsigned int len,
12114 		  void *buf, unsigned int size)
12115 {
12116 	struct rte_flow_item_flex *spec, *mask;
12117 	const struct rte_flow_item_flex *src_spec, *src_mask;
12118 	const struct arg *arg = pop_args(ctx);
12119 	uint32_t offset;
12120 	uint16_t handle;
12121 	int ret;
12122 
12123 	if (!arg) {
12124 		printf("Bad environment\n");
12125 		return -1;
12126 	}
12127 	offset = arg->offset;
12128 	push_args(ctx, arg);
12129 	ret = parse_int(ctx, token, str, len, buf, size);
12130 	if (ret <= 0 || !ctx->object)
12131 		return ret;
12132 	if (ctx->port >= RTE_MAX_ETHPORTS) {
12133 		printf("Bad port\n");
12134 		return -1;
12135 	}
12136 	if (offset == offsetof(struct rte_flow_item_flex, handle)) {
12137 		const struct flex_item *fp;
12138 		spec = ctx->object;
12139 		handle = (uint16_t)(uintptr_t)spec->handle;
12140 		if (handle >= FLEX_MAX_PARSERS_NUM) {
12141 			printf("Bad flex item handle\n");
12142 			return -1;
12143 		}
12144 		fp = flex_items[ctx->port][handle];
12145 		if (!fp) {
12146 			printf("Bad flex item handle\n");
12147 			return -1;
12148 		}
12149 		spec->handle = fp->flex_handle;
12150 		mask = spec + 2; /* spec, last, mask */
12151 		mask->handle = fp->flex_handle;
12152 	} else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
12153 		handle = (uint16_t)(uintptr_t)
12154 			((struct rte_flow_item_flex *)ctx->object)->pattern;
12155 		if (handle >= FLEX_MAX_PATTERNS_NUM) {
12156 			printf("Bad pattern handle\n");
12157 			return -1;
12158 		}
12159 		src_spec = &flex_patterns[handle].spec;
12160 		src_mask = &flex_patterns[handle].mask;
12161 		spec = ctx->object;
12162 		mask = spec + 2; /* spec, last, mask */
12163 		/* fill flow rule spec and mask parameters */
12164 		spec->length = src_spec->length;
12165 		spec->pattern = src_spec->pattern;
12166 		mask->length = src_mask->length;
12167 		mask->pattern = src_mask->pattern;
12168 	} else {
12169 		printf("Bad arguments - unknown flex item offset\n");
12170 		return -1;
12171 	}
12172 	return ret;
12173 }
12174 
12175 /** Parse Meter color name */
12176 static int
12177 parse_meter_color(struct context *ctx, const struct token *token,
12178 		  const char *str, unsigned int len, void *buf,
12179 		  unsigned int size)
12180 {
12181 	struct rte_flow_item_meter_color *meter_color;
12182 	unsigned int i;
12183 
12184 	(void)token;
12185 	(void)buf;
12186 	(void)size;
12187 	for (i = 0; meter_colors[i]; ++i)
12188 		if (!strcmp_partial(meter_colors[i], str, len))
12189 			break;
12190 	if (!meter_colors[i])
12191 		return -1;
12192 	if (!ctx->object)
12193 		return len;
12194 	meter_color = ctx->object;
12195 	meter_color->color = (enum rte_color)i;
12196 	return len;
12197 }
12198 
12199 /** Parse Insertion Table Type name */
12200 static int
12201 parse_insertion_table_type(struct context *ctx, const struct token *token,
12202 			   const char *str, unsigned int len, void *buf,
12203 			   unsigned int size)
12204 {
12205 	const struct arg *arg = pop_args(ctx);
12206 	unsigned int i;
12207 	char tmp[2];
12208 	int ret;
12209 
12210 	(void)size;
12211 	/* Argument is expected. */
12212 	if (!arg)
12213 		return -1;
12214 	for (i = 0; table_insertion_types[i]; ++i)
12215 		if (!strcmp_partial(table_insertion_types[i], str, len))
12216 			break;
12217 	if (!table_insertion_types[i])
12218 		return -1;
12219 	push_args(ctx, arg);
12220 	snprintf(tmp, sizeof(tmp), "%u", i);
12221 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12222 	return ret > 0 ? (int)len : ret;
12223 }
12224 
12225 /** Parse Hash Calculation Table Type name */
12226 static int
12227 parse_hash_table_type(struct context *ctx, const struct token *token,
12228 		      const char *str, unsigned int len, void *buf,
12229 		      unsigned int size)
12230 {
12231 	const struct arg *arg = pop_args(ctx);
12232 	unsigned int i;
12233 	char tmp[2];
12234 	int ret;
12235 
12236 	(void)size;
12237 	/* Argument is expected. */
12238 	if (!arg)
12239 		return -1;
12240 	for (i = 0; table_hash_funcs[i]; ++i)
12241 		if (!strcmp_partial(table_hash_funcs[i], str, len))
12242 			break;
12243 	if (!table_hash_funcs[i])
12244 		return -1;
12245 	push_args(ctx, arg);
12246 	snprintf(tmp, sizeof(tmp), "%u", i);
12247 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12248 	return ret > 0 ? (int)len : ret;
12249 }
12250 
12251 static int
12252 parse_name_to_index(struct context *ctx, const struct token *token,
12253 		    const char *str, unsigned int len, void *buf,
12254 		    unsigned int size,
12255 		    const char *const names[], size_t names_size, uint32_t *dst)
12256 {
12257 	int ret;
12258 	uint32_t i;
12259 
12260 	RTE_SET_USED(token);
12261 	RTE_SET_USED(buf);
12262 	RTE_SET_USED(size);
12263 	if (!ctx->object)
12264 		return len;
12265 	for (i = 0; i < names_size; i++) {
12266 		if (!names[i])
12267 			continue;
12268 		ret = strcmp_partial(names[i], str,
12269 				     RTE_MIN(len, strlen(names[i])));
12270 		if (!ret) {
12271 			*dst = i;
12272 			return len;
12273 		}
12274 	}
12275 	return -1;
12276 }
12277 
12278 static const char *const quota_mode_names[] = {
12279 	NULL,
12280 	[RTE_FLOW_QUOTA_MODE_PACKET] = "packet",
12281 	[RTE_FLOW_QUOTA_MODE_L2] = "l2",
12282 	[RTE_FLOW_QUOTA_MODE_L3] = "l3"
12283 };
12284 
12285 static const char *const quota_state_names[] = {
12286 	[RTE_FLOW_QUOTA_STATE_PASS] = "pass",
12287 	[RTE_FLOW_QUOTA_STATE_BLOCK] = "block"
12288 };
12289 
12290 static const char *const quota_update_names[] = {
12291 	[RTE_FLOW_UPDATE_QUOTA_SET] = "set",
12292 	[RTE_FLOW_UPDATE_QUOTA_ADD] = "add"
12293 };
12294 
12295 static const char *const query_update_mode_names[] = {
12296 	[RTE_FLOW_QU_QUERY_FIRST] = "query_first",
12297 	[RTE_FLOW_QU_UPDATE_FIRST] = "update_first"
12298 };
12299 
12300 static int
12301 parse_quota_state_name(struct context *ctx, const struct token *token,
12302 		       const char *str, unsigned int len, void *buf,
12303 		       unsigned int size)
12304 {
12305 	struct rte_flow_item_quota *quota = ctx->object;
12306 
12307 	return parse_name_to_index(ctx, token, str, len, buf, size,
12308 				   quota_state_names,
12309 				   RTE_DIM(quota_state_names),
12310 				   (uint32_t *)&quota->state);
12311 }
12312 
12313 static int
12314 parse_quota_mode_name(struct context *ctx, const struct token *token,
12315 		      const char *str, unsigned int len, void *buf,
12316 		      unsigned int size)
12317 {
12318 	struct rte_flow_action_quota *quota = ctx->object;
12319 
12320 	return parse_name_to_index(ctx, token, str, len, buf, size,
12321 				   quota_mode_names,
12322 				   RTE_DIM(quota_mode_names),
12323 				   (uint32_t *)&quota->mode);
12324 }
12325 
12326 static int
12327 parse_quota_update_name(struct context *ctx, const struct token *token,
12328 			const char *str, unsigned int len, void *buf,
12329 			unsigned int size)
12330 {
12331 	struct rte_flow_update_quota *update = ctx->object;
12332 
12333 	return parse_name_to_index(ctx, token, str, len, buf, size,
12334 				   quota_update_names,
12335 				   RTE_DIM(quota_update_names),
12336 				   (uint32_t *)&update->op);
12337 }
12338 
12339 static int
12340 parse_qu_mode_name(struct context *ctx, const struct token *token,
12341 		   const char *str, unsigned int len, void *buf,
12342 		   unsigned int size)
12343 {
12344 	struct buffer *out = ctx->object;
12345 
12346 	return parse_name_to_index(ctx, token, str, len, buf, size,
12347 				   query_update_mode_names,
12348 				   RTE_DIM(query_update_mode_names),
12349 				   (uint32_t *)&out->args.ia.qu_mode);
12350 }
12351 
12352 /** No completion. */
12353 static int
12354 comp_none(struct context *ctx, const struct token *token,
12355 	  unsigned int ent, char *buf, unsigned int size)
12356 {
12357 	(void)ctx;
12358 	(void)token;
12359 	(void)ent;
12360 	(void)buf;
12361 	(void)size;
12362 	return 0;
12363 }
12364 
12365 /** Complete boolean values. */
12366 static int
12367 comp_boolean(struct context *ctx, const struct token *token,
12368 	     unsigned int ent, char *buf, unsigned int size)
12369 {
12370 	unsigned int i;
12371 
12372 	(void)ctx;
12373 	(void)token;
12374 	for (i = 0; boolean_name[i]; ++i)
12375 		if (buf && i == ent)
12376 			return strlcpy(buf, boolean_name[i], size);
12377 	if (buf)
12378 		return -1;
12379 	return i;
12380 }
12381 
12382 /** Complete action names. */
12383 static int
12384 comp_action(struct context *ctx, const struct token *token,
12385 	    unsigned int ent, char *buf, unsigned int size)
12386 {
12387 	unsigned int i;
12388 
12389 	(void)ctx;
12390 	(void)token;
12391 	for (i = 0; next_action[i]; ++i)
12392 		if (buf && i == ent)
12393 			return strlcpy(buf, token_list[next_action[i]].name,
12394 				       size);
12395 	if (buf)
12396 		return -1;
12397 	return i;
12398 }
12399 
12400 /** Complete available ports. */
12401 static int
12402 comp_port(struct context *ctx, const struct token *token,
12403 	  unsigned int ent, char *buf, unsigned int size)
12404 {
12405 	unsigned int i = 0;
12406 	portid_t p;
12407 
12408 	(void)ctx;
12409 	(void)token;
12410 	RTE_ETH_FOREACH_DEV(p) {
12411 		if (buf && i == ent)
12412 			return snprintf(buf, size, "%u", p);
12413 		++i;
12414 	}
12415 	if (buf)
12416 		return -1;
12417 	return i;
12418 }
12419 
12420 /** Complete available rule IDs. */
12421 static int
12422 comp_rule_id(struct context *ctx, const struct token *token,
12423 	     unsigned int ent, char *buf, unsigned int size)
12424 {
12425 	unsigned int i = 0;
12426 	struct rte_port *port;
12427 	struct port_flow *pf;
12428 
12429 	(void)token;
12430 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12431 	    ctx->port == (portid_t)RTE_PORT_ALL)
12432 		return -1;
12433 	port = &ports[ctx->port];
12434 	for (pf = port->flow_list; pf != NULL; pf = pf->next) {
12435 		if (buf && i == ent)
12436 			return snprintf(buf, size, "%"PRIu64, pf->id);
12437 		++i;
12438 	}
12439 	if (buf)
12440 		return -1;
12441 	return i;
12442 }
12443 
12444 /** Complete operation for compare match item. */
12445 static int
12446 comp_set_compare_op(struct context *ctx, const struct token *token,
12447 		    unsigned int ent, char *buf, unsigned int size)
12448 {
12449 	RTE_SET_USED(ctx);
12450 	RTE_SET_USED(token);
12451 	if (!buf)
12452 		return RTE_DIM(compare_ops);
12453 	if (ent < RTE_DIM(compare_ops) - 1)
12454 		return strlcpy(buf, compare_ops[ent], size);
12455 	return -1;
12456 }
12457 
12458 /** Complete field id for compare match item. */
12459 static int
12460 comp_set_compare_field_id(struct context *ctx, const struct token *token,
12461 			  unsigned int ent, char *buf, unsigned int size)
12462 {
12463 	const char *name;
12464 
12465 	RTE_SET_USED(token);
12466 	if (!buf)
12467 		return RTE_DIM(flow_field_ids);
12468 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12469 		return -1;
12470 	name = flow_field_ids[ent];
12471 	if (ctx->curr == ITEM_COMPARE_FIELD_B_TYPE ||
12472 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12473 		return strlcpy(buf, name, size);
12474 	return -1;
12475 }
12476 
12477 /** Complete type field for RSS action. */
12478 static int
12479 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
12480 			unsigned int ent, char *buf, unsigned int size)
12481 {
12482 	unsigned int i;
12483 
12484 	(void)ctx;
12485 	(void)token;
12486 	for (i = 0; rss_type_table[i].str; ++i)
12487 		;
12488 	if (!buf)
12489 		return i + 1;
12490 	if (ent < i)
12491 		return strlcpy(buf, rss_type_table[ent].str, size);
12492 	if (ent == i)
12493 		return snprintf(buf, size, "end");
12494 	return -1;
12495 }
12496 
12497 /** Complete queue field for RSS action. */
12498 static int
12499 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
12500 			 unsigned int ent, char *buf, unsigned int size)
12501 {
12502 	(void)ctx;
12503 	(void)token;
12504 	if (!buf)
12505 		return nb_rxq + 1;
12506 	if (ent < nb_rxq)
12507 		return snprintf(buf, size, "%u", ent);
12508 	if (ent == nb_rxq)
12509 		return snprintf(buf, size, "end");
12510 	return -1;
12511 }
12512 
12513 /** Complete index number for set raw_encap/raw_decap commands. */
12514 static int
12515 comp_set_raw_index(struct context *ctx, const struct token *token,
12516 		   unsigned int ent, char *buf, unsigned int size)
12517 {
12518 	uint16_t idx = 0;
12519 	uint16_t nb = 0;
12520 
12521 	RTE_SET_USED(ctx);
12522 	RTE_SET_USED(token);
12523 	for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
12524 		if (buf && idx == ent)
12525 			return snprintf(buf, size, "%u", idx);
12526 		++nb;
12527 	}
12528 	return nb;
12529 }
12530 
12531 /** Complete index number for set raw_ipv6_ext_push/ipv6_ext_remove commands. */
12532 static int
12533 comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
12534 			unsigned int ent, char *buf, unsigned int size)
12535 {
12536 	uint16_t idx = 0;
12537 	uint16_t nb = 0;
12538 
12539 	RTE_SET_USED(ctx);
12540 	RTE_SET_USED(token);
12541 	for (idx = 0; idx < IPV6_EXT_PUSH_CONFS_MAX_NUM; ++idx) {
12542 		if (buf && idx == ent)
12543 			return snprintf(buf, size, "%u", idx);
12544 		++nb;
12545 	}
12546 	return nb;
12547 }
12548 
12549 /** Complete index number for set raw_encap/raw_decap commands. */
12550 static int
12551 comp_set_sample_index(struct context *ctx, const struct token *token,
12552 		   unsigned int ent, char *buf, unsigned int size)
12553 {
12554 	uint16_t idx = 0;
12555 	uint16_t nb = 0;
12556 
12557 	RTE_SET_USED(ctx);
12558 	RTE_SET_USED(token);
12559 	for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
12560 		if (buf && idx == ent)
12561 			return snprintf(buf, size, "%u", idx);
12562 		++nb;
12563 	}
12564 	return nb;
12565 }
12566 
12567 /** Complete operation for modify_field command. */
12568 static int
12569 comp_set_modify_field_op(struct context *ctx, const struct token *token,
12570 		   unsigned int ent, char *buf, unsigned int size)
12571 {
12572 	RTE_SET_USED(ctx);
12573 	RTE_SET_USED(token);
12574 	if (!buf)
12575 		return RTE_DIM(modify_field_ops);
12576 	if (ent < RTE_DIM(modify_field_ops) - 1)
12577 		return strlcpy(buf, modify_field_ops[ent], size);
12578 	return -1;
12579 }
12580 
12581 /** Complete field id for modify_field command. */
12582 static int
12583 comp_set_modify_field_id(struct context *ctx, const struct token *token,
12584 		   unsigned int ent, char *buf, unsigned int size)
12585 {
12586 	const char *name;
12587 
12588 	RTE_SET_USED(token);
12589 	if (!buf)
12590 		return RTE_DIM(flow_field_ids);
12591 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12592 		return -1;
12593 	name = flow_field_ids[ent];
12594 	if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
12595 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12596 		return strlcpy(buf, name, size);
12597 	return -1;
12598 }
12599 
12600 /** Complete available pattern template IDs. */
12601 static int
12602 comp_pattern_template_id(struct context *ctx, const struct token *token,
12603 			 unsigned int ent, char *buf, unsigned int size)
12604 {
12605 	unsigned int i = 0;
12606 	struct rte_port *port;
12607 	struct port_template *pt;
12608 
12609 	(void)token;
12610 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12611 	    ctx->port == (portid_t)RTE_PORT_ALL)
12612 		return -1;
12613 	port = &ports[ctx->port];
12614 	for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) {
12615 		if (buf && i == ent)
12616 			return snprintf(buf, size, "%u", pt->id);
12617 		++i;
12618 	}
12619 	if (buf)
12620 		return -1;
12621 	return i;
12622 }
12623 
12624 /** Complete available actions template IDs. */
12625 static int
12626 comp_actions_template_id(struct context *ctx, const struct token *token,
12627 			 unsigned int ent, char *buf, unsigned int size)
12628 {
12629 	unsigned int i = 0;
12630 	struct rte_port *port;
12631 	struct port_template *pt;
12632 
12633 	(void)token;
12634 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12635 	    ctx->port == (portid_t)RTE_PORT_ALL)
12636 		return -1;
12637 	port = &ports[ctx->port];
12638 	for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) {
12639 		if (buf && i == ent)
12640 			return snprintf(buf, size, "%u", pt->id);
12641 		++i;
12642 	}
12643 	if (buf)
12644 		return -1;
12645 	return i;
12646 }
12647 
12648 /** Complete available table IDs. */
12649 static int
12650 comp_table_id(struct context *ctx, const struct token *token,
12651 	      unsigned int ent, char *buf, unsigned int size)
12652 {
12653 	unsigned int i = 0;
12654 	struct rte_port *port;
12655 	struct port_table *pt;
12656 
12657 	(void)token;
12658 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12659 	    ctx->port == (portid_t)RTE_PORT_ALL)
12660 		return -1;
12661 	port = &ports[ctx->port];
12662 	for (pt = port->table_list; pt != NULL; pt = pt->next) {
12663 		if (buf && i == ent)
12664 			return snprintf(buf, size, "%u", pt->id);
12665 		++i;
12666 	}
12667 	if (buf)
12668 		return -1;
12669 	return i;
12670 }
12671 
12672 /** Complete available queue IDs. */
12673 static int
12674 comp_queue_id(struct context *ctx, const struct token *token,
12675 	      unsigned int ent, char *buf, unsigned int size)
12676 {
12677 	unsigned int i = 0;
12678 	struct rte_port *port;
12679 
12680 	(void)token;
12681 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12682 	    ctx->port == (portid_t)RTE_PORT_ALL)
12683 		return -1;
12684 	port = &ports[ctx->port];
12685 	for (i = 0; i < port->queue_nb; i++) {
12686 		if (buf && i == ent)
12687 			return snprintf(buf, size, "%u", i);
12688 	}
12689 	if (buf)
12690 		return -1;
12691 	return i;
12692 }
12693 
12694 static int
12695 comp_names_to_index(struct context *ctx, const struct token *token,
12696 		    unsigned int ent, char *buf, unsigned int size,
12697 		    const char *const names[], size_t names_size)
12698 {
12699 	RTE_SET_USED(ctx);
12700 	RTE_SET_USED(token);
12701 	if (!buf)
12702 		return names_size;
12703 	if (names[ent] && ent < names_size)
12704 		return rte_strscpy(buf, names[ent], size);
12705 	return -1;
12706 
12707 }
12708 
12709 /** Complete available Meter colors. */
12710 static int
12711 comp_meter_color(struct context *ctx, const struct token *token,
12712 		 unsigned int ent, char *buf, unsigned int size)
12713 {
12714 	RTE_SET_USED(ctx);
12715 	RTE_SET_USED(token);
12716 	if (!buf)
12717 		return RTE_DIM(meter_colors);
12718 	if (ent < RTE_DIM(meter_colors) - 1)
12719 		return strlcpy(buf, meter_colors[ent], size);
12720 	return -1;
12721 }
12722 
12723 /** Complete available Insertion Table types. */
12724 static int
12725 comp_insertion_table_type(struct context *ctx, const struct token *token,
12726 			  unsigned int ent, char *buf, unsigned int size)
12727 {
12728 	RTE_SET_USED(ctx);
12729 	RTE_SET_USED(token);
12730 	if (!buf)
12731 		return RTE_DIM(table_insertion_types);
12732 	if (ent < RTE_DIM(table_insertion_types) - 1)
12733 		return rte_strscpy(buf, table_insertion_types[ent], size);
12734 	return -1;
12735 }
12736 
12737 /** Complete available Hash Calculation Table types. */
12738 static int
12739 comp_hash_table_type(struct context *ctx, const struct token *token,
12740 		     unsigned int ent, char *buf, unsigned int size)
12741 {
12742 	RTE_SET_USED(ctx);
12743 	RTE_SET_USED(token);
12744 	if (!buf)
12745 		return RTE_DIM(table_hash_funcs);
12746 	if (ent < RTE_DIM(table_hash_funcs) - 1)
12747 		return rte_strscpy(buf, table_hash_funcs[ent], size);
12748 	return -1;
12749 }
12750 
12751 static int
12752 comp_quota_state_name(struct context *ctx, const struct token *token,
12753 		      unsigned int ent, char *buf, unsigned int size)
12754 {
12755 	return comp_names_to_index(ctx, token, ent, buf, size,
12756 				   quota_state_names,
12757 				   RTE_DIM(quota_state_names));
12758 }
12759 
12760 static int
12761 comp_quota_mode_name(struct context *ctx, const struct token *token,
12762 		     unsigned int ent, char *buf, unsigned int size)
12763 {
12764 	return comp_names_to_index(ctx, token, ent, buf, size,
12765 				   quota_mode_names,
12766 				   RTE_DIM(quota_mode_names));
12767 }
12768 
12769 static int
12770 comp_quota_update_name(struct context *ctx, const struct token *token,
12771 		       unsigned int ent, char *buf, unsigned int size)
12772 {
12773 	return comp_names_to_index(ctx, token, ent, buf, size,
12774 				   quota_update_names,
12775 				   RTE_DIM(quota_update_names));
12776 }
12777 
12778 static int
12779 comp_qu_mode_name(struct context *ctx, const struct token *token,
12780 		  unsigned int ent, char *buf, unsigned int size)
12781 {
12782 	return comp_names_to_index(ctx, token, ent, buf, size,
12783 				   query_update_mode_names,
12784 				   RTE_DIM(query_update_mode_names));
12785 }
12786 
12787 /** Internal context. */
12788 static struct context cmd_flow_context;
12789 
12790 /** Global parser instance (cmdline API). */
12791 cmdline_parse_inst_t cmd_flow;
12792 cmdline_parse_inst_t cmd_set_raw;
12793 
12794 /** Initialize context. */
12795 static void
12796 cmd_flow_context_init(struct context *ctx)
12797 {
12798 	/* A full memset() is not necessary. */
12799 	ctx->curr = ZERO;
12800 	ctx->prev = ZERO;
12801 	ctx->next_num = 0;
12802 	ctx->args_num = 0;
12803 	ctx->eol = 0;
12804 	ctx->last = 0;
12805 	ctx->port = 0;
12806 	ctx->objdata = 0;
12807 	ctx->object = NULL;
12808 	ctx->objmask = NULL;
12809 }
12810 
12811 /** Parse a token (cmdline API). */
12812 static int
12813 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
12814 	       unsigned int size)
12815 {
12816 	struct context *ctx = &cmd_flow_context;
12817 	const struct token *token;
12818 	const enum index *list;
12819 	int len;
12820 	int i;
12821 
12822 	(void)hdr;
12823 	token = &token_list[ctx->curr];
12824 	/* Check argument length. */
12825 	ctx->eol = 0;
12826 	ctx->last = 1;
12827 	for (len = 0; src[len]; ++len)
12828 		if (src[len] == '#' || isspace(src[len]))
12829 			break;
12830 	if (!len)
12831 		return -1;
12832 	/* Last argument and EOL detection. */
12833 	for (i = len; src[i]; ++i)
12834 		if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
12835 			break;
12836 		else if (!isspace(src[i])) {
12837 			ctx->last = 0;
12838 			break;
12839 		}
12840 	for (; src[i]; ++i)
12841 		if (src[i] == '\r' || src[i] == '\n') {
12842 			ctx->eol = 1;
12843 			break;
12844 		}
12845 	/* Initialize context if necessary. */
12846 	if (!ctx->next_num) {
12847 		if (!token->next)
12848 			return 0;
12849 		ctx->next[ctx->next_num++] = token->next[0];
12850 	}
12851 	/* Process argument through candidates. */
12852 	ctx->prev = ctx->curr;
12853 	list = ctx->next[ctx->next_num - 1];
12854 	for (i = 0; list[i]; ++i) {
12855 		const struct token *next = &token_list[list[i]];
12856 		int tmp;
12857 
12858 		ctx->curr = list[i];
12859 		if (next->call)
12860 			tmp = next->call(ctx, next, src, len, result, size);
12861 		else
12862 			tmp = parse_default(ctx, next, src, len, result, size);
12863 		if (tmp == -1 || tmp != len)
12864 			continue;
12865 		token = next;
12866 		break;
12867 	}
12868 	if (!list[i])
12869 		return -1;
12870 	--ctx->next_num;
12871 	/* Push subsequent tokens if any. */
12872 	if (token->next)
12873 		for (i = 0; token->next[i]; ++i) {
12874 			if (ctx->next_num == RTE_DIM(ctx->next))
12875 				return -1;
12876 			ctx->next[ctx->next_num++] = token->next[i];
12877 		}
12878 	/* Push arguments if any. */
12879 	if (token->args)
12880 		for (i = 0; token->args[i]; ++i) {
12881 			if (ctx->args_num == RTE_DIM(ctx->args))
12882 				return -1;
12883 			ctx->args[ctx->args_num++] = token->args[i];
12884 		}
12885 	return len;
12886 }
12887 
12888 int
12889 flow_parse(const char *src, void *result, unsigned int size,
12890 	   struct rte_flow_attr **attr,
12891 	   struct rte_flow_item **pattern, struct rte_flow_action **actions)
12892 {
12893 	int ret;
12894 	struct context saved_flow_ctx = cmd_flow_context;
12895 
12896 	cmd_flow_context_init(&cmd_flow_context);
12897 	do {
12898 		ret = cmd_flow_parse(NULL, src, result, size);
12899 		if (ret > 0) {
12900 			src += ret;
12901 			while (isspace(*src))
12902 				src++;
12903 		}
12904 	} while (ret > 0 && strlen(src));
12905 	cmd_flow_context = saved_flow_ctx;
12906 	*attr = &((struct buffer *)result)->args.vc.attr;
12907 	*pattern = ((struct buffer *)result)->args.vc.pattern;
12908 	*actions = ((struct buffer *)result)->args.vc.actions;
12909 	return (ret >= 0 && !strlen(src)) ? 0 : -1;
12910 }
12911 
12912 /** Return number of completion entries (cmdline API). */
12913 static int
12914 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
12915 {
12916 	struct context *ctx = &cmd_flow_context;
12917 	const struct token *token = &token_list[ctx->curr];
12918 	const enum index *list;
12919 	int i;
12920 
12921 	(void)hdr;
12922 	/* Count number of tokens in current list. */
12923 	if (ctx->next_num)
12924 		list = ctx->next[ctx->next_num - 1];
12925 	else
12926 		list = token->next[0];
12927 	for (i = 0; list[i]; ++i)
12928 		;
12929 	if (!i)
12930 		return 0;
12931 	/*
12932 	 * If there is a single token, use its completion callback, otherwise
12933 	 * return the number of entries.
12934 	 */
12935 	token = &token_list[list[0]];
12936 	if (i == 1 && token->comp) {
12937 		/* Save index for cmd_flow_get_help(). */
12938 		ctx->prev = list[0];
12939 		return token->comp(ctx, token, 0, NULL, 0);
12940 	}
12941 	return i;
12942 }
12943 
12944 /** Return a completion entry (cmdline API). */
12945 static int
12946 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
12947 			  char *dst, unsigned int size)
12948 {
12949 	struct context *ctx = &cmd_flow_context;
12950 	const struct token *token = &token_list[ctx->curr];
12951 	const enum index *list;
12952 	int i;
12953 
12954 	(void)hdr;
12955 	/* Count number of tokens in current list. */
12956 	if (ctx->next_num)
12957 		list = ctx->next[ctx->next_num - 1];
12958 	else
12959 		list = token->next[0];
12960 	for (i = 0; list[i]; ++i)
12961 		;
12962 	if (!i)
12963 		return -1;
12964 	/* If there is a single token, use its completion callback. */
12965 	token = &token_list[list[0]];
12966 	if (i == 1 && token->comp) {
12967 		/* Save index for cmd_flow_get_help(). */
12968 		ctx->prev = list[0];
12969 		return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
12970 	}
12971 	/* Otherwise make sure the index is valid and use defaults. */
12972 	if (index >= i)
12973 		return -1;
12974 	token = &token_list[list[index]];
12975 	strlcpy(dst, token->name, size);
12976 	/* Save index for cmd_flow_get_help(). */
12977 	ctx->prev = list[index];
12978 	return 0;
12979 }
12980 
12981 /** Populate help strings for current token (cmdline API). */
12982 static int
12983 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
12984 {
12985 	struct context *ctx = &cmd_flow_context;
12986 	const struct token *token = &token_list[ctx->prev];
12987 
12988 	(void)hdr;
12989 	if (!size)
12990 		return -1;
12991 	/* Set token type and update global help with details. */
12992 	strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
12993 	if (token->help)
12994 		cmd_flow.help_str = token->help;
12995 	else
12996 		cmd_flow.help_str = token->name;
12997 	return 0;
12998 }
12999 
13000 /** Token definition template (cmdline API). */
13001 static struct cmdline_token_hdr cmd_flow_token_hdr = {
13002 	.ops = &(struct cmdline_token_ops){
13003 		.parse = cmd_flow_parse,
13004 		.complete_get_nb = cmd_flow_complete_get_nb,
13005 		.complete_get_elt = cmd_flow_complete_get_elt,
13006 		.get_help = cmd_flow_get_help,
13007 	},
13008 	.offset = 0,
13009 };
13010 
13011 /** Populate the next dynamic token. */
13012 static void
13013 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
13014 	     cmdline_parse_token_hdr_t **hdr_inst)
13015 {
13016 	struct context *ctx = &cmd_flow_context;
13017 
13018 	/* Always reinitialize context before requesting the first token. */
13019 	if (!(hdr_inst - cmd_flow.tokens))
13020 		cmd_flow_context_init(ctx);
13021 	/* Return NULL when no more tokens are expected. */
13022 	if (!ctx->next_num && ctx->curr) {
13023 		*hdr = NULL;
13024 		return;
13025 	}
13026 	/* Determine if command should end here. */
13027 	if (ctx->eol && ctx->last && ctx->next_num) {
13028 		const enum index *list = ctx->next[ctx->next_num - 1];
13029 		int i;
13030 
13031 		for (i = 0; list[i]; ++i) {
13032 			if (list[i] != END)
13033 				continue;
13034 			*hdr = NULL;
13035 			return;
13036 		}
13037 	}
13038 	*hdr = &cmd_flow_token_hdr;
13039 }
13040 
13041 static SLIST_HEAD(, indlst_conf) indlst_conf_head =
13042 	SLIST_HEAD_INITIALIZER();
13043 
13044 static void
13045 indirect_action_flow_conf_create(const struct buffer *in)
13046 {
13047 	int len, ret;
13048 	uint32_t i;
13049 	struct indlst_conf *indlst_conf = NULL;
13050 	size_t base = RTE_ALIGN(sizeof(*indlst_conf), 8);
13051 	struct rte_flow_action *src = in->args.vc.actions;
13052 
13053 	if (!in->args.vc.actions_n)
13054 		goto end;
13055 	len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, src, NULL);
13056 	if (len <= 0)
13057 		goto end;
13058 	len = RTE_ALIGN(len, 16);
13059 
13060 	indlst_conf = calloc(1, base + len +
13061 			     in->args.vc.actions_n * sizeof(uintptr_t));
13062 	if (!indlst_conf)
13063 		goto end;
13064 	indlst_conf->id = in->args.vc.attr.group;
13065 	indlst_conf->conf_num = in->args.vc.actions_n - 1;
13066 	indlst_conf->actions = RTE_PTR_ADD(indlst_conf, base);
13067 	ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, indlst_conf->actions,
13068 			    len, src, NULL);
13069 	if (ret <= 0) {
13070 		free(indlst_conf);
13071 		indlst_conf = NULL;
13072 		goto end;
13073 	}
13074 	indlst_conf->conf = RTE_PTR_ADD(indlst_conf, base + len);
13075 	for (i = 0; i < indlst_conf->conf_num; i++)
13076 		indlst_conf->conf[i] = indlst_conf->actions[i].conf;
13077 	SLIST_INSERT_HEAD(&indlst_conf_head, indlst_conf, next);
13078 end:
13079 	if (indlst_conf)
13080 		printf("created indirect action list configuration %u\n",
13081 		       in->args.vc.attr.group);
13082 	else
13083 		printf("cannot create indirect action list configuration %u\n",
13084 		       in->args.vc.attr.group);
13085 }
13086 
13087 static const struct indlst_conf *
13088 indirect_action_list_conf_get(uint32_t conf_id)
13089 {
13090 	const struct indlst_conf *conf;
13091 
13092 	SLIST_FOREACH(conf, &indlst_conf_head, next) {
13093 		if (conf->id == conf_id)
13094 			return conf;
13095 	}
13096 	return NULL;
13097 }
13098 
13099 /** Dispatch parsed buffer to function calls. */
13100 static void
13101 cmd_flow_parsed(const struct buffer *in)
13102 {
13103 	switch (in->command) {
13104 	case INFO:
13105 		port_flow_get_info(in->port);
13106 		break;
13107 	case CONFIGURE:
13108 		port_flow_configure(in->port,
13109 				    &in->args.configure.port_attr,
13110 				    in->args.configure.nb_queue,
13111 				    &in->args.configure.queue_attr);
13112 		break;
13113 	case PATTERN_TEMPLATE_CREATE:
13114 		port_flow_pattern_template_create(in->port,
13115 				in->args.vc.pat_templ_id,
13116 				&((const struct rte_flow_pattern_template_attr) {
13117 					.relaxed_matching = in->args.vc.attr.reserved,
13118 					.ingress = in->args.vc.attr.ingress,
13119 					.egress = in->args.vc.attr.egress,
13120 					.transfer = in->args.vc.attr.transfer,
13121 				}),
13122 				in->args.vc.pattern);
13123 		break;
13124 	case PATTERN_TEMPLATE_DESTROY:
13125 		port_flow_pattern_template_destroy(in->port,
13126 				in->args.templ_destroy.template_id_n,
13127 				in->args.templ_destroy.template_id);
13128 		break;
13129 	case ACTIONS_TEMPLATE_CREATE:
13130 		port_flow_actions_template_create(in->port,
13131 				in->args.vc.act_templ_id,
13132 				&((const struct rte_flow_actions_template_attr) {
13133 					.ingress = in->args.vc.attr.ingress,
13134 					.egress = in->args.vc.attr.egress,
13135 					.transfer = in->args.vc.attr.transfer,
13136 				}),
13137 				in->args.vc.actions,
13138 				in->args.vc.masks);
13139 		break;
13140 	case ACTIONS_TEMPLATE_DESTROY:
13141 		port_flow_actions_template_destroy(in->port,
13142 				in->args.templ_destroy.template_id_n,
13143 				in->args.templ_destroy.template_id);
13144 		break;
13145 	case TABLE_CREATE:
13146 		port_flow_template_table_create(in->port, in->args.table.id,
13147 			&in->args.table.attr, in->args.table.pat_templ_id_n,
13148 			in->args.table.pat_templ_id, in->args.table.act_templ_id_n,
13149 			in->args.table.act_templ_id);
13150 		break;
13151 	case TABLE_DESTROY:
13152 		port_flow_template_table_destroy(in->port,
13153 					in->args.table_destroy.table_id_n,
13154 					in->args.table_destroy.table_id);
13155 		break;
13156 	case TABLE_RESIZE_COMPLETE:
13157 		port_flow_template_table_resize_complete
13158 			(in->port, in->args.table_destroy.table_id[0]);
13159 		break;
13160 	case GROUP_SET_MISS_ACTIONS:
13161 		port_queue_group_set_miss_actions(in->port, &in->args.vc.attr,
13162 						  in->args.vc.actions);
13163 		break;
13164 	case TABLE_RESIZE:
13165 		port_flow_template_table_resize(in->port, in->args.table.id,
13166 						in->args.table.attr.nb_flows);
13167 		break;
13168 	case QUEUE_CREATE:
13169 		port_queue_flow_create(in->port, in->queue, in->postpone,
13170 			in->args.vc.table_id, in->args.vc.rule_id,
13171 			in->args.vc.pat_templ_id, in->args.vc.act_templ_id,
13172 			in->args.vc.pattern, in->args.vc.actions);
13173 		break;
13174 	case QUEUE_DESTROY:
13175 		port_queue_flow_destroy(in->port, in->queue, in->postpone,
13176 					in->args.destroy.rule_n,
13177 					in->args.destroy.rule);
13178 		break;
13179 	case QUEUE_FLOW_UPDATE_RESIZED:
13180 		port_queue_flow_update_resized(in->port, in->queue,
13181 					       in->postpone,
13182 					       in->args.destroy.rule[0]);
13183 		break;
13184 	case QUEUE_UPDATE:
13185 		port_queue_flow_update(in->port, in->queue, in->postpone,
13186 				in->args.vc.rule_id, in->args.vc.act_templ_id,
13187 				in->args.vc.actions);
13188 		break;
13189 	case PUSH:
13190 		port_queue_flow_push(in->port, in->queue);
13191 		break;
13192 	case PULL:
13193 		port_queue_flow_pull(in->port, in->queue);
13194 		break;
13195 	case HASH:
13196 		if (!in->args.vc.encap_hash)
13197 			port_flow_hash_calc(in->port, in->args.vc.table_id,
13198 					    in->args.vc.pat_templ_id,
13199 					    in->args.vc.pattern);
13200 		else
13201 			port_flow_hash_calc_encap(in->port, in->args.vc.field,
13202 						  in->args.vc.pattern);
13203 		break;
13204 	case QUEUE_AGED:
13205 		port_queue_flow_aged(in->port, in->queue,
13206 				     in->args.aged.destroy);
13207 		break;
13208 	case QUEUE_INDIRECT_ACTION_CREATE:
13209 	case QUEUE_INDIRECT_ACTION_LIST_CREATE:
13210 		port_queue_action_handle_create(
13211 				in->port, in->queue, in->postpone,
13212 				in->args.vc.attr.group,
13213 				&((const struct rte_flow_indir_action_conf) {
13214 					.ingress = in->args.vc.attr.ingress,
13215 					.egress = in->args.vc.attr.egress,
13216 					.transfer = in->args.vc.attr.transfer,
13217 				}),
13218 				in->args.vc.actions);
13219 		break;
13220 	case QUEUE_INDIRECT_ACTION_DESTROY:
13221 		port_queue_action_handle_destroy(in->port,
13222 					   in->queue, in->postpone,
13223 					   in->args.ia_destroy.action_id_n,
13224 					   in->args.ia_destroy.action_id);
13225 		break;
13226 	case QUEUE_INDIRECT_ACTION_UPDATE:
13227 		port_queue_action_handle_update(in->port,
13228 						in->queue, in->postpone,
13229 						in->args.vc.attr.group,
13230 						in->args.vc.actions);
13231 		break;
13232 	case QUEUE_INDIRECT_ACTION_QUERY:
13233 		port_queue_action_handle_query(in->port,
13234 					       in->queue, in->postpone,
13235 					       in->args.ia.action_id);
13236 		break;
13237 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
13238 		port_queue_action_handle_query_update(in->port, in->queue,
13239 						      in->postpone,
13240 						      in->args.ia.action_id,
13241 						      in->args.ia.qu_mode,
13242 						      in->args.vc.actions);
13243 		break;
13244 	case INDIRECT_ACTION_CREATE:
13245 	case INDIRECT_ACTION_LIST_CREATE:
13246 		port_action_handle_create(
13247 				in->port, in->args.vc.attr.group,
13248 				in->command == INDIRECT_ACTION_LIST_CREATE,
13249 				&((const struct rte_flow_indir_action_conf) {
13250 					.ingress = in->args.vc.attr.ingress,
13251 					.egress = in->args.vc.attr.egress,
13252 					.transfer = in->args.vc.attr.transfer,
13253 				}),
13254 				in->args.vc.actions);
13255 		break;
13256 	case INDIRECT_ACTION_FLOW_CONF_CREATE:
13257 		indirect_action_flow_conf_create(in);
13258 		break;
13259 	case INDIRECT_ACTION_DESTROY:
13260 		port_action_handle_destroy(in->port,
13261 					   in->args.ia_destroy.action_id_n,
13262 					   in->args.ia_destroy.action_id);
13263 		break;
13264 	case INDIRECT_ACTION_UPDATE:
13265 		port_action_handle_update(in->port, in->args.vc.attr.group,
13266 					  in->args.vc.actions);
13267 		break;
13268 	case INDIRECT_ACTION_QUERY:
13269 		port_action_handle_query(in->port, in->args.ia.action_id);
13270 		break;
13271 	case INDIRECT_ACTION_QUERY_UPDATE:
13272 		port_action_handle_query_update(in->port,
13273 						in->args.ia.action_id,
13274 						in->args.ia.qu_mode,
13275 						in->args.vc.actions);
13276 		break;
13277 	case VALIDATE:
13278 		port_flow_validate(in->port, &in->args.vc.attr,
13279 				   in->args.vc.pattern, in->args.vc.actions,
13280 				   &in->args.vc.tunnel_ops);
13281 		break;
13282 	case CREATE:
13283 		port_flow_create(in->port, &in->args.vc.attr,
13284 				 in->args.vc.pattern, in->args.vc.actions,
13285 				 &in->args.vc.tunnel_ops, in->args.vc.user_id);
13286 		break;
13287 	case DESTROY:
13288 		port_flow_destroy(in->port, in->args.destroy.rule_n,
13289 				  in->args.destroy.rule,
13290 				  in->args.destroy.is_user_id);
13291 		break;
13292 	case FLUSH:
13293 		port_flow_flush(in->port);
13294 		break;
13295 	case DUMP_ONE:
13296 	case DUMP_ALL:
13297 		port_flow_dump(in->port, in->args.dump.mode,
13298 				in->args.dump.rule, in->args.dump.file,
13299 				in->args.dump.is_user_id);
13300 		break;
13301 	case QUERY:
13302 		port_flow_query(in->port, in->args.query.rule,
13303 				&in->args.query.action,
13304 				in->args.query.is_user_id);
13305 		break;
13306 	case LIST:
13307 		port_flow_list(in->port, in->args.list.group_n,
13308 			       in->args.list.group);
13309 		break;
13310 	case ISOLATE:
13311 		port_flow_isolate(in->port, in->args.isolate.set);
13312 		break;
13313 	case AGED:
13314 		port_flow_aged(in->port, in->args.aged.destroy);
13315 		break;
13316 	case TUNNEL_CREATE:
13317 		port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
13318 		break;
13319 	case TUNNEL_DESTROY:
13320 		port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
13321 		break;
13322 	case TUNNEL_LIST:
13323 		port_flow_tunnel_list(in->port);
13324 		break;
13325 	case ACTION_POL_G:
13326 		port_meter_policy_add(in->port, in->args.policy.policy_id,
13327 					in->args.vc.actions);
13328 		break;
13329 	case FLEX_ITEM_CREATE:
13330 		flex_item_create(in->port, in->args.flex.token,
13331 				 in->args.flex.filename);
13332 		break;
13333 	case FLEX_ITEM_DESTROY:
13334 		flex_item_destroy(in->port, in->args.flex.token);
13335 		break;
13336 	default:
13337 		break;
13338 	}
13339 	fflush(stdout);
13340 }
13341 
13342 /** Token generator and output processing callback (cmdline API). */
13343 static void
13344 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
13345 {
13346 	if (cl == NULL)
13347 		cmd_flow_tok(arg0, arg2);
13348 	else
13349 		cmd_flow_parsed(arg0);
13350 }
13351 
13352 /** Global parser instance (cmdline API). */
13353 cmdline_parse_inst_t cmd_flow = {
13354 	.f = cmd_flow_cb,
13355 	.data = NULL, /**< Unused. */
13356 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
13357 	.tokens = {
13358 		NULL,
13359 	}, /**< Tokens are returned by cmd_flow_tok(). */
13360 };
13361 
13362 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
13363 
13364 static void
13365 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
13366 {
13367 	struct rte_ipv4_hdr *ipv4;
13368 	struct rte_ether_hdr *eth;
13369 	struct rte_ipv6_hdr *ipv6;
13370 	struct rte_vxlan_hdr *vxlan;
13371 	struct rte_vxlan_gpe_hdr *gpe;
13372 	struct rte_flow_item_nvgre *nvgre;
13373 	uint32_t ipv6_vtc_flow;
13374 
13375 	switch (item->type) {
13376 	case RTE_FLOW_ITEM_TYPE_ETH:
13377 		eth = (struct rte_ether_hdr *)buf;
13378 		if (next_proto)
13379 			eth->ether_type = rte_cpu_to_be_16(next_proto);
13380 		break;
13381 	case RTE_FLOW_ITEM_TYPE_IPV4:
13382 		ipv4 = (struct rte_ipv4_hdr *)buf;
13383 		if (!ipv4->version_ihl)
13384 			ipv4->version_ihl = RTE_IPV4_VHL_DEF;
13385 		if (next_proto && ipv4->next_proto_id == 0)
13386 			ipv4->next_proto_id = (uint8_t)next_proto;
13387 		break;
13388 	case RTE_FLOW_ITEM_TYPE_IPV6:
13389 		ipv6 = (struct rte_ipv6_hdr *)buf;
13390 		if (next_proto && ipv6->proto == 0)
13391 			ipv6->proto = (uint8_t)next_proto;
13392 		ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
13393 		ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
13394 		ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
13395 		ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
13396 		break;
13397 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13398 		vxlan = (struct rte_vxlan_hdr *)buf;
13399 		vxlan->vx_flags = 0x08;
13400 		break;
13401 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13402 		gpe = (struct rte_vxlan_gpe_hdr *)buf;
13403 		gpe->vx_flags = 0x0C;
13404 		break;
13405 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13406 		nvgre = (struct rte_flow_item_nvgre *)buf;
13407 		nvgre->protocol = rte_cpu_to_be_16(0x6558);
13408 		nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
13409 		break;
13410 	default:
13411 		break;
13412 	}
13413 }
13414 
13415 /** Helper of get item's default mask. */
13416 static const void *
13417 flow_item_default_mask(const struct rte_flow_item *item)
13418 {
13419 	const void *mask = NULL;
13420 	static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
13421 	static struct rte_flow_item_ipv6_routing_ext ipv6_routing_ext_default_mask = {
13422 		.hdr = {
13423 			.next_hdr = 0xff,
13424 			.type = 0xff,
13425 			.segments_left = 0xff,
13426 		},
13427 	};
13428 
13429 	switch (item->type) {
13430 	case RTE_FLOW_ITEM_TYPE_ANY:
13431 		mask = &rte_flow_item_any_mask;
13432 		break;
13433 	case RTE_FLOW_ITEM_TYPE_PORT_ID:
13434 		mask = &rte_flow_item_port_id_mask;
13435 		break;
13436 	case RTE_FLOW_ITEM_TYPE_RAW:
13437 		mask = &rte_flow_item_raw_mask;
13438 		break;
13439 	case RTE_FLOW_ITEM_TYPE_ETH:
13440 		mask = &rte_flow_item_eth_mask;
13441 		break;
13442 	case RTE_FLOW_ITEM_TYPE_VLAN:
13443 		mask = &rte_flow_item_vlan_mask;
13444 		break;
13445 	case RTE_FLOW_ITEM_TYPE_IPV4:
13446 		mask = &rte_flow_item_ipv4_mask;
13447 		break;
13448 	case RTE_FLOW_ITEM_TYPE_IPV6:
13449 		mask = &rte_flow_item_ipv6_mask;
13450 		break;
13451 	case RTE_FLOW_ITEM_TYPE_ICMP:
13452 		mask = &rte_flow_item_icmp_mask;
13453 		break;
13454 	case RTE_FLOW_ITEM_TYPE_UDP:
13455 		mask = &rte_flow_item_udp_mask;
13456 		break;
13457 	case RTE_FLOW_ITEM_TYPE_TCP:
13458 		mask = &rte_flow_item_tcp_mask;
13459 		break;
13460 	case RTE_FLOW_ITEM_TYPE_SCTP:
13461 		mask = &rte_flow_item_sctp_mask;
13462 		break;
13463 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13464 		mask = &rte_flow_item_vxlan_mask;
13465 		break;
13466 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13467 		mask = &rte_flow_item_vxlan_gpe_mask;
13468 		break;
13469 	case RTE_FLOW_ITEM_TYPE_E_TAG:
13470 		mask = &rte_flow_item_e_tag_mask;
13471 		break;
13472 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13473 		mask = &rte_flow_item_nvgre_mask;
13474 		break;
13475 	case RTE_FLOW_ITEM_TYPE_MPLS:
13476 		mask = &rte_flow_item_mpls_mask;
13477 		break;
13478 	case RTE_FLOW_ITEM_TYPE_GRE:
13479 		mask = &rte_flow_item_gre_mask;
13480 		break;
13481 	case RTE_FLOW_ITEM_TYPE_GRE_KEY:
13482 		mask = &gre_key_default_mask;
13483 		break;
13484 	case RTE_FLOW_ITEM_TYPE_META:
13485 		mask = &rte_flow_item_meta_mask;
13486 		break;
13487 	case RTE_FLOW_ITEM_TYPE_RANDOM:
13488 		mask = &rte_flow_item_random_mask;
13489 		break;
13490 	case RTE_FLOW_ITEM_TYPE_FUZZY:
13491 		mask = &rte_flow_item_fuzzy_mask;
13492 		break;
13493 	case RTE_FLOW_ITEM_TYPE_GTP:
13494 		mask = &rte_flow_item_gtp_mask;
13495 		break;
13496 	case RTE_FLOW_ITEM_TYPE_GTP_PSC:
13497 		mask = &rte_flow_item_gtp_psc_mask;
13498 		break;
13499 	case RTE_FLOW_ITEM_TYPE_GENEVE:
13500 		mask = &rte_flow_item_geneve_mask;
13501 		break;
13502 	case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
13503 		mask = &rte_flow_item_geneve_opt_mask;
13504 		break;
13505 	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
13506 		mask = &rte_flow_item_pppoe_proto_id_mask;
13507 		break;
13508 	case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
13509 		mask = &rte_flow_item_l2tpv3oip_mask;
13510 		break;
13511 	case RTE_FLOW_ITEM_TYPE_ESP:
13512 		mask = &rte_flow_item_esp_mask;
13513 		break;
13514 	case RTE_FLOW_ITEM_TYPE_AH:
13515 		mask = &rte_flow_item_ah_mask;
13516 		break;
13517 	case RTE_FLOW_ITEM_TYPE_PFCP:
13518 		mask = &rte_flow_item_pfcp_mask;
13519 		break;
13520 	case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
13521 	case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
13522 		mask = &rte_flow_item_ethdev_mask;
13523 		break;
13524 	case RTE_FLOW_ITEM_TYPE_L2TPV2:
13525 		mask = &rte_flow_item_l2tpv2_mask;
13526 		break;
13527 	case RTE_FLOW_ITEM_TYPE_PPP:
13528 		mask = &rte_flow_item_ppp_mask;
13529 		break;
13530 	case RTE_FLOW_ITEM_TYPE_METER_COLOR:
13531 		mask = &rte_flow_item_meter_color_mask;
13532 		break;
13533 	case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13534 		mask = &ipv6_routing_ext_default_mask;
13535 		break;
13536 	case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
13537 		mask = &rte_flow_item_aggr_affinity_mask;
13538 		break;
13539 	case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
13540 		mask = &rte_flow_item_tx_queue_mask;
13541 		break;
13542 	case RTE_FLOW_ITEM_TYPE_IB_BTH:
13543 		mask = &rte_flow_item_ib_bth_mask;
13544 		break;
13545 	case RTE_FLOW_ITEM_TYPE_PTYPE:
13546 		mask = &rte_flow_item_ptype_mask;
13547 		break;
13548 	default:
13549 		break;
13550 	}
13551 	return mask;
13552 }
13553 
13554 /** Dispatch parsed buffer to function calls. */
13555 static void
13556 cmd_set_ipv6_ext_parsed(const struct buffer *in)
13557 {
13558 	uint32_t n = in->args.vc.pattern_n;
13559 	int i = 0;
13560 	struct rte_flow_item *item = NULL;
13561 	size_t size = 0;
13562 	uint8_t *data = NULL;
13563 	uint8_t *type = NULL;
13564 	size_t *total_size = NULL;
13565 	uint16_t idx = in->port; /* We borrow port field as index */
13566 	struct rte_flow_item_ipv6_routing_ext *ext;
13567 	const struct rte_flow_item_ipv6_ext *ipv6_ext;
13568 
13569 	RTE_ASSERT(in->command == SET_IPV6_EXT_PUSH ||
13570 		   in->command == SET_IPV6_EXT_REMOVE);
13571 
13572 	if (in->command == SET_IPV6_EXT_REMOVE) {
13573 		if (n != 1 || in->args.vc.pattern->type !=
13574 		    RTE_FLOW_ITEM_TYPE_IPV6_EXT) {
13575 			fprintf(stderr, "Error - Not supported item\n");
13576 			return;
13577 		}
13578 		type = (uint8_t *)&ipv6_ext_remove_confs[idx].type;
13579 		item = in->args.vc.pattern;
13580 		ipv6_ext = item->spec;
13581 		*type = ipv6_ext->next_hdr;
13582 		return;
13583 	}
13584 
13585 	total_size = &ipv6_ext_push_confs[idx].size;
13586 	data = (uint8_t *)&ipv6_ext_push_confs[idx].data;
13587 	type = (uint8_t *)&ipv6_ext_push_confs[idx].type;
13588 
13589 	*total_size = 0;
13590 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13591 	for (i = n - 1 ; i >= 0; --i) {
13592 		item = in->args.vc.pattern + i;
13593 		switch (item->type) {
13594 		case RTE_FLOW_ITEM_TYPE_IPV6_EXT:
13595 			ipv6_ext = item->spec;
13596 			*type = ipv6_ext->next_hdr;
13597 			break;
13598 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13599 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13600 			if (!ext->hdr.hdr_len) {
13601 				size = sizeof(struct rte_ipv6_routing_ext) +
13602 				(ext->hdr.segments_left << 4);
13603 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
13604 				/* Indicate no TLV once SRH. */
13605 				if (ext->hdr.type == 4)
13606 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
13607 			} else {
13608 				size = sizeof(struct rte_ipv6_routing_ext) +
13609 				(ext->hdr.hdr_len << 3);
13610 			}
13611 			*total_size += size;
13612 			memcpy(data, ext, size);
13613 			break;
13614 		default:
13615 			fprintf(stderr, "Error - Not supported item\n");
13616 			goto error;
13617 		}
13618 	}
13619 	RTE_ASSERT((*total_size) <= ACTION_IPV6_EXT_PUSH_MAX_DATA);
13620 	return;
13621 error:
13622 	*total_size = 0;
13623 	memset(data, 0x00, ACTION_IPV6_EXT_PUSH_MAX_DATA);
13624 }
13625 
13626 /** Dispatch parsed buffer to function calls. */
13627 static void
13628 cmd_set_raw_parsed_sample(const struct buffer *in)
13629 {
13630 	uint32_t n = in->args.vc.actions_n;
13631 	uint32_t i = 0;
13632 	struct rte_flow_action *action = NULL;
13633 	struct rte_flow_action *data = NULL;
13634 	const struct rte_flow_action_rss *rss = NULL;
13635 	size_t size = 0;
13636 	uint16_t idx = in->port; /* We borrow port field as index */
13637 	uint32_t max_size = sizeof(struct rte_flow_action) *
13638 						ACTION_SAMPLE_ACTIONS_NUM;
13639 
13640 	RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
13641 	data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
13642 	memset(data, 0x00, max_size);
13643 	for (; i <= n - 1; i++) {
13644 		action = in->args.vc.actions + i;
13645 		if (action->type == RTE_FLOW_ACTION_TYPE_END)
13646 			break;
13647 		switch (action->type) {
13648 		case RTE_FLOW_ACTION_TYPE_MARK:
13649 			size = sizeof(struct rte_flow_action_mark);
13650 			rte_memcpy(&sample_mark[idx],
13651 				(const void *)action->conf, size);
13652 			action->conf = &sample_mark[idx];
13653 			break;
13654 		case RTE_FLOW_ACTION_TYPE_COUNT:
13655 			size = sizeof(struct rte_flow_action_count);
13656 			rte_memcpy(&sample_count[idx],
13657 				(const void *)action->conf, size);
13658 			action->conf = &sample_count[idx];
13659 			break;
13660 		case RTE_FLOW_ACTION_TYPE_QUEUE:
13661 			size = sizeof(struct rte_flow_action_queue);
13662 			rte_memcpy(&sample_queue[idx],
13663 				(const void *)action->conf, size);
13664 			action->conf = &sample_queue[idx];
13665 			break;
13666 		case RTE_FLOW_ACTION_TYPE_RSS:
13667 			size = sizeof(struct rte_flow_action_rss);
13668 			rss = action->conf;
13669 			rte_memcpy(&sample_rss_data[idx].conf,
13670 				   (const void *)rss, size);
13671 			if (rss->key_len && rss->key) {
13672 				sample_rss_data[idx].conf.key =
13673 						sample_rss_data[idx].key;
13674 				rte_memcpy((void *)((uintptr_t)
13675 					   sample_rss_data[idx].conf.key),
13676 					   (const void *)rss->key,
13677 					   sizeof(uint8_t) * rss->key_len);
13678 			}
13679 			if (rss->queue_num && rss->queue) {
13680 				sample_rss_data[idx].conf.queue =
13681 						sample_rss_data[idx].queue;
13682 				rte_memcpy((void *)((uintptr_t)
13683 					   sample_rss_data[idx].conf.queue),
13684 					   (const void *)rss->queue,
13685 					   sizeof(uint16_t) * rss->queue_num);
13686 			}
13687 			action->conf = &sample_rss_data[idx].conf;
13688 			break;
13689 		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
13690 			size = sizeof(struct rte_flow_action_raw_encap);
13691 			rte_memcpy(&sample_encap[idx],
13692 				(const void *)action->conf, size);
13693 			action->conf = &sample_encap[idx];
13694 			break;
13695 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
13696 			size = sizeof(struct rte_flow_action_port_id);
13697 			rte_memcpy(&sample_port_id[idx],
13698 				(const void *)action->conf, size);
13699 			action->conf = &sample_port_id[idx];
13700 			break;
13701 		case RTE_FLOW_ACTION_TYPE_PF:
13702 			break;
13703 		case RTE_FLOW_ACTION_TYPE_VF:
13704 			size = sizeof(struct rte_flow_action_vf);
13705 			rte_memcpy(&sample_vf[idx],
13706 					(const void *)action->conf, size);
13707 			action->conf = &sample_vf[idx];
13708 			break;
13709 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
13710 			size = sizeof(struct rte_flow_action_vxlan_encap);
13711 			parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
13712 			action->conf = &sample_vxlan_encap[idx].conf;
13713 			break;
13714 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
13715 			size = sizeof(struct rte_flow_action_nvgre_encap);
13716 			parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
13717 			action->conf = &sample_nvgre_encap[idx];
13718 			break;
13719 		case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
13720 			size = sizeof(struct rte_flow_action_ethdev);
13721 			rte_memcpy(&sample_port_representor[idx],
13722 					(const void *)action->conf, size);
13723 			action->conf = &sample_port_representor[idx];
13724 			break;
13725 		case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
13726 			size = sizeof(struct rte_flow_action_ethdev);
13727 			rte_memcpy(&sample_represented_port[idx],
13728 					(const void *)action->conf, size);
13729 			action->conf = &sample_represented_port[idx];
13730 			break;
13731 		default:
13732 			fprintf(stderr, "Error - Not supported action\n");
13733 			return;
13734 		}
13735 		rte_memcpy(data, action, sizeof(struct rte_flow_action));
13736 		data++;
13737 	}
13738 }
13739 
13740 /** Dispatch parsed buffer to function calls. */
13741 static void
13742 cmd_set_raw_parsed(const struct buffer *in)
13743 {
13744 	uint32_t n = in->args.vc.pattern_n;
13745 	int i = 0;
13746 	struct rte_flow_item *item = NULL;
13747 	size_t size = 0;
13748 	uint8_t *data = NULL;
13749 	uint8_t *data_tail = NULL;
13750 	size_t *total_size = NULL;
13751 	uint16_t upper_layer = 0;
13752 	uint16_t proto = 0;
13753 	uint16_t idx = in->port; /* We borrow port field as index */
13754 	int gtp_psc = -1; /* GTP PSC option index. */
13755 	const void *src_spec;
13756 
13757 	if (in->command == SET_SAMPLE_ACTIONS)
13758 		return cmd_set_raw_parsed_sample(in);
13759 	else if (in->command == SET_IPV6_EXT_PUSH ||
13760 		 in->command == SET_IPV6_EXT_REMOVE)
13761 		return cmd_set_ipv6_ext_parsed(in);
13762 	RTE_ASSERT(in->command == SET_RAW_ENCAP ||
13763 		   in->command == SET_RAW_DECAP);
13764 	if (in->command == SET_RAW_ENCAP) {
13765 		total_size = &raw_encap_confs[idx].size;
13766 		data = (uint8_t *)&raw_encap_confs[idx].data;
13767 	} else {
13768 		total_size = &raw_decap_confs[idx].size;
13769 		data = (uint8_t *)&raw_decap_confs[idx].data;
13770 	}
13771 	*total_size = 0;
13772 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13773 	/* process hdr from upper layer to low layer (L3/L4 -> L2). */
13774 	data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
13775 	for (i = n - 1 ; i >= 0; --i) {
13776 		const struct rte_flow_item_gtp *gtp;
13777 		const struct rte_flow_item_geneve_opt *opt;
13778 		struct rte_flow_item_ipv6_routing_ext *ext;
13779 
13780 		item = in->args.vc.pattern + i;
13781 		if (item->spec == NULL)
13782 			item->spec = flow_item_default_mask(item);
13783 		src_spec = item->spec;
13784 		switch (item->type) {
13785 		case RTE_FLOW_ITEM_TYPE_ETH:
13786 			size = sizeof(struct rte_ether_hdr);
13787 			break;
13788 		case RTE_FLOW_ITEM_TYPE_VLAN:
13789 			size = sizeof(struct rte_vlan_hdr);
13790 			proto = RTE_ETHER_TYPE_VLAN;
13791 			break;
13792 		case RTE_FLOW_ITEM_TYPE_IPV4:
13793 			size = sizeof(struct rte_ipv4_hdr);
13794 			proto = RTE_ETHER_TYPE_IPV4;
13795 			break;
13796 		case RTE_FLOW_ITEM_TYPE_IPV6:
13797 			size = sizeof(struct rte_ipv6_hdr);
13798 			proto = RTE_ETHER_TYPE_IPV6;
13799 			break;
13800 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13801 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13802 			if (!ext->hdr.hdr_len) {
13803 				size = sizeof(struct rte_ipv6_routing_ext) +
13804 					(ext->hdr.segments_left << 4);
13805 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
13806 				/* SRv6 without TLV. */
13807 				if (ext->hdr.type == RTE_IPV6_SRCRT_TYPE_4)
13808 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
13809 			} else {
13810 				size = sizeof(struct rte_ipv6_routing_ext) +
13811 					(ext->hdr.hdr_len << 3);
13812 			}
13813 			proto = IPPROTO_ROUTING;
13814 			break;
13815 		case RTE_FLOW_ITEM_TYPE_UDP:
13816 			size = sizeof(struct rte_udp_hdr);
13817 			proto = 0x11;
13818 			break;
13819 		case RTE_FLOW_ITEM_TYPE_TCP:
13820 			size = sizeof(struct rte_tcp_hdr);
13821 			proto = 0x06;
13822 			break;
13823 		case RTE_FLOW_ITEM_TYPE_VXLAN:
13824 			size = sizeof(struct rte_vxlan_hdr);
13825 			break;
13826 		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13827 			size = sizeof(struct rte_vxlan_gpe_hdr);
13828 			break;
13829 		case RTE_FLOW_ITEM_TYPE_GRE:
13830 			size = sizeof(struct rte_gre_hdr);
13831 			proto = 0x2F;
13832 			break;
13833 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
13834 			size = sizeof(rte_be32_t);
13835 			proto = 0x0;
13836 			break;
13837 		case RTE_FLOW_ITEM_TYPE_MPLS:
13838 			size = sizeof(struct rte_mpls_hdr);
13839 			proto = 0x0;
13840 			break;
13841 		case RTE_FLOW_ITEM_TYPE_NVGRE:
13842 			size = sizeof(struct rte_flow_item_nvgre);
13843 			proto = 0x2F;
13844 			break;
13845 		case RTE_FLOW_ITEM_TYPE_GENEVE:
13846 			size = sizeof(struct rte_geneve_hdr);
13847 			break;
13848 		case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
13849 			opt = (const struct rte_flow_item_geneve_opt *)
13850 								item->spec;
13851 			size = offsetof(struct rte_flow_item_geneve_opt,
13852 					option_len) + sizeof(uint8_t);
13853 			if (opt->option_len && opt->data) {
13854 				*total_size += opt->option_len *
13855 					       sizeof(uint32_t);
13856 				rte_memcpy(data_tail - (*total_size),
13857 					   opt->data,
13858 					   opt->option_len * sizeof(uint32_t));
13859 			}
13860 			break;
13861 		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
13862 			size = sizeof(rte_be32_t);
13863 			proto = 0x73;
13864 			break;
13865 		case RTE_FLOW_ITEM_TYPE_ESP:
13866 			size = sizeof(struct rte_esp_hdr);
13867 			proto = 0x32;
13868 			break;
13869 		case RTE_FLOW_ITEM_TYPE_AH:
13870 			size = sizeof(struct rte_flow_item_ah);
13871 			proto = 0x33;
13872 			break;
13873 		case RTE_FLOW_ITEM_TYPE_GTP:
13874 			if (gtp_psc < 0) {
13875 				size = sizeof(struct rte_gtp_hdr);
13876 				break;
13877 			}
13878 			if (gtp_psc != i + 1) {
13879 				fprintf(stderr,
13880 					"Error - GTP PSC does not follow GTP\n");
13881 				goto error;
13882 			}
13883 			gtp = item->spec;
13884 			if (gtp->hdr.s == 1 || gtp->hdr.pn == 1) {
13885 				/* Only E flag should be set. */
13886 				fprintf(stderr,
13887 					"Error - GTP unsupported flags\n");
13888 				goto error;
13889 			} else {
13890 				struct rte_gtp_hdr_ext_word ext_word = {
13891 					.next_ext = 0x85
13892 				};
13893 
13894 				/* We have to add GTP header extra word. */
13895 				*total_size += sizeof(ext_word);
13896 				rte_memcpy(data_tail - (*total_size),
13897 					   &ext_word, sizeof(ext_word));
13898 			}
13899 			size = sizeof(struct rte_gtp_hdr);
13900 			break;
13901 		case RTE_FLOW_ITEM_TYPE_GTP_PSC:
13902 			if (gtp_psc >= 0) {
13903 				fprintf(stderr,
13904 					"Error - Multiple GTP PSC items\n");
13905 				goto error;
13906 			} else {
13907 				const struct rte_flow_item_gtp_psc
13908 					*opt = item->spec;
13909 				struct rte_gtp_psc_generic_hdr *hdr;
13910 				size_t hdr_size = RTE_ALIGN(sizeof(*hdr),
13911 							 sizeof(int32_t));
13912 
13913 				*total_size += hdr_size;
13914 				hdr = (typeof(hdr))(data_tail - (*total_size));
13915 				memset(hdr, 0, hdr_size);
13916 				*hdr = opt->hdr;
13917 				hdr->ext_hdr_len = 1;
13918 				gtp_psc = i;
13919 				size = 0;
13920 			}
13921 			break;
13922 		case RTE_FLOW_ITEM_TYPE_PFCP:
13923 			size = sizeof(struct rte_flow_item_pfcp);
13924 			break;
13925 		case RTE_FLOW_ITEM_TYPE_FLEX:
13926 			if (item->spec != NULL) {
13927 				size = ((const struct rte_flow_item_flex *)item->spec)->length;
13928 				src_spec = ((const struct rte_flow_item_flex *)item->spec)->pattern;
13929 			} else {
13930 				size = 0;
13931 				src_spec = NULL;
13932 			}
13933 			break;
13934 		case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
13935 			size = 0;
13936 			if (item->spec) {
13937 				const struct rte_flow_item_gre_opt
13938 					*opt = item->spec;
13939 				if (opt->checksum_rsvd.checksum) {
13940 					*total_size +=
13941 						sizeof(opt->checksum_rsvd);
13942 					rte_memcpy(data_tail - (*total_size),
13943 						   &opt->checksum_rsvd,
13944 						   sizeof(opt->checksum_rsvd));
13945 				}
13946 				if (opt->key.key) {
13947 					*total_size += sizeof(opt->key.key);
13948 					rte_memcpy(data_tail - (*total_size),
13949 						   &opt->key.key,
13950 						   sizeof(opt->key.key));
13951 				}
13952 				if (opt->sequence.sequence) {
13953 					*total_size += sizeof(opt->sequence.sequence);
13954 					rte_memcpy(data_tail - (*total_size),
13955 						   &opt->sequence.sequence,
13956 						   sizeof(opt->sequence.sequence));
13957 				}
13958 			}
13959 			proto = 0x2F;
13960 			break;
13961 		default:
13962 			fprintf(stderr, "Error - Not supported item\n");
13963 			goto error;
13964 		}
13965 		if (size) {
13966 			*total_size += size;
13967 			rte_memcpy(data_tail - (*total_size), src_spec, size);
13968 			/* update some fields which cannot be set by cmdline */
13969 			update_fields((data_tail - (*total_size)), item,
13970 				      upper_layer);
13971 			upper_layer = proto;
13972 		}
13973 	}
13974 	if (verbose_level & 0x1)
13975 		printf("total data size is %zu\n", (*total_size));
13976 	RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
13977 	memmove(data, (data_tail - (*total_size)), *total_size);
13978 	return;
13979 
13980 error:
13981 	*total_size = 0;
13982 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13983 }
13984 
13985 /** Populate help strings for current token (cmdline API). */
13986 static int
13987 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
13988 		     unsigned int size)
13989 {
13990 	struct context *ctx = &cmd_flow_context;
13991 	const struct token *token = &token_list[ctx->prev];
13992 
13993 	(void)hdr;
13994 	if (!size)
13995 		return -1;
13996 	/* Set token type and update global help with details. */
13997 	snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
13998 	if (token->help)
13999 		cmd_set_raw.help_str = token->help;
14000 	else
14001 		cmd_set_raw.help_str = token->name;
14002 	return 0;
14003 }
14004 
14005 /** Token definition template (cmdline API). */
14006 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
14007 	.ops = &(struct cmdline_token_ops){
14008 		.parse = cmd_flow_parse,
14009 		.complete_get_nb = cmd_flow_complete_get_nb,
14010 		.complete_get_elt = cmd_flow_complete_get_elt,
14011 		.get_help = cmd_set_raw_get_help,
14012 	},
14013 	.offset = 0,
14014 };
14015 
14016 /** Populate the next dynamic token. */
14017 static void
14018 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
14019 	     cmdline_parse_token_hdr_t **hdr_inst)
14020 {
14021 	struct context *ctx = &cmd_flow_context;
14022 
14023 	/* Always reinitialize context before requesting the first token. */
14024 	if (!(hdr_inst - cmd_set_raw.tokens)) {
14025 		cmd_flow_context_init(ctx);
14026 		ctx->curr = START_SET;
14027 	}
14028 	/* Return NULL when no more tokens are expected. */
14029 	if (!ctx->next_num && (ctx->curr != START_SET)) {
14030 		*hdr = NULL;
14031 		return;
14032 	}
14033 	/* Determine if command should end here. */
14034 	if (ctx->eol && ctx->last && ctx->next_num) {
14035 		const enum index *list = ctx->next[ctx->next_num - 1];
14036 		int i;
14037 
14038 		for (i = 0; list[i]; ++i) {
14039 			if (list[i] != END)
14040 				continue;
14041 			*hdr = NULL;
14042 			return;
14043 		}
14044 	}
14045 	*hdr = &cmd_set_raw_token_hdr;
14046 }
14047 
14048 /** Token generator and output processing callback (cmdline API). */
14049 static void
14050 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
14051 {
14052 	if (cl == NULL)
14053 		cmd_set_raw_tok(arg0, arg2);
14054 	else
14055 		cmd_set_raw_parsed(arg0);
14056 }
14057 
14058 /** Global parser instance (cmdline API). */
14059 cmdline_parse_inst_t cmd_set_raw = {
14060 	.f = cmd_set_raw_cb,
14061 	.data = NULL, /**< Unused. */
14062 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
14063 	.tokens = {
14064 		NULL,
14065 	}, /**< Tokens are returned by cmd_flow_tok(). */
14066 };
14067 
14068 /* *** display raw_encap/raw_decap buf */
14069 struct cmd_show_set_raw_result {
14070 	cmdline_fixed_string_t cmd_show;
14071 	cmdline_fixed_string_t cmd_what;
14072 	cmdline_fixed_string_t cmd_all;
14073 	uint16_t cmd_index;
14074 };
14075 
14076 static void
14077 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
14078 {
14079 	struct cmd_show_set_raw_result *res = parsed_result;
14080 	uint16_t index = res->cmd_index;
14081 	uint8_t all = 0;
14082 	uint8_t *raw_data = NULL;
14083 	size_t raw_size = 0;
14084 	char title[16] = {0};
14085 
14086 	RTE_SET_USED(cl);
14087 	RTE_SET_USED(data);
14088 	if (!strcmp(res->cmd_all, "all")) {
14089 		all = 1;
14090 		index = 0;
14091 	} else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
14092 		fprintf(stderr, "index should be 0-%u\n",
14093 			RAW_ENCAP_CONFS_MAX_NUM - 1);
14094 		return;
14095 	}
14096 	do {
14097 		if (!strcmp(res->cmd_what, "raw_encap")) {
14098 			raw_data = (uint8_t *)&raw_encap_confs[index].data;
14099 			raw_size = raw_encap_confs[index].size;
14100 			snprintf(title, 16, "\nindex: %u", index);
14101 			rte_hexdump(stdout, title, raw_data, raw_size);
14102 		} else {
14103 			raw_data = (uint8_t *)&raw_decap_confs[index].data;
14104 			raw_size = raw_decap_confs[index].size;
14105 			snprintf(title, 16, "\nindex: %u", index);
14106 			rte_hexdump(stdout, title, raw_data, raw_size);
14107 		}
14108 	} while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
14109 }
14110 
14111 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
14112 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14113 			cmd_show, "show");
14114 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
14115 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14116 			cmd_what, "raw_encap#raw_decap");
14117 static cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
14118 	TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
14119 			cmd_index, RTE_UINT16);
14120 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
14121 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14122 			cmd_all, "all");
14123 cmdline_parse_inst_t cmd_show_set_raw = {
14124 	.f = cmd_show_set_raw_parsed,
14125 	.data = NULL,
14126 	.help_str = "show <raw_encap|raw_decap> <index>",
14127 	.tokens = {
14128 		(void *)&cmd_show_set_raw_cmd_show,
14129 		(void *)&cmd_show_set_raw_cmd_what,
14130 		(void *)&cmd_show_set_raw_cmd_index,
14131 		NULL,
14132 	},
14133 };
14134 cmdline_parse_inst_t cmd_show_set_raw_all = {
14135 	.f = cmd_show_set_raw_parsed,
14136 	.data = NULL,
14137 	.help_str = "show <raw_encap|raw_decap> all",
14138 	.tokens = {
14139 		(void *)&cmd_show_set_raw_cmd_show,
14140 		(void *)&cmd_show_set_raw_cmd_what,
14141 		(void *)&cmd_show_set_raw_cmd_all,
14142 		NULL,
14143 	},
14144 };
14145