xref: /dpdk/app/test-pmd/cmdline_flow.c (revision d46b9fa83f136beb0e6feedd0a7b3a228b0d8cd3)
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 	UPDATE,
95 	FLUSH,
96 	DUMP,
97 	QUERY,
98 	LIST,
99 	AGED,
100 	ISOLATE,
101 	TUNNEL,
102 	FLEX,
103 	QUEUE,
104 	PUSH,
105 	PULL,
106 	HASH,
107 
108 	/* Flex arguments */
109 	FLEX_ITEM_INIT,
110 	FLEX_ITEM_CREATE,
111 	FLEX_ITEM_DESTROY,
112 
113 	/* Pattern template arguments. */
114 	PATTERN_TEMPLATE_CREATE,
115 	PATTERN_TEMPLATE_DESTROY,
116 	PATTERN_TEMPLATE_CREATE_ID,
117 	PATTERN_TEMPLATE_DESTROY_ID,
118 	PATTERN_TEMPLATE_RELAXED_MATCHING,
119 	PATTERN_TEMPLATE_INGRESS,
120 	PATTERN_TEMPLATE_EGRESS,
121 	PATTERN_TEMPLATE_TRANSFER,
122 	PATTERN_TEMPLATE_SPEC,
123 
124 	/* Actions template arguments. */
125 	ACTIONS_TEMPLATE_CREATE,
126 	ACTIONS_TEMPLATE_DESTROY,
127 	ACTIONS_TEMPLATE_CREATE_ID,
128 	ACTIONS_TEMPLATE_DESTROY_ID,
129 	ACTIONS_TEMPLATE_INGRESS,
130 	ACTIONS_TEMPLATE_EGRESS,
131 	ACTIONS_TEMPLATE_TRANSFER,
132 	ACTIONS_TEMPLATE_SPEC,
133 	ACTIONS_TEMPLATE_MASK,
134 
135 	/* Queue arguments. */
136 	QUEUE_CREATE,
137 	QUEUE_DESTROY,
138 	QUEUE_FLOW_UPDATE_RESIZED,
139 	QUEUE_UPDATE,
140 	QUEUE_AGED,
141 	QUEUE_INDIRECT_ACTION,
142 
143 	/* Queue create arguments. */
144 	QUEUE_CREATE_POSTPONE,
145 	QUEUE_TEMPLATE_TABLE,
146 	QUEUE_PATTERN_TEMPLATE,
147 	QUEUE_ACTIONS_TEMPLATE,
148 	QUEUE_RULE_ID,
149 
150 	/* Queue destroy arguments. */
151 	QUEUE_DESTROY_ID,
152 	QUEUE_DESTROY_POSTPONE,
153 
154 	/* Queue update arguments. */
155 	QUEUE_UPDATE_ID,
156 
157 	/* Queue indirect action arguments */
158 	QUEUE_INDIRECT_ACTION_CREATE,
159 	QUEUE_INDIRECT_ACTION_LIST_CREATE,
160 	QUEUE_INDIRECT_ACTION_UPDATE,
161 	QUEUE_INDIRECT_ACTION_DESTROY,
162 	QUEUE_INDIRECT_ACTION_QUERY,
163 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
164 
165 	/* Queue indirect action create arguments */
166 	QUEUE_INDIRECT_ACTION_CREATE_ID,
167 	QUEUE_INDIRECT_ACTION_INGRESS,
168 	QUEUE_INDIRECT_ACTION_EGRESS,
169 	QUEUE_INDIRECT_ACTION_TRANSFER,
170 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
171 	QUEUE_INDIRECT_ACTION_SPEC,
172 	QUEUE_INDIRECT_ACTION_LIST,
173 
174 	/* Queue indirect action update arguments */
175 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
176 
177 	/* Queue indirect action destroy arguments */
178 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
179 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
180 
181 	/* Queue indirect action query arguments */
182 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
183 
184 	/* Queue indirect action query_update arguments */
185 	QUEUE_INDIRECT_ACTION_QU_MODE,
186 
187 	/* Push arguments. */
188 	PUSH_QUEUE,
189 
190 	/* Pull arguments. */
191 	PULL_QUEUE,
192 
193 	/* Table arguments. */
194 	TABLE_CREATE,
195 	TABLE_DESTROY,
196 	TABLE_RESIZE,
197 	TABLE_RESIZE_COMPLETE,
198 	TABLE_CREATE_ID,
199 	TABLE_DESTROY_ID,
200 	TABLE_RESIZE_ID,
201 	TABLE_RESIZE_RULES_NUMBER,
202 	TABLE_INSERTION_TYPE,
203 	TABLE_INSERTION_TYPE_NAME,
204 	TABLE_HASH_FUNC,
205 	TABLE_HASH_FUNC_NAME,
206 	TABLE_GROUP,
207 	TABLE_PRIORITY,
208 	TABLE_INGRESS,
209 	TABLE_EGRESS,
210 	TABLE_TRANSFER,
211 	TABLE_TRANSFER_WIRE_ORIG,
212 	TABLE_TRANSFER_VPORT_ORIG,
213 	TABLE_RESIZABLE,
214 	TABLE_RULES_NUMBER,
215 	TABLE_PATTERN_TEMPLATE,
216 	TABLE_ACTIONS_TEMPLATE,
217 
218 	/* Group arguments */
219 	GROUP_ID,
220 	GROUP_INGRESS,
221 	GROUP_EGRESS,
222 	GROUP_TRANSFER,
223 	GROUP_SET_MISS_ACTIONS,
224 
225 	/* Hash calculation arguments. */
226 	HASH_CALC_TABLE,
227 	HASH_CALC_PATTERN_INDEX,
228 	HASH_CALC_PATTERN,
229 	HASH_CALC_ENCAP,
230 	HASH_CALC_DEST,
231 	ENCAP_HASH_FIELD_SRC_PORT,
232 	ENCAP_HASH_FIELD_GRE_FLOW_ID,
233 
234 	/* Tunnel arguments. */
235 	TUNNEL_CREATE,
236 	TUNNEL_CREATE_TYPE,
237 	TUNNEL_LIST,
238 	TUNNEL_DESTROY,
239 	TUNNEL_DESTROY_ID,
240 
241 	/* Destroy arguments. */
242 	DESTROY_RULE,
243 	DESTROY_IS_USER_ID,
244 
245 	/* Query arguments. */
246 	QUERY_ACTION,
247 	QUERY_IS_USER_ID,
248 
249 	/* List arguments. */
250 	LIST_GROUP,
251 
252 	/* Destroy aged flow arguments. */
253 	AGED_DESTROY,
254 
255 	/* Validate/create arguments. */
256 	VC_GROUP,
257 	VC_PRIORITY,
258 	VC_INGRESS,
259 	VC_EGRESS,
260 	VC_TRANSFER,
261 	VC_TUNNEL_SET,
262 	VC_TUNNEL_MATCH,
263 	VC_USER_ID,
264 	VC_IS_USER_ID,
265 
266 	/* Dump arguments */
267 	DUMP_ALL,
268 	DUMP_ONE,
269 	DUMP_IS_USER_ID,
270 
271 	/* Configure arguments */
272 	CONFIG_QUEUES_NUMBER,
273 	CONFIG_QUEUES_SIZE,
274 	CONFIG_COUNTERS_NUMBER,
275 	CONFIG_AGING_OBJECTS_NUMBER,
276 	CONFIG_METERS_NUMBER,
277 	CONFIG_CONN_TRACK_NUMBER,
278 	CONFIG_QUOTAS_NUMBER,
279 	CONFIG_FLAGS,
280 	CONFIG_HOST_PORT,
281 
282 	/* Indirect action arguments */
283 	INDIRECT_ACTION_CREATE,
284 	INDIRECT_ACTION_LIST_CREATE,
285 	INDIRECT_ACTION_FLOW_CONF_CREATE,
286 	INDIRECT_ACTION_UPDATE,
287 	INDIRECT_ACTION_DESTROY,
288 	INDIRECT_ACTION_QUERY,
289 	INDIRECT_ACTION_QUERY_UPDATE,
290 
291 	/* Indirect action create arguments */
292 	INDIRECT_ACTION_CREATE_ID,
293 	INDIRECT_ACTION_INGRESS,
294 	INDIRECT_ACTION_EGRESS,
295 	INDIRECT_ACTION_TRANSFER,
296 	INDIRECT_ACTION_SPEC,
297 	INDIRECT_ACTION_LIST,
298 	INDIRECT_ACTION_FLOW_CONF,
299 
300 	/* Indirect action destroy arguments */
301 	INDIRECT_ACTION_DESTROY_ID,
302 
303 	/* Indirect action query-and-update arguments */
304 	INDIRECT_ACTION_QU_MODE,
305 	INDIRECT_ACTION_QU_MODE_NAME,
306 
307 	/* Validate/create pattern. */
308 	ITEM_PATTERN,
309 	ITEM_PARAM_IS,
310 	ITEM_PARAM_SPEC,
311 	ITEM_PARAM_LAST,
312 	ITEM_PARAM_MASK,
313 	ITEM_PARAM_PREFIX,
314 	ITEM_NEXT,
315 	ITEM_END,
316 	ITEM_VOID,
317 	ITEM_INVERT,
318 	ITEM_ANY,
319 	ITEM_ANY_NUM,
320 	ITEM_PORT_ID,
321 	ITEM_PORT_ID_ID,
322 	ITEM_MARK,
323 	ITEM_MARK_ID,
324 	ITEM_RAW,
325 	ITEM_RAW_RELATIVE,
326 	ITEM_RAW_SEARCH,
327 	ITEM_RAW_OFFSET,
328 	ITEM_RAW_LIMIT,
329 	ITEM_RAW_PATTERN,
330 	ITEM_RAW_PATTERN_HEX,
331 	ITEM_ETH,
332 	ITEM_ETH_DST,
333 	ITEM_ETH_SRC,
334 	ITEM_ETH_TYPE,
335 	ITEM_ETH_HAS_VLAN,
336 	ITEM_VLAN,
337 	ITEM_VLAN_TCI,
338 	ITEM_VLAN_PCP,
339 	ITEM_VLAN_DEI,
340 	ITEM_VLAN_VID,
341 	ITEM_VLAN_INNER_TYPE,
342 	ITEM_VLAN_HAS_MORE_VLAN,
343 	ITEM_IPV4,
344 	ITEM_IPV4_VER_IHL,
345 	ITEM_IPV4_TOS,
346 	ITEM_IPV4_LENGTH,
347 	ITEM_IPV4_ID,
348 	ITEM_IPV4_FRAGMENT_OFFSET,
349 	ITEM_IPV4_TTL,
350 	ITEM_IPV4_PROTO,
351 	ITEM_IPV4_SRC,
352 	ITEM_IPV4_DST,
353 	ITEM_IPV6,
354 	ITEM_IPV6_TC,
355 	ITEM_IPV6_FLOW,
356 	ITEM_IPV6_LEN,
357 	ITEM_IPV6_PROTO,
358 	ITEM_IPV6_HOP,
359 	ITEM_IPV6_SRC,
360 	ITEM_IPV6_DST,
361 	ITEM_IPV6_HAS_FRAG_EXT,
362 	ITEM_IPV6_ROUTING_EXT,
363 	ITEM_IPV6_ROUTING_EXT_TYPE,
364 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
365 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
366 	ITEM_ICMP,
367 	ITEM_ICMP_TYPE,
368 	ITEM_ICMP_CODE,
369 	ITEM_ICMP_IDENT,
370 	ITEM_ICMP_SEQ,
371 	ITEM_UDP,
372 	ITEM_UDP_SRC,
373 	ITEM_UDP_DST,
374 	ITEM_TCP,
375 	ITEM_TCP_SRC,
376 	ITEM_TCP_DST,
377 	ITEM_TCP_FLAGS,
378 	ITEM_SCTP,
379 	ITEM_SCTP_SRC,
380 	ITEM_SCTP_DST,
381 	ITEM_SCTP_TAG,
382 	ITEM_SCTP_CKSUM,
383 	ITEM_VXLAN,
384 	ITEM_VXLAN_VNI,
385 	ITEM_VXLAN_FLAG_G,
386 	ITEM_VXLAN_FLAG_VER,
387 	ITEM_VXLAN_FLAG_I,
388 	ITEM_VXLAN_FLAG_P,
389 	ITEM_VXLAN_FLAG_B,
390 	ITEM_VXLAN_FLAG_O,
391 	ITEM_VXLAN_FLAG_D,
392 	ITEM_VXLAN_FLAG_A,
393 	ITEM_VXLAN_GBP_ID,
394 	ITEM_VXLAN_GPE_PROTO,
395 	ITEM_VXLAN_FIRST_RSVD,
396 	ITEM_VXLAN_SECND_RSVD,
397 	ITEM_VXLAN_THIRD_RSVD,
398 	ITEM_VXLAN_LAST_RSVD,
399 	ITEM_E_TAG,
400 	ITEM_E_TAG_GRP_ECID_B,
401 	ITEM_NVGRE,
402 	ITEM_NVGRE_TNI,
403 	ITEM_MPLS,
404 	ITEM_MPLS_LABEL,
405 	ITEM_MPLS_TC,
406 	ITEM_MPLS_S,
407 	ITEM_MPLS_TTL,
408 	ITEM_GRE,
409 	ITEM_GRE_PROTO,
410 	ITEM_GRE_C_RSVD0_VER,
411 	ITEM_GRE_C_BIT,
412 	ITEM_GRE_K_BIT,
413 	ITEM_GRE_S_BIT,
414 	ITEM_FUZZY,
415 	ITEM_FUZZY_THRESH,
416 	ITEM_GTP,
417 	ITEM_GTP_FLAGS,
418 	ITEM_GTP_MSG_TYPE,
419 	ITEM_GTP_TEID,
420 	ITEM_GTPC,
421 	ITEM_GTPU,
422 	ITEM_GENEVE,
423 	ITEM_GENEVE_VNI,
424 	ITEM_GENEVE_PROTO,
425 	ITEM_GENEVE_OPTLEN,
426 	ITEM_ARP_ETH_IPV4,
427 	ITEM_ARP_ETH_IPV4_SHA,
428 	ITEM_ARP_ETH_IPV4_SPA,
429 	ITEM_ARP_ETH_IPV4_THA,
430 	ITEM_ARP_ETH_IPV4_TPA,
431 	ITEM_IPV6_EXT,
432 	ITEM_IPV6_EXT_NEXT_HDR,
433 	ITEM_IPV6_FRAG_EXT,
434 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
435 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
436 	ITEM_IPV6_FRAG_EXT_ID,
437 	ITEM_ICMP6,
438 	ITEM_ICMP6_TYPE,
439 	ITEM_ICMP6_CODE,
440 	ITEM_ICMP6_ECHO_REQUEST,
441 	ITEM_ICMP6_ECHO_REQUEST_ID,
442 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
443 	ITEM_ICMP6_ECHO_REPLY,
444 	ITEM_ICMP6_ECHO_REPLY_ID,
445 	ITEM_ICMP6_ECHO_REPLY_SEQ,
446 	ITEM_ICMP6_ND_NS,
447 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
448 	ITEM_ICMP6_ND_NA,
449 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
450 	ITEM_ICMP6_ND_OPT,
451 	ITEM_ICMP6_ND_OPT_TYPE,
452 	ITEM_ICMP6_ND_OPT_SLA_ETH,
453 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
454 	ITEM_ICMP6_ND_OPT_TLA_ETH,
455 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
456 	ITEM_META,
457 	ITEM_META_DATA,
458 	ITEM_RANDOM,
459 	ITEM_RANDOM_VALUE,
460 	ITEM_GRE_KEY,
461 	ITEM_GRE_KEY_VALUE,
462 	ITEM_GRE_OPTION,
463 	ITEM_GRE_OPTION_CHECKSUM,
464 	ITEM_GRE_OPTION_KEY,
465 	ITEM_GRE_OPTION_SEQUENCE,
466 	ITEM_GTP_PSC,
467 	ITEM_GTP_PSC_QFI,
468 	ITEM_GTP_PSC_PDU_T,
469 	ITEM_PPPOES,
470 	ITEM_PPPOED,
471 	ITEM_PPPOE_SEID,
472 	ITEM_PPPOE_PROTO_ID,
473 	ITEM_HIGIG2,
474 	ITEM_HIGIG2_CLASSIFICATION,
475 	ITEM_HIGIG2_VID,
476 	ITEM_TAG,
477 	ITEM_TAG_DATA,
478 	ITEM_TAG_INDEX,
479 	ITEM_L2TPV3OIP,
480 	ITEM_L2TPV3OIP_SESSION_ID,
481 	ITEM_ESP,
482 	ITEM_ESP_SPI,
483 	ITEM_AH,
484 	ITEM_AH_SPI,
485 	ITEM_PFCP,
486 	ITEM_PFCP_S_FIELD,
487 	ITEM_PFCP_SEID,
488 	ITEM_ECPRI,
489 	ITEM_ECPRI_COMMON,
490 	ITEM_ECPRI_COMMON_TYPE,
491 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
492 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
493 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
494 	ITEM_ECPRI_MSG_IQ_DATA_PCID,
495 	ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
496 	ITEM_ECPRI_MSG_DLY_MSR_MSRID,
497 	ITEM_GENEVE_OPT,
498 	ITEM_GENEVE_OPT_CLASS,
499 	ITEM_GENEVE_OPT_TYPE,
500 	ITEM_GENEVE_OPT_LENGTH,
501 	ITEM_GENEVE_OPT_DATA,
502 	ITEM_INTEGRITY,
503 	ITEM_INTEGRITY_LEVEL,
504 	ITEM_INTEGRITY_VALUE,
505 	ITEM_CONNTRACK,
506 	ITEM_POL_PORT,
507 	ITEM_POL_METER,
508 	ITEM_POL_POLICY,
509 	ITEM_PORT_REPRESENTOR,
510 	ITEM_PORT_REPRESENTOR_PORT_ID,
511 	ITEM_REPRESENTED_PORT,
512 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
513 	ITEM_FLEX,
514 	ITEM_FLEX_ITEM_HANDLE,
515 	ITEM_FLEX_PATTERN_HANDLE,
516 	ITEM_L2TPV2,
517 	ITEM_L2TPV2_TYPE,
518 	ITEM_L2TPV2_TYPE_DATA,
519 	ITEM_L2TPV2_TYPE_DATA_L,
520 	ITEM_L2TPV2_TYPE_DATA_S,
521 	ITEM_L2TPV2_TYPE_DATA_O,
522 	ITEM_L2TPV2_TYPE_DATA_L_S,
523 	ITEM_L2TPV2_TYPE_CTRL,
524 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
525 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
526 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
527 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
528 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
529 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
530 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
531 	ITEM_L2TPV2_MSG_DATA_S_NS,
532 	ITEM_L2TPV2_MSG_DATA_S_NR,
533 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
534 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
535 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
536 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
537 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
538 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
539 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
540 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
541 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
542 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
543 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
544 	ITEM_L2TPV2_MSG_CTRL_NS,
545 	ITEM_L2TPV2_MSG_CTRL_NR,
546 	ITEM_PPP,
547 	ITEM_PPP_ADDR,
548 	ITEM_PPP_CTRL,
549 	ITEM_PPP_PROTO_ID,
550 	ITEM_METER,
551 	ITEM_METER_COLOR,
552 	ITEM_METER_COLOR_NAME,
553 	ITEM_QUOTA,
554 	ITEM_QUOTA_STATE,
555 	ITEM_QUOTA_STATE_NAME,
556 	ITEM_AGGR_AFFINITY,
557 	ITEM_AGGR_AFFINITY_VALUE,
558 	ITEM_TX_QUEUE,
559 	ITEM_TX_QUEUE_VALUE,
560 	ITEM_IB_BTH,
561 	ITEM_IB_BTH_OPCODE,
562 	ITEM_IB_BTH_PKEY,
563 	ITEM_IB_BTH_DST_QPN,
564 	ITEM_IB_BTH_PSN,
565 	ITEM_IPV6_PUSH_REMOVE_EXT,
566 	ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
567 	ITEM_PTYPE,
568 	ITEM_PTYPE_VALUE,
569 	ITEM_NSH,
570 	ITEM_COMPARE,
571 	ITEM_COMPARE_OP,
572 	ITEM_COMPARE_OP_VALUE,
573 	ITEM_COMPARE_FIELD_A_TYPE,
574 	ITEM_COMPARE_FIELD_A_TYPE_VALUE,
575 	ITEM_COMPARE_FIELD_A_LEVEL,
576 	ITEM_COMPARE_FIELD_A_LEVEL_VALUE,
577 	ITEM_COMPARE_FIELD_A_TAG_INDEX,
578 	ITEM_COMPARE_FIELD_A_TYPE_ID,
579 	ITEM_COMPARE_FIELD_A_CLASS_ID,
580 	ITEM_COMPARE_FIELD_A_OFFSET,
581 	ITEM_COMPARE_FIELD_B_TYPE,
582 	ITEM_COMPARE_FIELD_B_TYPE_VALUE,
583 	ITEM_COMPARE_FIELD_B_LEVEL,
584 	ITEM_COMPARE_FIELD_B_LEVEL_VALUE,
585 	ITEM_COMPARE_FIELD_B_TAG_INDEX,
586 	ITEM_COMPARE_FIELD_B_TYPE_ID,
587 	ITEM_COMPARE_FIELD_B_CLASS_ID,
588 	ITEM_COMPARE_FIELD_B_OFFSET,
589 	ITEM_COMPARE_FIELD_B_VALUE,
590 	ITEM_COMPARE_FIELD_B_POINTER,
591 	ITEM_COMPARE_FIELD_WIDTH,
592 
593 	/* Validate/create actions. */
594 	ACTIONS,
595 	ACTION_NEXT,
596 	ACTION_END,
597 	ACTION_VOID,
598 	ACTION_PASSTHRU,
599 	ACTION_SKIP_CMAN,
600 	ACTION_JUMP,
601 	ACTION_JUMP_GROUP,
602 	ACTION_MARK,
603 	ACTION_MARK_ID,
604 	ACTION_FLAG,
605 	ACTION_QUEUE,
606 	ACTION_QUEUE_INDEX,
607 	ACTION_DROP,
608 	ACTION_COUNT,
609 	ACTION_COUNT_ID,
610 	ACTION_RSS,
611 	ACTION_RSS_FUNC,
612 	ACTION_RSS_LEVEL,
613 	ACTION_RSS_FUNC_DEFAULT,
614 	ACTION_RSS_FUNC_TOEPLITZ,
615 	ACTION_RSS_FUNC_SIMPLE_XOR,
616 	ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
617 	ACTION_RSS_TYPES,
618 	ACTION_RSS_TYPE,
619 	ACTION_RSS_KEY,
620 	ACTION_RSS_KEY_LEN,
621 	ACTION_RSS_QUEUES,
622 	ACTION_RSS_QUEUE,
623 	ACTION_PF,
624 	ACTION_VF,
625 	ACTION_VF_ORIGINAL,
626 	ACTION_VF_ID,
627 	ACTION_PORT_ID,
628 	ACTION_PORT_ID_ORIGINAL,
629 	ACTION_PORT_ID_ID,
630 	ACTION_METER,
631 	ACTION_METER_COLOR,
632 	ACTION_METER_COLOR_TYPE,
633 	ACTION_METER_COLOR_GREEN,
634 	ACTION_METER_COLOR_YELLOW,
635 	ACTION_METER_COLOR_RED,
636 	ACTION_METER_ID,
637 	ACTION_METER_MARK,
638 	ACTION_METER_PROFILE,
639 	ACTION_METER_PROFILE_ID2PTR,
640 	ACTION_METER_POLICY,
641 	ACTION_METER_POLICY_ID2PTR,
642 	ACTION_METER_COLOR_MODE,
643 	ACTION_METER_STATE,
644 	ACTION_OF_DEC_NW_TTL,
645 	ACTION_OF_POP_VLAN,
646 	ACTION_OF_PUSH_VLAN,
647 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
648 	ACTION_OF_SET_VLAN_VID,
649 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
650 	ACTION_OF_SET_VLAN_PCP,
651 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
652 	ACTION_OF_POP_MPLS,
653 	ACTION_OF_POP_MPLS_ETHERTYPE,
654 	ACTION_OF_PUSH_MPLS,
655 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
656 	ACTION_VXLAN_ENCAP,
657 	ACTION_VXLAN_DECAP,
658 	ACTION_NVGRE_ENCAP,
659 	ACTION_NVGRE_DECAP,
660 	ACTION_L2_ENCAP,
661 	ACTION_L2_DECAP,
662 	ACTION_MPLSOGRE_ENCAP,
663 	ACTION_MPLSOGRE_DECAP,
664 	ACTION_MPLSOUDP_ENCAP,
665 	ACTION_MPLSOUDP_DECAP,
666 	ACTION_SET_IPV4_SRC,
667 	ACTION_SET_IPV4_SRC_IPV4_SRC,
668 	ACTION_SET_IPV4_DST,
669 	ACTION_SET_IPV4_DST_IPV4_DST,
670 	ACTION_SET_IPV6_SRC,
671 	ACTION_SET_IPV6_SRC_IPV6_SRC,
672 	ACTION_SET_IPV6_DST,
673 	ACTION_SET_IPV6_DST_IPV6_DST,
674 	ACTION_SET_TP_SRC,
675 	ACTION_SET_TP_SRC_TP_SRC,
676 	ACTION_SET_TP_DST,
677 	ACTION_SET_TP_DST_TP_DST,
678 	ACTION_MAC_SWAP,
679 	ACTION_DEC_TTL,
680 	ACTION_SET_TTL,
681 	ACTION_SET_TTL_TTL,
682 	ACTION_SET_MAC_SRC,
683 	ACTION_SET_MAC_SRC_MAC_SRC,
684 	ACTION_SET_MAC_DST,
685 	ACTION_SET_MAC_DST_MAC_DST,
686 	ACTION_INC_TCP_SEQ,
687 	ACTION_INC_TCP_SEQ_VALUE,
688 	ACTION_DEC_TCP_SEQ,
689 	ACTION_DEC_TCP_SEQ_VALUE,
690 	ACTION_INC_TCP_ACK,
691 	ACTION_INC_TCP_ACK_VALUE,
692 	ACTION_DEC_TCP_ACK,
693 	ACTION_DEC_TCP_ACK_VALUE,
694 	ACTION_RAW_ENCAP,
695 	ACTION_RAW_DECAP,
696 	ACTION_RAW_ENCAP_SIZE,
697 	ACTION_RAW_ENCAP_INDEX,
698 	ACTION_RAW_ENCAP_INDEX_VALUE,
699 	ACTION_RAW_DECAP_INDEX,
700 	ACTION_RAW_DECAP_INDEX_VALUE,
701 	ACTION_SET_TAG,
702 	ACTION_SET_TAG_DATA,
703 	ACTION_SET_TAG_INDEX,
704 	ACTION_SET_TAG_MASK,
705 	ACTION_SET_META,
706 	ACTION_SET_META_DATA,
707 	ACTION_SET_META_MASK,
708 	ACTION_SET_IPV4_DSCP,
709 	ACTION_SET_IPV4_DSCP_VALUE,
710 	ACTION_SET_IPV6_DSCP,
711 	ACTION_SET_IPV6_DSCP_VALUE,
712 	ACTION_AGE,
713 	ACTION_AGE_TIMEOUT,
714 	ACTION_AGE_UPDATE,
715 	ACTION_AGE_UPDATE_TIMEOUT,
716 	ACTION_AGE_UPDATE_TOUCH,
717 	ACTION_SAMPLE,
718 	ACTION_SAMPLE_RATIO,
719 	ACTION_SAMPLE_INDEX,
720 	ACTION_SAMPLE_INDEX_VALUE,
721 	ACTION_INDIRECT,
722 	ACTION_INDIRECT_LIST,
723 	ACTION_INDIRECT_LIST_HANDLE,
724 	ACTION_INDIRECT_LIST_CONF,
725 	INDIRECT_LIST_ACTION_ID2PTR_HANDLE,
726 	INDIRECT_LIST_ACTION_ID2PTR_CONF,
727 	ACTION_SHARED_INDIRECT,
728 	INDIRECT_ACTION_PORT,
729 	INDIRECT_ACTION_ID2PTR,
730 	ACTION_MODIFY_FIELD,
731 	ACTION_MODIFY_FIELD_OP,
732 	ACTION_MODIFY_FIELD_OP_VALUE,
733 	ACTION_MODIFY_FIELD_DST_TYPE,
734 	ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
735 	ACTION_MODIFY_FIELD_DST_LEVEL,
736 	ACTION_MODIFY_FIELD_DST_LEVEL_VALUE,
737 	ACTION_MODIFY_FIELD_DST_TAG_INDEX,
738 	ACTION_MODIFY_FIELD_DST_TYPE_ID,
739 	ACTION_MODIFY_FIELD_DST_CLASS_ID,
740 	ACTION_MODIFY_FIELD_DST_OFFSET,
741 	ACTION_MODIFY_FIELD_SRC_TYPE,
742 	ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
743 	ACTION_MODIFY_FIELD_SRC_LEVEL,
744 	ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE,
745 	ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
746 	ACTION_MODIFY_FIELD_SRC_TYPE_ID,
747 	ACTION_MODIFY_FIELD_SRC_CLASS_ID,
748 	ACTION_MODIFY_FIELD_SRC_OFFSET,
749 	ACTION_MODIFY_FIELD_SRC_VALUE,
750 	ACTION_MODIFY_FIELD_SRC_POINTER,
751 	ACTION_MODIFY_FIELD_WIDTH,
752 	ACTION_CONNTRACK,
753 	ACTION_CONNTRACK_UPDATE,
754 	ACTION_CONNTRACK_UPDATE_DIR,
755 	ACTION_CONNTRACK_UPDATE_CTX,
756 	ACTION_POL_G,
757 	ACTION_POL_Y,
758 	ACTION_POL_R,
759 	ACTION_PORT_REPRESENTOR,
760 	ACTION_PORT_REPRESENTOR_PORT_ID,
761 	ACTION_REPRESENTED_PORT,
762 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
763 	ACTION_SEND_TO_KERNEL,
764 	ACTION_QUOTA_CREATE,
765 	ACTION_QUOTA_CREATE_LIMIT,
766 	ACTION_QUOTA_CREATE_MODE,
767 	ACTION_QUOTA_CREATE_MODE_NAME,
768 	ACTION_QUOTA_QU,
769 	ACTION_QUOTA_QU_LIMIT,
770 	ACTION_QUOTA_QU_UPDATE_OP,
771 	ACTION_QUOTA_QU_UPDATE_OP_NAME,
772 	ACTION_IPV6_EXT_REMOVE,
773 	ACTION_IPV6_EXT_REMOVE_INDEX,
774 	ACTION_IPV6_EXT_REMOVE_INDEX_VALUE,
775 	ACTION_IPV6_EXT_PUSH,
776 	ACTION_IPV6_EXT_PUSH_INDEX,
777 	ACTION_IPV6_EXT_PUSH_INDEX_VALUE,
778 	ACTION_NAT64,
779 	ACTION_NAT64_MODE,
780 };
781 
782 /** Maximum size for pattern in struct rte_flow_item_raw. */
783 #define ITEM_RAW_PATTERN_SIZE 512
784 
785 /** Maximum size for GENEVE option data pattern in bytes. */
786 #define ITEM_GENEVE_OPT_DATA_SIZE 124
787 
788 /** Storage size for struct rte_flow_item_raw including pattern. */
789 #define ITEM_RAW_SIZE \
790 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
791 
792 static const char *const compare_ops[] = {
793 	"eq", "ne", "lt", "le", "gt", "ge", NULL
794 };
795 
796 /** Maximum size for external pattern in struct rte_flow_field_data. */
797 #define FLOW_FIELD_PATTERN_SIZE 32
798 
799 /** Storage size for struct rte_flow_action_modify_field including pattern. */
800 #define ACTION_MODIFY_SIZE \
801 	(sizeof(struct rte_flow_action_modify_field) + \
802 	FLOW_FIELD_PATTERN_SIZE)
803 
804 /** Maximum number of queue indices in struct rte_flow_action_rss. */
805 #define ACTION_RSS_QUEUE_NUM 128
806 
807 /** Storage for struct rte_flow_action_rss including external data. */
808 struct action_rss_data {
809 	struct rte_flow_action_rss conf;
810 	uint8_t key[RSS_HASH_KEY_LENGTH];
811 	uint16_t queue[ACTION_RSS_QUEUE_NUM];
812 };
813 
814 /** Maximum data size in struct rte_flow_action_raw_encap. */
815 #define ACTION_RAW_ENCAP_MAX_DATA 512
816 #define RAW_ENCAP_CONFS_MAX_NUM 8
817 
818 /** Storage for struct rte_flow_action_raw_encap. */
819 struct raw_encap_conf {
820 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
821 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
822 	size_t size;
823 };
824 
825 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
826 
827 /** Storage for struct rte_flow_action_raw_encap including external data. */
828 struct action_raw_encap_data {
829 	struct rte_flow_action_raw_encap conf;
830 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
831 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
832 	uint16_t idx;
833 };
834 
835 /** Storage for struct rte_flow_action_raw_decap. */
836 struct raw_decap_conf {
837 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
838 	size_t size;
839 };
840 
841 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
842 
843 /** Storage for struct rte_flow_action_raw_decap including external data. */
844 struct action_raw_decap_data {
845 	struct rte_flow_action_raw_decap conf;
846 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
847 	uint16_t idx;
848 };
849 
850 /** Maximum data size in struct rte_flow_action_ipv6_ext_push. */
851 #define ACTION_IPV6_EXT_PUSH_MAX_DATA 512
852 #define IPV6_EXT_PUSH_CONFS_MAX_NUM 8
853 
854 /** Storage for struct rte_flow_action_ipv6_ext_push. */
855 struct ipv6_ext_push_conf {
856 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
857 	size_t size;
858 	uint8_t type;
859 };
860 
861 struct ipv6_ext_push_conf ipv6_ext_push_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
862 
863 /** Storage for struct rte_flow_action_ipv6_ext_push including external data. */
864 struct action_ipv6_ext_push_data {
865 	struct rte_flow_action_ipv6_ext_push conf;
866 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
867 	uint8_t type;
868 	uint16_t idx;
869 };
870 
871 /** Storage for struct rte_flow_action_ipv6_ext_remove. */
872 struct ipv6_ext_remove_conf {
873 	struct rte_flow_action_ipv6_ext_remove conf;
874 	uint8_t type;
875 };
876 
877 struct ipv6_ext_remove_conf ipv6_ext_remove_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
878 
879 /** Storage for struct rte_flow_action_ipv6_ext_remove including external data. */
880 struct action_ipv6_ext_remove_data {
881 	struct rte_flow_action_ipv6_ext_remove conf;
882 	uint8_t type;
883 	uint16_t idx;
884 };
885 
886 struct vxlan_encap_conf vxlan_encap_conf = {
887 	.select_ipv4 = 1,
888 	.select_vlan = 0,
889 	.select_tos_ttl = 0,
890 	.vni = "\x00\x00\x00",
891 	.udp_src = 0,
892 	.udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
893 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
894 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
895 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
896 		"\x00\x00\x00\x00\x00\x00\x00\x01",
897 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
898 		"\x00\x00\x00\x00\x00\x00\x11\x11",
899 	.vlan_tci = 0,
900 	.ip_tos = 0,
901 	.ip_ttl = 255,
902 	.eth_src = "\x00\x00\x00\x00\x00\x00",
903 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
904 };
905 
906 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
907 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
908 
909 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
910 struct action_vxlan_encap_data {
911 	struct rte_flow_action_vxlan_encap conf;
912 	struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
913 	struct rte_flow_item_eth item_eth;
914 	struct rte_flow_item_vlan item_vlan;
915 	union {
916 		struct rte_flow_item_ipv4 item_ipv4;
917 		struct rte_flow_item_ipv6 item_ipv6;
918 	};
919 	struct rte_flow_item_udp item_udp;
920 	struct rte_flow_item_vxlan item_vxlan;
921 };
922 
923 struct nvgre_encap_conf nvgre_encap_conf = {
924 	.select_ipv4 = 1,
925 	.select_vlan = 0,
926 	.tni = "\x00\x00\x00",
927 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
928 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
929 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
930 		"\x00\x00\x00\x00\x00\x00\x00\x01",
931 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
932 		"\x00\x00\x00\x00\x00\x00\x11\x11",
933 	.vlan_tci = 0,
934 	.eth_src = "\x00\x00\x00\x00\x00\x00",
935 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
936 };
937 
938 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
939 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
940 
941 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
942 struct action_nvgre_encap_data {
943 	struct rte_flow_action_nvgre_encap conf;
944 	struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
945 	struct rte_flow_item_eth item_eth;
946 	struct rte_flow_item_vlan item_vlan;
947 	union {
948 		struct rte_flow_item_ipv4 item_ipv4;
949 		struct rte_flow_item_ipv6 item_ipv6;
950 	};
951 	struct rte_flow_item_nvgre item_nvgre;
952 };
953 
954 struct l2_encap_conf l2_encap_conf;
955 
956 struct l2_decap_conf l2_decap_conf;
957 
958 struct mplsogre_encap_conf mplsogre_encap_conf;
959 
960 struct mplsogre_decap_conf mplsogre_decap_conf;
961 
962 struct mplsoudp_encap_conf mplsoudp_encap_conf;
963 
964 struct mplsoudp_decap_conf mplsoudp_decap_conf;
965 
966 struct rte_flow_action_conntrack conntrack_context;
967 
968 #define ACTION_SAMPLE_ACTIONS_NUM 10
969 #define RAW_SAMPLE_CONFS_MAX_NUM 8
970 /** Storage for struct rte_flow_action_sample including external data. */
971 struct action_sample_data {
972 	struct rte_flow_action_sample conf;
973 	uint32_t idx;
974 };
975 /** Storage for struct rte_flow_action_sample. */
976 struct raw_sample_conf {
977 	struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
978 };
979 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
980 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
981 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
982 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
983 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
984 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
985 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
986 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
987 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
988 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
989 struct rte_flow_action_ethdev sample_port_representor[RAW_SAMPLE_CONFS_MAX_NUM];
990 struct rte_flow_action_ethdev sample_represented_port[RAW_SAMPLE_CONFS_MAX_NUM];
991 
992 static const char *const modify_field_ops[] = {
993 	"set", "add", "sub", NULL
994 };
995 
996 static const char *const flow_field_ids[] = {
997 	"start", "mac_dst", "mac_src",
998 	"vlan_type", "vlan_id", "mac_type",
999 	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
1000 	"ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
1001 	"tcp_port_src", "tcp_port_dst",
1002 	"tcp_seq_num", "tcp_ack_num", "tcp_flags",
1003 	"udp_port_src", "udp_port_dst",
1004 	"vxlan_vni", "geneve_vni", "gtp_teid",
1005 	"tag", "mark", "meta", "pointer", "value",
1006 	"ipv4_ecn", "ipv6_ecn", "gtp_psc_qfi", "meter_color",
1007 	"ipv6_proto",
1008 	"flex_item",
1009 	"hash_result",
1010 	"geneve_opt_type", "geneve_opt_class", "geneve_opt_data", "mpls",
1011 	"tcp_data_off", "ipv4_ihl", "ipv4_total_len", "ipv6_payload_len",
1012 	"ipv4_proto",
1013 	"ipv6_flow_label", "ipv6_traffic_class",
1014 	"esp_spi", "esp_seq_num", "esp_proto",
1015 	"random",
1016 	"vxlan_last_rsvd",
1017 	NULL
1018 };
1019 
1020 static const char *const meter_colors[] = {
1021 	"green", "yellow", "red", "all", NULL
1022 };
1023 
1024 static const char *const table_insertion_types[] = {
1025 	"pattern", "index", NULL
1026 };
1027 
1028 static const char *const table_hash_funcs[] = {
1029 	"default", "linear", "crc32", "crc16", NULL
1030 };
1031 
1032 #define RAW_IPSEC_CONFS_MAX_NUM 8
1033 
1034 /** Maximum number of subsequent tokens and arguments on the stack. */
1035 #define CTX_STACK_SIZE 16
1036 
1037 /** Parser context. */
1038 struct context {
1039 	/** Stack of subsequent token lists to process. */
1040 	const enum index *next[CTX_STACK_SIZE];
1041 	/** Arguments for stacked tokens. */
1042 	const void *args[CTX_STACK_SIZE];
1043 	enum index curr; /**< Current token index. */
1044 	enum index prev; /**< Index of the last token seen. */
1045 	int next_num; /**< Number of entries in next[]. */
1046 	int args_num; /**< Number of entries in args[]. */
1047 	uint32_t eol:1; /**< EOL has been detected. */
1048 	uint32_t last:1; /**< No more arguments. */
1049 	portid_t port; /**< Current port ID (for completions). */
1050 	uint32_t objdata; /**< Object-specific data. */
1051 	void *object; /**< Address of current object for relative offsets. */
1052 	void *objmask; /**< Object a full mask must be written to. */
1053 };
1054 
1055 /** Token argument. */
1056 struct arg {
1057 	uint32_t hton:1; /**< Use network byte ordering. */
1058 	uint32_t sign:1; /**< Value is signed. */
1059 	uint32_t bounded:1; /**< Value is bounded. */
1060 	uintmax_t min; /**< Minimum value if bounded. */
1061 	uintmax_t max; /**< Maximum value if bounded. */
1062 	uint32_t offset; /**< Relative offset from ctx->object. */
1063 	uint32_t size; /**< Field size. */
1064 	const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
1065 };
1066 
1067 /** Parser token definition. */
1068 struct token {
1069 	/** Type displayed during completion (defaults to "TOKEN"). */
1070 	const char *type;
1071 	/** Help displayed during completion (defaults to token name). */
1072 	const char *help;
1073 	/** Private data used by parser functions. */
1074 	const void *priv;
1075 	/**
1076 	 * Lists of subsequent tokens to push on the stack. Each call to the
1077 	 * parser consumes the last entry of that stack.
1078 	 */
1079 	const enum index *const *next;
1080 	/** Arguments stack for subsequent tokens that need them. */
1081 	const struct arg *const *args;
1082 	/**
1083 	 * Token-processing callback, returns -1 in case of error, the
1084 	 * length of the matched string otherwise. If NULL, attempts to
1085 	 * match the token name.
1086 	 *
1087 	 * If buf is not NULL, the result should be stored in it according
1088 	 * to context. An error is returned if not large enough.
1089 	 */
1090 	int (*call)(struct context *ctx, const struct token *token,
1091 		    const char *str, unsigned int len,
1092 		    void *buf, unsigned int size);
1093 	/**
1094 	 * Callback that provides possible values for this token, used for
1095 	 * completion. Returns -1 in case of error, the number of possible
1096 	 * values otherwise. If NULL, the token name is used.
1097 	 *
1098 	 * If buf is not NULL, entry index ent is written to buf and the
1099 	 * full length of the entry is returned (same behavior as
1100 	 * snprintf()).
1101 	 */
1102 	int (*comp)(struct context *ctx, const struct token *token,
1103 		    unsigned int ent, char *buf, unsigned int size);
1104 	/** Mandatory token name, no default value. */
1105 	const char *name;
1106 };
1107 
1108 /** Static initializer for the next field. */
1109 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
1110 
1111 /** Static initializer for a NEXT() entry. */
1112 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
1113 
1114 /** Static initializer for the args field. */
1115 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
1116 
1117 /** Static initializer for ARGS() to target a field. */
1118 #define ARGS_ENTRY(s, f) \
1119 	(&(const struct arg){ \
1120 		.offset = offsetof(s, f), \
1121 		.size = sizeof(((s *)0)->f), \
1122 	})
1123 
1124 /** Static initializer for ARGS() to target a bit-field. */
1125 #define ARGS_ENTRY_BF(s, f, b) \
1126 	(&(const struct arg){ \
1127 		.size = sizeof(s), \
1128 		.mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
1129 	})
1130 
1131 /** Static initializer for ARGS() to target a field with limits. */
1132 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
1133 	(&(const struct arg){ \
1134 		.bounded = 1, \
1135 		.min = (i), \
1136 		.max = (a), \
1137 		.offset = offsetof(s, f), \
1138 		.size = sizeof(((s *)0)->f), \
1139 	})
1140 
1141 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
1142 #define ARGS_ENTRY_MASK(s, f, m) \
1143 	(&(const struct arg){ \
1144 		.offset = offsetof(s, f), \
1145 		.size = sizeof(((s *)0)->f), \
1146 		.mask = (const void *)(m), \
1147 	})
1148 
1149 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
1150 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
1151 	(&(const struct arg){ \
1152 		.hton = 1, \
1153 		.offset = offsetof(s, f), \
1154 		.size = sizeof(((s *)0)->f), \
1155 		.mask = (const void *)(m), \
1156 	})
1157 
1158 /** Static initializer for ARGS() to target a pointer. */
1159 #define ARGS_ENTRY_PTR(s, f) \
1160 	(&(const struct arg){ \
1161 		.size = sizeof(*((s *)0)->f), \
1162 	})
1163 
1164 /** Static initializer for ARGS() with arbitrary offset and size. */
1165 #define ARGS_ENTRY_ARB(o, s) \
1166 	(&(const struct arg){ \
1167 		.offset = (o), \
1168 		.size = (s), \
1169 	})
1170 
1171 /** Same as ARGS_ENTRY_ARB() with bounded values. */
1172 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
1173 	(&(const struct arg){ \
1174 		.bounded = 1, \
1175 		.min = (i), \
1176 		.max = (a), \
1177 		.offset = (o), \
1178 		.size = (s), \
1179 	})
1180 
1181 /** Same as ARGS_ENTRY() using network byte ordering. */
1182 #define ARGS_ENTRY_HTON(s, f) \
1183 	(&(const struct arg){ \
1184 		.hton = 1, \
1185 		.offset = offsetof(s, f), \
1186 		.size = sizeof(((s *)0)->f), \
1187 	})
1188 
1189 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
1190 #define ARG_ENTRY_HTON(s) \
1191 	(&(const struct arg){ \
1192 		.hton = 1, \
1193 		.offset = 0, \
1194 		.size = sizeof(s), \
1195 	})
1196 
1197 /** Parser output buffer layout expected by cmd_flow_parsed(). */
1198 struct buffer {
1199 	enum index command; /**< Flow command. */
1200 	portid_t port; /**< Affected port ID. */
1201 	queueid_t queue; /** Async queue ID. */
1202 	bool postpone; /** Postpone async operation */
1203 	union {
1204 		struct {
1205 			struct rte_flow_port_attr port_attr;
1206 			uint32_t nb_queue;
1207 			struct rte_flow_queue_attr queue_attr;
1208 		} configure; /**< Configuration arguments. */
1209 		struct {
1210 			uint32_t *template_id;
1211 			uint32_t template_id_n;
1212 		} templ_destroy; /**< Template destroy arguments. */
1213 		struct {
1214 			uint32_t id;
1215 			struct rte_flow_template_table_attr attr;
1216 			uint32_t *pat_templ_id;
1217 			uint32_t pat_templ_id_n;
1218 			uint32_t *act_templ_id;
1219 			uint32_t act_templ_id_n;
1220 		} table; /**< Table arguments. */
1221 		struct {
1222 			uint32_t *table_id;
1223 			uint32_t table_id_n;
1224 		} table_destroy; /**< Template destroy arguments. */
1225 		struct {
1226 			uint32_t *action_id;
1227 			uint32_t action_id_n;
1228 		} ia_destroy; /**< Indirect action destroy arguments. */
1229 		struct {
1230 			uint32_t action_id;
1231 			enum rte_flow_query_update_mode qu_mode;
1232 		} ia; /* Indirect action query arguments */
1233 		struct {
1234 			uint32_t table_id;
1235 			uint32_t pat_templ_id;
1236 			uint32_t rule_id;
1237 			uint32_t act_templ_id;
1238 			struct rte_flow_attr attr;
1239 			struct tunnel_ops tunnel_ops;
1240 			uintptr_t user_id;
1241 			struct rte_flow_item *pattern;
1242 			struct rte_flow_action *actions;
1243 			struct rte_flow_action *masks;
1244 			uint32_t pattern_n;
1245 			uint32_t actions_n;
1246 			uint8_t *data;
1247 			enum rte_flow_encap_hash_field field;
1248 			uint8_t encap_hash;
1249 		} vc; /**< Validate/create arguments. */
1250 		struct {
1251 			uint64_t *rule;
1252 			uint64_t rule_n;
1253 			bool is_user_id;
1254 		} destroy; /**< Destroy arguments. */
1255 		struct {
1256 			char file[128];
1257 			bool mode;
1258 			uint64_t rule;
1259 			bool is_user_id;
1260 		} dump; /**< Dump arguments. */
1261 		struct {
1262 			uint64_t rule;
1263 			struct rte_flow_action action;
1264 			bool is_user_id;
1265 		} query; /**< Query arguments. */
1266 		struct {
1267 			uint32_t *group;
1268 			uint32_t group_n;
1269 		} list; /**< List arguments. */
1270 		struct {
1271 			int set;
1272 		} isolate; /**< Isolated mode arguments. */
1273 		struct {
1274 			int destroy;
1275 		} aged; /**< Aged arguments. */
1276 		struct {
1277 			uint32_t policy_id;
1278 		} policy;/**< Policy arguments. */
1279 		struct {
1280 			uint16_t token;
1281 			uintptr_t uintptr;
1282 			char filename[128];
1283 		} flex; /**< Flex arguments*/
1284 	} args; /**< Command arguments. */
1285 };
1286 
1287 /** Private data for pattern items. */
1288 struct parse_item_priv {
1289 	enum rte_flow_item_type type; /**< Item type. */
1290 	uint32_t size; /**< Size of item specification structure. */
1291 };
1292 
1293 #define PRIV_ITEM(t, s) \
1294 	(&(const struct parse_item_priv){ \
1295 		.type = RTE_FLOW_ITEM_TYPE_ ## t, \
1296 		.size = s, \
1297 	})
1298 
1299 /** Private data for actions. */
1300 struct parse_action_priv {
1301 	enum rte_flow_action_type type; /**< Action type. */
1302 	uint32_t size; /**< Size of action configuration structure. */
1303 };
1304 
1305 #define PRIV_ACTION(t, s) \
1306 	(&(const struct parse_action_priv){ \
1307 		.type = RTE_FLOW_ACTION_TYPE_ ## t, \
1308 		.size = s, \
1309 	})
1310 
1311 static const enum index next_flex_item[] = {
1312 	FLEX_ITEM_INIT,
1313 	FLEX_ITEM_CREATE,
1314 	FLEX_ITEM_DESTROY,
1315 	ZERO,
1316 };
1317 
1318 static const enum index next_config_attr[] = {
1319 	CONFIG_QUEUES_NUMBER,
1320 	CONFIG_QUEUES_SIZE,
1321 	CONFIG_COUNTERS_NUMBER,
1322 	CONFIG_AGING_OBJECTS_NUMBER,
1323 	CONFIG_METERS_NUMBER,
1324 	CONFIG_CONN_TRACK_NUMBER,
1325 	CONFIG_QUOTAS_NUMBER,
1326 	CONFIG_FLAGS,
1327 	CONFIG_HOST_PORT,
1328 	END,
1329 	ZERO,
1330 };
1331 
1332 static const enum index next_pt_subcmd[] = {
1333 	PATTERN_TEMPLATE_CREATE,
1334 	PATTERN_TEMPLATE_DESTROY,
1335 	ZERO,
1336 };
1337 
1338 static const enum index next_pt_attr[] = {
1339 	PATTERN_TEMPLATE_CREATE_ID,
1340 	PATTERN_TEMPLATE_RELAXED_MATCHING,
1341 	PATTERN_TEMPLATE_INGRESS,
1342 	PATTERN_TEMPLATE_EGRESS,
1343 	PATTERN_TEMPLATE_TRANSFER,
1344 	PATTERN_TEMPLATE_SPEC,
1345 	ZERO,
1346 };
1347 
1348 static const enum index next_pt_destroy_attr[] = {
1349 	PATTERN_TEMPLATE_DESTROY_ID,
1350 	END,
1351 	ZERO,
1352 };
1353 
1354 static const enum index next_at_subcmd[] = {
1355 	ACTIONS_TEMPLATE_CREATE,
1356 	ACTIONS_TEMPLATE_DESTROY,
1357 	ZERO,
1358 };
1359 
1360 static const enum index next_at_attr[] = {
1361 	ACTIONS_TEMPLATE_CREATE_ID,
1362 	ACTIONS_TEMPLATE_INGRESS,
1363 	ACTIONS_TEMPLATE_EGRESS,
1364 	ACTIONS_TEMPLATE_TRANSFER,
1365 	ACTIONS_TEMPLATE_SPEC,
1366 	ZERO,
1367 };
1368 
1369 static const enum index next_at_destroy_attr[] = {
1370 	ACTIONS_TEMPLATE_DESTROY_ID,
1371 	END,
1372 	ZERO,
1373 };
1374 
1375 static const enum index next_group_attr[] = {
1376 	GROUP_INGRESS,
1377 	GROUP_EGRESS,
1378 	GROUP_TRANSFER,
1379 	GROUP_SET_MISS_ACTIONS,
1380 	ZERO,
1381 };
1382 
1383 static const enum index next_table_subcmd[] = {
1384 	TABLE_CREATE,
1385 	TABLE_DESTROY,
1386 	TABLE_RESIZE,
1387 	TABLE_RESIZE_COMPLETE,
1388 	ZERO,
1389 };
1390 
1391 static const enum index next_table_attr[] = {
1392 	TABLE_CREATE_ID,
1393 	TABLE_GROUP,
1394 	TABLE_INSERTION_TYPE,
1395 	TABLE_HASH_FUNC,
1396 	TABLE_PRIORITY,
1397 	TABLE_INGRESS,
1398 	TABLE_EGRESS,
1399 	TABLE_TRANSFER,
1400 	TABLE_TRANSFER_WIRE_ORIG,
1401 	TABLE_TRANSFER_VPORT_ORIG,
1402 	TABLE_RESIZABLE,
1403 	TABLE_RULES_NUMBER,
1404 	TABLE_PATTERN_TEMPLATE,
1405 	TABLE_ACTIONS_TEMPLATE,
1406 	END,
1407 	ZERO,
1408 };
1409 
1410 static const enum index next_table_destroy_attr[] = {
1411 	TABLE_DESTROY_ID,
1412 	END,
1413 	ZERO,
1414 };
1415 
1416 static const enum index next_queue_subcmd[] = {
1417 	QUEUE_CREATE,
1418 	QUEUE_DESTROY,
1419 	QUEUE_FLOW_UPDATE_RESIZED,
1420 	QUEUE_UPDATE,
1421 	QUEUE_AGED,
1422 	QUEUE_INDIRECT_ACTION,
1423 	ZERO,
1424 };
1425 
1426 static const enum index next_queue_destroy_attr[] = {
1427 	QUEUE_DESTROY_ID,
1428 	END,
1429 	ZERO,
1430 };
1431 
1432 static const enum index next_qia_subcmd[] = {
1433 	QUEUE_INDIRECT_ACTION_CREATE,
1434 	QUEUE_INDIRECT_ACTION_UPDATE,
1435 	QUEUE_INDIRECT_ACTION_DESTROY,
1436 	QUEUE_INDIRECT_ACTION_QUERY,
1437 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
1438 	ZERO,
1439 };
1440 
1441 static const enum index next_qia_create_attr[] = {
1442 	QUEUE_INDIRECT_ACTION_CREATE_ID,
1443 	QUEUE_INDIRECT_ACTION_INGRESS,
1444 	QUEUE_INDIRECT_ACTION_EGRESS,
1445 	QUEUE_INDIRECT_ACTION_TRANSFER,
1446 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
1447 	QUEUE_INDIRECT_ACTION_SPEC,
1448 	QUEUE_INDIRECT_ACTION_LIST,
1449 	ZERO,
1450 };
1451 
1452 static const enum index next_qia_update_attr[] = {
1453 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1454 	QUEUE_INDIRECT_ACTION_SPEC,
1455 	ZERO,
1456 };
1457 
1458 static const enum index next_qia_destroy_attr[] = {
1459 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
1460 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
1461 	END,
1462 	ZERO,
1463 };
1464 
1465 static const enum index next_qia_query_attr[] = {
1466 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
1467 	END,
1468 	ZERO,
1469 };
1470 
1471 static const enum index next_ia_create_attr[] = {
1472 	INDIRECT_ACTION_CREATE_ID,
1473 	INDIRECT_ACTION_INGRESS,
1474 	INDIRECT_ACTION_EGRESS,
1475 	INDIRECT_ACTION_TRANSFER,
1476 	INDIRECT_ACTION_SPEC,
1477 	INDIRECT_ACTION_LIST,
1478 	INDIRECT_ACTION_FLOW_CONF,
1479 	ZERO,
1480 };
1481 
1482 static const enum index next_ia[] = {
1483 	INDIRECT_ACTION_ID2PTR,
1484 	ACTION_NEXT,
1485 	ZERO
1486 };
1487 
1488 static const enum index next_ial[] = {
1489 	ACTION_INDIRECT_LIST_HANDLE,
1490 	ACTION_INDIRECT_LIST_CONF,
1491 	ACTION_NEXT,
1492 	ZERO
1493 };
1494 
1495 static const enum index next_qia_qu_attr[] = {
1496 	QUEUE_INDIRECT_ACTION_QU_MODE,
1497 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1498 	INDIRECT_ACTION_SPEC,
1499 	ZERO
1500 };
1501 
1502 static const enum index next_ia_qu_attr[] = {
1503 	INDIRECT_ACTION_QU_MODE,
1504 	INDIRECT_ACTION_SPEC,
1505 	ZERO
1506 };
1507 
1508 static const enum index next_dump_subcmd[] = {
1509 	DUMP_ALL,
1510 	DUMP_ONE,
1511 	DUMP_IS_USER_ID,
1512 	ZERO,
1513 };
1514 
1515 static const enum index next_ia_subcmd[] = {
1516 	INDIRECT_ACTION_CREATE,
1517 	INDIRECT_ACTION_UPDATE,
1518 	INDIRECT_ACTION_DESTROY,
1519 	INDIRECT_ACTION_QUERY,
1520 	INDIRECT_ACTION_QUERY_UPDATE,
1521 	ZERO,
1522 };
1523 
1524 static const enum index next_vc_attr[] = {
1525 	VC_GROUP,
1526 	VC_PRIORITY,
1527 	VC_INGRESS,
1528 	VC_EGRESS,
1529 	VC_TRANSFER,
1530 	VC_TUNNEL_SET,
1531 	VC_TUNNEL_MATCH,
1532 	VC_USER_ID,
1533 	ITEM_PATTERN,
1534 	ZERO,
1535 };
1536 
1537 static const enum index next_destroy_attr[] = {
1538 	DESTROY_RULE,
1539 	DESTROY_IS_USER_ID,
1540 	END,
1541 	ZERO,
1542 };
1543 
1544 static const enum index next_dump_attr[] = {
1545 	COMMON_FILE_PATH,
1546 	END,
1547 	ZERO,
1548 };
1549 
1550 static const enum index next_query_attr[] = {
1551 	QUERY_IS_USER_ID,
1552 	END,
1553 	ZERO,
1554 };
1555 
1556 static const enum index next_list_attr[] = {
1557 	LIST_GROUP,
1558 	END,
1559 	ZERO,
1560 };
1561 
1562 static const enum index next_aged_attr[] = {
1563 	AGED_DESTROY,
1564 	END,
1565 	ZERO,
1566 };
1567 
1568 static const enum index next_ia_destroy_attr[] = {
1569 	INDIRECT_ACTION_DESTROY_ID,
1570 	END,
1571 	ZERO,
1572 };
1573 
1574 static const enum index next_async_insert_subcmd[] = {
1575 	QUEUE_PATTERN_TEMPLATE,
1576 	QUEUE_RULE_ID,
1577 	ZERO,
1578 };
1579 
1580 static const enum index item_param[] = {
1581 	ITEM_PARAM_IS,
1582 	ITEM_PARAM_SPEC,
1583 	ITEM_PARAM_LAST,
1584 	ITEM_PARAM_MASK,
1585 	ITEM_PARAM_PREFIX,
1586 	ZERO,
1587 };
1588 
1589 static const enum index next_item[] = {
1590 	ITEM_END,
1591 	ITEM_VOID,
1592 	ITEM_INVERT,
1593 	ITEM_ANY,
1594 	ITEM_PORT_ID,
1595 	ITEM_MARK,
1596 	ITEM_RAW,
1597 	ITEM_ETH,
1598 	ITEM_VLAN,
1599 	ITEM_IPV4,
1600 	ITEM_IPV6,
1601 	ITEM_ICMP,
1602 	ITEM_UDP,
1603 	ITEM_TCP,
1604 	ITEM_SCTP,
1605 	ITEM_VXLAN,
1606 	ITEM_E_TAG,
1607 	ITEM_NVGRE,
1608 	ITEM_MPLS,
1609 	ITEM_GRE,
1610 	ITEM_FUZZY,
1611 	ITEM_GTP,
1612 	ITEM_GTPC,
1613 	ITEM_GTPU,
1614 	ITEM_GENEVE,
1615 	ITEM_ARP_ETH_IPV4,
1616 	ITEM_IPV6_EXT,
1617 	ITEM_IPV6_FRAG_EXT,
1618 	ITEM_IPV6_ROUTING_EXT,
1619 	ITEM_ICMP6,
1620 	ITEM_ICMP6_ECHO_REQUEST,
1621 	ITEM_ICMP6_ECHO_REPLY,
1622 	ITEM_ICMP6_ND_NS,
1623 	ITEM_ICMP6_ND_NA,
1624 	ITEM_ICMP6_ND_OPT,
1625 	ITEM_ICMP6_ND_OPT_SLA_ETH,
1626 	ITEM_ICMP6_ND_OPT_TLA_ETH,
1627 	ITEM_META,
1628 	ITEM_RANDOM,
1629 	ITEM_GRE_KEY,
1630 	ITEM_GRE_OPTION,
1631 	ITEM_GTP_PSC,
1632 	ITEM_PPPOES,
1633 	ITEM_PPPOED,
1634 	ITEM_PPPOE_PROTO_ID,
1635 	ITEM_HIGIG2,
1636 	ITEM_TAG,
1637 	ITEM_L2TPV3OIP,
1638 	ITEM_ESP,
1639 	ITEM_AH,
1640 	ITEM_PFCP,
1641 	ITEM_ECPRI,
1642 	ITEM_GENEVE_OPT,
1643 	ITEM_INTEGRITY,
1644 	ITEM_CONNTRACK,
1645 	ITEM_PORT_REPRESENTOR,
1646 	ITEM_REPRESENTED_PORT,
1647 	ITEM_FLEX,
1648 	ITEM_L2TPV2,
1649 	ITEM_PPP,
1650 	ITEM_METER,
1651 	ITEM_QUOTA,
1652 	ITEM_AGGR_AFFINITY,
1653 	ITEM_TX_QUEUE,
1654 	ITEM_IB_BTH,
1655 	ITEM_PTYPE,
1656 	ITEM_NSH,
1657 	ITEM_COMPARE,
1658 	END_SET,
1659 	ZERO,
1660 };
1661 
1662 static const enum index item_fuzzy[] = {
1663 	ITEM_FUZZY_THRESH,
1664 	ITEM_NEXT,
1665 	ZERO,
1666 };
1667 
1668 static const enum index item_any[] = {
1669 	ITEM_ANY_NUM,
1670 	ITEM_NEXT,
1671 	ZERO,
1672 };
1673 
1674 static const enum index item_port_id[] = {
1675 	ITEM_PORT_ID_ID,
1676 	ITEM_NEXT,
1677 	ZERO,
1678 };
1679 
1680 static const enum index item_mark[] = {
1681 	ITEM_MARK_ID,
1682 	ITEM_NEXT,
1683 	ZERO,
1684 };
1685 
1686 static const enum index item_raw[] = {
1687 	ITEM_RAW_RELATIVE,
1688 	ITEM_RAW_SEARCH,
1689 	ITEM_RAW_OFFSET,
1690 	ITEM_RAW_LIMIT,
1691 	ITEM_RAW_PATTERN,
1692 	ITEM_RAW_PATTERN_HEX,
1693 	ITEM_NEXT,
1694 	ZERO,
1695 };
1696 
1697 static const enum index item_eth[] = {
1698 	ITEM_ETH_DST,
1699 	ITEM_ETH_SRC,
1700 	ITEM_ETH_TYPE,
1701 	ITEM_ETH_HAS_VLAN,
1702 	ITEM_NEXT,
1703 	ZERO,
1704 };
1705 
1706 static const enum index item_vlan[] = {
1707 	ITEM_VLAN_TCI,
1708 	ITEM_VLAN_PCP,
1709 	ITEM_VLAN_DEI,
1710 	ITEM_VLAN_VID,
1711 	ITEM_VLAN_INNER_TYPE,
1712 	ITEM_VLAN_HAS_MORE_VLAN,
1713 	ITEM_NEXT,
1714 	ZERO,
1715 };
1716 
1717 static const enum index item_ipv4[] = {
1718 	ITEM_IPV4_VER_IHL,
1719 	ITEM_IPV4_TOS,
1720 	ITEM_IPV4_LENGTH,
1721 	ITEM_IPV4_ID,
1722 	ITEM_IPV4_FRAGMENT_OFFSET,
1723 	ITEM_IPV4_TTL,
1724 	ITEM_IPV4_PROTO,
1725 	ITEM_IPV4_SRC,
1726 	ITEM_IPV4_DST,
1727 	ITEM_NEXT,
1728 	ZERO,
1729 };
1730 
1731 static const enum index item_ipv6[] = {
1732 	ITEM_IPV6_TC,
1733 	ITEM_IPV6_FLOW,
1734 	ITEM_IPV6_LEN,
1735 	ITEM_IPV6_PROTO,
1736 	ITEM_IPV6_HOP,
1737 	ITEM_IPV6_SRC,
1738 	ITEM_IPV6_DST,
1739 	ITEM_IPV6_HAS_FRAG_EXT,
1740 	ITEM_IPV6_ROUTING_EXT,
1741 	ITEM_NEXT,
1742 	ZERO,
1743 };
1744 
1745 static const enum index item_ipv6_routing_ext[] = {
1746 	ITEM_IPV6_ROUTING_EXT_TYPE,
1747 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
1748 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
1749 	ITEM_NEXT,
1750 	ZERO,
1751 };
1752 
1753 static const enum index item_icmp[] = {
1754 	ITEM_ICMP_TYPE,
1755 	ITEM_ICMP_CODE,
1756 	ITEM_ICMP_IDENT,
1757 	ITEM_ICMP_SEQ,
1758 	ITEM_NEXT,
1759 	ZERO,
1760 };
1761 
1762 static const enum index item_udp[] = {
1763 	ITEM_UDP_SRC,
1764 	ITEM_UDP_DST,
1765 	ITEM_NEXT,
1766 	ZERO,
1767 };
1768 
1769 static const enum index item_tcp[] = {
1770 	ITEM_TCP_SRC,
1771 	ITEM_TCP_DST,
1772 	ITEM_TCP_FLAGS,
1773 	ITEM_NEXT,
1774 	ZERO,
1775 };
1776 
1777 static const enum index item_sctp[] = {
1778 	ITEM_SCTP_SRC,
1779 	ITEM_SCTP_DST,
1780 	ITEM_SCTP_TAG,
1781 	ITEM_SCTP_CKSUM,
1782 	ITEM_NEXT,
1783 	ZERO,
1784 };
1785 
1786 static const enum index item_vxlan[] = {
1787 	ITEM_VXLAN_VNI,
1788 	ITEM_VXLAN_FLAG_G,
1789 	ITEM_VXLAN_FLAG_VER,
1790 	ITEM_VXLAN_FLAG_I,
1791 	ITEM_VXLAN_FLAG_P,
1792 	ITEM_VXLAN_FLAG_B,
1793 	ITEM_VXLAN_FLAG_O,
1794 	ITEM_VXLAN_FLAG_D,
1795 	ITEM_VXLAN_FLAG_A,
1796 	ITEM_VXLAN_GBP_ID,
1797 	ITEM_VXLAN_GPE_PROTO,
1798 	ITEM_VXLAN_FIRST_RSVD,
1799 	ITEM_VXLAN_SECND_RSVD,
1800 	ITEM_VXLAN_THIRD_RSVD,
1801 	ITEM_VXLAN_LAST_RSVD,
1802 	ITEM_NEXT,
1803 	ZERO,
1804 };
1805 
1806 static const enum index item_e_tag[] = {
1807 	ITEM_E_TAG_GRP_ECID_B,
1808 	ITEM_NEXT,
1809 	ZERO,
1810 };
1811 
1812 static const enum index item_nvgre[] = {
1813 	ITEM_NVGRE_TNI,
1814 	ITEM_NEXT,
1815 	ZERO,
1816 };
1817 
1818 static const enum index item_mpls[] = {
1819 	ITEM_MPLS_LABEL,
1820 	ITEM_MPLS_TC,
1821 	ITEM_MPLS_S,
1822 	ITEM_MPLS_TTL,
1823 	ITEM_NEXT,
1824 	ZERO,
1825 };
1826 
1827 static const enum index item_gre[] = {
1828 	ITEM_GRE_PROTO,
1829 	ITEM_GRE_C_RSVD0_VER,
1830 	ITEM_GRE_C_BIT,
1831 	ITEM_GRE_K_BIT,
1832 	ITEM_GRE_S_BIT,
1833 	ITEM_NEXT,
1834 	ZERO,
1835 };
1836 
1837 static const enum index item_gre_key[] = {
1838 	ITEM_GRE_KEY_VALUE,
1839 	ITEM_NEXT,
1840 	ZERO,
1841 };
1842 
1843 static const enum index item_gre_option[] = {
1844 	ITEM_GRE_OPTION_CHECKSUM,
1845 	ITEM_GRE_OPTION_KEY,
1846 	ITEM_GRE_OPTION_SEQUENCE,
1847 	ITEM_NEXT,
1848 	ZERO,
1849 };
1850 
1851 static const enum index item_gtp[] = {
1852 	ITEM_GTP_FLAGS,
1853 	ITEM_GTP_MSG_TYPE,
1854 	ITEM_GTP_TEID,
1855 	ITEM_NEXT,
1856 	ZERO,
1857 };
1858 
1859 static const enum index item_geneve[] = {
1860 	ITEM_GENEVE_VNI,
1861 	ITEM_GENEVE_PROTO,
1862 	ITEM_GENEVE_OPTLEN,
1863 	ITEM_NEXT,
1864 	ZERO,
1865 };
1866 
1867 static const enum index item_arp_eth_ipv4[] = {
1868 	ITEM_ARP_ETH_IPV4_SHA,
1869 	ITEM_ARP_ETH_IPV4_SPA,
1870 	ITEM_ARP_ETH_IPV4_THA,
1871 	ITEM_ARP_ETH_IPV4_TPA,
1872 	ITEM_NEXT,
1873 	ZERO,
1874 };
1875 
1876 static const enum index item_ipv6_ext[] = {
1877 	ITEM_IPV6_EXT_NEXT_HDR,
1878 	ITEM_NEXT,
1879 	ZERO,
1880 };
1881 
1882 static const enum index item_ipv6_frag_ext[] = {
1883 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1884 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1885 	ITEM_IPV6_FRAG_EXT_ID,
1886 	ITEM_NEXT,
1887 	ZERO,
1888 };
1889 
1890 static const enum index item_icmp6[] = {
1891 	ITEM_ICMP6_TYPE,
1892 	ITEM_ICMP6_CODE,
1893 	ITEM_NEXT,
1894 	ZERO,
1895 };
1896 
1897 static const enum index item_icmp6_echo_request[] = {
1898 	ITEM_ICMP6_ECHO_REQUEST_ID,
1899 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
1900 	ITEM_NEXT,
1901 	ZERO,
1902 };
1903 
1904 static const enum index item_icmp6_echo_reply[] = {
1905 	ITEM_ICMP6_ECHO_REPLY_ID,
1906 	ITEM_ICMP6_ECHO_REPLY_SEQ,
1907 	ITEM_NEXT,
1908 	ZERO,
1909 };
1910 
1911 static const enum index item_icmp6_nd_ns[] = {
1912 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
1913 	ITEM_NEXT,
1914 	ZERO,
1915 };
1916 
1917 static const enum index item_icmp6_nd_na[] = {
1918 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
1919 	ITEM_NEXT,
1920 	ZERO,
1921 };
1922 
1923 static const enum index item_icmp6_nd_opt[] = {
1924 	ITEM_ICMP6_ND_OPT_TYPE,
1925 	ITEM_NEXT,
1926 	ZERO,
1927 };
1928 
1929 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1930 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1931 	ITEM_NEXT,
1932 	ZERO,
1933 };
1934 
1935 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1936 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1937 	ITEM_NEXT,
1938 	ZERO,
1939 };
1940 
1941 static const enum index item_meta[] = {
1942 	ITEM_META_DATA,
1943 	ITEM_NEXT,
1944 	ZERO,
1945 };
1946 
1947 static const enum index item_random[] = {
1948 	ITEM_RANDOM_VALUE,
1949 	ITEM_NEXT,
1950 	ZERO,
1951 };
1952 
1953 static const enum index item_gtp_psc[] = {
1954 	ITEM_GTP_PSC_QFI,
1955 	ITEM_GTP_PSC_PDU_T,
1956 	ITEM_NEXT,
1957 	ZERO,
1958 };
1959 
1960 static const enum index item_pppoed[] = {
1961 	ITEM_PPPOE_SEID,
1962 	ITEM_NEXT,
1963 	ZERO,
1964 };
1965 
1966 static const enum index item_pppoes[] = {
1967 	ITEM_PPPOE_SEID,
1968 	ITEM_NEXT,
1969 	ZERO,
1970 };
1971 
1972 static const enum index item_pppoe_proto_id[] = {
1973 	ITEM_NEXT,
1974 	ZERO,
1975 };
1976 
1977 static const enum index item_higig2[] = {
1978 	ITEM_HIGIG2_CLASSIFICATION,
1979 	ITEM_HIGIG2_VID,
1980 	ITEM_NEXT,
1981 	ZERO,
1982 };
1983 
1984 static const enum index item_esp[] = {
1985 	ITEM_ESP_SPI,
1986 	ITEM_NEXT,
1987 	ZERO,
1988 };
1989 
1990 static const enum index item_ah[] = {
1991 	ITEM_AH_SPI,
1992 	ITEM_NEXT,
1993 	ZERO,
1994 };
1995 
1996 static const enum index item_pfcp[] = {
1997 	ITEM_PFCP_S_FIELD,
1998 	ITEM_PFCP_SEID,
1999 	ITEM_NEXT,
2000 	ZERO,
2001 };
2002 
2003 static const enum index next_set_raw[] = {
2004 	SET_RAW_INDEX,
2005 	ITEM_ETH,
2006 	ZERO,
2007 };
2008 
2009 static const enum index item_tag[] = {
2010 	ITEM_TAG_DATA,
2011 	ITEM_TAG_INDEX,
2012 	ITEM_NEXT,
2013 	ZERO,
2014 };
2015 
2016 static const enum index item_l2tpv3oip[] = {
2017 	ITEM_L2TPV3OIP_SESSION_ID,
2018 	ITEM_NEXT,
2019 	ZERO,
2020 };
2021 
2022 static const enum index item_ecpri[] = {
2023 	ITEM_ECPRI_COMMON,
2024 	ITEM_NEXT,
2025 	ZERO,
2026 };
2027 
2028 static const enum index item_ecpri_common[] = {
2029 	ITEM_ECPRI_COMMON_TYPE,
2030 	ZERO,
2031 };
2032 
2033 static const enum index item_ecpri_common_type[] = {
2034 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
2035 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
2036 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
2037 	ZERO,
2038 };
2039 
2040 static const enum index item_geneve_opt[] = {
2041 	ITEM_GENEVE_OPT_CLASS,
2042 	ITEM_GENEVE_OPT_TYPE,
2043 	ITEM_GENEVE_OPT_LENGTH,
2044 	ITEM_GENEVE_OPT_DATA,
2045 	ITEM_NEXT,
2046 	ZERO,
2047 };
2048 
2049 static const enum index item_integrity[] = {
2050 	ITEM_INTEGRITY_LEVEL,
2051 	ITEM_INTEGRITY_VALUE,
2052 	ZERO,
2053 };
2054 
2055 static const enum index item_integrity_lv[] = {
2056 	ITEM_INTEGRITY_LEVEL,
2057 	ITEM_INTEGRITY_VALUE,
2058 	ITEM_NEXT,
2059 	ZERO,
2060 };
2061 
2062 static const enum index item_port_representor[] = {
2063 	ITEM_PORT_REPRESENTOR_PORT_ID,
2064 	ITEM_NEXT,
2065 	ZERO,
2066 };
2067 
2068 static const enum index item_represented_port[] = {
2069 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
2070 	ITEM_NEXT,
2071 	ZERO,
2072 };
2073 
2074 static const enum index item_flex[] = {
2075 	ITEM_FLEX_PATTERN_HANDLE,
2076 	ITEM_FLEX_ITEM_HANDLE,
2077 	ITEM_NEXT,
2078 	ZERO,
2079 };
2080 
2081 static const enum index item_l2tpv2[] = {
2082 	ITEM_L2TPV2_TYPE,
2083 	ITEM_NEXT,
2084 	ZERO,
2085 };
2086 
2087 static const enum index item_l2tpv2_type[] = {
2088 	ITEM_L2TPV2_TYPE_DATA,
2089 	ITEM_L2TPV2_TYPE_DATA_L,
2090 	ITEM_L2TPV2_TYPE_DATA_S,
2091 	ITEM_L2TPV2_TYPE_DATA_O,
2092 	ITEM_L2TPV2_TYPE_DATA_L_S,
2093 	ITEM_L2TPV2_TYPE_CTRL,
2094 	ZERO,
2095 };
2096 
2097 static const enum index item_l2tpv2_type_data[] = {
2098 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
2099 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
2100 	ITEM_NEXT,
2101 	ZERO,
2102 };
2103 
2104 static const enum index item_l2tpv2_type_data_l[] = {
2105 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
2106 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
2107 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
2108 	ITEM_NEXT,
2109 	ZERO,
2110 };
2111 
2112 static const enum index item_l2tpv2_type_data_s[] = {
2113 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
2114 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
2115 	ITEM_L2TPV2_MSG_DATA_S_NS,
2116 	ITEM_L2TPV2_MSG_DATA_S_NR,
2117 	ITEM_NEXT,
2118 	ZERO,
2119 };
2120 
2121 static const enum index item_l2tpv2_type_data_o[] = {
2122 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
2123 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
2124 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
2125 	ITEM_NEXT,
2126 	ZERO,
2127 };
2128 
2129 static const enum index item_l2tpv2_type_data_l_s[] = {
2130 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
2131 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
2132 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
2133 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
2134 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
2135 	ITEM_NEXT,
2136 	ZERO,
2137 };
2138 
2139 static const enum index item_l2tpv2_type_ctrl[] = {
2140 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
2141 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
2142 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
2143 	ITEM_L2TPV2_MSG_CTRL_NS,
2144 	ITEM_L2TPV2_MSG_CTRL_NR,
2145 	ITEM_NEXT,
2146 	ZERO,
2147 };
2148 
2149 static const enum index item_ppp[] = {
2150 	ITEM_PPP_ADDR,
2151 	ITEM_PPP_CTRL,
2152 	ITEM_PPP_PROTO_ID,
2153 	ITEM_NEXT,
2154 	ZERO,
2155 };
2156 
2157 static const enum index item_meter[] = {
2158 	ITEM_METER_COLOR,
2159 	ITEM_NEXT,
2160 	ZERO,
2161 };
2162 
2163 static const enum index item_quota[] = {
2164 	ITEM_QUOTA_STATE,
2165 	ITEM_NEXT,
2166 	ZERO,
2167 };
2168 
2169 static const enum index item_aggr_affinity[] = {
2170 	ITEM_AGGR_AFFINITY_VALUE,
2171 	ITEM_NEXT,
2172 	ZERO,
2173 };
2174 
2175 static const enum index item_tx_queue[] = {
2176 	ITEM_TX_QUEUE_VALUE,
2177 	ITEM_NEXT,
2178 	ZERO,
2179 };
2180 
2181 static const enum index item_ib_bth[] = {
2182 	ITEM_IB_BTH_OPCODE,
2183 	ITEM_IB_BTH_PKEY,
2184 	ITEM_IB_BTH_DST_QPN,
2185 	ITEM_IB_BTH_PSN,
2186 	ITEM_NEXT,
2187 	ZERO,
2188 };
2189 
2190 static const enum index item_ptype[] = {
2191 	ITEM_PTYPE_VALUE,
2192 	ITEM_NEXT,
2193 	ZERO,
2194 };
2195 
2196 static const enum index item_nsh[] = {
2197 	ITEM_NEXT,
2198 	ZERO,
2199 };
2200 
2201 static const enum index item_compare_field[] = {
2202 	ITEM_COMPARE_OP,
2203 	ITEM_COMPARE_FIELD_A_TYPE,
2204 	ITEM_COMPARE_FIELD_B_TYPE,
2205 	ITEM_NEXT,
2206 	ZERO,
2207 };
2208 
2209 static const enum index compare_field_a[] = {
2210 	ITEM_COMPARE_FIELD_A_TYPE,
2211 	ITEM_COMPARE_FIELD_A_LEVEL,
2212 	ITEM_COMPARE_FIELD_A_TAG_INDEX,
2213 	ITEM_COMPARE_FIELD_A_TYPE_ID,
2214 	ITEM_COMPARE_FIELD_A_CLASS_ID,
2215 	ITEM_COMPARE_FIELD_A_OFFSET,
2216 	ITEM_COMPARE_FIELD_B_TYPE,
2217 	ZERO,
2218 };
2219 
2220 static const enum index compare_field_b[] = {
2221 	ITEM_COMPARE_FIELD_B_TYPE,
2222 	ITEM_COMPARE_FIELD_B_LEVEL,
2223 	ITEM_COMPARE_FIELD_B_TAG_INDEX,
2224 	ITEM_COMPARE_FIELD_B_TYPE_ID,
2225 	ITEM_COMPARE_FIELD_B_CLASS_ID,
2226 	ITEM_COMPARE_FIELD_B_OFFSET,
2227 	ITEM_COMPARE_FIELD_B_VALUE,
2228 	ITEM_COMPARE_FIELD_B_POINTER,
2229 	ITEM_COMPARE_FIELD_WIDTH,
2230 	ZERO,
2231 };
2232 
2233 static const enum index next_action[] = {
2234 	ACTION_END,
2235 	ACTION_VOID,
2236 	ACTION_PASSTHRU,
2237 	ACTION_SKIP_CMAN,
2238 	ACTION_JUMP,
2239 	ACTION_MARK,
2240 	ACTION_FLAG,
2241 	ACTION_QUEUE,
2242 	ACTION_DROP,
2243 	ACTION_COUNT,
2244 	ACTION_RSS,
2245 	ACTION_PF,
2246 	ACTION_VF,
2247 	ACTION_PORT_ID,
2248 	ACTION_METER,
2249 	ACTION_METER_COLOR,
2250 	ACTION_METER_MARK,
2251 	ACTION_OF_DEC_NW_TTL,
2252 	ACTION_OF_POP_VLAN,
2253 	ACTION_OF_PUSH_VLAN,
2254 	ACTION_OF_SET_VLAN_VID,
2255 	ACTION_OF_SET_VLAN_PCP,
2256 	ACTION_OF_POP_MPLS,
2257 	ACTION_OF_PUSH_MPLS,
2258 	ACTION_VXLAN_ENCAP,
2259 	ACTION_VXLAN_DECAP,
2260 	ACTION_NVGRE_ENCAP,
2261 	ACTION_NVGRE_DECAP,
2262 	ACTION_L2_ENCAP,
2263 	ACTION_L2_DECAP,
2264 	ACTION_MPLSOGRE_ENCAP,
2265 	ACTION_MPLSOGRE_DECAP,
2266 	ACTION_MPLSOUDP_ENCAP,
2267 	ACTION_MPLSOUDP_DECAP,
2268 	ACTION_SET_IPV4_SRC,
2269 	ACTION_SET_IPV4_DST,
2270 	ACTION_SET_IPV6_SRC,
2271 	ACTION_SET_IPV6_DST,
2272 	ACTION_SET_TP_SRC,
2273 	ACTION_SET_TP_DST,
2274 	ACTION_MAC_SWAP,
2275 	ACTION_DEC_TTL,
2276 	ACTION_SET_TTL,
2277 	ACTION_SET_MAC_SRC,
2278 	ACTION_SET_MAC_DST,
2279 	ACTION_INC_TCP_SEQ,
2280 	ACTION_DEC_TCP_SEQ,
2281 	ACTION_INC_TCP_ACK,
2282 	ACTION_DEC_TCP_ACK,
2283 	ACTION_RAW_ENCAP,
2284 	ACTION_RAW_DECAP,
2285 	ACTION_SET_TAG,
2286 	ACTION_SET_META,
2287 	ACTION_SET_IPV4_DSCP,
2288 	ACTION_SET_IPV6_DSCP,
2289 	ACTION_AGE,
2290 	ACTION_AGE_UPDATE,
2291 	ACTION_SAMPLE,
2292 	ACTION_INDIRECT,
2293 	ACTION_INDIRECT_LIST,
2294 	ACTION_SHARED_INDIRECT,
2295 	ACTION_MODIFY_FIELD,
2296 	ACTION_CONNTRACK,
2297 	ACTION_CONNTRACK_UPDATE,
2298 	ACTION_PORT_REPRESENTOR,
2299 	ACTION_REPRESENTED_PORT,
2300 	ACTION_SEND_TO_KERNEL,
2301 	ACTION_QUOTA_CREATE,
2302 	ACTION_QUOTA_QU,
2303 	ACTION_IPV6_EXT_REMOVE,
2304 	ACTION_IPV6_EXT_PUSH,
2305 	ACTION_NAT64,
2306 	ZERO,
2307 };
2308 
2309 static const enum index action_quota_create[] = {
2310 	ACTION_QUOTA_CREATE_LIMIT,
2311 	ACTION_QUOTA_CREATE_MODE,
2312 	ACTION_NEXT,
2313 	ZERO
2314 };
2315 
2316 static const enum index action_quota_update[] = {
2317 	ACTION_QUOTA_QU_LIMIT,
2318 	ACTION_QUOTA_QU_UPDATE_OP,
2319 	ACTION_NEXT,
2320 	ZERO
2321 };
2322 
2323 static const enum index action_mark[] = {
2324 	ACTION_MARK_ID,
2325 	ACTION_NEXT,
2326 	ZERO,
2327 };
2328 
2329 static const enum index action_queue[] = {
2330 	ACTION_QUEUE_INDEX,
2331 	ACTION_NEXT,
2332 	ZERO,
2333 };
2334 
2335 static const enum index action_count[] = {
2336 	ACTION_COUNT_ID,
2337 	ACTION_NEXT,
2338 	ZERO,
2339 };
2340 
2341 static const enum index action_rss[] = {
2342 	ACTION_RSS_FUNC,
2343 	ACTION_RSS_LEVEL,
2344 	ACTION_RSS_TYPES,
2345 	ACTION_RSS_KEY,
2346 	ACTION_RSS_KEY_LEN,
2347 	ACTION_RSS_QUEUES,
2348 	ACTION_NEXT,
2349 	ZERO,
2350 };
2351 
2352 static const enum index action_vf[] = {
2353 	ACTION_VF_ORIGINAL,
2354 	ACTION_VF_ID,
2355 	ACTION_NEXT,
2356 	ZERO,
2357 };
2358 
2359 static const enum index action_port_id[] = {
2360 	ACTION_PORT_ID_ORIGINAL,
2361 	ACTION_PORT_ID_ID,
2362 	ACTION_NEXT,
2363 	ZERO,
2364 };
2365 
2366 static const enum index action_meter[] = {
2367 	ACTION_METER_ID,
2368 	ACTION_NEXT,
2369 	ZERO,
2370 };
2371 
2372 static const enum index action_meter_color[] = {
2373 	ACTION_METER_COLOR_TYPE,
2374 	ACTION_NEXT,
2375 	ZERO,
2376 };
2377 
2378 static const enum index action_meter_mark[] = {
2379 	ACTION_METER_PROFILE,
2380 	ACTION_METER_POLICY,
2381 	ACTION_METER_COLOR_MODE,
2382 	ACTION_METER_STATE,
2383 	ACTION_NEXT,
2384 	ZERO,
2385 };
2386 
2387 static const enum index action_of_push_vlan[] = {
2388 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
2389 	ACTION_NEXT,
2390 	ZERO,
2391 };
2392 
2393 static const enum index action_of_set_vlan_vid[] = {
2394 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
2395 	ACTION_NEXT,
2396 	ZERO,
2397 };
2398 
2399 static const enum index action_of_set_vlan_pcp[] = {
2400 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
2401 	ACTION_NEXT,
2402 	ZERO,
2403 };
2404 
2405 static const enum index action_of_pop_mpls[] = {
2406 	ACTION_OF_POP_MPLS_ETHERTYPE,
2407 	ACTION_NEXT,
2408 	ZERO,
2409 };
2410 
2411 static const enum index action_of_push_mpls[] = {
2412 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
2413 	ACTION_NEXT,
2414 	ZERO,
2415 };
2416 
2417 static const enum index action_set_ipv4_src[] = {
2418 	ACTION_SET_IPV4_SRC_IPV4_SRC,
2419 	ACTION_NEXT,
2420 	ZERO,
2421 };
2422 
2423 static const enum index action_set_mac_src[] = {
2424 	ACTION_SET_MAC_SRC_MAC_SRC,
2425 	ACTION_NEXT,
2426 	ZERO,
2427 };
2428 
2429 static const enum index action_set_ipv4_dst[] = {
2430 	ACTION_SET_IPV4_DST_IPV4_DST,
2431 	ACTION_NEXT,
2432 	ZERO,
2433 };
2434 
2435 static const enum index action_set_ipv6_src[] = {
2436 	ACTION_SET_IPV6_SRC_IPV6_SRC,
2437 	ACTION_NEXT,
2438 	ZERO,
2439 };
2440 
2441 static const enum index action_set_ipv6_dst[] = {
2442 	ACTION_SET_IPV6_DST_IPV6_DST,
2443 	ACTION_NEXT,
2444 	ZERO,
2445 };
2446 
2447 static const enum index action_set_tp_src[] = {
2448 	ACTION_SET_TP_SRC_TP_SRC,
2449 	ACTION_NEXT,
2450 	ZERO,
2451 };
2452 
2453 static const enum index action_set_tp_dst[] = {
2454 	ACTION_SET_TP_DST_TP_DST,
2455 	ACTION_NEXT,
2456 	ZERO,
2457 };
2458 
2459 static const enum index action_set_ttl[] = {
2460 	ACTION_SET_TTL_TTL,
2461 	ACTION_NEXT,
2462 	ZERO,
2463 };
2464 
2465 static const enum index action_jump[] = {
2466 	ACTION_JUMP_GROUP,
2467 	ACTION_NEXT,
2468 	ZERO,
2469 };
2470 
2471 static const enum index action_set_mac_dst[] = {
2472 	ACTION_SET_MAC_DST_MAC_DST,
2473 	ACTION_NEXT,
2474 	ZERO,
2475 };
2476 
2477 static const enum index action_inc_tcp_seq[] = {
2478 	ACTION_INC_TCP_SEQ_VALUE,
2479 	ACTION_NEXT,
2480 	ZERO,
2481 };
2482 
2483 static const enum index action_dec_tcp_seq[] = {
2484 	ACTION_DEC_TCP_SEQ_VALUE,
2485 	ACTION_NEXT,
2486 	ZERO,
2487 };
2488 
2489 static const enum index action_inc_tcp_ack[] = {
2490 	ACTION_INC_TCP_ACK_VALUE,
2491 	ACTION_NEXT,
2492 	ZERO,
2493 };
2494 
2495 static const enum index action_dec_tcp_ack[] = {
2496 	ACTION_DEC_TCP_ACK_VALUE,
2497 	ACTION_NEXT,
2498 	ZERO,
2499 };
2500 
2501 static const enum index action_raw_encap[] = {
2502 	ACTION_RAW_ENCAP_SIZE,
2503 	ACTION_RAW_ENCAP_INDEX,
2504 	ACTION_NEXT,
2505 	ZERO,
2506 };
2507 
2508 static const enum index action_raw_decap[] = {
2509 	ACTION_RAW_DECAP_INDEX,
2510 	ACTION_NEXT,
2511 	ZERO,
2512 };
2513 
2514 static const enum index action_ipv6_ext_remove[] = {
2515 	ACTION_IPV6_EXT_REMOVE_INDEX,
2516 	ACTION_NEXT,
2517 	ZERO,
2518 };
2519 
2520 static const enum index action_ipv6_ext_push[] = {
2521 	ACTION_IPV6_EXT_PUSH_INDEX,
2522 	ACTION_NEXT,
2523 	ZERO,
2524 };
2525 
2526 static const enum index action_set_tag[] = {
2527 	ACTION_SET_TAG_DATA,
2528 	ACTION_SET_TAG_INDEX,
2529 	ACTION_SET_TAG_MASK,
2530 	ACTION_NEXT,
2531 	ZERO,
2532 };
2533 
2534 static const enum index action_set_meta[] = {
2535 	ACTION_SET_META_DATA,
2536 	ACTION_SET_META_MASK,
2537 	ACTION_NEXT,
2538 	ZERO,
2539 };
2540 
2541 static const enum index action_set_ipv4_dscp[] = {
2542 	ACTION_SET_IPV4_DSCP_VALUE,
2543 	ACTION_NEXT,
2544 	ZERO,
2545 };
2546 
2547 static const enum index action_set_ipv6_dscp[] = {
2548 	ACTION_SET_IPV6_DSCP_VALUE,
2549 	ACTION_NEXT,
2550 	ZERO,
2551 };
2552 
2553 static const enum index action_age[] = {
2554 	ACTION_AGE,
2555 	ACTION_AGE_TIMEOUT,
2556 	ACTION_NEXT,
2557 	ZERO,
2558 };
2559 
2560 static const enum index action_age_update[] = {
2561 	ACTION_AGE_UPDATE,
2562 	ACTION_AGE_UPDATE_TIMEOUT,
2563 	ACTION_AGE_UPDATE_TOUCH,
2564 	ACTION_NEXT,
2565 	ZERO,
2566 };
2567 
2568 static const enum index action_sample[] = {
2569 	ACTION_SAMPLE,
2570 	ACTION_SAMPLE_RATIO,
2571 	ACTION_SAMPLE_INDEX,
2572 	ACTION_NEXT,
2573 	ZERO,
2574 };
2575 
2576 static const enum index next_action_sample[] = {
2577 	ACTION_QUEUE,
2578 	ACTION_RSS,
2579 	ACTION_MARK,
2580 	ACTION_COUNT,
2581 	ACTION_PORT_ID,
2582 	ACTION_RAW_ENCAP,
2583 	ACTION_VXLAN_ENCAP,
2584 	ACTION_NVGRE_ENCAP,
2585 	ACTION_REPRESENTED_PORT,
2586 	ACTION_PORT_REPRESENTOR,
2587 	ACTION_NEXT,
2588 	ZERO,
2589 };
2590 
2591 static const enum index item_ipv6_push_ext[] = {
2592 	ITEM_IPV6_PUSH_REMOVE_EXT,
2593 	ZERO,
2594 };
2595 
2596 static const enum index item_ipv6_push_ext_type[] = {
2597 	ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
2598 	ZERO,
2599 };
2600 
2601 static const enum index item_ipv6_push_ext_header[] = {
2602 	ITEM_IPV6_ROUTING_EXT,
2603 	ITEM_NEXT,
2604 	ZERO,
2605 };
2606 
2607 static const enum index action_modify_field_dst[] = {
2608 	ACTION_MODIFY_FIELD_DST_LEVEL,
2609 	ACTION_MODIFY_FIELD_DST_TAG_INDEX,
2610 	ACTION_MODIFY_FIELD_DST_TYPE_ID,
2611 	ACTION_MODIFY_FIELD_DST_CLASS_ID,
2612 	ACTION_MODIFY_FIELD_DST_OFFSET,
2613 	ACTION_MODIFY_FIELD_SRC_TYPE,
2614 	ZERO,
2615 };
2616 
2617 static const enum index action_modify_field_src[] = {
2618 	ACTION_MODIFY_FIELD_SRC_LEVEL,
2619 	ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
2620 	ACTION_MODIFY_FIELD_SRC_TYPE_ID,
2621 	ACTION_MODIFY_FIELD_SRC_CLASS_ID,
2622 	ACTION_MODIFY_FIELD_SRC_OFFSET,
2623 	ACTION_MODIFY_FIELD_SRC_VALUE,
2624 	ACTION_MODIFY_FIELD_SRC_POINTER,
2625 	ACTION_MODIFY_FIELD_WIDTH,
2626 	ZERO,
2627 };
2628 
2629 static const enum index action_update_conntrack[] = {
2630 	ACTION_CONNTRACK_UPDATE_DIR,
2631 	ACTION_CONNTRACK_UPDATE_CTX,
2632 	ACTION_NEXT,
2633 	ZERO,
2634 };
2635 
2636 static const enum index action_port_representor[] = {
2637 	ACTION_PORT_REPRESENTOR_PORT_ID,
2638 	ACTION_NEXT,
2639 	ZERO,
2640 };
2641 
2642 static const enum index action_represented_port[] = {
2643 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
2644 	ACTION_NEXT,
2645 	ZERO,
2646 };
2647 
2648 static const enum index action_nat64[] = {
2649 	ACTION_NAT64_MODE,
2650 	ACTION_NEXT,
2651 	ZERO,
2652 };
2653 
2654 static const enum index next_hash_subcmd[] = {
2655 	HASH_CALC_TABLE,
2656 	HASH_CALC_ENCAP,
2657 	ZERO,
2658 };
2659 
2660 static const enum index next_hash_encap_dest_subcmd[] = {
2661 	ENCAP_HASH_FIELD_SRC_PORT,
2662 	ENCAP_HASH_FIELD_GRE_FLOW_ID,
2663 	ZERO,
2664 };
2665 
2666 static int parse_set_raw_encap_decap(struct context *, const struct token *,
2667 				     const char *, unsigned int,
2668 				     void *, unsigned int);
2669 static int parse_set_sample_action(struct context *, const struct token *,
2670 				   const char *, unsigned int,
2671 				   void *, unsigned int);
2672 static int parse_set_ipv6_ext_action(struct context *, const struct token *,
2673 				     const char *, unsigned int,
2674 				     void *, unsigned int);
2675 static int parse_set_init(struct context *, const struct token *,
2676 			  const char *, unsigned int,
2677 			  void *, unsigned int);
2678 static int
2679 parse_flex_handle(struct context *, const struct token *,
2680 		  const char *, unsigned int, void *, unsigned int);
2681 static int parse_init(struct context *, const struct token *,
2682 		      const char *, unsigned int,
2683 		      void *, unsigned int);
2684 static int parse_vc(struct context *, const struct token *,
2685 		    const char *, unsigned int,
2686 		    void *, unsigned int);
2687 static int parse_vc_spec(struct context *, const struct token *,
2688 			 const char *, unsigned int, void *, unsigned int);
2689 static int parse_vc_conf(struct context *, const struct token *,
2690 			 const char *, unsigned int, void *, unsigned int);
2691 static int parse_vc_conf_timeout(struct context *, const struct token *,
2692 				 const char *, unsigned int, void *,
2693 				 unsigned int);
2694 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
2695 				    const char *, unsigned int,
2696 				    void *, unsigned int);
2697 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *,
2698 				    const char *, unsigned int,
2699 				    void *, unsigned int);
2700 static int parse_vc_action_meter_color_type(struct context *,
2701 					const struct token *,
2702 					const char *, unsigned int, void *,
2703 					unsigned int);
2704 static int parse_vc_action_rss(struct context *, const struct token *,
2705 			       const char *, unsigned int, void *,
2706 			       unsigned int);
2707 static int parse_vc_action_rss_func(struct context *, const struct token *,
2708 				    const char *, unsigned int, void *,
2709 				    unsigned int);
2710 static int parse_vc_action_rss_type(struct context *, const struct token *,
2711 				    const char *, unsigned int, void *,
2712 				    unsigned int);
2713 static int parse_vc_action_rss_queue(struct context *, const struct token *,
2714 				     const char *, unsigned int, void *,
2715 				     unsigned int);
2716 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
2717 				       const char *, unsigned int, void *,
2718 				       unsigned int);
2719 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
2720 				       const char *, unsigned int, void *,
2721 				       unsigned int);
2722 static int parse_vc_action_l2_encap(struct context *, const struct token *,
2723 				    const char *, unsigned int, void *,
2724 				    unsigned int);
2725 static int parse_vc_action_l2_decap(struct context *, const struct token *,
2726 				    const char *, unsigned int, void *,
2727 				    unsigned int);
2728 static int parse_vc_action_mplsogre_encap(struct context *,
2729 					  const struct token *, const char *,
2730 					  unsigned int, void *, unsigned int);
2731 static int parse_vc_action_mplsogre_decap(struct context *,
2732 					  const struct token *, const char *,
2733 					  unsigned int, void *, unsigned int);
2734 static int parse_vc_action_mplsoudp_encap(struct context *,
2735 					  const struct token *, const char *,
2736 					  unsigned int, void *, unsigned int);
2737 static int parse_vc_action_mplsoudp_decap(struct context *,
2738 					  const struct token *, const char *,
2739 					  unsigned int, void *, unsigned int);
2740 static int parse_vc_action_raw_encap(struct context *,
2741 				     const struct token *, const char *,
2742 				     unsigned int, void *, unsigned int);
2743 static int parse_vc_action_raw_decap(struct context *,
2744 				     const struct token *, const char *,
2745 				     unsigned int, void *, unsigned int);
2746 static int parse_vc_action_raw_encap_index(struct context *,
2747 					   const struct token *, const char *,
2748 					   unsigned int, void *, unsigned int);
2749 static int parse_vc_action_raw_decap_index(struct context *,
2750 					   const struct token *, const char *,
2751 					   unsigned int, void *, unsigned int);
2752 static int parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
2753 					   const char *str, unsigned int len, void *buf,
2754 					   unsigned int size);
2755 static int parse_vc_action_ipv6_ext_remove_index(struct context *ctx,
2756 						 const struct token *token,
2757 						 const char *str, unsigned int len,
2758 						 void *buf,
2759 						 unsigned int size);
2760 static int parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
2761 					 const char *str, unsigned int len, void *buf,
2762 					 unsigned int size);
2763 static int parse_vc_action_ipv6_ext_push_index(struct context *ctx,
2764 					       const struct token *token,
2765 					       const char *str, unsigned int len,
2766 					       void *buf,
2767 					       unsigned int size);
2768 static int parse_vc_action_set_meta(struct context *ctx,
2769 				    const struct token *token, const char *str,
2770 				    unsigned int len, void *buf,
2771 					unsigned int size);
2772 static int parse_vc_action_sample(struct context *ctx,
2773 				    const struct token *token, const char *str,
2774 				    unsigned int len, void *buf,
2775 				    unsigned int size);
2776 static int
2777 parse_vc_action_sample_index(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_modify_field_op(struct context *ctx, const struct token *token,
2782 				const char *str, unsigned int len, void *buf,
2783 				unsigned int size);
2784 static int
2785 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
2786 				const char *str, unsigned int len, void *buf,
2787 				unsigned int size);
2788 static int
2789 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
2790 				const char *str, unsigned int len, void *buf,
2791 				unsigned int size);
2792 static int
2793 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
2794 			 const char *str, unsigned int len, void *buf,
2795 			 unsigned int size);
2796 static int parse_destroy(struct context *, const struct token *,
2797 			 const char *, unsigned int,
2798 			 void *, unsigned int);
2799 static int parse_flush(struct context *, const struct token *,
2800 		       const char *, unsigned int,
2801 		       void *, unsigned int);
2802 static int parse_dump(struct context *, const struct token *,
2803 		      const char *, unsigned int,
2804 		      void *, unsigned int);
2805 static int parse_query(struct context *, const struct token *,
2806 		       const char *, unsigned int,
2807 		       void *, unsigned int);
2808 static int parse_action(struct context *, const struct token *,
2809 			const char *, unsigned int,
2810 			void *, unsigned int);
2811 static int parse_list(struct context *, const struct token *,
2812 		      const char *, unsigned int,
2813 		      void *, unsigned int);
2814 static int parse_aged(struct context *, const struct token *,
2815 		      const char *, unsigned int,
2816 		      void *, unsigned int);
2817 static int parse_isolate(struct context *, const struct token *,
2818 			 const char *, unsigned int,
2819 			 void *, unsigned int);
2820 static int parse_configure(struct context *, const struct token *,
2821 			   const char *, unsigned int,
2822 			   void *, unsigned int);
2823 static int parse_template(struct context *, const struct token *,
2824 			  const char *, unsigned int,
2825 			  void *, unsigned int);
2826 static int parse_template_destroy(struct context *, const struct token *,
2827 				  const char *, unsigned int,
2828 				  void *, unsigned int);
2829 static int parse_table(struct context *, const struct token *,
2830 		       const char *, unsigned int, void *, unsigned int);
2831 static int parse_table_destroy(struct context *, const struct token *,
2832 			       const char *, unsigned int,
2833 			       void *, unsigned int);
2834 static int parse_qo(struct context *, const struct token *,
2835 		    const char *, unsigned int,
2836 		    void *, unsigned int);
2837 static int parse_qo_destroy(struct context *, const struct token *,
2838 			    const char *, unsigned int,
2839 			    void *, unsigned int);
2840 static int parse_qia(struct context *, const struct token *,
2841 		     const char *, unsigned int,
2842 		     void *, unsigned int);
2843 static int parse_qia_destroy(struct context *, const struct token *,
2844 			     const char *, unsigned int,
2845 			     void *, unsigned int);
2846 static int parse_push(struct context *, const struct token *,
2847 		      const char *, unsigned int,
2848 		      void *, unsigned int);
2849 static int parse_pull(struct context *, const struct token *,
2850 		      const char *, unsigned int,
2851 		      void *, unsigned int);
2852 static int parse_group(struct context *, const struct token *,
2853 		       const char *, unsigned int,
2854 		       void *, unsigned int);
2855 static int parse_hash(struct context *, const struct token *,
2856 		      const char *, unsigned int,
2857 		      void *, unsigned int);
2858 static int parse_tunnel(struct context *, const struct token *,
2859 			const char *, unsigned int,
2860 			void *, unsigned int);
2861 static int parse_flex(struct context *, const struct token *,
2862 		      const char *, unsigned int, void *, unsigned int);
2863 static int parse_int(struct context *, const struct token *,
2864 		     const char *, unsigned int,
2865 		     void *, unsigned int);
2866 static int parse_prefix(struct context *, const struct token *,
2867 			const char *, unsigned int,
2868 			void *, unsigned int);
2869 static int parse_boolean(struct context *, const struct token *,
2870 			 const char *, unsigned int,
2871 			 void *, unsigned int);
2872 static int parse_string(struct context *, const struct token *,
2873 			const char *, unsigned int,
2874 			void *, unsigned int);
2875 static int parse_hex(struct context *ctx, const struct token *token,
2876 			const char *str, unsigned int len,
2877 			void *buf, unsigned int size);
2878 static int parse_string0(struct context *, const struct token *,
2879 			const char *, unsigned int,
2880 			void *, unsigned int);
2881 static int parse_mac_addr(struct context *, const struct token *,
2882 			  const char *, unsigned int,
2883 			  void *, unsigned int);
2884 static int parse_ipv4_addr(struct context *, const struct token *,
2885 			   const char *, unsigned int,
2886 			   void *, unsigned int);
2887 static int parse_ipv6_addr(struct context *, const struct token *,
2888 			   const char *, unsigned int,
2889 			   void *, unsigned int);
2890 static int parse_port(struct context *, const struct token *,
2891 		      const char *, unsigned int,
2892 		      void *, unsigned int);
2893 static int parse_ia(struct context *, const struct token *,
2894 		    const char *, unsigned int,
2895 		    void *, unsigned int);
2896 static int parse_ia_destroy(struct context *ctx, const struct token *token,
2897 			    const char *str, unsigned int len,
2898 			    void *buf, unsigned int size);
2899 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
2900 			   const char *str, unsigned int len, void *buf,
2901 			   unsigned int size);
2902 
2903 static int parse_indlst_id2ptr(struct context *ctx, const struct token *token,
2904 			       const char *str, unsigned int len, void *buf,
2905 			       unsigned int size);
2906 static int parse_ia_port(struct context *ctx, const struct token *token,
2907 			 const char *str, unsigned int len, void *buf,
2908 			 unsigned int size);
2909 static int parse_mp(struct context *, const struct token *,
2910 		    const char *, unsigned int,
2911 		    void *, unsigned int);
2912 static int parse_meter_profile_id2ptr(struct context *ctx,
2913 				      const struct token *token,
2914 				      const char *str, unsigned int len,
2915 				      void *buf, unsigned int size);
2916 static int parse_meter_policy_id2ptr(struct context *ctx,
2917 				     const struct token *token,
2918 				     const char *str, unsigned int len,
2919 				     void *buf, unsigned int size);
2920 static int parse_meter_color(struct context *ctx, const struct token *token,
2921 			     const char *str, unsigned int len, void *buf,
2922 			     unsigned int size);
2923 static int parse_insertion_table_type(struct context *ctx, const struct token *token,
2924 				      const char *str, unsigned int len, void *buf,
2925 				      unsigned int size);
2926 static int parse_hash_table_type(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_quota_state_name(struct context *ctx, const struct token *token,
2931 		       const char *str, unsigned int len, void *buf,
2932 		       unsigned int size);
2933 static int
2934 parse_quota_mode_name(struct context *ctx, const struct token *token,
2935 		      const char *str, unsigned int len, void *buf,
2936 		      unsigned int size);
2937 static int
2938 parse_quota_update_name(struct context *ctx, const struct token *token,
2939 			const char *str, unsigned int len, void *buf,
2940 			unsigned int size);
2941 static int
2942 parse_qu_mode_name(struct context *ctx, const struct token *token,
2943 		   const char *str, unsigned int len, void *buf,
2944 		   unsigned int size);
2945 static int comp_none(struct context *, const struct token *,
2946 		     unsigned int, char *, unsigned int);
2947 static int comp_boolean(struct context *, const struct token *,
2948 			unsigned int, char *, unsigned int);
2949 static int comp_action(struct context *, const struct token *,
2950 		       unsigned int, char *, unsigned int);
2951 static int comp_port(struct context *, const struct token *,
2952 		     unsigned int, char *, unsigned int);
2953 static int comp_rule_id(struct context *, const struct token *,
2954 			unsigned int, char *, unsigned int);
2955 static int comp_vc_action_rss_type(struct context *, const struct token *,
2956 				   unsigned int, char *, unsigned int);
2957 static int comp_vc_action_rss_queue(struct context *, const struct token *,
2958 				    unsigned int, char *, unsigned int);
2959 static int comp_set_raw_index(struct context *, const struct token *,
2960 			      unsigned int, char *, unsigned int);
2961 static int comp_set_sample_index(struct context *, const struct token *,
2962 			      unsigned int, char *, unsigned int);
2963 static int comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
2964 				   unsigned int ent, char *buf, unsigned int size);
2965 static int comp_set_modify_field_op(struct context *, const struct token *,
2966 			      unsigned int, char *, unsigned int);
2967 static int comp_set_modify_field_id(struct context *, const struct token *,
2968 			      unsigned int, char *, unsigned int);
2969 static int comp_pattern_template_id(struct context *, const struct token *,
2970 				    unsigned int, char *, unsigned int);
2971 static int comp_actions_template_id(struct context *, const struct token *,
2972 				    unsigned int, char *, unsigned int);
2973 static int comp_table_id(struct context *, const struct token *,
2974 			 unsigned int, char *, unsigned int);
2975 static int comp_queue_id(struct context *, const struct token *,
2976 			 unsigned int, char *, unsigned int);
2977 static int comp_meter_color(struct context *, const struct token *,
2978 			    unsigned int, char *, unsigned int);
2979 static int comp_insertion_table_type(struct context *, const struct token *,
2980 				     unsigned int, char *, unsigned int);
2981 static int comp_hash_table_type(struct context *, const struct token *,
2982 				unsigned int, char *, unsigned int);
2983 static int
2984 comp_quota_state_name(struct context *ctx, const struct token *token,
2985 		      unsigned int ent, char *buf, unsigned int size);
2986 static int
2987 comp_quota_mode_name(struct context *ctx, const struct token *token,
2988 		     unsigned int ent, char *buf, unsigned int size);
2989 static int
2990 comp_quota_update_name(struct context *ctx, const struct token *token,
2991 		       unsigned int ent, char *buf, unsigned int size);
2992 static int
2993 comp_qu_mode_name(struct context *ctx, const struct token *token,
2994 		  unsigned int ent, char *buf, unsigned int size);
2995 static int
2996 comp_set_compare_field_id(struct context *ctx, const struct token *token,
2997 			  unsigned int ent, char *buf, unsigned int size);
2998 static int
2999 comp_set_compare_op(struct context *ctx, const struct token *token,
3000 		    unsigned int ent, char *buf, unsigned int size);
3001 static int
3002 parse_vc_compare_op(struct context *ctx, const struct token *token,
3003 			 const char *str, unsigned int len, void *buf,
3004 			 unsigned int size);
3005 static int
3006 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
3007 			  const char *str, unsigned int len, void *buf,
3008 			  unsigned int size);
3009 static int
3010 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
3011 			     const char *str, unsigned int len, void *buf,
3012 			     unsigned int size);
3013 
3014 struct indlst_conf {
3015 	uint32_t id;
3016 	uint32_t conf_num;
3017 	struct rte_flow_action *actions;
3018 	const void **conf;
3019 	SLIST_ENTRY(indlst_conf) next;
3020 };
3021 
3022 static const struct indlst_conf *indirect_action_list_conf_get(uint32_t conf_id);
3023 
3024 /** Token definitions. */
3025 static const struct token token_list[] = {
3026 	/* Special tokens. */
3027 	[ZERO] = {
3028 		.name = "ZERO",
3029 		.help = "null entry, abused as the entry point",
3030 		.next = NEXT(NEXT_ENTRY(FLOW, ADD)),
3031 	},
3032 	[END] = {
3033 		.name = "",
3034 		.type = "RETURN",
3035 		.help = "command may end here",
3036 	},
3037 	[START_SET] = {
3038 		.name = "START_SET",
3039 		.help = "null entry, abused as the entry point for set",
3040 		.next = NEXT(NEXT_ENTRY(SET)),
3041 	},
3042 	[END_SET] = {
3043 		.name = "end_set",
3044 		.type = "RETURN",
3045 		.help = "set command may end here",
3046 	},
3047 	/* Common tokens. */
3048 	[COMMON_INTEGER] = {
3049 		.name = "{int}",
3050 		.type = "INTEGER",
3051 		.help = "integer value",
3052 		.call = parse_int,
3053 		.comp = comp_none,
3054 	},
3055 	[COMMON_UNSIGNED] = {
3056 		.name = "{unsigned}",
3057 		.type = "UNSIGNED",
3058 		.help = "unsigned integer value",
3059 		.call = parse_int,
3060 		.comp = comp_none,
3061 	},
3062 	[COMMON_PREFIX] = {
3063 		.name = "{prefix}",
3064 		.type = "PREFIX",
3065 		.help = "prefix length for bit-mask",
3066 		.call = parse_prefix,
3067 		.comp = comp_none,
3068 	},
3069 	[COMMON_BOOLEAN] = {
3070 		.name = "{boolean}",
3071 		.type = "BOOLEAN",
3072 		.help = "any boolean value",
3073 		.call = parse_boolean,
3074 		.comp = comp_boolean,
3075 	},
3076 	[COMMON_STRING] = {
3077 		.name = "{string}",
3078 		.type = "STRING",
3079 		.help = "fixed string",
3080 		.call = parse_string,
3081 		.comp = comp_none,
3082 	},
3083 	[COMMON_HEX] = {
3084 		.name = "{hex}",
3085 		.type = "HEX",
3086 		.help = "fixed string",
3087 		.call = parse_hex,
3088 	},
3089 	[COMMON_FILE_PATH] = {
3090 		.name = "{file path}",
3091 		.type = "STRING",
3092 		.help = "file path",
3093 		.call = parse_string0,
3094 		.comp = comp_none,
3095 	},
3096 	[COMMON_MAC_ADDR] = {
3097 		.name = "{MAC address}",
3098 		.type = "MAC-48",
3099 		.help = "standard MAC address notation",
3100 		.call = parse_mac_addr,
3101 		.comp = comp_none,
3102 	},
3103 	[COMMON_IPV4_ADDR] = {
3104 		.name = "{IPv4 address}",
3105 		.type = "IPV4 ADDRESS",
3106 		.help = "standard IPv4 address notation",
3107 		.call = parse_ipv4_addr,
3108 		.comp = comp_none,
3109 	},
3110 	[COMMON_IPV6_ADDR] = {
3111 		.name = "{IPv6 address}",
3112 		.type = "IPV6 ADDRESS",
3113 		.help = "standard IPv6 address notation",
3114 		.call = parse_ipv6_addr,
3115 		.comp = comp_none,
3116 	},
3117 	[COMMON_RULE_ID] = {
3118 		.name = "{rule id}",
3119 		.type = "RULE ID",
3120 		.help = "rule identifier",
3121 		.call = parse_int,
3122 		.comp = comp_rule_id,
3123 	},
3124 	[COMMON_PORT_ID] = {
3125 		.name = "{port_id}",
3126 		.type = "PORT ID",
3127 		.help = "port identifier",
3128 		.call = parse_port,
3129 		.comp = comp_port,
3130 	},
3131 	[COMMON_GROUP_ID] = {
3132 		.name = "{group_id}",
3133 		.type = "GROUP ID",
3134 		.help = "group identifier",
3135 		.call = parse_int,
3136 		.comp = comp_none,
3137 	},
3138 	[COMMON_PRIORITY_LEVEL] = {
3139 		.name = "{level}",
3140 		.type = "PRIORITY",
3141 		.help = "priority level",
3142 		.call = parse_int,
3143 		.comp = comp_none,
3144 	},
3145 	[COMMON_INDIRECT_ACTION_ID] = {
3146 		.name = "{indirect_action_id}",
3147 		.type = "INDIRECT_ACTION_ID",
3148 		.help = "indirect action id",
3149 		.call = parse_int,
3150 		.comp = comp_none,
3151 	},
3152 	[COMMON_PROFILE_ID] = {
3153 		.name = "{profile_id}",
3154 		.type = "PROFILE_ID",
3155 		.help = "profile id",
3156 		.call = parse_int,
3157 		.comp = comp_none,
3158 	},
3159 	[COMMON_POLICY_ID] = {
3160 		.name = "{policy_id}",
3161 		.type = "POLICY_ID",
3162 		.help = "policy id",
3163 		.call = parse_int,
3164 		.comp = comp_none,
3165 	},
3166 	[COMMON_FLEX_TOKEN] = {
3167 		.name = "{flex token}",
3168 		.type = "flex token",
3169 		.help = "flex token",
3170 		.call = parse_int,
3171 		.comp = comp_none,
3172 	},
3173 	[COMMON_FLEX_HANDLE] = {
3174 		.name = "{flex handle}",
3175 		.type = "FLEX HANDLE",
3176 		.help = "fill flex item data",
3177 		.call = parse_flex_handle,
3178 		.comp = comp_none,
3179 	},
3180 	[COMMON_PATTERN_TEMPLATE_ID] = {
3181 		.name = "{pattern_template_id}",
3182 		.type = "PATTERN_TEMPLATE_ID",
3183 		.help = "pattern template id",
3184 		.call = parse_int,
3185 		.comp = comp_pattern_template_id,
3186 	},
3187 	[COMMON_ACTIONS_TEMPLATE_ID] = {
3188 		.name = "{actions_template_id}",
3189 		.type = "ACTIONS_TEMPLATE_ID",
3190 		.help = "actions template id",
3191 		.call = parse_int,
3192 		.comp = comp_actions_template_id,
3193 	},
3194 	[COMMON_TABLE_ID] = {
3195 		.name = "{table_id}",
3196 		.type = "TABLE_ID",
3197 		.help = "table id",
3198 		.call = parse_int,
3199 		.comp = comp_table_id,
3200 	},
3201 	[COMMON_QUEUE_ID] = {
3202 		.name = "{queue_id}",
3203 		.type = "QUEUE_ID",
3204 		.help = "queue id",
3205 		.call = parse_int,
3206 		.comp = comp_queue_id,
3207 	},
3208 	/* Top-level command. */
3209 	[FLOW] = {
3210 		.name = "flow",
3211 		.type = "{command} {port_id} [{arg} [...]]",
3212 		.help = "manage ingress/egress flow rules",
3213 		.next = NEXT(NEXT_ENTRY
3214 			     (INFO,
3215 			      CONFIGURE,
3216 			      PATTERN_TEMPLATE,
3217 			      ACTIONS_TEMPLATE,
3218 			      TABLE,
3219 			      FLOW_GROUP,
3220 			      INDIRECT_ACTION,
3221 			      VALIDATE,
3222 			      CREATE,
3223 			      DESTROY,
3224 			      UPDATE,
3225 			      FLUSH,
3226 			      DUMP,
3227 			      LIST,
3228 			      AGED,
3229 			      QUERY,
3230 			      ISOLATE,
3231 			      TUNNEL,
3232 			      FLEX,
3233 			      QUEUE,
3234 			      PUSH,
3235 			      PULL,
3236 			      HASH)),
3237 		.call = parse_init,
3238 	},
3239 	/* Top-level command. */
3240 	[INFO] = {
3241 		.name = "info",
3242 		.help = "get information about flow engine",
3243 		.next = NEXT(NEXT_ENTRY(END),
3244 			     NEXT_ENTRY(COMMON_PORT_ID)),
3245 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3246 		.call = parse_configure,
3247 	},
3248 	/* Top-level command. */
3249 	[CONFIGURE] = {
3250 		.name = "configure",
3251 		.help = "configure flow engine",
3252 		.next = NEXT(next_config_attr,
3253 			     NEXT_ENTRY(COMMON_PORT_ID)),
3254 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3255 		.call = parse_configure,
3256 	},
3257 	/* Configure arguments. */
3258 	[CONFIG_QUEUES_NUMBER] = {
3259 		.name = "queues_number",
3260 		.help = "number of queues",
3261 		.next = NEXT(next_config_attr,
3262 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3263 		.args = ARGS(ARGS_ENTRY(struct buffer,
3264 					args.configure.nb_queue)),
3265 	},
3266 	[CONFIG_QUEUES_SIZE] = {
3267 		.name = "queues_size",
3268 		.help = "number of elements in queues",
3269 		.next = NEXT(next_config_attr,
3270 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3271 		.args = ARGS(ARGS_ENTRY(struct buffer,
3272 					args.configure.queue_attr.size)),
3273 	},
3274 	[CONFIG_COUNTERS_NUMBER] = {
3275 		.name = "counters_number",
3276 		.help = "number of counters",
3277 		.next = NEXT(next_config_attr,
3278 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3279 		.args = ARGS(ARGS_ENTRY(struct buffer,
3280 					args.configure.port_attr.nb_counters)),
3281 	},
3282 	[CONFIG_AGING_OBJECTS_NUMBER] = {
3283 		.name = "aging_counters_number",
3284 		.help = "number of aging objects",
3285 		.next = NEXT(next_config_attr,
3286 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3287 		.args = ARGS(ARGS_ENTRY(struct buffer,
3288 					args.configure.port_attr.nb_aging_objects)),
3289 	},
3290 	[CONFIG_QUOTAS_NUMBER] = {
3291 		.name = "quotas_number",
3292 		.help = "number of quotas",
3293 		.next = NEXT(next_config_attr,
3294 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3295 		.args = ARGS(ARGS_ENTRY(struct buffer,
3296 				     args.configure.port_attr.nb_quotas)),
3297 	},
3298 	[CONFIG_METERS_NUMBER] = {
3299 		.name = "meters_number",
3300 		.help = "number of meters",
3301 		.next = NEXT(next_config_attr,
3302 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3303 		.args = ARGS(ARGS_ENTRY(struct buffer,
3304 					args.configure.port_attr.nb_meters)),
3305 	},
3306 	[CONFIG_CONN_TRACK_NUMBER] = {
3307 		.name = "conn_tracks_number",
3308 		.help = "number of connection trackings",
3309 		.next = NEXT(next_config_attr,
3310 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3311 		.args = ARGS(ARGS_ENTRY(struct buffer,
3312 					args.configure.port_attr.nb_conn_tracks)),
3313 	},
3314 	[CONFIG_FLAGS] = {
3315 		.name = "flags",
3316 		.help = "configuration flags",
3317 		.next = NEXT(next_config_attr,
3318 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3319 		.args = ARGS(ARGS_ENTRY(struct buffer,
3320 					args.configure.port_attr.flags)),
3321 	},
3322 	[CONFIG_HOST_PORT] = {
3323 		.name = "host_port",
3324 		.help = "host port for shared objects",
3325 		.next = NEXT(next_config_attr,
3326 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3327 		.args = ARGS(ARGS_ENTRY(struct buffer,
3328 					args.configure.port_attr.host_port_id)),
3329 	},
3330 	/* Top-level command. */
3331 	[PATTERN_TEMPLATE] = {
3332 		.name = "pattern_template",
3333 		.type = "{command} {port_id} [{arg} [...]]",
3334 		.help = "manage pattern templates",
3335 		.next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3336 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3337 		.call = parse_template,
3338 	},
3339 	/* Sub-level commands. */
3340 	[PATTERN_TEMPLATE_CREATE] = {
3341 		.name = "create",
3342 		.help = "create pattern template",
3343 		.next = NEXT(next_pt_attr),
3344 		.call = parse_template,
3345 	},
3346 	[PATTERN_TEMPLATE_DESTROY] = {
3347 		.name = "destroy",
3348 		.help = "destroy pattern template",
3349 		.next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)),
3350 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3351 		.call = parse_template_destroy,
3352 	},
3353 	/* Pattern template arguments. */
3354 	[PATTERN_TEMPLATE_CREATE_ID] = {
3355 		.name = "pattern_template_id",
3356 		.help = "specify a pattern template id to create",
3357 		.next = NEXT(next_pt_attr,
3358 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3359 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)),
3360 	},
3361 	[PATTERN_TEMPLATE_DESTROY_ID] = {
3362 		.name = "pattern_template",
3363 		.help = "specify a pattern template id to destroy",
3364 		.next = NEXT(next_pt_destroy_attr,
3365 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3366 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3367 					    args.templ_destroy.template_id)),
3368 		.call = parse_template_destroy,
3369 	},
3370 	[PATTERN_TEMPLATE_RELAXED_MATCHING] = {
3371 		.name = "relaxed",
3372 		.help = "is matching relaxed",
3373 		.next = NEXT(next_pt_attr,
3374 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3375 		.args = ARGS(ARGS_ENTRY_BF(struct buffer,
3376 			     args.vc.attr.reserved, 1)),
3377 	},
3378 	[PATTERN_TEMPLATE_INGRESS] = {
3379 		.name = "ingress",
3380 		.help = "attribute pattern to ingress",
3381 		.next = NEXT(next_pt_attr),
3382 		.call = parse_template,
3383 	},
3384 	[PATTERN_TEMPLATE_EGRESS] = {
3385 		.name = "egress",
3386 		.help = "attribute pattern to egress",
3387 		.next = NEXT(next_pt_attr),
3388 		.call = parse_template,
3389 	},
3390 	[PATTERN_TEMPLATE_TRANSFER] = {
3391 		.name = "transfer",
3392 		.help = "attribute pattern to transfer",
3393 		.next = NEXT(next_pt_attr),
3394 		.call = parse_template,
3395 	},
3396 	[PATTERN_TEMPLATE_SPEC] = {
3397 		.name = "template",
3398 		.help = "specify item to create pattern template",
3399 		.next = NEXT(next_item),
3400 	},
3401 	/* Top-level command. */
3402 	[ACTIONS_TEMPLATE] = {
3403 		.name = "actions_template",
3404 		.type = "{command} {port_id} [{arg} [...]]",
3405 		.help = "manage actions templates",
3406 		.next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3407 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3408 		.call = parse_template,
3409 	},
3410 	/* Sub-level commands. */
3411 	[ACTIONS_TEMPLATE_CREATE] = {
3412 		.name = "create",
3413 		.help = "create actions template",
3414 		.next = NEXT(next_at_attr),
3415 		.call = parse_template,
3416 	},
3417 	[ACTIONS_TEMPLATE_DESTROY] = {
3418 		.name = "destroy",
3419 		.help = "destroy actions template",
3420 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)),
3421 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3422 		.call = parse_template_destroy,
3423 	},
3424 	/* Actions template arguments. */
3425 	[ACTIONS_TEMPLATE_CREATE_ID] = {
3426 		.name = "actions_template_id",
3427 		.help = "specify an actions template id to create",
3428 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK),
3429 			     NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC),
3430 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3431 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)),
3432 	},
3433 	[ACTIONS_TEMPLATE_DESTROY_ID] = {
3434 		.name = "actions_template",
3435 		.help = "specify an actions template id to destroy",
3436 		.next = NEXT(next_at_destroy_attr,
3437 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3438 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3439 					    args.templ_destroy.template_id)),
3440 		.call = parse_template_destroy,
3441 	},
3442 	[ACTIONS_TEMPLATE_INGRESS] = {
3443 		.name = "ingress",
3444 		.help = "attribute actions to ingress",
3445 		.next = NEXT(next_at_attr),
3446 		.call = parse_template,
3447 	},
3448 	[ACTIONS_TEMPLATE_EGRESS] = {
3449 		.name = "egress",
3450 		.help = "attribute actions to egress",
3451 		.next = NEXT(next_at_attr),
3452 		.call = parse_template,
3453 	},
3454 	[ACTIONS_TEMPLATE_TRANSFER] = {
3455 		.name = "transfer",
3456 		.help = "attribute actions to transfer",
3457 		.next = NEXT(next_at_attr),
3458 		.call = parse_template,
3459 	},
3460 	[ACTIONS_TEMPLATE_SPEC] = {
3461 		.name = "template",
3462 		.help = "specify action to create actions template",
3463 		.next = NEXT(next_action),
3464 		.call = parse_template,
3465 	},
3466 	[ACTIONS_TEMPLATE_MASK] = {
3467 		.name = "mask",
3468 		.help = "specify action mask to create actions template",
3469 		.next = NEXT(next_action),
3470 		.call = parse_template,
3471 	},
3472 	/* Top-level command. */
3473 	[TABLE] = {
3474 		.name = "template_table",
3475 		.type = "{command} {port_id} [{arg} [...]]",
3476 		.help = "manage template tables",
3477 		.next = NEXT(next_table_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3478 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3479 		.call = parse_table,
3480 	},
3481 	/* Sub-level commands. */
3482 	[TABLE_CREATE] = {
3483 		.name = "create",
3484 		.help = "create template table",
3485 		.next = NEXT(next_table_attr),
3486 		.call = parse_table,
3487 	},
3488 	[TABLE_DESTROY] = {
3489 		.name = "destroy",
3490 		.help = "destroy template table",
3491 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3492 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3493 		.call = parse_table_destroy,
3494 	},
3495 	[TABLE_RESIZE] = {
3496 		.name = "resize",
3497 		.help = "resize template table",
3498 		.next = NEXT(NEXT_ENTRY(TABLE_RESIZE_ID)),
3499 		.call = parse_table
3500 	},
3501 	[TABLE_RESIZE_COMPLETE] = {
3502 		.name = "resize_complete",
3503 		.help = "complete table resize",
3504 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3505 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3506 		.call = parse_table_destroy,
3507 	},
3508 	/* Table  arguments. */
3509 	[TABLE_CREATE_ID] = {
3510 		.name = "table_id",
3511 		.help = "specify table id to create",
3512 		.next = NEXT(next_table_attr,
3513 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3514 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3515 	},
3516 	[TABLE_DESTROY_ID] = {
3517 		.name = "table",
3518 		.help = "table id",
3519 		.next = NEXT(next_table_destroy_attr,
3520 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3521 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3522 					    args.table_destroy.table_id)),
3523 		.call = parse_table_destroy,
3524 	},
3525 	[TABLE_RESIZE_ID] = {
3526 		.name = "table_resize_id",
3527 		.help = "table resize id",
3528 		.next = NEXT(NEXT_ENTRY(TABLE_RESIZE_RULES_NUMBER),
3529 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3530 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3531 		.call = parse_table
3532 	},
3533 	[TABLE_RESIZE_RULES_NUMBER] = {
3534 		.name = "table_resize_rules_num",
3535 		.help = "table resize rules number",
3536 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_UNSIGNED)),
3537 		.args = ARGS(ARGS_ENTRY(struct buffer,
3538 					args.table.attr.nb_flows)),
3539 		.call = parse_table
3540 	},
3541 	[TABLE_INSERTION_TYPE] = {
3542 		.name = "insertion_type",
3543 		.help = "specify insertion type",
3544 		.next = NEXT(next_table_attr,
3545 			     NEXT_ENTRY(TABLE_INSERTION_TYPE_NAME)),
3546 		.args = ARGS(ARGS_ENTRY(struct buffer,
3547 					args.table.attr.insertion_type)),
3548 	},
3549 	[TABLE_INSERTION_TYPE_NAME] = {
3550 		.name = "insertion_type_name",
3551 		.help = "insertion type name",
3552 		.call = parse_insertion_table_type,
3553 		.comp = comp_insertion_table_type,
3554 	},
3555 	[TABLE_HASH_FUNC] = {
3556 		.name = "hash_func",
3557 		.help = "specify hash calculation function",
3558 		.next = NEXT(next_table_attr,
3559 			     NEXT_ENTRY(TABLE_HASH_FUNC_NAME)),
3560 		.args = ARGS(ARGS_ENTRY(struct buffer,
3561 					args.table.attr.hash_func)),
3562 	},
3563 	[TABLE_HASH_FUNC_NAME] = {
3564 		.name = "hash_func_name",
3565 		.help = "hash calculation function name",
3566 		.call = parse_hash_table_type,
3567 		.comp = comp_hash_table_type,
3568 	},
3569 	[TABLE_GROUP] = {
3570 		.name = "group",
3571 		.help = "specify a group",
3572 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3573 		.args = ARGS(ARGS_ENTRY(struct buffer,
3574 					args.table.attr.flow_attr.group)),
3575 	},
3576 	[TABLE_PRIORITY] = {
3577 		.name = "priority",
3578 		.help = "specify a priority level",
3579 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
3580 		.args = ARGS(ARGS_ENTRY(struct buffer,
3581 					args.table.attr.flow_attr.priority)),
3582 	},
3583 	[TABLE_EGRESS] = {
3584 		.name = "egress",
3585 		.help = "affect rule to egress",
3586 		.next = NEXT(next_table_attr),
3587 		.call = parse_table,
3588 	},
3589 	[TABLE_INGRESS] = {
3590 		.name = "ingress",
3591 		.help = "affect rule to ingress",
3592 		.next = NEXT(next_table_attr),
3593 		.call = parse_table,
3594 	},
3595 	[TABLE_TRANSFER] = {
3596 		.name = "transfer",
3597 		.help = "affect rule to transfer",
3598 		.next = NEXT(next_table_attr),
3599 		.call = parse_table,
3600 	},
3601 	[TABLE_TRANSFER_WIRE_ORIG] = {
3602 		.name = "wire_orig",
3603 		.help = "affect rule direction to transfer",
3604 		.next = NEXT(next_table_attr),
3605 		.call = parse_table,
3606 	},
3607 	[TABLE_TRANSFER_VPORT_ORIG] = {
3608 		.name = "vport_orig",
3609 		.help = "affect rule direction to transfer",
3610 		.next = NEXT(next_table_attr),
3611 		.call = parse_table,
3612 	},
3613 	[TABLE_RESIZABLE] = {
3614 		.name = "resizable",
3615 		.help = "set resizable attribute",
3616 		.next = NEXT(next_table_attr),
3617 		.call = parse_table,
3618 	},
3619 	[TABLE_RULES_NUMBER] = {
3620 		.name = "rules_number",
3621 		.help = "number of rules in table",
3622 		.next = NEXT(next_table_attr,
3623 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3624 		.args = ARGS(ARGS_ENTRY(struct buffer,
3625 					args.table.attr.nb_flows)),
3626 		.call = parse_table,
3627 	},
3628 	[TABLE_PATTERN_TEMPLATE] = {
3629 		.name = "pattern_template",
3630 		.help = "specify pattern template id",
3631 		.next = NEXT(next_table_attr,
3632 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3633 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3634 					    args.table.pat_templ_id)),
3635 		.call = parse_table,
3636 	},
3637 	[TABLE_ACTIONS_TEMPLATE] = {
3638 		.name = "actions_template",
3639 		.help = "specify actions template id",
3640 		.next = NEXT(next_table_attr,
3641 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3642 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3643 					    args.table.act_templ_id)),
3644 		.call = parse_table,
3645 	},
3646 	/* Top-level command. */
3647 	[FLOW_GROUP] = {
3648 		.name = "group",
3649 		.help = "manage flow groups",
3650 		.next = NEXT(NEXT_ENTRY(GROUP_ID), NEXT_ENTRY(COMMON_PORT_ID)),
3651 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3652 		.call = parse_group,
3653 	},
3654 	/* Sub-level commands. */
3655 	[GROUP_SET_MISS_ACTIONS] = {
3656 		.name = "set_miss_actions",
3657 		.help = "set group miss actions",
3658 		.next = NEXT(next_action),
3659 		.call = parse_group,
3660 	},
3661 	/* Group arguments */
3662 	[GROUP_ID]	= {
3663 		.name = "group_id",
3664 		.help = "group id",
3665 		.next = NEXT(next_group_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3666 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3667 	},
3668 	[GROUP_INGRESS] = {
3669 		.name = "ingress",
3670 		.help = "group ingress attr",
3671 		.next = NEXT(next_group_attr),
3672 		.call = parse_group,
3673 	},
3674 	[GROUP_EGRESS] = {
3675 		.name = "egress",
3676 		.help = "group egress attr",
3677 		.next = NEXT(next_group_attr),
3678 		.call = parse_group,
3679 	},
3680 	[GROUP_TRANSFER] = {
3681 		.name = "transfer",
3682 		.help = "group transfer attr",
3683 		.next = NEXT(next_group_attr),
3684 		.call = parse_group,
3685 	},
3686 	/* Top-level command. */
3687 	[QUEUE] = {
3688 		.name = "queue",
3689 		.help = "queue a flow rule operation",
3690 		.next = NEXT(next_queue_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3691 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3692 		.call = parse_qo,
3693 	},
3694 	/* Sub-level commands. */
3695 	[QUEUE_CREATE] = {
3696 		.name = "create",
3697 		.help = "create a flow rule",
3698 		.next = NEXT(NEXT_ENTRY(QUEUE_TEMPLATE_TABLE),
3699 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3700 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3701 		.call = parse_qo,
3702 	},
3703 	[QUEUE_DESTROY] = {
3704 		.name = "destroy",
3705 		.help = "destroy a flow rule",
3706 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3707 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3708 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3709 		.call = parse_qo_destroy,
3710 	},
3711 	[QUEUE_FLOW_UPDATE_RESIZED] = {
3712 		.name = "update_resized",
3713 		.help = "update a flow after table resize",
3714 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3715 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3716 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3717 		.call = parse_qo_destroy,
3718 	},
3719 	[QUEUE_UPDATE] = {
3720 		.name = "update",
3721 		.help = "update a flow rule",
3722 		.next = NEXT(NEXT_ENTRY(QUEUE_UPDATE_ID),
3723 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3724 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3725 		.call = parse_qo,
3726 	},
3727 	[QUEUE_AGED] = {
3728 		.name = "aged",
3729 		.help = "list and destroy aged flows",
3730 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_QUEUE_ID)),
3731 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3732 		.call = parse_aged,
3733 	},
3734 	[QUEUE_INDIRECT_ACTION] = {
3735 		.name = "indirect_action",
3736 		.help = "queue indirect actions",
3737 		.next = NEXT(next_qia_subcmd, NEXT_ENTRY(COMMON_QUEUE_ID)),
3738 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3739 		.call = parse_qia,
3740 	},
3741 	/* Queue  arguments. */
3742 	[QUEUE_TEMPLATE_TABLE] = {
3743 		.name = "template_table",
3744 		.help = "specify table id",
3745 		.next = NEXT(next_async_insert_subcmd,
3746 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3747 		.args = ARGS(ARGS_ENTRY(struct buffer,
3748 					args.vc.table_id)),
3749 		.call = parse_qo,
3750 	},
3751 	[QUEUE_PATTERN_TEMPLATE] = {
3752 		.name = "pattern_template",
3753 		.help = "specify pattern template index",
3754 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3755 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3756 		.args = ARGS(ARGS_ENTRY(struct buffer,
3757 					args.vc.pat_templ_id)),
3758 		.call = parse_qo,
3759 	},
3760 	[QUEUE_ACTIONS_TEMPLATE] = {
3761 		.name = "actions_template",
3762 		.help = "specify actions template index",
3763 		.next = NEXT(NEXT_ENTRY(QUEUE_CREATE_POSTPONE),
3764 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3765 		.args = ARGS(ARGS_ENTRY(struct buffer,
3766 					args.vc.act_templ_id)),
3767 		.call = parse_qo,
3768 	},
3769 	[QUEUE_RULE_ID] = {
3770 		.name = "rule_index",
3771 		.help = "specify flow rule index",
3772 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3773 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3774 		.args = ARGS(ARGS_ENTRY(struct buffer,
3775 					args.vc.rule_id)),
3776 		.call = parse_qo,
3777 	},
3778 	[QUEUE_CREATE_POSTPONE] = {
3779 		.name = "postpone",
3780 		.help = "postpone create operation",
3781 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
3782 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3783 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3784 		.call = parse_qo,
3785 	},
3786 	[QUEUE_DESTROY_POSTPONE] = {
3787 		.name = "postpone",
3788 		.help = "postpone destroy operation",
3789 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3790 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3791 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3792 		.call = parse_qo_destroy,
3793 	},
3794 	[QUEUE_DESTROY_ID] = {
3795 		.name = "rule",
3796 		.help = "specify rule id to destroy",
3797 		.next = NEXT(next_queue_destroy_attr,
3798 			NEXT_ENTRY(COMMON_UNSIGNED)),
3799 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3800 					    args.destroy.rule)),
3801 		.call = parse_qo_destroy,
3802 	},
3803 	[QUEUE_UPDATE_ID] = {
3804 		.name = "rule",
3805 		.help = "specify rule id to update",
3806 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3807 			NEXT_ENTRY(COMMON_UNSIGNED)),
3808 		.args = ARGS(ARGS_ENTRY(struct buffer,
3809 				     args.vc.rule_id)),
3810 		.call = parse_qo,
3811 	},
3812 	/* Queue indirect action arguments */
3813 	[QUEUE_INDIRECT_ACTION_CREATE] = {
3814 		.name = "create",
3815 		.help = "create indirect action",
3816 		.next = NEXT(next_qia_create_attr),
3817 		.call = parse_qia,
3818 	},
3819 	[QUEUE_INDIRECT_ACTION_UPDATE] = {
3820 		.name = "update",
3821 		.help = "update indirect action",
3822 		.next = NEXT(next_qia_update_attr,
3823 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3824 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3825 		.call = parse_qia,
3826 	},
3827 	[QUEUE_INDIRECT_ACTION_DESTROY] = {
3828 		.name = "destroy",
3829 		.help = "destroy indirect action",
3830 		.next = NEXT(next_qia_destroy_attr),
3831 		.call = parse_qia_destroy,
3832 	},
3833 	[QUEUE_INDIRECT_ACTION_QUERY] = {
3834 		.name = "query",
3835 		.help = "query indirect action",
3836 		.next = NEXT(next_qia_query_attr,
3837 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3838 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3839 		.call = parse_qia,
3840 	},
3841 	/* Indirect action destroy arguments. */
3842 	[QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE] = {
3843 		.name = "postpone",
3844 		.help = "postpone destroy operation",
3845 		.next = NEXT(next_qia_destroy_attr,
3846 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3847 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3848 	},
3849 	[QUEUE_INDIRECT_ACTION_DESTROY_ID] = {
3850 		.name = "action_id",
3851 		.help = "specify a indirect action id to destroy",
3852 		.next = NEXT(next_qia_destroy_attr,
3853 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3854 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3855 					    args.ia_destroy.action_id)),
3856 		.call = parse_qia_destroy,
3857 	},
3858 	[QUEUE_INDIRECT_ACTION_QUERY_UPDATE] = {
3859 		.name = "query_update",
3860 		.help = "indirect query [and|or] update action",
3861 		.next = NEXT(next_qia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3862 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3863 		.call = parse_qia
3864 	},
3865 	[QUEUE_INDIRECT_ACTION_QU_MODE] = {
3866 		.name = "mode",
3867 		.help = "indirect query [and|or] update action",
3868 		.next = NEXT(next_qia_qu_attr,
3869 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
3870 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
3871 		.call = parse_qia
3872 	},
3873 	/* Indirect action update arguments. */
3874 	[QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE] = {
3875 		.name = "postpone",
3876 		.help = "postpone update operation",
3877 		.next = NEXT(next_qia_update_attr,
3878 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3879 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3880 	},
3881 	/* Indirect action update arguments. */
3882 	[QUEUE_INDIRECT_ACTION_QUERY_POSTPONE] = {
3883 		.name = "postpone",
3884 		.help = "postpone query operation",
3885 		.next = NEXT(next_qia_query_attr,
3886 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3887 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3888 	},
3889 	/* Indirect action create arguments. */
3890 	[QUEUE_INDIRECT_ACTION_CREATE_ID] = {
3891 		.name = "action_id",
3892 		.help = "specify a indirect action id to create",
3893 		.next = NEXT(next_qia_create_attr,
3894 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3895 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3896 	},
3897 	[QUEUE_INDIRECT_ACTION_INGRESS] = {
3898 		.name = "ingress",
3899 		.help = "affect rule to ingress",
3900 		.next = NEXT(next_qia_create_attr),
3901 		.call = parse_qia,
3902 	},
3903 	[QUEUE_INDIRECT_ACTION_EGRESS] = {
3904 		.name = "egress",
3905 		.help = "affect rule to egress",
3906 		.next = NEXT(next_qia_create_attr),
3907 		.call = parse_qia,
3908 	},
3909 	[QUEUE_INDIRECT_ACTION_TRANSFER] = {
3910 		.name = "transfer",
3911 		.help = "affect rule to transfer",
3912 		.next = NEXT(next_qia_create_attr),
3913 		.call = parse_qia,
3914 	},
3915 	[QUEUE_INDIRECT_ACTION_CREATE_POSTPONE] = {
3916 		.name = "postpone",
3917 		.help = "postpone create operation",
3918 		.next = NEXT(next_qia_create_attr,
3919 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3920 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3921 	},
3922 	[QUEUE_INDIRECT_ACTION_SPEC] = {
3923 		.name = "action",
3924 		.help = "specify action to create indirect handle",
3925 		.next = NEXT(next_action),
3926 	},
3927 	[QUEUE_INDIRECT_ACTION_LIST] = {
3928 		.name = "list",
3929 		.help = "specify actions for indirect handle list",
3930 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
3931 		.call = parse_qia,
3932 	},
3933 	/* Top-level command. */
3934 	[PUSH] = {
3935 		.name = "push",
3936 		.help = "push enqueued operations",
3937 		.next = NEXT(NEXT_ENTRY(PUSH_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3938 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3939 		.call = parse_push,
3940 	},
3941 	/* Sub-level commands. */
3942 	[PUSH_QUEUE] = {
3943 		.name = "queue",
3944 		.help = "specify queue id",
3945 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3946 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3947 	},
3948 	/* Top-level command. */
3949 	[PULL] = {
3950 		.name = "pull",
3951 		.help = "pull flow operations results",
3952 		.next = NEXT(NEXT_ENTRY(PULL_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3953 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3954 		.call = parse_pull,
3955 	},
3956 	/* Sub-level commands. */
3957 	[PULL_QUEUE] = {
3958 		.name = "queue",
3959 		.help = "specify queue id",
3960 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3961 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3962 	},
3963 	/* Top-level command. */
3964 	[HASH] = {
3965 		.name = "hash",
3966 		.help = "calculate hash for a given pattern in a given template table",
3967 		.next = NEXT(next_hash_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3968 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3969 		.call = parse_hash,
3970 	},
3971 	/* Sub-level commands. */
3972 	[HASH_CALC_TABLE] = {
3973 		.name = "template_table",
3974 		.help = "specify table id",
3975 		.next = NEXT(NEXT_ENTRY(HASH_CALC_PATTERN_INDEX),
3976 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3977 		.args = ARGS(ARGS_ENTRY(struct buffer,
3978 					args.vc.table_id)),
3979 		.call = parse_hash,
3980 	},
3981 	[HASH_CALC_ENCAP] = {
3982 		.name = "encap",
3983 		.help = "calculates encap hash",
3984 		.next = NEXT(next_hash_encap_dest_subcmd),
3985 		.call = parse_hash,
3986 	},
3987 	[HASH_CALC_PATTERN_INDEX] = {
3988 		.name = "pattern_template",
3989 		.help = "specify pattern template id",
3990 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
3991 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3992 		.args = ARGS(ARGS_ENTRY(struct buffer,
3993 					args.vc.pat_templ_id)),
3994 		.call = parse_hash,
3995 	},
3996 	[ENCAP_HASH_FIELD_SRC_PORT] = {
3997 		.name = "hash_field_sport",
3998 		.help = "the encap hash field is src port",
3999 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
4000 		.call = parse_hash,
4001 	},
4002 	[ENCAP_HASH_FIELD_GRE_FLOW_ID] = {
4003 		.name = "hash_field_flow_id",
4004 		.help = "the encap hash field is NVGRE flow id",
4005 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
4006 		.call = parse_hash,
4007 	},
4008 	/* Top-level command. */
4009 	[INDIRECT_ACTION] = {
4010 		.name = "indirect_action",
4011 		.type = "{command} {port_id} [{arg} [...]]",
4012 		.help = "manage indirect actions",
4013 		.next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
4014 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4015 		.call = parse_ia,
4016 	},
4017 	/* Sub-level commands. */
4018 	[INDIRECT_ACTION_CREATE] = {
4019 		.name = "create",
4020 		.help = "create indirect action",
4021 		.next = NEXT(next_ia_create_attr),
4022 		.call = parse_ia,
4023 	},
4024 	[INDIRECT_ACTION_UPDATE] = {
4025 		.name = "update",
4026 		.help = "update indirect action",
4027 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
4028 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4029 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
4030 		.call = parse_ia,
4031 	},
4032 	[INDIRECT_ACTION_DESTROY] = {
4033 		.name = "destroy",
4034 		.help = "destroy indirect action",
4035 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
4036 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4037 		.call = parse_ia_destroy,
4038 	},
4039 	[INDIRECT_ACTION_QUERY] = {
4040 		.name = "query",
4041 		.help = "query indirect action",
4042 		.next = NEXT(NEXT_ENTRY(END),
4043 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4044 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
4045 		.call = parse_ia,
4046 	},
4047 	[INDIRECT_ACTION_QUERY_UPDATE] = {
4048 		.name = "query_update",
4049 		.help = "query [and|or] update",
4050 		.next = NEXT(next_ia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4051 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
4052 		.call = parse_ia
4053 	},
4054 	[INDIRECT_ACTION_QU_MODE] = {
4055 		.name = "mode",
4056 		.help = "query_update mode",
4057 		.next = NEXT(next_ia_qu_attr,
4058 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
4059 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
4060 		.call = parse_ia,
4061 	},
4062 	[INDIRECT_ACTION_QU_MODE_NAME] = {
4063 		.name = "mode_name",
4064 		.help = "query-update mode name",
4065 		.call = parse_qu_mode_name,
4066 		.comp = comp_qu_mode_name,
4067 	},
4068 	[VALIDATE] = {
4069 		.name = "validate",
4070 		.help = "check whether a flow rule can be created",
4071 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4072 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4073 		.call = parse_vc,
4074 	},
4075 	[CREATE] = {
4076 		.name = "create",
4077 		.help = "create a flow rule",
4078 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4079 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4080 		.call = parse_vc,
4081 	},
4082 	[DESTROY] = {
4083 		.name = "destroy",
4084 		.help = "destroy specific flow rules",
4085 		.next = NEXT(next_destroy_attr,
4086 			     NEXT_ENTRY(COMMON_PORT_ID)),
4087 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4088 		.call = parse_destroy,
4089 	},
4090 	[UPDATE] = {
4091 		.name = "update",
4092 		.help = "update a flow rule with new actions",
4093 		.next = NEXT(NEXT_ENTRY(VC_IS_USER_ID, END),
4094 			     NEXT_ENTRY(ACTIONS),
4095 			     NEXT_ENTRY(COMMON_RULE_ID),
4096 			     NEXT_ENTRY(COMMON_PORT_ID)),
4097 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.rule_id),
4098 			     ARGS_ENTRY(struct buffer, port)),
4099 		.call = parse_vc,
4100 	},
4101 	[FLUSH] = {
4102 		.name = "flush",
4103 		.help = "destroy all flow rules",
4104 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4105 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4106 		.call = parse_flush,
4107 	},
4108 	[DUMP] = {
4109 		.name = "dump",
4110 		.help = "dump single/all flow rules to file",
4111 		.next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
4112 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4113 		.call = parse_dump,
4114 	},
4115 	[QUERY] = {
4116 		.name = "query",
4117 		.help = "query an existing flow rule",
4118 		.next = NEXT(next_query_attr, NEXT_ENTRY(QUERY_ACTION),
4119 			     NEXT_ENTRY(COMMON_RULE_ID),
4120 			     NEXT_ENTRY(COMMON_PORT_ID)),
4121 		.args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
4122 			     ARGS_ENTRY(struct buffer, args.query.rule),
4123 			     ARGS_ENTRY(struct buffer, port)),
4124 		.call = parse_query,
4125 	},
4126 	[LIST] = {
4127 		.name = "list",
4128 		.help = "list existing flow rules",
4129 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4130 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4131 		.call = parse_list,
4132 	},
4133 	[AGED] = {
4134 		.name = "aged",
4135 		.help = "list and destroy aged flows",
4136 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4137 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4138 		.call = parse_aged,
4139 	},
4140 	[ISOLATE] = {
4141 		.name = "isolate",
4142 		.help = "restrict ingress traffic to the defined flow rules",
4143 		.next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
4144 			     NEXT_ENTRY(COMMON_PORT_ID)),
4145 		.args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
4146 			     ARGS_ENTRY(struct buffer, port)),
4147 		.call = parse_isolate,
4148 	},
4149 	[FLEX] = {
4150 		.name = "flex_item",
4151 		.help = "flex item API",
4152 		.next = NEXT(next_flex_item),
4153 		.call = parse_flex,
4154 	},
4155 	[FLEX_ITEM_INIT] = {
4156 		.name = "init",
4157 		.help = "flex item init",
4158 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
4159 			     ARGS_ENTRY(struct buffer, port)),
4160 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
4161 			     NEXT_ENTRY(COMMON_PORT_ID)),
4162 		.call = parse_flex
4163 	},
4164 	[FLEX_ITEM_CREATE] = {
4165 		.name = "create",
4166 		.help = "flex item create",
4167 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename),
4168 			     ARGS_ENTRY(struct buffer, args.flex.token),
4169 			     ARGS_ENTRY(struct buffer, port)),
4170 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH),
4171 			     NEXT_ENTRY(COMMON_FLEX_TOKEN),
4172 			     NEXT_ENTRY(COMMON_PORT_ID)),
4173 		.call = parse_flex
4174 	},
4175 	[FLEX_ITEM_DESTROY] = {
4176 		.name = "destroy",
4177 		.help = "flex item destroy",
4178 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
4179 			     ARGS_ENTRY(struct buffer, port)),
4180 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
4181 			     NEXT_ENTRY(COMMON_PORT_ID)),
4182 		.call = parse_flex
4183 	},
4184 	[TUNNEL] = {
4185 		.name = "tunnel",
4186 		.help = "new tunnel API",
4187 		.next = NEXT(NEXT_ENTRY
4188 			     (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
4189 		.call = parse_tunnel,
4190 	},
4191 	/* Tunnel arguments. */
4192 	[TUNNEL_CREATE] = {
4193 		.name = "create",
4194 		.help = "create new tunnel object",
4195 		.next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
4196 			     NEXT_ENTRY(COMMON_PORT_ID)),
4197 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4198 		.call = parse_tunnel,
4199 	},
4200 	[TUNNEL_CREATE_TYPE] = {
4201 		.name = "type",
4202 		.help = "create new tunnel",
4203 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
4204 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
4205 		.call = parse_tunnel,
4206 	},
4207 	[TUNNEL_DESTROY] = {
4208 		.name = "destroy",
4209 		.help = "destroy tunnel",
4210 		.next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
4211 			     NEXT_ENTRY(COMMON_PORT_ID)),
4212 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4213 		.call = parse_tunnel,
4214 	},
4215 	[TUNNEL_DESTROY_ID] = {
4216 		.name = "id",
4217 		.help = "tunnel identifier to destroy",
4218 		.next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
4219 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4220 		.call = parse_tunnel,
4221 	},
4222 	[TUNNEL_LIST] = {
4223 		.name = "list",
4224 		.help = "list existing tunnels",
4225 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4226 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4227 		.call = parse_tunnel,
4228 	},
4229 	/* Destroy arguments. */
4230 	[DESTROY_RULE] = {
4231 		.name = "rule",
4232 		.help = "specify a rule identifier",
4233 		.next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4234 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
4235 		.call = parse_destroy,
4236 	},
4237 	[DESTROY_IS_USER_ID] = {
4238 		.name = "user_id",
4239 		.help = "rule identifier is user-id",
4240 		.next = NEXT(next_destroy_attr),
4241 		.call = parse_destroy,
4242 	},
4243 	/* Dump arguments. */
4244 	[DUMP_ALL] = {
4245 		.name = "all",
4246 		.help = "dump all",
4247 		.next = NEXT(next_dump_attr),
4248 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
4249 		.call = parse_dump,
4250 	},
4251 	[DUMP_ONE] = {
4252 		.name = "rule",
4253 		.help = "dump one rule",
4254 		.next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4255 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
4256 				ARGS_ENTRY(struct buffer, args.dump.rule)),
4257 		.call = parse_dump,
4258 	},
4259 	[DUMP_IS_USER_ID] = {
4260 		.name = "user_id",
4261 		.help = "rule identifier is user-id",
4262 		.next = NEXT(next_dump_subcmd),
4263 		.call = parse_dump,
4264 	},
4265 	/* Query arguments. */
4266 	[QUERY_ACTION] = {
4267 		.name = "{action}",
4268 		.type = "ACTION",
4269 		.help = "action to query, must be part of the rule",
4270 		.call = parse_action,
4271 		.comp = comp_action,
4272 	},
4273 	[QUERY_IS_USER_ID] = {
4274 		.name = "user_id",
4275 		.help = "rule identifier is user-id",
4276 		.next = NEXT(next_query_attr),
4277 		.call = parse_query,
4278 	},
4279 	/* List arguments. */
4280 	[LIST_GROUP] = {
4281 		.name = "group",
4282 		.help = "specify a group",
4283 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4284 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
4285 		.call = parse_list,
4286 	},
4287 	[AGED_DESTROY] = {
4288 		.name = "destroy",
4289 		.help = "specify aged flows need be destroyed",
4290 		.call = parse_aged,
4291 		.comp = comp_none,
4292 	},
4293 	/* Validate/create attributes. */
4294 	[VC_GROUP] = {
4295 		.name = "group",
4296 		.help = "specify a group",
4297 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4298 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
4299 		.call = parse_vc,
4300 	},
4301 	[VC_PRIORITY] = {
4302 		.name = "priority",
4303 		.help = "specify a priority level",
4304 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
4305 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
4306 		.call = parse_vc,
4307 	},
4308 	[VC_INGRESS] = {
4309 		.name = "ingress",
4310 		.help = "affect rule to ingress",
4311 		.next = NEXT(next_vc_attr),
4312 		.call = parse_vc,
4313 	},
4314 	[VC_EGRESS] = {
4315 		.name = "egress",
4316 		.help = "affect rule to egress",
4317 		.next = NEXT(next_vc_attr),
4318 		.call = parse_vc,
4319 	},
4320 	[VC_TRANSFER] = {
4321 		.name = "transfer",
4322 		.help = "apply rule directly to endpoints found in pattern",
4323 		.next = NEXT(next_vc_attr),
4324 		.call = parse_vc,
4325 	},
4326 	[VC_TUNNEL_SET] = {
4327 		.name = "tunnel_set",
4328 		.help = "tunnel steer rule",
4329 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4330 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4331 		.call = parse_vc,
4332 	},
4333 	[VC_TUNNEL_MATCH] = {
4334 		.name = "tunnel_match",
4335 		.help = "tunnel match rule",
4336 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4337 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4338 		.call = parse_vc,
4339 	},
4340 	[VC_USER_ID] = {
4341 		.name = "user_id",
4342 		.help = "specify a user id to create",
4343 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4344 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.user_id)),
4345 		.call = parse_vc,
4346 	},
4347 	[VC_IS_USER_ID] = {
4348 		.name = "user_id",
4349 		.help = "rule identifier is user-id",
4350 		.call = parse_vc,
4351 	},
4352 	/* Validate/create pattern. */
4353 	[ITEM_PATTERN] = {
4354 		.name = "pattern",
4355 		.help = "submit a list of pattern items",
4356 		.next = NEXT(next_item),
4357 		.call = parse_vc,
4358 	},
4359 	[ITEM_PARAM_IS] = {
4360 		.name = "is",
4361 		.help = "match value perfectly (with full bit-mask)",
4362 		.call = parse_vc_spec,
4363 	},
4364 	[ITEM_PARAM_SPEC] = {
4365 		.name = "spec",
4366 		.help = "match value according to configured bit-mask",
4367 		.call = parse_vc_spec,
4368 	},
4369 	[ITEM_PARAM_LAST] = {
4370 		.name = "last",
4371 		.help = "specify upper bound to establish a range",
4372 		.call = parse_vc_spec,
4373 	},
4374 	[ITEM_PARAM_MASK] = {
4375 		.name = "mask",
4376 		.help = "specify bit-mask with relevant bits set to one",
4377 		.call = parse_vc_spec,
4378 	},
4379 	[ITEM_PARAM_PREFIX] = {
4380 		.name = "prefix",
4381 		.help = "generate bit-mask from a prefix length",
4382 		.call = parse_vc_spec,
4383 	},
4384 	[ITEM_NEXT] = {
4385 		.name = "/",
4386 		.help = "specify next pattern item",
4387 		.next = NEXT(next_item),
4388 	},
4389 	[ITEM_END] = {
4390 		.name = "end",
4391 		.help = "end list of pattern items",
4392 		.priv = PRIV_ITEM(END, 0),
4393 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
4394 		.call = parse_vc,
4395 	},
4396 	[ITEM_VOID] = {
4397 		.name = "void",
4398 		.help = "no-op pattern item",
4399 		.priv = PRIV_ITEM(VOID, 0),
4400 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4401 		.call = parse_vc,
4402 	},
4403 	[ITEM_INVERT] = {
4404 		.name = "invert",
4405 		.help = "perform actions when pattern does not match",
4406 		.priv = PRIV_ITEM(INVERT, 0),
4407 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4408 		.call = parse_vc,
4409 	},
4410 	[ITEM_ANY] = {
4411 		.name = "any",
4412 		.help = "match any protocol for the current layer",
4413 		.priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
4414 		.next = NEXT(item_any),
4415 		.call = parse_vc,
4416 	},
4417 	[ITEM_ANY_NUM] = {
4418 		.name = "num",
4419 		.help = "number of layers covered",
4420 		.next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4421 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
4422 	},
4423 	[ITEM_PORT_ID] = {
4424 		.name = "port_id",
4425 		.help = "match traffic from/to a given DPDK port ID",
4426 		.priv = PRIV_ITEM(PORT_ID,
4427 				  sizeof(struct rte_flow_item_port_id)),
4428 		.next = NEXT(item_port_id),
4429 		.call = parse_vc,
4430 	},
4431 	[ITEM_PORT_ID_ID] = {
4432 		.name = "id",
4433 		.help = "DPDK port ID",
4434 		.next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
4435 			     item_param),
4436 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
4437 	},
4438 	[ITEM_MARK] = {
4439 		.name = "mark",
4440 		.help = "match traffic against value set in previously matched rule",
4441 		.priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
4442 		.next = NEXT(item_mark),
4443 		.call = parse_vc,
4444 	},
4445 	[ITEM_MARK_ID] = {
4446 		.name = "id",
4447 		.help = "Integer value to match against",
4448 		.next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
4449 			     item_param),
4450 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
4451 	},
4452 	[ITEM_RAW] = {
4453 		.name = "raw",
4454 		.help = "match an arbitrary byte string",
4455 		.priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
4456 		.next = NEXT(item_raw),
4457 		.call = parse_vc,
4458 	},
4459 	[ITEM_RAW_RELATIVE] = {
4460 		.name = "relative",
4461 		.help = "look for pattern after the previous item",
4462 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4463 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4464 					   relative, 1)),
4465 	},
4466 	[ITEM_RAW_SEARCH] = {
4467 		.name = "search",
4468 		.help = "search pattern from offset (see also limit)",
4469 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4470 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4471 					   search, 1)),
4472 	},
4473 	[ITEM_RAW_OFFSET] = {
4474 		.name = "offset",
4475 		.help = "absolute or relative offset for pattern",
4476 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
4477 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
4478 	},
4479 	[ITEM_RAW_LIMIT] = {
4480 		.name = "limit",
4481 		.help = "search area limit for start of pattern",
4482 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4483 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
4484 	},
4485 	[ITEM_RAW_PATTERN] = {
4486 		.name = "pattern",
4487 		.help = "byte string to look for",
4488 		.next = NEXT(item_raw,
4489 			     NEXT_ENTRY(COMMON_STRING),
4490 			     NEXT_ENTRY(ITEM_PARAM_IS,
4491 					ITEM_PARAM_SPEC,
4492 					ITEM_PARAM_MASK)),
4493 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4494 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4495 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4496 					    ITEM_RAW_PATTERN_SIZE)),
4497 	},
4498 	[ITEM_RAW_PATTERN_HEX] = {
4499 		.name = "pattern_hex",
4500 		.help = "hex string to look for",
4501 		.next = NEXT(item_raw,
4502 			     NEXT_ENTRY(COMMON_HEX),
4503 			     NEXT_ENTRY(ITEM_PARAM_IS,
4504 					ITEM_PARAM_SPEC,
4505 					ITEM_PARAM_MASK)),
4506 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4507 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4508 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4509 					    ITEM_RAW_PATTERN_SIZE)),
4510 	},
4511 	[ITEM_ETH] = {
4512 		.name = "eth",
4513 		.help = "match Ethernet header",
4514 		.priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
4515 		.next = NEXT(item_eth),
4516 		.call = parse_vc,
4517 	},
4518 	[ITEM_ETH_DST] = {
4519 		.name = "dst",
4520 		.help = "destination MAC",
4521 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4522 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.dst_addr)),
4523 	},
4524 	[ITEM_ETH_SRC] = {
4525 		.name = "src",
4526 		.help = "source MAC",
4527 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4528 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.src_addr)),
4529 	},
4530 	[ITEM_ETH_TYPE] = {
4531 		.name = "type",
4532 		.help = "EtherType",
4533 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4534 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.ether_type)),
4535 	},
4536 	[ITEM_ETH_HAS_VLAN] = {
4537 		.name = "has_vlan",
4538 		.help = "packet header contains VLAN",
4539 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4540 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
4541 					   has_vlan, 1)),
4542 	},
4543 	[ITEM_VLAN] = {
4544 		.name = "vlan",
4545 		.help = "match 802.1Q/ad VLAN tag",
4546 		.priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
4547 		.next = NEXT(item_vlan),
4548 		.call = parse_vc,
4549 	},
4550 	[ITEM_VLAN_TCI] = {
4551 		.name = "tci",
4552 		.help = "tag control information",
4553 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4554 			     item_param),
4555 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, hdr.vlan_tci)),
4556 	},
4557 	[ITEM_VLAN_PCP] = {
4558 		.name = "pcp",
4559 		.help = "priority code point",
4560 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4561 			     item_param),
4562 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4563 						  hdr.vlan_tci, "\xe0\x00")),
4564 	},
4565 	[ITEM_VLAN_DEI] = {
4566 		.name = "dei",
4567 		.help = "drop eligible indicator",
4568 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4569 			     item_param),
4570 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4571 						  hdr.vlan_tci, "\x10\x00")),
4572 	},
4573 	[ITEM_VLAN_VID] = {
4574 		.name = "vid",
4575 		.help = "VLAN identifier",
4576 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4577 			     item_param),
4578 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4579 						  hdr.vlan_tci, "\x0f\xff")),
4580 	},
4581 	[ITEM_VLAN_INNER_TYPE] = {
4582 		.name = "inner_type",
4583 		.help = "inner EtherType",
4584 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4585 			     item_param),
4586 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
4587 					     hdr.eth_proto)),
4588 	},
4589 	[ITEM_VLAN_HAS_MORE_VLAN] = {
4590 		.name = "has_more_vlan",
4591 		.help = "packet header contains another VLAN",
4592 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4593 			     item_param),
4594 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
4595 					   has_more_vlan, 1)),
4596 	},
4597 	[ITEM_IPV4] = {
4598 		.name = "ipv4",
4599 		.help = "match IPv4 header",
4600 		.priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
4601 		.next = NEXT(item_ipv4),
4602 		.call = parse_vc,
4603 	},
4604 	[ITEM_IPV4_VER_IHL] = {
4605 		.name = "version_ihl",
4606 		.help = "match header length",
4607 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4608 			     item_param),
4609 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
4610 				     hdr.version_ihl)),
4611 	},
4612 	[ITEM_IPV4_TOS] = {
4613 		.name = "tos",
4614 		.help = "type of service",
4615 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4616 			     item_param),
4617 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4618 					     hdr.type_of_service)),
4619 	},
4620 	[ITEM_IPV4_LENGTH] = {
4621 		.name = "length",
4622 		.help = "total length",
4623 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4624 			     item_param),
4625 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4626 					     hdr.total_length)),
4627 	},
4628 	[ITEM_IPV4_ID] = {
4629 		.name = "packet_id",
4630 		.help = "fragment packet id",
4631 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4632 			     item_param),
4633 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4634 					     hdr.packet_id)),
4635 	},
4636 	[ITEM_IPV4_FRAGMENT_OFFSET] = {
4637 		.name = "fragment_offset",
4638 		.help = "fragmentation flags and fragment offset",
4639 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4640 			     item_param),
4641 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4642 					     hdr.fragment_offset)),
4643 	},
4644 	[ITEM_IPV4_TTL] = {
4645 		.name = "ttl",
4646 		.help = "time to live",
4647 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4648 			     item_param),
4649 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4650 					     hdr.time_to_live)),
4651 	},
4652 	[ITEM_IPV4_PROTO] = {
4653 		.name = "proto",
4654 		.help = "next protocol ID",
4655 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4656 			     item_param),
4657 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4658 					     hdr.next_proto_id)),
4659 	},
4660 	[ITEM_IPV4_SRC] = {
4661 		.name = "src",
4662 		.help = "source address",
4663 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4664 			     item_param),
4665 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4666 					     hdr.src_addr)),
4667 	},
4668 	[ITEM_IPV4_DST] = {
4669 		.name = "dst",
4670 		.help = "destination address",
4671 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4672 			     item_param),
4673 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4674 					     hdr.dst_addr)),
4675 	},
4676 	[ITEM_IPV6] = {
4677 		.name = "ipv6",
4678 		.help = "match IPv6 header",
4679 		.priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
4680 		.next = NEXT(item_ipv6),
4681 		.call = parse_vc,
4682 	},
4683 	[ITEM_IPV6_TC] = {
4684 		.name = "tc",
4685 		.help = "traffic class",
4686 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4687 			     item_param),
4688 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4689 						  hdr.vtc_flow,
4690 						  "\x0f\xf0\x00\x00")),
4691 	},
4692 	[ITEM_IPV6_FLOW] = {
4693 		.name = "flow",
4694 		.help = "flow label",
4695 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4696 			     item_param),
4697 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4698 						  hdr.vtc_flow,
4699 						  "\x00\x0f\xff\xff")),
4700 	},
4701 	[ITEM_IPV6_LEN] = {
4702 		.name = "length",
4703 		.help = "payload length",
4704 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4705 			     item_param),
4706 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4707 					     hdr.payload_len)),
4708 	},
4709 	[ITEM_IPV6_PROTO] = {
4710 		.name = "proto",
4711 		.help = "protocol (next header)",
4712 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4713 			     item_param),
4714 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4715 					     hdr.proto)),
4716 	},
4717 	[ITEM_IPV6_HOP] = {
4718 		.name = "hop",
4719 		.help = "hop limit",
4720 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4721 			     item_param),
4722 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4723 					     hdr.hop_limits)),
4724 	},
4725 	[ITEM_IPV6_SRC] = {
4726 		.name = "src",
4727 		.help = "source address",
4728 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4729 			     item_param),
4730 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4731 					     hdr.src_addr)),
4732 	},
4733 	[ITEM_IPV6_DST] = {
4734 		.name = "dst",
4735 		.help = "destination address",
4736 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4737 			     item_param),
4738 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4739 					     hdr.dst_addr)),
4740 	},
4741 	[ITEM_IPV6_HAS_FRAG_EXT] = {
4742 		.name = "has_frag_ext",
4743 		.help = "fragment packet attribute",
4744 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4745 			     item_param),
4746 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
4747 					   has_frag_ext, 1)),
4748 	},
4749 	[ITEM_IPV6_ROUTING_EXT] = {
4750 		.name = "ipv6_routing_ext",
4751 		.help = "match IPv6 routing extension header",
4752 		.priv = PRIV_ITEM(IPV6_ROUTING_EXT,
4753 				  sizeof(struct rte_flow_item_ipv6_routing_ext)),
4754 		.next = NEXT(item_ipv6_routing_ext),
4755 		.call = parse_vc,
4756 	},
4757 	[ITEM_IPV6_ROUTING_EXT_TYPE] = {
4758 		.name = "ext_type",
4759 		.help = "match IPv6 routing extension header type",
4760 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4761 			     item_param),
4762 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4763 					     hdr.type)),
4764 	},
4765 	[ITEM_IPV6_ROUTING_EXT_NEXT_HDR] = {
4766 		.name = "ext_next_hdr",
4767 		.help = "match IPv6 routing extension header next header type",
4768 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4769 			     item_param),
4770 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4771 					     hdr.next_hdr)),
4772 	},
4773 	[ITEM_IPV6_ROUTING_EXT_SEG_LEFT] = {
4774 		.name = "ext_seg_left",
4775 		.help = "match IPv6 routing extension header segment left",
4776 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4777 			     item_param),
4778 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4779 					     hdr.segments_left)),
4780 	},
4781 	[ITEM_ICMP] = {
4782 		.name = "icmp",
4783 		.help = "match ICMP header",
4784 		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
4785 		.next = NEXT(item_icmp),
4786 		.call = parse_vc,
4787 	},
4788 	[ITEM_ICMP_TYPE] = {
4789 		.name = "type",
4790 		.help = "ICMP packet type",
4791 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4792 			     item_param),
4793 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4794 					     hdr.icmp_type)),
4795 	},
4796 	[ITEM_ICMP_CODE] = {
4797 		.name = "code",
4798 		.help = "ICMP packet code",
4799 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4800 			     item_param),
4801 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4802 					     hdr.icmp_code)),
4803 	},
4804 	[ITEM_ICMP_IDENT] = {
4805 		.name = "ident",
4806 		.help = "ICMP packet identifier",
4807 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4808 			     item_param),
4809 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4810 					     hdr.icmp_ident)),
4811 	},
4812 	[ITEM_ICMP_SEQ] = {
4813 		.name = "seq",
4814 		.help = "ICMP packet sequence number",
4815 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4816 			     item_param),
4817 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4818 					     hdr.icmp_seq_nb)),
4819 	},
4820 	[ITEM_UDP] = {
4821 		.name = "udp",
4822 		.help = "match UDP header",
4823 		.priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
4824 		.next = NEXT(item_udp),
4825 		.call = parse_vc,
4826 	},
4827 	[ITEM_UDP_SRC] = {
4828 		.name = "src",
4829 		.help = "UDP source port",
4830 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
4831 			     item_param),
4832 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4833 					     hdr.src_port)),
4834 	},
4835 	[ITEM_UDP_DST] = {
4836 		.name = "dst",
4837 		.help = "UDP destination port",
4838 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4839 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4840 					     hdr.dst_port)),
4841 	},
4842 	[ITEM_TCP] = {
4843 		.name = "tcp",
4844 		.help = "match TCP header",
4845 		.priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
4846 		.next = NEXT(item_tcp),
4847 		.call = parse_vc,
4848 	},
4849 	[ITEM_TCP_SRC] = {
4850 		.name = "src",
4851 		.help = "TCP source port",
4852 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4853 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4854 					     hdr.src_port)),
4855 	},
4856 	[ITEM_TCP_DST] = {
4857 		.name = "dst",
4858 		.help = "TCP destination port",
4859 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4860 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4861 					     hdr.dst_port)),
4862 	},
4863 	[ITEM_TCP_FLAGS] = {
4864 		.name = "flags",
4865 		.help = "TCP flags",
4866 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4867 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4868 					     hdr.tcp_flags)),
4869 	},
4870 	[ITEM_SCTP] = {
4871 		.name = "sctp",
4872 		.help = "match SCTP header",
4873 		.priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
4874 		.next = NEXT(item_sctp),
4875 		.call = parse_vc,
4876 	},
4877 	[ITEM_SCTP_SRC] = {
4878 		.name = "src",
4879 		.help = "SCTP source port",
4880 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4881 			     item_param),
4882 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4883 					     hdr.src_port)),
4884 	},
4885 	[ITEM_SCTP_DST] = {
4886 		.name = "dst",
4887 		.help = "SCTP destination port",
4888 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4889 			     item_param),
4890 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4891 					     hdr.dst_port)),
4892 	},
4893 	[ITEM_SCTP_TAG] = {
4894 		.name = "tag",
4895 		.help = "validation tag",
4896 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4897 			     item_param),
4898 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4899 					     hdr.tag)),
4900 	},
4901 	[ITEM_SCTP_CKSUM] = {
4902 		.name = "cksum",
4903 		.help = "checksum",
4904 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4905 			     item_param),
4906 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4907 					     hdr.cksum)),
4908 	},
4909 	[ITEM_VXLAN] = {
4910 		.name = "vxlan",
4911 		.help = "match VXLAN header",
4912 		.priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
4913 		.next = NEXT(item_vxlan),
4914 		.call = parse_vc,
4915 	},
4916 	[ITEM_VXLAN_VNI] = {
4917 		.name = "vni",
4918 		.help = "VXLAN identifier",
4919 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4920 			     item_param),
4921 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, hdr.vni)),
4922 	},
4923 	[ITEM_VXLAN_FLAG_G] = {
4924 		.name = "flag_g",
4925 		.help = "VXLAN GBP bit",
4926 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4927 			     item_param),
4928 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4929 					   hdr.flag_g, 1)),
4930 	},
4931 	[ITEM_VXLAN_FLAG_VER] = {
4932 		.name = "flag_ver",
4933 		.help = "VXLAN GPE version",
4934 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4935 			     item_param),
4936 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4937 					   hdr.flag_ver, 2)),
4938 	},
4939 	[ITEM_VXLAN_FLAG_I] = {
4940 		.name = "flag_i",
4941 		.help = "VXLAN Instance bit",
4942 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4943 			     item_param),
4944 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4945 					   hdr.flag_i, 1)),
4946 	},
4947 	[ITEM_VXLAN_FLAG_P] = {
4948 		.name = "flag_p",
4949 		.help = "VXLAN GPE Next Protocol bit",
4950 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4951 			     item_param),
4952 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4953 					   hdr.flag_p, 1)),
4954 	},
4955 	[ITEM_VXLAN_FLAG_B] = {
4956 		.name = "flag_b",
4957 		.help = "VXLAN GPE Ingress-Replicated BUM",
4958 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4959 			     item_param),
4960 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4961 					   hdr.flag_b, 1)),
4962 	},
4963 	[ITEM_VXLAN_FLAG_O] = {
4964 		.name = "flag_o",
4965 		.help = "VXLAN GPE OAM Packet bit",
4966 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4967 			     item_param),
4968 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4969 					   hdr.flag_o, 1)),
4970 	},
4971 	[ITEM_VXLAN_FLAG_D] = {
4972 		.name = "flag_d",
4973 		.help = "VXLAN GBP Don't Learn bit",
4974 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4975 			     item_param),
4976 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4977 					   hdr.flag_d, 1)),
4978 	},
4979 	[ITEM_VXLAN_FLAG_A] = {
4980 		.name = "flag_a",
4981 		.help = "VXLAN GBP Applied bit",
4982 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4983 			     item_param),
4984 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4985 					   hdr.flag_a, 1)),
4986 	},
4987 	[ITEM_VXLAN_GBP_ID] = {
4988 		.name = "group_policy_id",
4989 		.help = "VXLAN GBP ID",
4990 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4991 			     item_param),
4992 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
4993 					     hdr.policy_id)),
4994 	},
4995 	[ITEM_VXLAN_GPE_PROTO] = {
4996 		.name = "protocol",
4997 		.help = "VXLAN GPE next protocol",
4998 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4999 			     item_param),
5000 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5001 					     hdr.proto)),
5002 	},
5003 	[ITEM_VXLAN_FIRST_RSVD] = {
5004 		.name = "first_rsvd",
5005 		.help = "VXLAN rsvd0 first byte",
5006 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5007 			     item_param),
5008 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5009 					     hdr.rsvd0[0])),
5010 	},
5011 	[ITEM_VXLAN_SECND_RSVD] = {
5012 		.name = "second_rsvd",
5013 		.help = "VXLAN rsvd0 second byte",
5014 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5015 			     item_param),
5016 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5017 					     hdr.rsvd0[1])),
5018 	},
5019 	[ITEM_VXLAN_THIRD_RSVD] = {
5020 		.name = "third_rsvd",
5021 		.help = "VXLAN rsvd0 third byte",
5022 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5023 			     item_param),
5024 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5025 					     hdr.rsvd0[2])),
5026 	},
5027 	[ITEM_VXLAN_LAST_RSVD] = {
5028 		.name = "last_rsvd",
5029 		.help = "VXLAN last reserved byte",
5030 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5031 			     item_param),
5032 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5033 					     hdr.last_rsvd)),
5034 	},
5035 	[ITEM_E_TAG] = {
5036 		.name = "e_tag",
5037 		.help = "match E-Tag header",
5038 		.priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
5039 		.next = NEXT(item_e_tag),
5040 		.call = parse_vc,
5041 	},
5042 	[ITEM_E_TAG_GRP_ECID_B] = {
5043 		.name = "grp_ecid_b",
5044 		.help = "GRP and E-CID base",
5045 		.next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
5046 			     item_param),
5047 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
5048 						  rsvd_grp_ecid_b,
5049 						  "\x3f\xff")),
5050 	},
5051 	[ITEM_NVGRE] = {
5052 		.name = "nvgre",
5053 		.help = "match NVGRE header",
5054 		.priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
5055 		.next = NEXT(item_nvgre),
5056 		.call = parse_vc,
5057 	},
5058 	[ITEM_NVGRE_TNI] = {
5059 		.name = "tni",
5060 		.help = "virtual subnet ID",
5061 		.next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
5062 			     item_param),
5063 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
5064 	},
5065 	[ITEM_MPLS] = {
5066 		.name = "mpls",
5067 		.help = "match MPLS header",
5068 		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
5069 		.next = NEXT(item_mpls),
5070 		.call = parse_vc,
5071 	},
5072 	[ITEM_MPLS_LABEL] = {
5073 		.name = "label",
5074 		.help = "MPLS label",
5075 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
5076 			     item_param),
5077 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
5078 						  label_tc_s,
5079 						  "\xff\xff\xf0")),
5080 	},
5081 	[ITEM_MPLS_TC] = {
5082 		.name = "tc",
5083 		.help = "MPLS Traffic Class",
5084 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
5085 			     item_param),
5086 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
5087 						  label_tc_s,
5088 						  "\x00\x00\x0e")),
5089 	},
5090 	[ITEM_MPLS_S] = {
5091 		.name = "s",
5092 		.help = "MPLS Bottom-of-Stack",
5093 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
5094 			     item_param),
5095 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
5096 						  label_tc_s,
5097 						  "\x00\x00\x01")),
5098 	},
5099 	[ITEM_MPLS_TTL] = {
5100 		.name = "ttl",
5101 		.help = "MPLS Time-to-Live",
5102 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
5103 			     item_param),
5104 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_mpls, ttl)),
5105 	},
5106 	[ITEM_GRE] = {
5107 		.name = "gre",
5108 		.help = "match GRE header",
5109 		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
5110 		.next = NEXT(item_gre),
5111 		.call = parse_vc,
5112 	},
5113 	[ITEM_GRE_PROTO] = {
5114 		.name = "protocol",
5115 		.help = "GRE protocol type",
5116 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
5117 			     item_param),
5118 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
5119 					     protocol)),
5120 	},
5121 	[ITEM_GRE_C_RSVD0_VER] = {
5122 		.name = "c_rsvd0_ver",
5123 		.help =
5124 			"checksum (1b), undefined (1b), key bit (1b),"
5125 			" sequence number (1b), reserved 0 (9b),"
5126 			" version (3b)",
5127 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
5128 			     item_param),
5129 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
5130 					     c_rsvd0_ver)),
5131 	},
5132 	[ITEM_GRE_C_BIT] = {
5133 		.name = "c_bit",
5134 		.help = "checksum bit (C)",
5135 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
5136 			     item_param),
5137 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5138 						  c_rsvd0_ver,
5139 						  "\x80\x00\x00\x00")),
5140 	},
5141 	[ITEM_GRE_S_BIT] = {
5142 		.name = "s_bit",
5143 		.help = "sequence number bit (S)",
5144 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
5145 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5146 						  c_rsvd0_ver,
5147 						  "\x10\x00\x00\x00")),
5148 	},
5149 	[ITEM_GRE_K_BIT] = {
5150 		.name = "k_bit",
5151 		.help = "key bit (K)",
5152 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
5153 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5154 						  c_rsvd0_ver,
5155 						  "\x20\x00\x00\x00")),
5156 	},
5157 	[ITEM_FUZZY] = {
5158 		.name = "fuzzy",
5159 		.help = "fuzzy pattern match, expect faster than default",
5160 		.priv = PRIV_ITEM(FUZZY,
5161 				sizeof(struct rte_flow_item_fuzzy)),
5162 		.next = NEXT(item_fuzzy),
5163 		.call = parse_vc,
5164 	},
5165 	[ITEM_FUZZY_THRESH] = {
5166 		.name = "thresh",
5167 		.help = "match accuracy threshold",
5168 		.next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
5169 			     item_param),
5170 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
5171 					thresh)),
5172 	},
5173 	[ITEM_GTP] = {
5174 		.name = "gtp",
5175 		.help = "match GTP header",
5176 		.priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
5177 		.next = NEXT(item_gtp),
5178 		.call = parse_vc,
5179 	},
5180 	[ITEM_GTP_FLAGS] = {
5181 		.name = "v_pt_rsv_flags",
5182 		.help = "GTP flags",
5183 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5184 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
5185 					hdr.gtp_hdr_info)),
5186 	},
5187 	[ITEM_GTP_MSG_TYPE] = {
5188 		.name = "msg_type",
5189 		.help = "GTP message type",
5190 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5191 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, hdr.msg_type)),
5192 	},
5193 	[ITEM_GTP_TEID] = {
5194 		.name = "teid",
5195 		.help = "tunnel endpoint identifier",
5196 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5197 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, hdr.teid)),
5198 	},
5199 	[ITEM_GTPC] = {
5200 		.name = "gtpc",
5201 		.help = "match GTP header",
5202 		.priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
5203 		.next = NEXT(item_gtp),
5204 		.call = parse_vc,
5205 	},
5206 	[ITEM_GTPU] = {
5207 		.name = "gtpu",
5208 		.help = "match GTP header",
5209 		.priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
5210 		.next = NEXT(item_gtp),
5211 		.call = parse_vc,
5212 	},
5213 	[ITEM_GENEVE] = {
5214 		.name = "geneve",
5215 		.help = "match GENEVE header",
5216 		.priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
5217 		.next = NEXT(item_geneve),
5218 		.call = parse_vc,
5219 	},
5220 	[ITEM_GENEVE_VNI] = {
5221 		.name = "vni",
5222 		.help = "virtual network identifier",
5223 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5224 			     item_param),
5225 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
5226 	},
5227 	[ITEM_GENEVE_PROTO] = {
5228 		.name = "protocol",
5229 		.help = "GENEVE protocol type",
5230 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5231 			     item_param),
5232 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
5233 					     protocol)),
5234 	},
5235 	[ITEM_GENEVE_OPTLEN] = {
5236 		.name = "optlen",
5237 		.help = "GENEVE options length in dwords",
5238 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5239 			     item_param),
5240 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
5241 						  ver_opt_len_o_c_rsvd0,
5242 						  "\x3f\x00")),
5243 	},
5244 	[ITEM_ARP_ETH_IPV4] = {
5245 		.name = "arp_eth_ipv4",
5246 		.help = "match ARP header for Ethernet/IPv4",
5247 		.priv = PRIV_ITEM(ARP_ETH_IPV4,
5248 				  sizeof(struct rte_flow_item_arp_eth_ipv4)),
5249 		.next = NEXT(item_arp_eth_ipv4),
5250 		.call = parse_vc,
5251 	},
5252 	[ITEM_ARP_ETH_IPV4_SHA] = {
5253 		.name = "sha",
5254 		.help = "sender hardware address",
5255 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5256 			     item_param),
5257 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5258 					     hdr.arp_data.arp_sha)),
5259 	},
5260 	[ITEM_ARP_ETH_IPV4_SPA] = {
5261 		.name = "spa",
5262 		.help = "sender IPv4 address",
5263 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5264 			     item_param),
5265 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5266 					     hdr.arp_data.arp_sip)),
5267 	},
5268 	[ITEM_ARP_ETH_IPV4_THA] = {
5269 		.name = "tha",
5270 		.help = "target hardware address",
5271 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5272 			     item_param),
5273 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5274 					     hdr.arp_data.arp_tha)),
5275 	},
5276 	[ITEM_ARP_ETH_IPV4_TPA] = {
5277 		.name = "tpa",
5278 		.help = "target IPv4 address",
5279 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5280 			     item_param),
5281 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5282 					     hdr.arp_data.arp_tip)),
5283 	},
5284 	[ITEM_IPV6_EXT] = {
5285 		.name = "ipv6_ext",
5286 		.help = "match presence of any IPv6 extension header",
5287 		.priv = PRIV_ITEM(IPV6_EXT,
5288 				  sizeof(struct rte_flow_item_ipv6_ext)),
5289 		.next = NEXT(item_ipv6_ext),
5290 		.call = parse_vc,
5291 	},
5292 	[ITEM_IPV6_EXT_NEXT_HDR] = {
5293 		.name = "next_hdr",
5294 		.help = "next header",
5295 		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5296 			     item_param),
5297 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
5298 					     next_hdr)),
5299 	},
5300 	[ITEM_IPV6_FRAG_EXT] = {
5301 		.name = "ipv6_frag_ext",
5302 		.help = "match presence of IPv6 fragment extension header",
5303 		.priv = PRIV_ITEM(IPV6_FRAG_EXT,
5304 				sizeof(struct rte_flow_item_ipv6_frag_ext)),
5305 		.next = NEXT(item_ipv6_frag_ext),
5306 		.call = parse_vc,
5307 	},
5308 	[ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
5309 		.name = "next_hdr",
5310 		.help = "next header",
5311 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5312 			     item_param),
5313 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
5314 					hdr.next_header)),
5315 	},
5316 	[ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
5317 		.name = "frag_data",
5318 		.help = "fragment flags and offset",
5319 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5320 			     item_param),
5321 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5322 					     hdr.frag_data)),
5323 	},
5324 	[ITEM_IPV6_FRAG_EXT_ID] = {
5325 		.name = "packet_id",
5326 		.help = "fragment packet id",
5327 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5328 			     item_param),
5329 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5330 					     hdr.id)),
5331 	},
5332 	[ITEM_ICMP6] = {
5333 		.name = "icmp6",
5334 		.help = "match any ICMPv6 header",
5335 		.priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
5336 		.next = NEXT(item_icmp6),
5337 		.call = parse_vc,
5338 	},
5339 	[ITEM_ICMP6_TYPE] = {
5340 		.name = "type",
5341 		.help = "ICMPv6 type",
5342 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5343 			     item_param),
5344 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5345 					     type)),
5346 	},
5347 	[ITEM_ICMP6_CODE] = {
5348 		.name = "code",
5349 		.help = "ICMPv6 code",
5350 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5351 			     item_param),
5352 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5353 					     code)),
5354 	},
5355 	[ITEM_ICMP6_ECHO_REQUEST] = {
5356 		.name = "icmp6_echo_request",
5357 		.help = "match ICMPv6 echo request",
5358 		.priv = PRIV_ITEM(ICMP6_ECHO_REQUEST,
5359 				  sizeof(struct rte_flow_item_icmp6_echo)),
5360 		.next = NEXT(item_icmp6_echo_request),
5361 		.call = parse_vc,
5362 	},
5363 	[ITEM_ICMP6_ECHO_REQUEST_ID] = {
5364 		.name = "ident",
5365 		.help = "ICMPv6 echo request identifier",
5366 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5367 			     item_param),
5368 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5369 					     hdr.identifier)),
5370 	},
5371 	[ITEM_ICMP6_ECHO_REQUEST_SEQ] = {
5372 		.name = "seq",
5373 		.help = "ICMPv6 echo request sequence",
5374 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5375 			     item_param),
5376 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5377 					     hdr.sequence)),
5378 	},
5379 	[ITEM_ICMP6_ECHO_REPLY] = {
5380 		.name = "icmp6_echo_reply",
5381 		.help = "match ICMPv6 echo reply",
5382 		.priv = PRIV_ITEM(ICMP6_ECHO_REPLY,
5383 				  sizeof(struct rte_flow_item_icmp6_echo)),
5384 		.next = NEXT(item_icmp6_echo_reply),
5385 		.call = parse_vc,
5386 	},
5387 	[ITEM_ICMP6_ECHO_REPLY_ID] = {
5388 		.name = "ident",
5389 		.help = "ICMPv6 echo reply identifier",
5390 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5391 			     item_param),
5392 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5393 					     hdr.identifier)),
5394 	},
5395 	[ITEM_ICMP6_ECHO_REPLY_SEQ] = {
5396 		.name = "seq",
5397 		.help = "ICMPv6 echo reply sequence",
5398 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5399 			     item_param),
5400 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5401 					     hdr.sequence)),
5402 	},
5403 	[ITEM_ICMP6_ND_NS] = {
5404 		.name = "icmp6_nd_ns",
5405 		.help = "match ICMPv6 neighbor discovery solicitation",
5406 		.priv = PRIV_ITEM(ICMP6_ND_NS,
5407 				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
5408 		.next = NEXT(item_icmp6_nd_ns),
5409 		.call = parse_vc,
5410 	},
5411 	[ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
5412 		.name = "target_addr",
5413 		.help = "target address",
5414 		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
5415 			     item_param),
5416 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
5417 					     target_addr)),
5418 	},
5419 	[ITEM_ICMP6_ND_NA] = {
5420 		.name = "icmp6_nd_na",
5421 		.help = "match ICMPv6 neighbor discovery advertisement",
5422 		.priv = PRIV_ITEM(ICMP6_ND_NA,
5423 				  sizeof(struct rte_flow_item_icmp6_nd_na)),
5424 		.next = NEXT(item_icmp6_nd_na),
5425 		.call = parse_vc,
5426 	},
5427 	[ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
5428 		.name = "target_addr",
5429 		.help = "target address",
5430 		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
5431 			     item_param),
5432 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
5433 					     target_addr)),
5434 	},
5435 	[ITEM_ICMP6_ND_OPT] = {
5436 		.name = "icmp6_nd_opt",
5437 		.help = "match presence of any ICMPv6 neighbor discovery"
5438 			" option",
5439 		.priv = PRIV_ITEM(ICMP6_ND_OPT,
5440 				  sizeof(struct rte_flow_item_icmp6_nd_opt)),
5441 		.next = NEXT(item_icmp6_nd_opt),
5442 		.call = parse_vc,
5443 	},
5444 	[ITEM_ICMP6_ND_OPT_TYPE] = {
5445 		.name = "type",
5446 		.help = "ND option type",
5447 		.next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5448 			     item_param),
5449 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
5450 					     type)),
5451 	},
5452 	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
5453 		.name = "icmp6_nd_opt_sla_eth",
5454 		.help = "match ICMPv6 neighbor discovery source Ethernet"
5455 			" link-layer address option",
5456 		.priv = PRIV_ITEM
5457 			(ICMP6_ND_OPT_SLA_ETH,
5458 			 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
5459 		.next = NEXT(item_icmp6_nd_opt_sla_eth),
5460 		.call = parse_vc,
5461 	},
5462 	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
5463 		.name = "sla",
5464 		.help = "source Ethernet LLA",
5465 		.next = NEXT(item_icmp6_nd_opt_sla_eth,
5466 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5467 		.args = ARGS(ARGS_ENTRY_HTON
5468 			     (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
5469 	},
5470 	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
5471 		.name = "icmp6_nd_opt_tla_eth",
5472 		.help = "match ICMPv6 neighbor discovery target Ethernet"
5473 			" link-layer address option",
5474 		.priv = PRIV_ITEM
5475 			(ICMP6_ND_OPT_TLA_ETH,
5476 			 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
5477 		.next = NEXT(item_icmp6_nd_opt_tla_eth),
5478 		.call = parse_vc,
5479 	},
5480 	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
5481 		.name = "tla",
5482 		.help = "target Ethernet LLA",
5483 		.next = NEXT(item_icmp6_nd_opt_tla_eth,
5484 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5485 		.args = ARGS(ARGS_ENTRY_HTON
5486 			     (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
5487 	},
5488 	[ITEM_META] = {
5489 		.name = "meta",
5490 		.help = "match metadata header",
5491 		.priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
5492 		.next = NEXT(item_meta),
5493 		.call = parse_vc,
5494 	},
5495 	[ITEM_META_DATA] = {
5496 		.name = "data",
5497 		.help = "metadata value",
5498 		.next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
5499 			     item_param),
5500 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
5501 					     data, "\xff\xff\xff\xff")),
5502 	},
5503 	[ITEM_RANDOM] = {
5504 		.name = "random",
5505 		.help = "match random value",
5506 		.priv = PRIV_ITEM(RANDOM, sizeof(struct rte_flow_item_random)),
5507 		.next = NEXT(item_random),
5508 		.call = parse_vc,
5509 	},
5510 	[ITEM_RANDOM_VALUE] = {
5511 		.name = "value",
5512 		.help = "random value",
5513 		.next = NEXT(item_random, NEXT_ENTRY(COMMON_UNSIGNED),
5514 			     item_param),
5515 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_random,
5516 					     value, "\xff\xff")),
5517 	},
5518 	[ITEM_GRE_KEY] = {
5519 		.name = "gre_key",
5520 		.help = "match GRE key",
5521 		.priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
5522 		.next = NEXT(item_gre_key),
5523 		.call = parse_vc,
5524 	},
5525 	[ITEM_GRE_KEY_VALUE] = {
5526 		.name = "value",
5527 		.help = "key value",
5528 		.next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
5529 			     item_param),
5530 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5531 	},
5532 	[ITEM_GRE_OPTION] = {
5533 		.name = "gre_option",
5534 		.help = "match GRE optional fields",
5535 		.priv = PRIV_ITEM(GRE_OPTION,
5536 				  sizeof(struct rte_flow_item_gre_opt)),
5537 		.next = NEXT(item_gre_option),
5538 		.call = parse_vc,
5539 	},
5540 	[ITEM_GRE_OPTION_CHECKSUM] = {
5541 		.name = "checksum",
5542 		.help = "match GRE checksum",
5543 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5544 			     item_param),
5545 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5546 					     checksum_rsvd.checksum)),
5547 	},
5548 	[ITEM_GRE_OPTION_KEY] = {
5549 		.name = "key",
5550 		.help = "match GRE key",
5551 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5552 			     item_param),
5553 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5554 					     key.key)),
5555 	},
5556 	[ITEM_GRE_OPTION_SEQUENCE] = {
5557 		.name = "sequence",
5558 		.help = "match GRE sequence",
5559 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5560 			     item_param),
5561 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5562 					     sequence.sequence)),
5563 	},
5564 	[ITEM_GTP_PSC] = {
5565 		.name = "gtp_psc",
5566 		.help = "match GTP extension header with type 0x85",
5567 		.priv = PRIV_ITEM(GTP_PSC,
5568 				sizeof(struct rte_flow_item_gtp_psc)),
5569 		.next = NEXT(item_gtp_psc),
5570 		.call = parse_vc,
5571 	},
5572 	[ITEM_GTP_PSC_QFI] = {
5573 		.name = "qfi",
5574 		.help = "QoS flow identifier",
5575 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5576 			     item_param),
5577 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5578 					hdr.qfi, 6)),
5579 	},
5580 	[ITEM_GTP_PSC_PDU_T] = {
5581 		.name = "pdu_t",
5582 		.help = "PDU type",
5583 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5584 			     item_param),
5585 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5586 					hdr.type, 4)),
5587 	},
5588 	[ITEM_PPPOES] = {
5589 		.name = "pppoes",
5590 		.help = "match PPPoE session header",
5591 		.priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
5592 		.next = NEXT(item_pppoes),
5593 		.call = parse_vc,
5594 	},
5595 	[ITEM_PPPOED] = {
5596 		.name = "pppoed",
5597 		.help = "match PPPoE discovery header",
5598 		.priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
5599 		.next = NEXT(item_pppoed),
5600 		.call = parse_vc,
5601 	},
5602 	[ITEM_PPPOE_SEID] = {
5603 		.name = "seid",
5604 		.help = "session identifier",
5605 		.next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
5606 			     item_param),
5607 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
5608 					session_id)),
5609 	},
5610 	[ITEM_PPPOE_PROTO_ID] = {
5611 		.name = "pppoe_proto_id",
5612 		.help = "match PPPoE session protocol identifier",
5613 		.priv = PRIV_ITEM(PPPOE_PROTO_ID,
5614 				sizeof(struct rte_flow_item_pppoe_proto_id)),
5615 		.next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
5616 			     item_param),
5617 		.args = ARGS(ARGS_ENTRY_HTON
5618 			     (struct rte_flow_item_pppoe_proto_id, proto_id)),
5619 		.call = parse_vc,
5620 	},
5621 	[ITEM_HIGIG2] = {
5622 		.name = "higig2",
5623 		.help = "matches higig2 header",
5624 		.priv = PRIV_ITEM(HIGIG2,
5625 				sizeof(struct rte_flow_item_higig2_hdr)),
5626 		.next = NEXT(item_higig2),
5627 		.call = parse_vc,
5628 	},
5629 	[ITEM_HIGIG2_CLASSIFICATION] = {
5630 		.name = "classification",
5631 		.help = "matches classification of higig2 header",
5632 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5633 			     item_param),
5634 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5635 					hdr.ppt1.classification)),
5636 	},
5637 	[ITEM_HIGIG2_VID] = {
5638 		.name = "vid",
5639 		.help = "matches vid of higig2 header",
5640 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5641 			     item_param),
5642 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5643 					hdr.ppt1.vid)),
5644 	},
5645 	[ITEM_TAG] = {
5646 		.name = "tag",
5647 		.help = "match tag value",
5648 		.priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
5649 		.next = NEXT(item_tag),
5650 		.call = parse_vc,
5651 	},
5652 	[ITEM_TAG_DATA] = {
5653 		.name = "data",
5654 		.help = "tag value to match",
5655 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5656 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
5657 	},
5658 	[ITEM_TAG_INDEX] = {
5659 		.name = "index",
5660 		.help = "index of tag array to match",
5661 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
5662 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5663 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
5664 	},
5665 	[ITEM_L2TPV3OIP] = {
5666 		.name = "l2tpv3oip",
5667 		.help = "match L2TPv3 over IP header",
5668 		.priv = PRIV_ITEM(L2TPV3OIP,
5669 				  sizeof(struct rte_flow_item_l2tpv3oip)),
5670 		.next = NEXT(item_l2tpv3oip),
5671 		.call = parse_vc,
5672 	},
5673 	[ITEM_L2TPV3OIP_SESSION_ID] = {
5674 		.name = "session_id",
5675 		.help = "session identifier",
5676 		.next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
5677 			     item_param),
5678 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
5679 					     session_id)),
5680 	},
5681 	[ITEM_ESP] = {
5682 		.name = "esp",
5683 		.help = "match ESP header",
5684 		.priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
5685 		.next = NEXT(item_esp),
5686 		.call = parse_vc,
5687 	},
5688 	[ITEM_ESP_SPI] = {
5689 		.name = "spi",
5690 		.help = "security policy index",
5691 		.next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5692 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
5693 				hdr.spi)),
5694 	},
5695 	[ITEM_AH] = {
5696 		.name = "ah",
5697 		.help = "match AH header",
5698 		.priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
5699 		.next = NEXT(item_ah),
5700 		.call = parse_vc,
5701 	},
5702 	[ITEM_AH_SPI] = {
5703 		.name = "spi",
5704 		.help = "security parameters index",
5705 		.next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5706 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
5707 	},
5708 	[ITEM_PFCP] = {
5709 		.name = "pfcp",
5710 		.help = "match pfcp header",
5711 		.priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
5712 		.next = NEXT(item_pfcp),
5713 		.call = parse_vc,
5714 	},
5715 	[ITEM_PFCP_S_FIELD] = {
5716 		.name = "s_field",
5717 		.help = "S field",
5718 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5719 			     item_param),
5720 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
5721 				s_field)),
5722 	},
5723 	[ITEM_PFCP_SEID] = {
5724 		.name = "seid",
5725 		.help = "session endpoint identifier",
5726 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5727 			     item_param),
5728 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
5729 	},
5730 	[ITEM_ECPRI] = {
5731 		.name = "ecpri",
5732 		.help = "match eCPRI header",
5733 		.priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
5734 		.next = NEXT(item_ecpri),
5735 		.call = parse_vc,
5736 	},
5737 	[ITEM_ECPRI_COMMON] = {
5738 		.name = "common",
5739 		.help = "eCPRI common header",
5740 		.next = NEXT(item_ecpri_common),
5741 	},
5742 	[ITEM_ECPRI_COMMON_TYPE] = {
5743 		.name = "type",
5744 		.help = "type of common header",
5745 		.next = NEXT(item_ecpri_common_type),
5746 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
5747 	},
5748 	[ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
5749 		.name = "iq_data",
5750 		.help = "Type #0: IQ Data",
5751 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5752 					ITEM_NEXT)),
5753 		.call = parse_vc_item_ecpri_type,
5754 	},
5755 	[ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
5756 		.name = "pc_id",
5757 		.help = "Physical Channel ID",
5758 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5759 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5760 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5761 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5762 				hdr.type0.pc_id)),
5763 	},
5764 	[ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
5765 		.name = "rtc_ctrl",
5766 		.help = "Type #2: Real-Time Control Data",
5767 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5768 					ITEM_NEXT)),
5769 		.call = parse_vc_item_ecpri_type,
5770 	},
5771 	[ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
5772 		.name = "rtc_id",
5773 		.help = "Real-Time Control Data ID",
5774 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5775 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5776 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5777 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5778 				hdr.type2.rtc_id)),
5779 	},
5780 	[ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
5781 		.name = "delay_measure",
5782 		.help = "Type #5: One-Way Delay Measurement",
5783 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5784 					ITEM_NEXT)),
5785 		.call = parse_vc_item_ecpri_type,
5786 	},
5787 	[ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
5788 		.name = "msr_id",
5789 		.help = "Measurement ID",
5790 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5791 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5792 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5793 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5794 				hdr.type5.msr_id)),
5795 	},
5796 	[ITEM_GENEVE_OPT] = {
5797 		.name = "geneve-opt",
5798 		.help = "GENEVE header option",
5799 		.priv = PRIV_ITEM(GENEVE_OPT,
5800 				  sizeof(struct rte_flow_item_geneve_opt) +
5801 				  ITEM_GENEVE_OPT_DATA_SIZE),
5802 		.next = NEXT(item_geneve_opt),
5803 		.call = parse_vc,
5804 	},
5805 	[ITEM_GENEVE_OPT_CLASS]	= {
5806 		.name = "class",
5807 		.help = "GENEVE option class",
5808 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5809 			     item_param),
5810 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
5811 					     option_class)),
5812 	},
5813 	[ITEM_GENEVE_OPT_TYPE] = {
5814 		.name = "type",
5815 		.help = "GENEVE option type",
5816 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5817 			     item_param),
5818 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
5819 					option_type)),
5820 	},
5821 	[ITEM_GENEVE_OPT_LENGTH] = {
5822 		.name = "length",
5823 		.help = "GENEVE option data length (in 32b words)",
5824 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5825 			     item_param),
5826 		.args = ARGS(ARGS_ENTRY_BOUNDED(
5827 				struct rte_flow_item_geneve_opt, option_len,
5828 				0, 31)),
5829 	},
5830 	[ITEM_GENEVE_OPT_DATA] = {
5831 		.name = "data",
5832 		.help = "GENEVE option data pattern",
5833 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
5834 			     item_param),
5835 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
5836 			     ARGS_ENTRY_ARB(0, 0),
5837 			     ARGS_ENTRY_ARB
5838 				(sizeof(struct rte_flow_item_geneve_opt),
5839 				ITEM_GENEVE_OPT_DATA_SIZE)),
5840 	},
5841 	[ITEM_INTEGRITY] = {
5842 		.name = "integrity",
5843 		.help = "match packet integrity",
5844 		.priv = PRIV_ITEM(INTEGRITY,
5845 				  sizeof(struct rte_flow_item_integrity)),
5846 		.next = NEXT(item_integrity),
5847 		.call = parse_vc,
5848 	},
5849 	[ITEM_INTEGRITY_LEVEL] = {
5850 		.name = "level",
5851 		.help = "integrity level",
5852 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5853 			     item_param),
5854 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
5855 	},
5856 	[ITEM_INTEGRITY_VALUE] = {
5857 		.name = "value",
5858 		.help = "integrity value",
5859 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5860 			     item_param),
5861 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
5862 	},
5863 	[ITEM_CONNTRACK] = {
5864 		.name = "conntrack",
5865 		.help = "conntrack state",
5866 		.priv = PRIV_ITEM(CONNTRACK,
5867 				  sizeof(struct rte_flow_item_conntrack)),
5868 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
5869 			     item_param),
5870 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
5871 		.call = parse_vc,
5872 	},
5873 	[ITEM_PORT_REPRESENTOR] = {
5874 		.name = "port_representor",
5875 		.help = "match traffic entering the embedded switch from the given ethdev",
5876 		.priv = PRIV_ITEM(PORT_REPRESENTOR,
5877 				  sizeof(struct rte_flow_item_ethdev)),
5878 		.next = NEXT(item_port_representor),
5879 		.call = parse_vc,
5880 	},
5881 	[ITEM_PORT_REPRESENTOR_PORT_ID] = {
5882 		.name = "port_id",
5883 		.help = "ethdev port ID",
5884 		.next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
5885 			     item_param),
5886 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5887 	},
5888 	[ITEM_REPRESENTED_PORT] = {
5889 		.name = "represented_port",
5890 		.help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
5891 		.priv = PRIV_ITEM(REPRESENTED_PORT,
5892 				  sizeof(struct rte_flow_item_ethdev)),
5893 		.next = NEXT(item_represented_port),
5894 		.call = parse_vc,
5895 	},
5896 	[ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
5897 		.name = "ethdev_port_id",
5898 		.help = "ethdev port ID",
5899 		.next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
5900 			     item_param),
5901 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5902 	},
5903 	[ITEM_FLEX] = {
5904 		.name = "flex",
5905 		.help = "match flex header",
5906 		.priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
5907 		.next = NEXT(item_flex),
5908 		.call = parse_vc,
5909 	},
5910 	[ITEM_FLEX_ITEM_HANDLE] = {
5911 		.name = "item",
5912 		.help = "flex item handle",
5913 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5914 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5915 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
5916 	},
5917 	[ITEM_FLEX_PATTERN_HANDLE] = {
5918 		.name = "pattern",
5919 		.help = "flex pattern handle",
5920 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5921 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5922 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
5923 	},
5924 	[ITEM_L2TPV2] = {
5925 		.name = "l2tpv2",
5926 		.help = "match L2TPv2 header",
5927 		.priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
5928 		.next = NEXT(item_l2tpv2),
5929 		.call = parse_vc,
5930 	},
5931 	[ITEM_L2TPV2_TYPE] = {
5932 		.name = "type",
5933 		.help = "type of l2tpv2",
5934 		.next = NEXT(item_l2tpv2_type),
5935 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
5936 	},
5937 	[ITEM_L2TPV2_TYPE_DATA] = {
5938 		.name = "data",
5939 		.help = "Type #7: data message without any options",
5940 		.next = NEXT(item_l2tpv2_type_data),
5941 		.call = parse_vc_item_l2tpv2_type,
5942 	},
5943 	[ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
5944 		.name = "tunnel_id",
5945 		.help = "tunnel identifier",
5946 		.next = NEXT(item_l2tpv2_type_data,
5947 			     NEXT_ENTRY(COMMON_UNSIGNED),
5948 			     item_param),
5949 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5950 					     hdr.type7.tunnel_id)),
5951 	},
5952 	[ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
5953 		.name = "session_id",
5954 		.help = "session identifier",
5955 		.next = NEXT(item_l2tpv2_type_data,
5956 			     NEXT_ENTRY(COMMON_UNSIGNED),
5957 			     item_param),
5958 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5959 					     hdr.type7.session_id)),
5960 	},
5961 	[ITEM_L2TPV2_TYPE_DATA_L] = {
5962 		.name = "data_l",
5963 		.help = "Type #6: data message with length option",
5964 		.next = NEXT(item_l2tpv2_type_data_l),
5965 		.call = parse_vc_item_l2tpv2_type,
5966 	},
5967 	[ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
5968 		.name = "length",
5969 		.help = "message length",
5970 		.next = NEXT(item_l2tpv2_type_data_l,
5971 			     NEXT_ENTRY(COMMON_UNSIGNED),
5972 			     item_param),
5973 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5974 					     hdr.type6.length)),
5975 	},
5976 	[ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
5977 		.name = "tunnel_id",
5978 		.help = "tunnel identifier",
5979 		.next = NEXT(item_l2tpv2_type_data_l,
5980 			     NEXT_ENTRY(COMMON_UNSIGNED),
5981 			     item_param),
5982 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5983 					     hdr.type6.tunnel_id)),
5984 	},
5985 	[ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
5986 		.name = "session_id",
5987 		.help = "session identifier",
5988 		.next = NEXT(item_l2tpv2_type_data_l,
5989 			     NEXT_ENTRY(COMMON_UNSIGNED),
5990 			     item_param),
5991 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5992 					     hdr.type6.session_id)),
5993 	},
5994 	[ITEM_L2TPV2_TYPE_DATA_S] = {
5995 		.name = "data_s",
5996 		.help = "Type #5: data message with ns, nr option",
5997 		.next = NEXT(item_l2tpv2_type_data_s),
5998 		.call = parse_vc_item_l2tpv2_type,
5999 	},
6000 	[ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
6001 		.name = "tunnel_id",
6002 		.help = "tunnel identifier",
6003 		.next = NEXT(item_l2tpv2_type_data_s,
6004 			     NEXT_ENTRY(COMMON_UNSIGNED),
6005 			     item_param),
6006 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6007 					     hdr.type5.tunnel_id)),
6008 	},
6009 	[ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
6010 		.name = "session_id",
6011 		.help = "session identifier",
6012 		.next = NEXT(item_l2tpv2_type_data_s,
6013 			     NEXT_ENTRY(COMMON_UNSIGNED),
6014 			     item_param),
6015 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6016 					     hdr.type5.session_id)),
6017 	},
6018 	[ITEM_L2TPV2_MSG_DATA_S_NS] = {
6019 		.name = "ns",
6020 		.help = "sequence number for message",
6021 		.next = NEXT(item_l2tpv2_type_data_s,
6022 			     NEXT_ENTRY(COMMON_UNSIGNED),
6023 			     item_param),
6024 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6025 					     hdr.type5.ns)),
6026 	},
6027 	[ITEM_L2TPV2_MSG_DATA_S_NR] = {
6028 		.name = "nr",
6029 		.help = "sequence number for next receive message",
6030 		.next = NEXT(item_l2tpv2_type_data_s,
6031 			     NEXT_ENTRY(COMMON_UNSIGNED),
6032 			     item_param),
6033 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6034 					     hdr.type5.nr)),
6035 	},
6036 	[ITEM_L2TPV2_TYPE_DATA_O] = {
6037 		.name = "data_o",
6038 		.help = "Type #4: data message with offset option",
6039 		.next = NEXT(item_l2tpv2_type_data_o),
6040 		.call = parse_vc_item_l2tpv2_type,
6041 	},
6042 	[ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
6043 		.name = "tunnel_id",
6044 		.help = "tunnel identifier",
6045 		.next = NEXT(item_l2tpv2_type_data_o,
6046 			     NEXT_ENTRY(COMMON_UNSIGNED),
6047 			     item_param),
6048 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6049 					     hdr.type4.tunnel_id)),
6050 	},
6051 	[ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
6052 		.name = "session_id",
6053 		.help = "session identifier",
6054 		.next = NEXT(item_l2tpv2_type_data_o,
6055 			     NEXT_ENTRY(COMMON_UNSIGNED),
6056 			     item_param),
6057 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6058 					     hdr.type5.session_id)),
6059 	},
6060 	[ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
6061 		.name = "offset_size",
6062 		.help = "the size of offset padding",
6063 		.next = NEXT(item_l2tpv2_type_data_o,
6064 			     NEXT_ENTRY(COMMON_UNSIGNED),
6065 			     item_param),
6066 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6067 					     hdr.type4.offset_size)),
6068 	},
6069 	[ITEM_L2TPV2_TYPE_DATA_L_S] = {
6070 		.name = "data_l_s",
6071 		.help = "Type #3: data message contains length, ns, nr "
6072 			"options",
6073 		.next = NEXT(item_l2tpv2_type_data_l_s),
6074 		.call = parse_vc_item_l2tpv2_type,
6075 	},
6076 	[ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
6077 		.name = "length",
6078 		.help = "message length",
6079 		.next = NEXT(item_l2tpv2_type_data_l_s,
6080 			     NEXT_ENTRY(COMMON_UNSIGNED),
6081 			     item_param),
6082 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6083 					     hdr.type3.length)),
6084 	},
6085 	[ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
6086 		.name = "tunnel_id",
6087 		.help = "tunnel identifier",
6088 		.next = NEXT(item_l2tpv2_type_data_l_s,
6089 			     NEXT_ENTRY(COMMON_UNSIGNED),
6090 			     item_param),
6091 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6092 					     hdr.type3.tunnel_id)),
6093 	},
6094 	[ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
6095 		.name = "session_id",
6096 		.help = "session identifier",
6097 		.next = NEXT(item_l2tpv2_type_data_l_s,
6098 			     NEXT_ENTRY(COMMON_UNSIGNED),
6099 			     item_param),
6100 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6101 					     hdr.type3.session_id)),
6102 	},
6103 	[ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
6104 		.name = "ns",
6105 		.help = "sequence number for message",
6106 		.next = NEXT(item_l2tpv2_type_data_l_s,
6107 			     NEXT_ENTRY(COMMON_UNSIGNED),
6108 			     item_param),
6109 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6110 					     hdr.type3.ns)),
6111 	},
6112 	[ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
6113 		.name = "nr",
6114 		.help = "sequence number for next receive message",
6115 		.next = NEXT(item_l2tpv2_type_data_l_s,
6116 			     NEXT_ENTRY(COMMON_UNSIGNED),
6117 			     item_param),
6118 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6119 					     hdr.type3.nr)),
6120 	},
6121 	[ITEM_L2TPV2_TYPE_CTRL] = {
6122 		.name = "control",
6123 		.help = "Type #3: conrtol message contains length, ns, nr "
6124 			"options",
6125 		.next = NEXT(item_l2tpv2_type_ctrl),
6126 		.call = parse_vc_item_l2tpv2_type,
6127 	},
6128 	[ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
6129 		.name = "length",
6130 		.help = "message length",
6131 		.next = NEXT(item_l2tpv2_type_ctrl,
6132 			     NEXT_ENTRY(COMMON_UNSIGNED),
6133 			     item_param),
6134 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6135 					     hdr.type3.length)),
6136 	},
6137 	[ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
6138 		.name = "tunnel_id",
6139 		.help = "tunnel identifier",
6140 		.next = NEXT(item_l2tpv2_type_ctrl,
6141 			     NEXT_ENTRY(COMMON_UNSIGNED),
6142 			     item_param),
6143 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6144 					     hdr.type3.tunnel_id)),
6145 	},
6146 	[ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
6147 		.name = "session_id",
6148 		.help = "session identifier",
6149 		.next = NEXT(item_l2tpv2_type_ctrl,
6150 			     NEXT_ENTRY(COMMON_UNSIGNED),
6151 			     item_param),
6152 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6153 					     hdr.type3.session_id)),
6154 	},
6155 	[ITEM_L2TPV2_MSG_CTRL_NS] = {
6156 		.name = "ns",
6157 		.help = "sequence number for message",
6158 		.next = NEXT(item_l2tpv2_type_ctrl,
6159 			     NEXT_ENTRY(COMMON_UNSIGNED),
6160 			     item_param),
6161 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6162 					     hdr.type3.ns)),
6163 	},
6164 	[ITEM_L2TPV2_MSG_CTRL_NR] = {
6165 		.name = "nr",
6166 		.help = "sequence number for next receive message",
6167 		.next = NEXT(item_l2tpv2_type_ctrl,
6168 			     NEXT_ENTRY(COMMON_UNSIGNED),
6169 			     item_param),
6170 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6171 					     hdr.type3.nr)),
6172 	},
6173 	[ITEM_PPP] = {
6174 		.name = "ppp",
6175 		.help = "match PPP header",
6176 		.priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
6177 		.next = NEXT(item_ppp),
6178 		.call = parse_vc,
6179 	},
6180 	[ITEM_PPP_ADDR] = {
6181 		.name = "addr",
6182 		.help = "PPP address",
6183 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6184 			     item_param),
6185 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
6186 	},
6187 	[ITEM_PPP_CTRL] = {
6188 		.name = "ctrl",
6189 		.help = "PPP control",
6190 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6191 			     item_param),
6192 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
6193 	},
6194 	[ITEM_PPP_PROTO_ID] = {
6195 		.name = "proto_id",
6196 		.help = "PPP protocol identifier",
6197 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6198 			     item_param),
6199 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
6200 					hdr.proto_id)),
6201 	},
6202 	[ITEM_METER] = {
6203 		.name = "meter",
6204 		.help = "match meter color",
6205 		.priv = PRIV_ITEM(METER_COLOR,
6206 				  sizeof(struct rte_flow_item_meter_color)),
6207 		.next = NEXT(item_meter),
6208 		.call = parse_vc,
6209 	},
6210 	[ITEM_METER_COLOR] = {
6211 		.name = "color",
6212 		.help = "meter color",
6213 		.next = NEXT(item_meter,
6214 			     NEXT_ENTRY(ITEM_METER_COLOR_NAME),
6215 			     item_param),
6216 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_meter_color,
6217 					color)),
6218 	},
6219 	[ITEM_METER_COLOR_NAME] = {
6220 		.name = "color_name",
6221 		.help = "meter color name",
6222 		.call = parse_meter_color,
6223 		.comp = comp_meter_color,
6224 	},
6225 	[ITEM_QUOTA] = {
6226 		.name = "quota",
6227 		.help = "match quota",
6228 		.priv = PRIV_ITEM(QUOTA, sizeof(struct rte_flow_item_quota)),
6229 		.next = NEXT(item_quota),
6230 		.call = parse_vc
6231 	},
6232 	[ITEM_QUOTA_STATE] = {
6233 		.name = "quota_state",
6234 		.help = "quota state",
6235 		.next = NEXT(item_quota, NEXT_ENTRY(ITEM_QUOTA_STATE_NAME),
6236 			     NEXT_ENTRY(ITEM_PARAM_SPEC, ITEM_PARAM_MASK)),
6237 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_quota, state))
6238 	},
6239 	[ITEM_QUOTA_STATE_NAME] = {
6240 		.name = "state_name",
6241 		.help = "quota state name",
6242 		.call = parse_quota_state_name,
6243 		.comp = comp_quota_state_name
6244 	},
6245 	[ITEM_IB_BTH] = {
6246 		.name = "ib_bth",
6247 		.help = "match ib bth fields",
6248 		.priv = PRIV_ITEM(IB_BTH,
6249 				  sizeof(struct rte_flow_item_ib_bth)),
6250 		.next = NEXT(item_ib_bth),
6251 		.call = parse_vc,
6252 	},
6253 	[ITEM_IB_BTH_OPCODE] = {
6254 		.name = "opcode",
6255 		.help = "match ib bth opcode",
6256 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6257 				 item_param),
6258 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6259 						 hdr.opcode)),
6260 	},
6261 	[ITEM_IB_BTH_PKEY] = {
6262 		.name = "pkey",
6263 		.help = "partition key",
6264 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6265 				 item_param),
6266 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6267 						 hdr.pkey)),
6268 	},
6269 	[ITEM_IB_BTH_DST_QPN] = {
6270 		.name = "dst_qp",
6271 		.help = "destination qp",
6272 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6273 				 item_param),
6274 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6275 						 hdr.dst_qp)),
6276 	},
6277 	[ITEM_IB_BTH_PSN] = {
6278 		.name = "psn",
6279 		.help = "packet sequence number",
6280 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6281 				 item_param),
6282 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6283 						 hdr.psn)),
6284 	},
6285 	[ITEM_PTYPE] = {
6286 		.name = "ptype",
6287 		.help = "match L2/L3/L4 and tunnel information",
6288 		.priv = PRIV_ITEM(PTYPE,
6289 				  sizeof(struct rte_flow_item_ptype)),
6290 		.next = NEXT(item_ptype),
6291 		.call = parse_vc,
6292 	},
6293 	[ITEM_PTYPE_VALUE] = {
6294 		.name = "packet_type",
6295 		.help = "packet type as defined in rte_mbuf_ptype",
6296 		.next = NEXT(item_ptype, NEXT_ENTRY(COMMON_UNSIGNED),
6297 			     item_param),
6298 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ptype, packet_type)),
6299 	},
6300 	[ITEM_NSH] = {
6301 		.name = "nsh",
6302 		.help = "match NSH header",
6303 		.priv = PRIV_ITEM(NSH,
6304 				  sizeof(struct rte_flow_item_nsh)),
6305 		.next = NEXT(item_nsh),
6306 		.call = parse_vc,
6307 	},
6308 	[ITEM_COMPARE] = {
6309 		.name = "compare",
6310 		.help = "match with the comparison result",
6311 		.priv = PRIV_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
6312 		.next = NEXT(NEXT_ENTRY(ITEM_COMPARE_OP)),
6313 		.call = parse_vc,
6314 	},
6315 	[ITEM_COMPARE_OP] = {
6316 		.name = "op",
6317 		.help = "operation type",
6318 		.next = NEXT(item_compare_field,
6319 			NEXT_ENTRY(ITEM_COMPARE_OP_VALUE), item_param),
6320 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, operation)),
6321 	},
6322 	[ITEM_COMPARE_OP_VALUE] = {
6323 		.name = "{operation}",
6324 		.help = "operation type value",
6325 		.call = parse_vc_compare_op,
6326 		.comp = comp_set_compare_op,
6327 	},
6328 	[ITEM_COMPARE_FIELD_A_TYPE] = {
6329 		.name = "a_type",
6330 		.help = "compared field type",
6331 		.next = NEXT(compare_field_a,
6332 			NEXT_ENTRY(ITEM_COMPARE_FIELD_A_TYPE_VALUE), item_param),
6333 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.field)),
6334 	},
6335 	[ITEM_COMPARE_FIELD_A_TYPE_VALUE] = {
6336 		.name = "{a_type}",
6337 		.help = "compared field type value",
6338 		.call = parse_vc_compare_field_id,
6339 		.comp = comp_set_compare_field_id,
6340 	},
6341 	[ITEM_COMPARE_FIELD_A_LEVEL] = {
6342 		.name = "a_level",
6343 		.help = "compared field level",
6344 		.next = NEXT(compare_field_a,
6345 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_A_LEVEL_VALUE), item_param),
6346 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.level)),
6347 	},
6348 	[ITEM_COMPARE_FIELD_A_LEVEL_VALUE] = {
6349 		.name = "{a_level}",
6350 		.help = "compared field level value",
6351 		.call = parse_vc_compare_field_level,
6352 		.comp = comp_none,
6353 	},
6354 	[ITEM_COMPARE_FIELD_A_TAG_INDEX] = {
6355 		.name = "a_tag_index",
6356 		.help = "compared field tag array",
6357 		.next = NEXT(compare_field_a,
6358 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6359 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6360 					a.tag_index)),
6361 	},
6362 	[ITEM_COMPARE_FIELD_A_TYPE_ID] = {
6363 		.name = "a_type_id",
6364 		.help = "compared field type ID",
6365 		.next = NEXT(compare_field_a,
6366 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6367 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6368 					a.type)),
6369 	},
6370 	[ITEM_COMPARE_FIELD_A_CLASS_ID] = {
6371 		.name = "a_class",
6372 		.help = "compared field class ID",
6373 		.next = NEXT(compare_field_a,
6374 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6375 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6376 					     a.class_id)),
6377 	},
6378 	[ITEM_COMPARE_FIELD_A_OFFSET] = {
6379 		.name = "a_offset",
6380 		.help = "compared field bit offset",
6381 		.next = NEXT(compare_field_a,
6382 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6383 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6384 					a.offset)),
6385 	},
6386 	[ITEM_COMPARE_FIELD_B_TYPE] = {
6387 		.name = "b_type",
6388 		.help = "comparator field type",
6389 		.next = NEXT(compare_field_b,
6390 			NEXT_ENTRY(ITEM_COMPARE_FIELD_B_TYPE_VALUE), item_param),
6391 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6392 					b.field)),
6393 	},
6394 	[ITEM_COMPARE_FIELD_B_TYPE_VALUE] = {
6395 		.name = "{b_type}",
6396 		.help = "comparator field type value",
6397 		.call = parse_vc_compare_field_id,
6398 		.comp = comp_set_compare_field_id,
6399 	},
6400 	[ITEM_COMPARE_FIELD_B_LEVEL] = {
6401 		.name = "b_level",
6402 		.help = "comparator field level",
6403 		.next = NEXT(compare_field_b,
6404 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_B_LEVEL_VALUE), item_param),
6405 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6406 					b.level)),
6407 	},
6408 	[ITEM_COMPARE_FIELD_B_LEVEL_VALUE] = {
6409 		.name = "{b_level}",
6410 		.help = "comparator field level value",
6411 		.call = parse_vc_compare_field_level,
6412 		.comp = comp_none,
6413 	},
6414 	[ITEM_COMPARE_FIELD_B_TAG_INDEX] = {
6415 		.name = "b_tag_index",
6416 		.help = "comparator field tag array",
6417 		.next = NEXT(compare_field_b,
6418 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6419 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6420 					b.tag_index)),
6421 	},
6422 	[ITEM_COMPARE_FIELD_B_TYPE_ID] = {
6423 		.name = "b_type_id",
6424 		.help = "comparator field type ID",
6425 		.next = NEXT(compare_field_b,
6426 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6427 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6428 					b.type)),
6429 	},
6430 	[ITEM_COMPARE_FIELD_B_CLASS_ID] = {
6431 		.name = "b_class",
6432 		.help = "comparator field class ID",
6433 		.next = NEXT(compare_field_b,
6434 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6435 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6436 					     b.class_id)),
6437 	},
6438 	[ITEM_COMPARE_FIELD_B_OFFSET] = {
6439 		.name = "b_offset",
6440 		.help = "comparator field bit offset",
6441 		.next = NEXT(compare_field_b,
6442 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6443 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6444 					b.offset)),
6445 	},
6446 	[ITEM_COMPARE_FIELD_B_VALUE] = {
6447 		.name = "b_value",
6448 		.help = "comparator immediate value",
6449 		.next = NEXT(compare_field_b,
6450 			     NEXT_ENTRY(COMMON_HEX), item_param),
6451 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
6452 			     ARGS_ENTRY_ARB(0, 0),
6453 			     ARGS_ENTRY(struct rte_flow_item_compare,
6454 					b.value)),
6455 	},
6456 	[ITEM_COMPARE_FIELD_B_POINTER] = {
6457 		.name = "b_ptr",
6458 		.help = "pointer to comparator immediate value",
6459 		.next = NEXT(compare_field_b,
6460 			     NEXT_ENTRY(COMMON_HEX), item_param),
6461 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6462 					b.pvalue),
6463 			     ARGS_ENTRY_ARB(0, 0),
6464 			     ARGS_ENTRY_ARB
6465 				(sizeof(struct rte_flow_item_compare),
6466 				 FLOW_FIELD_PATTERN_SIZE)),
6467 	},
6468 	[ITEM_COMPARE_FIELD_WIDTH] = {
6469 		.name = "width",
6470 		.help = "number of bits to compare",
6471 		.next = NEXT(item_compare_field,
6472 			NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6473 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6474 					width)),
6475 	},
6476 
6477 	/* Validate/create actions. */
6478 	[ACTIONS] = {
6479 		.name = "actions",
6480 		.help = "submit a list of associated actions",
6481 		.next = NEXT(next_action),
6482 		.call = parse_vc,
6483 	},
6484 	[ACTION_NEXT] = {
6485 		.name = "/",
6486 		.help = "specify next action",
6487 		.next = NEXT(next_action),
6488 	},
6489 	[ACTION_END] = {
6490 		.name = "end",
6491 		.help = "end list of actions",
6492 		.priv = PRIV_ACTION(END, 0),
6493 		.call = parse_vc,
6494 	},
6495 	[ACTION_VOID] = {
6496 		.name = "void",
6497 		.help = "no-op action",
6498 		.priv = PRIV_ACTION(VOID, 0),
6499 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6500 		.call = parse_vc,
6501 	},
6502 	[ACTION_PASSTHRU] = {
6503 		.name = "passthru",
6504 		.help = "let subsequent rule process matched packets",
6505 		.priv = PRIV_ACTION(PASSTHRU, 0),
6506 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6507 		.call = parse_vc,
6508 	},
6509 	[ACTION_SKIP_CMAN] = {
6510 		.name = "skip_cman",
6511 		.help = "bypass cman on received packets",
6512 		.priv = PRIV_ACTION(SKIP_CMAN, 0),
6513 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6514 		.call = parse_vc,
6515 	},
6516 	[ACTION_JUMP] = {
6517 		.name = "jump",
6518 		.help = "redirect traffic to a given group",
6519 		.priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
6520 		.next = NEXT(action_jump),
6521 		.call = parse_vc,
6522 	},
6523 	[ACTION_JUMP_GROUP] = {
6524 		.name = "group",
6525 		.help = "group to redirect traffic to",
6526 		.next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
6527 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
6528 		.call = parse_vc_conf,
6529 	},
6530 	[ACTION_MARK] = {
6531 		.name = "mark",
6532 		.help = "attach 32 bit value to packets",
6533 		.priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
6534 		.next = NEXT(action_mark),
6535 		.call = parse_vc,
6536 	},
6537 	[ACTION_MARK_ID] = {
6538 		.name = "id",
6539 		.help = "32 bit value to return with packets",
6540 		.next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6541 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
6542 		.call = parse_vc_conf,
6543 	},
6544 	[ACTION_FLAG] = {
6545 		.name = "flag",
6546 		.help = "flag packets",
6547 		.priv = PRIV_ACTION(FLAG, 0),
6548 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6549 		.call = parse_vc,
6550 	},
6551 	[ACTION_QUEUE] = {
6552 		.name = "queue",
6553 		.help = "assign packets to a given queue index",
6554 		.priv = PRIV_ACTION(QUEUE,
6555 				    sizeof(struct rte_flow_action_queue)),
6556 		.next = NEXT(action_queue),
6557 		.call = parse_vc,
6558 	},
6559 	[ACTION_QUEUE_INDEX] = {
6560 		.name = "index",
6561 		.help = "queue index to use",
6562 		.next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
6563 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
6564 		.call = parse_vc_conf,
6565 	},
6566 	[ACTION_DROP] = {
6567 		.name = "drop",
6568 		.help = "drop packets (note: passthru has priority)",
6569 		.priv = PRIV_ACTION(DROP, 0),
6570 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6571 		.call = parse_vc,
6572 	},
6573 	[ACTION_COUNT] = {
6574 		.name = "count",
6575 		.help = "enable counters for this rule",
6576 		.priv = PRIV_ACTION(COUNT,
6577 				    sizeof(struct rte_flow_action_count)),
6578 		.next = NEXT(action_count),
6579 		.call = parse_vc,
6580 	},
6581 	[ACTION_COUNT_ID] = {
6582 		.name = "identifier",
6583 		.help = "counter identifier to use",
6584 		.next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
6585 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
6586 		.call = parse_vc_conf,
6587 	},
6588 	[ACTION_RSS] = {
6589 		.name = "rss",
6590 		.help = "spread packets among several queues",
6591 		.priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
6592 		.next = NEXT(action_rss),
6593 		.call = parse_vc_action_rss,
6594 	},
6595 	[ACTION_RSS_FUNC] = {
6596 		.name = "func",
6597 		.help = "RSS hash function to apply",
6598 		.next = NEXT(action_rss,
6599 			     NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
6600 					ACTION_RSS_FUNC_TOEPLITZ,
6601 					ACTION_RSS_FUNC_SIMPLE_XOR,
6602 					ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
6603 	},
6604 	[ACTION_RSS_FUNC_DEFAULT] = {
6605 		.name = "default",
6606 		.help = "default hash function",
6607 		.call = parse_vc_action_rss_func,
6608 	},
6609 	[ACTION_RSS_FUNC_TOEPLITZ] = {
6610 		.name = "toeplitz",
6611 		.help = "Toeplitz hash function",
6612 		.call = parse_vc_action_rss_func,
6613 	},
6614 	[ACTION_RSS_FUNC_SIMPLE_XOR] = {
6615 		.name = "simple_xor",
6616 		.help = "simple XOR hash function",
6617 		.call = parse_vc_action_rss_func,
6618 	},
6619 	[ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
6620 		.name = "symmetric_toeplitz",
6621 		.help = "Symmetric Toeplitz hash function",
6622 		.call = parse_vc_action_rss_func,
6623 	},
6624 	[ACTION_RSS_LEVEL] = {
6625 		.name = "level",
6626 		.help = "encapsulation level for \"types\"",
6627 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6628 		.args = ARGS(ARGS_ENTRY_ARB
6629 			     (offsetof(struct action_rss_data, conf) +
6630 			      offsetof(struct rte_flow_action_rss, level),
6631 			      sizeof(((struct rte_flow_action_rss *)0)->
6632 				     level))),
6633 	},
6634 	[ACTION_RSS_TYPES] = {
6635 		.name = "types",
6636 		.help = "specific RSS hash types",
6637 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
6638 	},
6639 	[ACTION_RSS_TYPE] = {
6640 		.name = "{type}",
6641 		.help = "RSS hash type",
6642 		.call = parse_vc_action_rss_type,
6643 		.comp = comp_vc_action_rss_type,
6644 	},
6645 	[ACTION_RSS_KEY] = {
6646 		.name = "key",
6647 		.help = "RSS hash key",
6648 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
6649 		.args = ARGS(ARGS_ENTRY_ARB
6650 			     (offsetof(struct action_rss_data, conf) +
6651 			      offsetof(struct rte_flow_action_rss, key),
6652 			      sizeof(((struct rte_flow_action_rss *)0)->key)),
6653 			     ARGS_ENTRY_ARB
6654 			     (offsetof(struct action_rss_data, conf) +
6655 			      offsetof(struct rte_flow_action_rss, key_len),
6656 			      sizeof(((struct rte_flow_action_rss *)0)->
6657 				     key_len)),
6658 			     ARGS_ENTRY(struct action_rss_data, key)),
6659 	},
6660 	[ACTION_RSS_KEY_LEN] = {
6661 		.name = "key_len",
6662 		.help = "RSS hash key length in bytes",
6663 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6664 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
6665 			     (offsetof(struct action_rss_data, conf) +
6666 			      offsetof(struct rte_flow_action_rss, key_len),
6667 			      sizeof(((struct rte_flow_action_rss *)0)->
6668 				     key_len),
6669 			      0,
6670 			      RSS_HASH_KEY_LENGTH)),
6671 	},
6672 	[ACTION_RSS_QUEUES] = {
6673 		.name = "queues",
6674 		.help = "queue indices to use",
6675 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
6676 		.call = parse_vc_conf,
6677 	},
6678 	[ACTION_RSS_QUEUE] = {
6679 		.name = "{queue}",
6680 		.help = "queue index",
6681 		.call = parse_vc_action_rss_queue,
6682 		.comp = comp_vc_action_rss_queue,
6683 	},
6684 	[ACTION_PF] = {
6685 		.name = "pf",
6686 		.help = "direct traffic to physical function",
6687 		.priv = PRIV_ACTION(PF, 0),
6688 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6689 		.call = parse_vc,
6690 	},
6691 	[ACTION_VF] = {
6692 		.name = "vf",
6693 		.help = "direct traffic to a virtual function ID",
6694 		.priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
6695 		.next = NEXT(action_vf),
6696 		.call = parse_vc,
6697 	},
6698 	[ACTION_VF_ORIGINAL] = {
6699 		.name = "original",
6700 		.help = "use original VF ID if possible",
6701 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
6702 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
6703 					   original, 1)),
6704 		.call = parse_vc_conf,
6705 	},
6706 	[ACTION_VF_ID] = {
6707 		.name = "id",
6708 		.help = "VF ID",
6709 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
6710 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
6711 		.call = parse_vc_conf,
6712 	},
6713 	[ACTION_PORT_ID] = {
6714 		.name = "port_id",
6715 		.help = "direct matching traffic to a given DPDK port ID",
6716 		.priv = PRIV_ACTION(PORT_ID,
6717 				    sizeof(struct rte_flow_action_port_id)),
6718 		.next = NEXT(action_port_id),
6719 		.call = parse_vc,
6720 	},
6721 	[ACTION_PORT_ID_ORIGINAL] = {
6722 		.name = "original",
6723 		.help = "use original DPDK port ID if possible",
6724 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
6725 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
6726 					   original, 1)),
6727 		.call = parse_vc_conf,
6728 	},
6729 	[ACTION_PORT_ID_ID] = {
6730 		.name = "id",
6731 		.help = "DPDK port ID",
6732 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
6733 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
6734 		.call = parse_vc_conf,
6735 	},
6736 	[ACTION_METER] = {
6737 		.name = "meter",
6738 		.help = "meter the directed packets at given id",
6739 		.priv = PRIV_ACTION(METER,
6740 				    sizeof(struct rte_flow_action_meter)),
6741 		.next = NEXT(action_meter),
6742 		.call = parse_vc,
6743 	},
6744 	[ACTION_METER_COLOR] = {
6745 		.name = "color",
6746 		.help = "meter color for the packets",
6747 		.priv = PRIV_ACTION(METER_COLOR,
6748 				sizeof(struct rte_flow_action_meter_color)),
6749 		.next = NEXT(action_meter_color),
6750 		.call = parse_vc,
6751 	},
6752 	[ACTION_METER_COLOR_TYPE] = {
6753 		.name = "type",
6754 		.help = "specific meter color",
6755 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
6756 				NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
6757 					ACTION_METER_COLOR_YELLOW,
6758 					ACTION_METER_COLOR_RED)),
6759 	},
6760 	[ACTION_METER_COLOR_GREEN] = {
6761 		.name = "green",
6762 		.help = "meter color green",
6763 		.call = parse_vc_action_meter_color_type,
6764 	},
6765 	[ACTION_METER_COLOR_YELLOW] = {
6766 		.name = "yellow",
6767 		.help = "meter color yellow",
6768 		.call = parse_vc_action_meter_color_type,
6769 	},
6770 	[ACTION_METER_COLOR_RED] = {
6771 		.name = "red",
6772 		.help = "meter color red",
6773 		.call = parse_vc_action_meter_color_type,
6774 	},
6775 	[ACTION_METER_ID] = {
6776 		.name = "mtr_id",
6777 		.help = "meter id to use",
6778 		.next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
6779 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
6780 		.call = parse_vc_conf,
6781 	},
6782 	[ACTION_METER_MARK] = {
6783 		.name = "meter_mark",
6784 		.help = "meter the directed packets using profile and policy",
6785 		.priv = PRIV_ACTION(METER_MARK,
6786 				    sizeof(struct rte_flow_action_meter_mark)),
6787 		.next = NEXT(action_meter_mark),
6788 		.call = parse_vc,
6789 	},
6790 	[ACTION_METER_PROFILE] = {
6791 		.name = "mtr_profile",
6792 		.help = "meter profile id to use",
6793 		.next = NEXT(NEXT_ENTRY(ACTION_METER_PROFILE_ID2PTR)),
6794 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6795 	},
6796 	[ACTION_METER_PROFILE_ID2PTR] = {
6797 		.name = "{mtr_profile_id}",
6798 		.type = "PROFILE_ID",
6799 		.help = "meter profile id",
6800 		.next = NEXT(action_meter_mark),
6801 		.call = parse_meter_profile_id2ptr,
6802 		.comp = comp_none,
6803 	},
6804 	[ACTION_METER_POLICY] = {
6805 		.name = "mtr_policy",
6806 		.help = "meter policy id to use",
6807 		.next = NEXT(NEXT_ENTRY(ACTION_METER_POLICY_ID2PTR)),
6808 		ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6809 	},
6810 	[ACTION_METER_POLICY_ID2PTR] = {
6811 		.name = "{mtr_policy_id}",
6812 		.type = "POLICY_ID",
6813 		.help = "meter policy id",
6814 		.next = NEXT(action_meter_mark),
6815 		.call = parse_meter_policy_id2ptr,
6816 		.comp = comp_none,
6817 	},
6818 	[ACTION_METER_COLOR_MODE] = {
6819 		.name = "mtr_color_mode",
6820 		.help = "meter color awareness mode",
6821 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6822 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, color_mode)),
6823 		.call = parse_vc_conf,
6824 	},
6825 	[ACTION_METER_STATE] = {
6826 		.name = "mtr_state",
6827 		.help = "meter state",
6828 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6829 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, state)),
6830 		.call = parse_vc_conf,
6831 	},
6832 	[ACTION_OF_DEC_NW_TTL] = {
6833 		.name = "of_dec_nw_ttl",
6834 		.help = "OpenFlow's OFPAT_DEC_NW_TTL",
6835 		.priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
6836 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6837 		.call = parse_vc,
6838 	},
6839 	[ACTION_OF_POP_VLAN] = {
6840 		.name = "of_pop_vlan",
6841 		.help = "OpenFlow's OFPAT_POP_VLAN",
6842 		.priv = PRIV_ACTION(OF_POP_VLAN, 0),
6843 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6844 		.call = parse_vc,
6845 	},
6846 	[ACTION_OF_PUSH_VLAN] = {
6847 		.name = "of_push_vlan",
6848 		.help = "OpenFlow's OFPAT_PUSH_VLAN",
6849 		.priv = PRIV_ACTION
6850 			(OF_PUSH_VLAN,
6851 			 sizeof(struct rte_flow_action_of_push_vlan)),
6852 		.next = NEXT(action_of_push_vlan),
6853 		.call = parse_vc,
6854 	},
6855 	[ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
6856 		.name = "ethertype",
6857 		.help = "EtherType",
6858 		.next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
6859 		.args = ARGS(ARGS_ENTRY_HTON
6860 			     (struct rte_flow_action_of_push_vlan,
6861 			      ethertype)),
6862 		.call = parse_vc_conf,
6863 	},
6864 	[ACTION_OF_SET_VLAN_VID] = {
6865 		.name = "of_set_vlan_vid",
6866 		.help = "OpenFlow's OFPAT_SET_VLAN_VID",
6867 		.priv = PRIV_ACTION
6868 			(OF_SET_VLAN_VID,
6869 			 sizeof(struct rte_flow_action_of_set_vlan_vid)),
6870 		.next = NEXT(action_of_set_vlan_vid),
6871 		.call = parse_vc,
6872 	},
6873 	[ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
6874 		.name = "vlan_vid",
6875 		.help = "VLAN id",
6876 		.next = NEXT(action_of_set_vlan_vid,
6877 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6878 		.args = ARGS(ARGS_ENTRY_HTON
6879 			     (struct rte_flow_action_of_set_vlan_vid,
6880 			      vlan_vid)),
6881 		.call = parse_vc_conf,
6882 	},
6883 	[ACTION_OF_SET_VLAN_PCP] = {
6884 		.name = "of_set_vlan_pcp",
6885 		.help = "OpenFlow's OFPAT_SET_VLAN_PCP",
6886 		.priv = PRIV_ACTION
6887 			(OF_SET_VLAN_PCP,
6888 			 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
6889 		.next = NEXT(action_of_set_vlan_pcp),
6890 		.call = parse_vc,
6891 	},
6892 	[ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
6893 		.name = "vlan_pcp",
6894 		.help = "VLAN priority",
6895 		.next = NEXT(action_of_set_vlan_pcp,
6896 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6897 		.args = ARGS(ARGS_ENTRY_HTON
6898 			     (struct rte_flow_action_of_set_vlan_pcp,
6899 			      vlan_pcp)),
6900 		.call = parse_vc_conf,
6901 	},
6902 	[ACTION_OF_POP_MPLS] = {
6903 		.name = "of_pop_mpls",
6904 		.help = "OpenFlow's OFPAT_POP_MPLS",
6905 		.priv = PRIV_ACTION(OF_POP_MPLS,
6906 				    sizeof(struct rte_flow_action_of_pop_mpls)),
6907 		.next = NEXT(action_of_pop_mpls),
6908 		.call = parse_vc,
6909 	},
6910 	[ACTION_OF_POP_MPLS_ETHERTYPE] = {
6911 		.name = "ethertype",
6912 		.help = "EtherType",
6913 		.next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6914 		.args = ARGS(ARGS_ENTRY_HTON
6915 			     (struct rte_flow_action_of_pop_mpls,
6916 			      ethertype)),
6917 		.call = parse_vc_conf,
6918 	},
6919 	[ACTION_OF_PUSH_MPLS] = {
6920 		.name = "of_push_mpls",
6921 		.help = "OpenFlow's OFPAT_PUSH_MPLS",
6922 		.priv = PRIV_ACTION
6923 			(OF_PUSH_MPLS,
6924 			 sizeof(struct rte_flow_action_of_push_mpls)),
6925 		.next = NEXT(action_of_push_mpls),
6926 		.call = parse_vc,
6927 	},
6928 	[ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
6929 		.name = "ethertype",
6930 		.help = "EtherType",
6931 		.next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6932 		.args = ARGS(ARGS_ENTRY_HTON
6933 			     (struct rte_flow_action_of_push_mpls,
6934 			      ethertype)),
6935 		.call = parse_vc_conf,
6936 	},
6937 	[ACTION_VXLAN_ENCAP] = {
6938 		.name = "vxlan_encap",
6939 		.help = "VXLAN encapsulation, uses configuration set by \"set"
6940 			" vxlan\"",
6941 		.priv = PRIV_ACTION(VXLAN_ENCAP,
6942 				    sizeof(struct action_vxlan_encap_data)),
6943 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6944 		.call = parse_vc_action_vxlan_encap,
6945 	},
6946 	[ACTION_VXLAN_DECAP] = {
6947 		.name = "vxlan_decap",
6948 		.help = "Performs a decapsulation action by stripping all"
6949 			" headers of the VXLAN tunnel network overlay from the"
6950 			" matched flow.",
6951 		.priv = PRIV_ACTION(VXLAN_DECAP, 0),
6952 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6953 		.call = parse_vc,
6954 	},
6955 	[ACTION_NVGRE_ENCAP] = {
6956 		.name = "nvgre_encap",
6957 		.help = "NVGRE encapsulation, uses configuration set by \"set"
6958 			" nvgre\"",
6959 		.priv = PRIV_ACTION(NVGRE_ENCAP,
6960 				    sizeof(struct action_nvgre_encap_data)),
6961 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6962 		.call = parse_vc_action_nvgre_encap,
6963 	},
6964 	[ACTION_NVGRE_DECAP] = {
6965 		.name = "nvgre_decap",
6966 		.help = "Performs a decapsulation action by stripping all"
6967 			" headers of the NVGRE tunnel network overlay from the"
6968 			" matched flow.",
6969 		.priv = PRIV_ACTION(NVGRE_DECAP, 0),
6970 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6971 		.call = parse_vc,
6972 	},
6973 	[ACTION_L2_ENCAP] = {
6974 		.name = "l2_encap",
6975 		.help = "l2 encap, uses configuration set by"
6976 			" \"set l2_encap\"",
6977 		.priv = PRIV_ACTION(RAW_ENCAP,
6978 				    sizeof(struct action_raw_encap_data)),
6979 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6980 		.call = parse_vc_action_l2_encap,
6981 	},
6982 	[ACTION_L2_DECAP] = {
6983 		.name = "l2_decap",
6984 		.help = "l2 decap, uses configuration set by"
6985 			" \"set l2_decap\"",
6986 		.priv = PRIV_ACTION(RAW_DECAP,
6987 				    sizeof(struct action_raw_decap_data)),
6988 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6989 		.call = parse_vc_action_l2_decap,
6990 	},
6991 	[ACTION_MPLSOGRE_ENCAP] = {
6992 		.name = "mplsogre_encap",
6993 		.help = "mplsogre encapsulation, uses configuration set by"
6994 			" \"set mplsogre_encap\"",
6995 		.priv = PRIV_ACTION(RAW_ENCAP,
6996 				    sizeof(struct action_raw_encap_data)),
6997 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6998 		.call = parse_vc_action_mplsogre_encap,
6999 	},
7000 	[ACTION_MPLSOGRE_DECAP] = {
7001 		.name = "mplsogre_decap",
7002 		.help = "mplsogre decapsulation, uses configuration set by"
7003 			" \"set mplsogre_decap\"",
7004 		.priv = PRIV_ACTION(RAW_DECAP,
7005 				    sizeof(struct action_raw_decap_data)),
7006 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7007 		.call = parse_vc_action_mplsogre_decap,
7008 	},
7009 	[ACTION_MPLSOUDP_ENCAP] = {
7010 		.name = "mplsoudp_encap",
7011 		.help = "mplsoudp encapsulation, uses configuration set by"
7012 			" \"set mplsoudp_encap\"",
7013 		.priv = PRIV_ACTION(RAW_ENCAP,
7014 				    sizeof(struct action_raw_encap_data)),
7015 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7016 		.call = parse_vc_action_mplsoudp_encap,
7017 	},
7018 	[ACTION_MPLSOUDP_DECAP] = {
7019 		.name = "mplsoudp_decap",
7020 		.help = "mplsoudp decapsulation, uses configuration set by"
7021 			" \"set mplsoudp_decap\"",
7022 		.priv = PRIV_ACTION(RAW_DECAP,
7023 				    sizeof(struct action_raw_decap_data)),
7024 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7025 		.call = parse_vc_action_mplsoudp_decap,
7026 	},
7027 	[ACTION_SET_IPV4_SRC] = {
7028 		.name = "set_ipv4_src",
7029 		.help = "Set a new IPv4 source address in the outermost"
7030 			" IPv4 header",
7031 		.priv = PRIV_ACTION(SET_IPV4_SRC,
7032 			sizeof(struct rte_flow_action_set_ipv4)),
7033 		.next = NEXT(action_set_ipv4_src),
7034 		.call = parse_vc,
7035 	},
7036 	[ACTION_SET_IPV4_SRC_IPV4_SRC] = {
7037 		.name = "ipv4_addr",
7038 		.help = "new IPv4 source address to set",
7039 		.next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
7040 		.args = ARGS(ARGS_ENTRY_HTON
7041 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
7042 		.call = parse_vc_conf,
7043 	},
7044 	[ACTION_SET_IPV4_DST] = {
7045 		.name = "set_ipv4_dst",
7046 		.help = "Set a new IPv4 destination address in the outermost"
7047 			" IPv4 header",
7048 		.priv = PRIV_ACTION(SET_IPV4_DST,
7049 			sizeof(struct rte_flow_action_set_ipv4)),
7050 		.next = NEXT(action_set_ipv4_dst),
7051 		.call = parse_vc,
7052 	},
7053 	[ACTION_SET_IPV4_DST_IPV4_DST] = {
7054 		.name = "ipv4_addr",
7055 		.help = "new IPv4 destination address to set",
7056 		.next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
7057 		.args = ARGS(ARGS_ENTRY_HTON
7058 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
7059 		.call = parse_vc_conf,
7060 	},
7061 	[ACTION_SET_IPV6_SRC] = {
7062 		.name = "set_ipv6_src",
7063 		.help = "Set a new IPv6 source address in the outermost"
7064 			" IPv6 header",
7065 		.priv = PRIV_ACTION(SET_IPV6_SRC,
7066 			sizeof(struct rte_flow_action_set_ipv6)),
7067 		.next = NEXT(action_set_ipv6_src),
7068 		.call = parse_vc,
7069 	},
7070 	[ACTION_SET_IPV6_SRC_IPV6_SRC] = {
7071 		.name = "ipv6_addr",
7072 		.help = "new IPv6 source address to set",
7073 		.next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
7074 		.args = ARGS(ARGS_ENTRY_HTON
7075 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
7076 		.call = parse_vc_conf,
7077 	},
7078 	[ACTION_SET_IPV6_DST] = {
7079 		.name = "set_ipv6_dst",
7080 		.help = "Set a new IPv6 destination address in the outermost"
7081 			" IPv6 header",
7082 		.priv = PRIV_ACTION(SET_IPV6_DST,
7083 			sizeof(struct rte_flow_action_set_ipv6)),
7084 		.next = NEXT(action_set_ipv6_dst),
7085 		.call = parse_vc,
7086 	},
7087 	[ACTION_SET_IPV6_DST_IPV6_DST] = {
7088 		.name = "ipv6_addr",
7089 		.help = "new IPv6 destination address to set",
7090 		.next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
7091 		.args = ARGS(ARGS_ENTRY_HTON
7092 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
7093 		.call = parse_vc_conf,
7094 	},
7095 	[ACTION_SET_TP_SRC] = {
7096 		.name = "set_tp_src",
7097 		.help = "set a new source port number in the outermost"
7098 			" TCP/UDP header",
7099 		.priv = PRIV_ACTION(SET_TP_SRC,
7100 			sizeof(struct rte_flow_action_set_tp)),
7101 		.next = NEXT(action_set_tp_src),
7102 		.call = parse_vc,
7103 	},
7104 	[ACTION_SET_TP_SRC_TP_SRC] = {
7105 		.name = "port",
7106 		.help = "new source port number to set",
7107 		.next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
7108 		.args = ARGS(ARGS_ENTRY_HTON
7109 			     (struct rte_flow_action_set_tp, port)),
7110 		.call = parse_vc_conf,
7111 	},
7112 	[ACTION_SET_TP_DST] = {
7113 		.name = "set_tp_dst",
7114 		.help = "set a new destination port number in the outermost"
7115 			" TCP/UDP header",
7116 		.priv = PRIV_ACTION(SET_TP_DST,
7117 			sizeof(struct rte_flow_action_set_tp)),
7118 		.next = NEXT(action_set_tp_dst),
7119 		.call = parse_vc,
7120 	},
7121 	[ACTION_SET_TP_DST_TP_DST] = {
7122 		.name = "port",
7123 		.help = "new destination port number to set",
7124 		.next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
7125 		.args = ARGS(ARGS_ENTRY_HTON
7126 			     (struct rte_flow_action_set_tp, port)),
7127 		.call = parse_vc_conf,
7128 	},
7129 	[ACTION_MAC_SWAP] = {
7130 		.name = "mac_swap",
7131 		.help = "Swap the source and destination MAC addresses"
7132 			" in the outermost Ethernet header",
7133 		.priv = PRIV_ACTION(MAC_SWAP, 0),
7134 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7135 		.call = parse_vc,
7136 	},
7137 	[ACTION_DEC_TTL] = {
7138 		.name = "dec_ttl",
7139 		.help = "decrease network TTL if available",
7140 		.priv = PRIV_ACTION(DEC_TTL, 0),
7141 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7142 		.call = parse_vc,
7143 	},
7144 	[ACTION_SET_TTL] = {
7145 		.name = "set_ttl",
7146 		.help = "set ttl value",
7147 		.priv = PRIV_ACTION(SET_TTL,
7148 			sizeof(struct rte_flow_action_set_ttl)),
7149 		.next = NEXT(action_set_ttl),
7150 		.call = parse_vc,
7151 	},
7152 	[ACTION_SET_TTL_TTL] = {
7153 		.name = "ttl_value",
7154 		.help = "new ttl value to set",
7155 		.next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
7156 		.args = ARGS(ARGS_ENTRY_HTON
7157 			     (struct rte_flow_action_set_ttl, ttl_value)),
7158 		.call = parse_vc_conf,
7159 	},
7160 	[ACTION_SET_MAC_SRC] = {
7161 		.name = "set_mac_src",
7162 		.help = "set source mac address",
7163 		.priv = PRIV_ACTION(SET_MAC_SRC,
7164 			sizeof(struct rte_flow_action_set_mac)),
7165 		.next = NEXT(action_set_mac_src),
7166 		.call = parse_vc,
7167 	},
7168 	[ACTION_SET_MAC_SRC_MAC_SRC] = {
7169 		.name = "mac_addr",
7170 		.help = "new source mac address",
7171 		.next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
7172 		.args = ARGS(ARGS_ENTRY_HTON
7173 			     (struct rte_flow_action_set_mac, mac_addr)),
7174 		.call = parse_vc_conf,
7175 	},
7176 	[ACTION_SET_MAC_DST] = {
7177 		.name = "set_mac_dst",
7178 		.help = "set destination mac address",
7179 		.priv = PRIV_ACTION(SET_MAC_DST,
7180 			sizeof(struct rte_flow_action_set_mac)),
7181 		.next = NEXT(action_set_mac_dst),
7182 		.call = parse_vc,
7183 	},
7184 	[ACTION_SET_MAC_DST_MAC_DST] = {
7185 		.name = "mac_addr",
7186 		.help = "new destination mac address to set",
7187 		.next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
7188 		.args = ARGS(ARGS_ENTRY_HTON
7189 			     (struct rte_flow_action_set_mac, mac_addr)),
7190 		.call = parse_vc_conf,
7191 	},
7192 	[ACTION_INC_TCP_SEQ] = {
7193 		.name = "inc_tcp_seq",
7194 		.help = "increase TCP sequence number",
7195 		.priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
7196 		.next = NEXT(action_inc_tcp_seq),
7197 		.call = parse_vc,
7198 	},
7199 	[ACTION_INC_TCP_SEQ_VALUE] = {
7200 		.name = "value",
7201 		.help = "the value to increase TCP sequence number by",
7202 		.next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7203 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7204 		.call = parse_vc_conf,
7205 	},
7206 	[ACTION_DEC_TCP_SEQ] = {
7207 		.name = "dec_tcp_seq",
7208 		.help = "decrease TCP sequence number",
7209 		.priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
7210 		.next = NEXT(action_dec_tcp_seq),
7211 		.call = parse_vc,
7212 	},
7213 	[ACTION_DEC_TCP_SEQ_VALUE] = {
7214 		.name = "value",
7215 		.help = "the value to decrease TCP sequence number by",
7216 		.next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7217 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7218 		.call = parse_vc_conf,
7219 	},
7220 	[ACTION_INC_TCP_ACK] = {
7221 		.name = "inc_tcp_ack",
7222 		.help = "increase TCP acknowledgment number",
7223 		.priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
7224 		.next = NEXT(action_inc_tcp_ack),
7225 		.call = parse_vc,
7226 	},
7227 	[ACTION_INC_TCP_ACK_VALUE] = {
7228 		.name = "value",
7229 		.help = "the value to increase TCP acknowledgment number by",
7230 		.next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7231 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7232 		.call = parse_vc_conf,
7233 	},
7234 	[ACTION_DEC_TCP_ACK] = {
7235 		.name = "dec_tcp_ack",
7236 		.help = "decrease TCP acknowledgment number",
7237 		.priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
7238 		.next = NEXT(action_dec_tcp_ack),
7239 		.call = parse_vc,
7240 	},
7241 	[ACTION_DEC_TCP_ACK_VALUE] = {
7242 		.name = "value",
7243 		.help = "the value to decrease TCP acknowledgment number by",
7244 		.next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7245 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7246 		.call = parse_vc_conf,
7247 	},
7248 	[ACTION_RAW_ENCAP] = {
7249 		.name = "raw_encap",
7250 		.help = "encapsulation data, defined by set raw_encap",
7251 		.priv = PRIV_ACTION(RAW_ENCAP,
7252 			sizeof(struct action_raw_encap_data)),
7253 		.next = NEXT(action_raw_encap),
7254 		.call = parse_vc_action_raw_encap,
7255 	},
7256 	[ACTION_RAW_ENCAP_SIZE] = {
7257 		.name = "size",
7258 		.help = "raw encap size",
7259 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7260 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7261 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_raw_encap, size)),
7262 		.call = parse_vc_conf,
7263 	},
7264 	[ACTION_RAW_ENCAP_INDEX] = {
7265 		.name = "index",
7266 		.help = "the index of raw_encap_confs",
7267 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
7268 	},
7269 	[ACTION_RAW_ENCAP_INDEX_VALUE] = {
7270 		.name = "{index}",
7271 		.type = "UNSIGNED",
7272 		.help = "unsigned integer value",
7273 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7274 		.call = parse_vc_action_raw_encap_index,
7275 		.comp = comp_set_raw_index,
7276 	},
7277 	[ACTION_RAW_DECAP] = {
7278 		.name = "raw_decap",
7279 		.help = "decapsulation data, defined by set raw_encap",
7280 		.priv = PRIV_ACTION(RAW_DECAP,
7281 			sizeof(struct action_raw_decap_data)),
7282 		.next = NEXT(action_raw_decap),
7283 		.call = parse_vc_action_raw_decap,
7284 	},
7285 	[ACTION_RAW_DECAP_INDEX] = {
7286 		.name = "index",
7287 		.help = "the index of raw_encap_confs",
7288 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
7289 	},
7290 	[ACTION_RAW_DECAP_INDEX_VALUE] = {
7291 		.name = "{index}",
7292 		.type = "UNSIGNED",
7293 		.help = "unsigned integer value",
7294 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7295 		.call = parse_vc_action_raw_decap_index,
7296 		.comp = comp_set_raw_index,
7297 	},
7298 	[ACTION_MODIFY_FIELD] = {
7299 		.name = "modify_field",
7300 		.help = "modify destination field with data from source field",
7301 		.priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
7302 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
7303 		.call = parse_vc,
7304 	},
7305 	[ACTION_MODIFY_FIELD_OP] = {
7306 		.name = "op",
7307 		.help = "operation type",
7308 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
7309 			NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
7310 		.call = parse_vc_conf,
7311 	},
7312 	[ACTION_MODIFY_FIELD_OP_VALUE] = {
7313 		.name = "{operation}",
7314 		.help = "operation type value",
7315 		.call = parse_vc_modify_field_op,
7316 		.comp = comp_set_modify_field_op,
7317 	},
7318 	[ACTION_MODIFY_FIELD_DST_TYPE] = {
7319 		.name = "dst_type",
7320 		.help = "destination field type",
7321 		.next = NEXT(action_modify_field_dst,
7322 			NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
7323 		.call = parse_vc_conf,
7324 	},
7325 	[ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
7326 		.name = "{dst_type}",
7327 		.help = "destination field type value",
7328 		.call = parse_vc_modify_field_id,
7329 		.comp = comp_set_modify_field_id,
7330 	},
7331 	[ACTION_MODIFY_FIELD_DST_LEVEL] = {
7332 		.name = "dst_level",
7333 		.help = "destination field level",
7334 		.next = NEXT(action_modify_field_dst,
7335 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)),
7336 		.call = parse_vc_conf,
7337 	},
7338 	[ACTION_MODIFY_FIELD_DST_LEVEL_VALUE] = {
7339 		.name = "{dst_level}",
7340 		.help = "destination field level value",
7341 		.call = parse_vc_modify_field_level,
7342 		.comp = comp_none,
7343 	},
7344 	[ACTION_MODIFY_FIELD_DST_TAG_INDEX] = {
7345 		.name = "dst_tag_index",
7346 		.help = "destination field tag array",
7347 		.next = NEXT(action_modify_field_dst,
7348 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7349 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7350 					dst.tag_index)),
7351 		.call = parse_vc_conf,
7352 	},
7353 	[ACTION_MODIFY_FIELD_DST_TYPE_ID] = {
7354 		.name = "dst_type_id",
7355 		.help = "destination field type ID",
7356 		.next = NEXT(action_modify_field_dst,
7357 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7358 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7359 					dst.type)),
7360 		.call = parse_vc_conf,
7361 	},
7362 	[ACTION_MODIFY_FIELD_DST_CLASS_ID] = {
7363 		.name = "dst_class",
7364 		.help = "destination field class ID",
7365 		.next = NEXT(action_modify_field_dst,
7366 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7367 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7368 					     dst.class_id)),
7369 		.call = parse_vc_conf,
7370 	},
7371 	[ACTION_MODIFY_FIELD_DST_OFFSET] = {
7372 		.name = "dst_offset",
7373 		.help = "destination field bit offset",
7374 		.next = NEXT(action_modify_field_dst,
7375 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7376 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7377 					dst.offset)),
7378 		.call = parse_vc_conf,
7379 	},
7380 	[ACTION_MODIFY_FIELD_SRC_TYPE] = {
7381 		.name = "src_type",
7382 		.help = "source field type",
7383 		.next = NEXT(action_modify_field_src,
7384 			NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
7385 		.call = parse_vc_conf,
7386 	},
7387 	[ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
7388 		.name = "{src_type}",
7389 		.help = "source field type value",
7390 		.call = parse_vc_modify_field_id,
7391 		.comp = comp_set_modify_field_id,
7392 	},
7393 	[ACTION_MODIFY_FIELD_SRC_LEVEL] = {
7394 		.name = "src_level",
7395 		.help = "source field level",
7396 		.next = NEXT(action_modify_field_src,
7397 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)),
7398 		.call = parse_vc_conf,
7399 	},
7400 	[ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE] = {
7401 		.name = "{src_level}",
7402 		.help = "source field level value",
7403 		.call = parse_vc_modify_field_level,
7404 		.comp = comp_none,
7405 	},
7406 	[ACTION_MODIFY_FIELD_SRC_TAG_INDEX] = {
7407 		.name = "src_tag_index",
7408 		.help = "source field tag array",
7409 		.next = NEXT(action_modify_field_src,
7410 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7411 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7412 					src.tag_index)),
7413 		.call = parse_vc_conf,
7414 	},
7415 	[ACTION_MODIFY_FIELD_SRC_TYPE_ID] = {
7416 		.name = "src_type_id",
7417 		.help = "source field type ID",
7418 		.next = NEXT(action_modify_field_src,
7419 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7420 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7421 					src.type)),
7422 		.call = parse_vc_conf,
7423 	},
7424 	[ACTION_MODIFY_FIELD_SRC_CLASS_ID] = {
7425 		.name = "src_class",
7426 		.help = "source field class ID",
7427 		.next = NEXT(action_modify_field_src,
7428 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7429 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7430 					     src.class_id)),
7431 		.call = parse_vc_conf,
7432 	},
7433 	[ACTION_MODIFY_FIELD_SRC_OFFSET] = {
7434 		.name = "src_offset",
7435 		.help = "source field bit offset",
7436 		.next = NEXT(action_modify_field_src,
7437 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7438 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7439 					src.offset)),
7440 		.call = parse_vc_conf,
7441 	},
7442 	[ACTION_MODIFY_FIELD_SRC_VALUE] = {
7443 		.name = "src_value",
7444 		.help = "source immediate value",
7445 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7446 			     NEXT_ENTRY(COMMON_HEX)),
7447 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
7448 			     ARGS_ENTRY_ARB(0, 0),
7449 			     ARGS_ENTRY(struct rte_flow_action_modify_field,
7450 					src.value)),
7451 		.call = parse_vc_conf,
7452 	},
7453 	[ACTION_MODIFY_FIELD_SRC_POINTER] = {
7454 		.name = "src_ptr",
7455 		.help = "pointer to source immediate value",
7456 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7457 			     NEXT_ENTRY(COMMON_HEX)),
7458 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7459 					src.pvalue),
7460 			     ARGS_ENTRY_ARB(0, 0),
7461 			     ARGS_ENTRY_ARB
7462 				(sizeof(struct rte_flow_action_modify_field),
7463 				 FLOW_FIELD_PATTERN_SIZE)),
7464 		.call = parse_vc_conf,
7465 	},
7466 	[ACTION_MODIFY_FIELD_WIDTH] = {
7467 		.name = "width",
7468 		.help = "number of bits to copy",
7469 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7470 			NEXT_ENTRY(COMMON_UNSIGNED)),
7471 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7472 					width)),
7473 		.call = parse_vc_conf,
7474 	},
7475 	[ACTION_SEND_TO_KERNEL] = {
7476 		.name = "send_to_kernel",
7477 		.help = "send packets to kernel",
7478 		.priv = PRIV_ACTION(SEND_TO_KERNEL, 0),
7479 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7480 		.call = parse_vc,
7481 	},
7482 	[ACTION_IPV6_EXT_REMOVE] = {
7483 		.name = "ipv6_ext_remove",
7484 		.help = "IPv6 extension type, defined by set ipv6_ext_remove",
7485 		.priv = PRIV_ACTION(IPV6_EXT_REMOVE,
7486 			sizeof(struct action_ipv6_ext_remove_data)),
7487 		.next = NEXT(action_ipv6_ext_remove),
7488 		.call = parse_vc_action_ipv6_ext_remove,
7489 	},
7490 	[ACTION_IPV6_EXT_REMOVE_INDEX] = {
7491 		.name = "index",
7492 		.help = "the index of ipv6_ext_remove",
7493 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_REMOVE_INDEX_VALUE)),
7494 	},
7495 	[ACTION_IPV6_EXT_REMOVE_INDEX_VALUE] = {
7496 		.name = "{index}",
7497 		.type = "UNSIGNED",
7498 		.help = "unsigned integer value",
7499 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7500 		.call = parse_vc_action_ipv6_ext_remove_index,
7501 		.comp = comp_set_ipv6_ext_index,
7502 	},
7503 	[ACTION_IPV6_EXT_PUSH] = {
7504 		.name = "ipv6_ext_push",
7505 		.help = "IPv6 extension data, defined by set ipv6_ext_push",
7506 		.priv = PRIV_ACTION(IPV6_EXT_PUSH,
7507 			sizeof(struct action_ipv6_ext_push_data)),
7508 		.next = NEXT(action_ipv6_ext_push),
7509 		.call = parse_vc_action_ipv6_ext_push,
7510 	},
7511 	[ACTION_IPV6_EXT_PUSH_INDEX] = {
7512 		.name = "index",
7513 		.help = "the index of ipv6_ext_push",
7514 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_PUSH_INDEX_VALUE)),
7515 	},
7516 	[ACTION_IPV6_EXT_PUSH_INDEX_VALUE] = {
7517 		.name = "{index}",
7518 		.type = "UNSIGNED",
7519 		.help = "unsigned integer value",
7520 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7521 		.call = parse_vc_action_ipv6_ext_push_index,
7522 		.comp = comp_set_ipv6_ext_index,
7523 	},
7524 	[ACTION_NAT64] = {
7525 		.name = "nat64",
7526 		.help = "NAT64 IP headers translation",
7527 		.priv = PRIV_ACTION(NAT64, sizeof(struct rte_flow_action_nat64)),
7528 		.next = NEXT(action_nat64),
7529 		.call = parse_vc,
7530 	},
7531 	[ACTION_NAT64_MODE] = {
7532 		.name = "type",
7533 		.help = "NAT64 translation type",
7534 		.next = NEXT(action_nat64, NEXT_ENTRY(COMMON_UNSIGNED)),
7535 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_nat64, type)),
7536 		.call = parse_vc_conf,
7537 	},
7538 	/* Top level command. */
7539 	[SET] = {
7540 		.name = "set",
7541 		.help = "set raw encap/decap/sample data",
7542 		.type = "set raw_encap|raw_decap <index> <pattern>"
7543 				" or set sample_actions <index> <action>",
7544 		.next = NEXT(NEXT_ENTRY
7545 			     (SET_RAW_ENCAP,
7546 			      SET_RAW_DECAP,
7547 			      SET_SAMPLE_ACTIONS,
7548 			      SET_IPV6_EXT_REMOVE,
7549 			      SET_IPV6_EXT_PUSH)),
7550 		.call = parse_set_init,
7551 	},
7552 	/* Sub-level commands. */
7553 	[SET_RAW_ENCAP] = {
7554 		.name = "raw_encap",
7555 		.help = "set raw encap data",
7556 		.next = NEXT(next_set_raw),
7557 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7558 				(offsetof(struct buffer, port),
7559 				 sizeof(((struct buffer *)0)->port),
7560 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7561 		.call = parse_set_raw_encap_decap,
7562 	},
7563 	[SET_RAW_DECAP] = {
7564 		.name = "raw_decap",
7565 		.help = "set raw decap data",
7566 		.next = NEXT(next_set_raw),
7567 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7568 				(offsetof(struct buffer, port),
7569 				 sizeof(((struct buffer *)0)->port),
7570 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7571 		.call = parse_set_raw_encap_decap,
7572 	},
7573 	[SET_RAW_INDEX] = {
7574 		.name = "{index}",
7575 		.type = "COMMON_UNSIGNED",
7576 		.help = "index of raw_encap/raw_decap data",
7577 		.next = NEXT(next_item),
7578 		.call = parse_port,
7579 	},
7580 	[SET_SAMPLE_INDEX] = {
7581 		.name = "{index}",
7582 		.type = "UNSIGNED",
7583 		.help = "index of sample actions",
7584 		.next = NEXT(next_action_sample),
7585 		.call = parse_port,
7586 	},
7587 	[SET_SAMPLE_ACTIONS] = {
7588 		.name = "sample_actions",
7589 		.help = "set sample actions list",
7590 		.next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
7591 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7592 				(offsetof(struct buffer, port),
7593 				 sizeof(((struct buffer *)0)->port),
7594 				 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
7595 		.call = parse_set_sample_action,
7596 	},
7597 	[SET_IPV6_EXT_PUSH] = {
7598 		.name = "ipv6_ext_push",
7599 		.help = "set IPv6 extension header",
7600 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7601 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7602 				(offsetof(struct buffer, port),
7603 				 sizeof(((struct buffer *)0)->port),
7604 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7605 		.call = parse_set_ipv6_ext_action,
7606 	},
7607 	[SET_IPV6_EXT_REMOVE] = {
7608 		.name = "ipv6_ext_remove",
7609 		.help = "set IPv6 extension header",
7610 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7611 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7612 				(offsetof(struct buffer, port),
7613 				 sizeof(((struct buffer *)0)->port),
7614 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7615 		.call = parse_set_ipv6_ext_action,
7616 	},
7617 	[SET_IPV6_EXT_INDEX] = {
7618 		.name = "{index}",
7619 		.type = "UNSIGNED",
7620 		.help = "index of ipv6 extension push/remove actions",
7621 		.next = NEXT(item_ipv6_push_ext),
7622 		.call = parse_port,
7623 	},
7624 	[ITEM_IPV6_PUSH_REMOVE_EXT] = {
7625 		.name = "ipv6_ext",
7626 		.help = "set IPv6 extension header",
7627 		.priv = PRIV_ITEM(IPV6_EXT,
7628 				  sizeof(struct rte_flow_item_ipv6_ext)),
7629 		.next = NEXT(item_ipv6_push_ext_type),
7630 		.call = parse_vc,
7631 	},
7632 	[ITEM_IPV6_PUSH_REMOVE_EXT_TYPE] = {
7633 		.name = "type",
7634 		.help = "set IPv6 extension type",
7635 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
7636 					     next_hdr)),
7637 		.next = NEXT(item_ipv6_push_ext_header, NEXT_ENTRY(COMMON_UNSIGNED),
7638 			     item_param),
7639 	},
7640 	[ACTION_SET_TAG] = {
7641 		.name = "set_tag",
7642 		.help = "set tag",
7643 		.priv = PRIV_ACTION(SET_TAG,
7644 			sizeof(struct rte_flow_action_set_tag)),
7645 		.next = NEXT(action_set_tag),
7646 		.call = parse_vc,
7647 	},
7648 	[ACTION_SET_TAG_INDEX] = {
7649 		.name = "index",
7650 		.help = "index of tag array",
7651 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7652 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
7653 		.call = parse_vc_conf,
7654 	},
7655 	[ACTION_SET_TAG_DATA] = {
7656 		.name = "data",
7657 		.help = "tag value",
7658 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7659 		.args = ARGS(ARGS_ENTRY
7660 			     (struct rte_flow_action_set_tag, data)),
7661 		.call = parse_vc_conf,
7662 	},
7663 	[ACTION_SET_TAG_MASK] = {
7664 		.name = "mask",
7665 		.help = "mask for tag value",
7666 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7667 		.args = ARGS(ARGS_ENTRY
7668 			     (struct rte_flow_action_set_tag, mask)),
7669 		.call = parse_vc_conf,
7670 	},
7671 	[ACTION_SET_META] = {
7672 		.name = "set_meta",
7673 		.help = "set metadata",
7674 		.priv = PRIV_ACTION(SET_META,
7675 			sizeof(struct rte_flow_action_set_meta)),
7676 		.next = NEXT(action_set_meta),
7677 		.call = parse_vc_action_set_meta,
7678 	},
7679 	[ACTION_SET_META_DATA] = {
7680 		.name = "data",
7681 		.help = "metadata value",
7682 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7683 		.args = ARGS(ARGS_ENTRY
7684 			     (struct rte_flow_action_set_meta, data)),
7685 		.call = parse_vc_conf,
7686 	},
7687 	[ACTION_SET_META_MASK] = {
7688 		.name = "mask",
7689 		.help = "mask for metadata value",
7690 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7691 		.args = ARGS(ARGS_ENTRY
7692 			     (struct rte_flow_action_set_meta, mask)),
7693 		.call = parse_vc_conf,
7694 	},
7695 	[ACTION_SET_IPV4_DSCP] = {
7696 		.name = "set_ipv4_dscp",
7697 		.help = "set DSCP value",
7698 		.priv = PRIV_ACTION(SET_IPV4_DSCP,
7699 			sizeof(struct rte_flow_action_set_dscp)),
7700 		.next = NEXT(action_set_ipv4_dscp),
7701 		.call = parse_vc,
7702 	},
7703 	[ACTION_SET_IPV4_DSCP_VALUE] = {
7704 		.name = "dscp_value",
7705 		.help = "new IPv4 DSCP value to set",
7706 		.next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7707 		.args = ARGS(ARGS_ENTRY
7708 			     (struct rte_flow_action_set_dscp, dscp)),
7709 		.call = parse_vc_conf,
7710 	},
7711 	[ACTION_SET_IPV6_DSCP] = {
7712 		.name = "set_ipv6_dscp",
7713 		.help = "set DSCP value",
7714 		.priv = PRIV_ACTION(SET_IPV6_DSCP,
7715 			sizeof(struct rte_flow_action_set_dscp)),
7716 		.next = NEXT(action_set_ipv6_dscp),
7717 		.call = parse_vc,
7718 	},
7719 	[ACTION_SET_IPV6_DSCP_VALUE] = {
7720 		.name = "dscp_value",
7721 		.help = "new IPv6 DSCP value to set",
7722 		.next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7723 		.args = ARGS(ARGS_ENTRY
7724 			     (struct rte_flow_action_set_dscp, dscp)),
7725 		.call = parse_vc_conf,
7726 	},
7727 	[ACTION_AGE] = {
7728 		.name = "age",
7729 		.help = "set a specific metadata header",
7730 		.next = NEXT(action_age),
7731 		.priv = PRIV_ACTION(AGE,
7732 			sizeof(struct rte_flow_action_age)),
7733 		.call = parse_vc,
7734 	},
7735 	[ACTION_AGE_TIMEOUT] = {
7736 		.name = "timeout",
7737 		.help = "flow age timeout value",
7738 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
7739 					   timeout, 24)),
7740 		.next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
7741 		.call = parse_vc_conf,
7742 	},
7743 	[ACTION_AGE_UPDATE] = {
7744 		.name = "age_update",
7745 		.help = "update aging parameter",
7746 		.next = NEXT(action_age_update),
7747 		.priv = PRIV_ACTION(AGE,
7748 				    sizeof(struct rte_flow_update_age)),
7749 		.call = parse_vc,
7750 	},
7751 	[ACTION_AGE_UPDATE_TIMEOUT] = {
7752 		.name = "timeout",
7753 		.help = "age timeout update value",
7754 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7755 					   timeout, 24)),
7756 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_UNSIGNED)),
7757 		.call = parse_vc_conf_timeout,
7758 	},
7759 	[ACTION_AGE_UPDATE_TOUCH] = {
7760 		.name = "touch",
7761 		.help = "this flow is touched",
7762 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_BOOLEAN)),
7763 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7764 					   touch, 1)),
7765 		.call = parse_vc_conf,
7766 	},
7767 	[ACTION_SAMPLE] = {
7768 		.name = "sample",
7769 		.help = "set a sample action",
7770 		.next = NEXT(action_sample),
7771 		.priv = PRIV_ACTION(SAMPLE,
7772 			sizeof(struct action_sample_data)),
7773 		.call = parse_vc_action_sample,
7774 	},
7775 	[ACTION_SAMPLE_RATIO] = {
7776 		.name = "ratio",
7777 		.help = "flow sample ratio value",
7778 		.next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
7779 		.args = ARGS(ARGS_ENTRY_ARB
7780 			     (offsetof(struct action_sample_data, conf) +
7781 			      offsetof(struct rte_flow_action_sample, ratio),
7782 			      sizeof(((struct rte_flow_action_sample *)0)->
7783 				     ratio))),
7784 	},
7785 	[ACTION_SAMPLE_INDEX] = {
7786 		.name = "index",
7787 		.help = "the index of sample actions list",
7788 		.next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
7789 	},
7790 	[ACTION_SAMPLE_INDEX_VALUE] = {
7791 		.name = "{index}",
7792 		.type = "COMMON_UNSIGNED",
7793 		.help = "unsigned integer value",
7794 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7795 		.call = parse_vc_action_sample_index,
7796 		.comp = comp_set_sample_index,
7797 	},
7798 	[ACTION_CONNTRACK] = {
7799 		.name = "conntrack",
7800 		.help = "create a conntrack object",
7801 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7802 		.priv = PRIV_ACTION(CONNTRACK,
7803 				    sizeof(struct rte_flow_action_conntrack)),
7804 		.call = parse_vc,
7805 	},
7806 	[ACTION_CONNTRACK_UPDATE] = {
7807 		.name = "conntrack_update",
7808 		.help = "update a conntrack object",
7809 		.next = NEXT(action_update_conntrack),
7810 		.priv = PRIV_ACTION(CONNTRACK,
7811 				    sizeof(struct rte_flow_modify_conntrack)),
7812 		.call = parse_vc,
7813 	},
7814 	[ACTION_CONNTRACK_UPDATE_DIR] = {
7815 		.name = "dir",
7816 		.help = "update a conntrack object direction",
7817 		.next = NEXT(action_update_conntrack),
7818 		.call = parse_vc_action_conntrack_update,
7819 	},
7820 	[ACTION_CONNTRACK_UPDATE_CTX] = {
7821 		.name = "ctx",
7822 		.help = "update a conntrack object context",
7823 		.next = NEXT(action_update_conntrack),
7824 		.call = parse_vc_action_conntrack_update,
7825 	},
7826 	[ACTION_PORT_REPRESENTOR] = {
7827 		.name = "port_representor",
7828 		.help = "at embedded switch level, send matching traffic to the given ethdev",
7829 		.priv = PRIV_ACTION(PORT_REPRESENTOR,
7830 				    sizeof(struct rte_flow_action_ethdev)),
7831 		.next = NEXT(action_port_representor),
7832 		.call = parse_vc,
7833 	},
7834 	[ACTION_PORT_REPRESENTOR_PORT_ID] = {
7835 		.name = "port_id",
7836 		.help = "ethdev port ID",
7837 		.next = NEXT(action_port_representor,
7838 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7839 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7840 					port_id)),
7841 		.call = parse_vc_conf,
7842 	},
7843 	[ACTION_REPRESENTED_PORT] = {
7844 		.name = "represented_port",
7845 		.help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
7846 		.priv = PRIV_ACTION(REPRESENTED_PORT,
7847 				sizeof(struct rte_flow_action_ethdev)),
7848 		.next = NEXT(action_represented_port),
7849 		.call = parse_vc,
7850 	},
7851 	[ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
7852 		.name = "ethdev_port_id",
7853 		.help = "ethdev port ID",
7854 		.next = NEXT(action_represented_port,
7855 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7856 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7857 					port_id)),
7858 		.call = parse_vc_conf,
7859 	},
7860 	/* Indirect action destroy arguments. */
7861 	[INDIRECT_ACTION_DESTROY_ID] = {
7862 		.name = "action_id",
7863 		.help = "specify a indirect action id to destroy",
7864 		.next = NEXT(next_ia_destroy_attr,
7865 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7866 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
7867 					    args.ia_destroy.action_id)),
7868 		.call = parse_ia_destroy,
7869 	},
7870 	/* Indirect action create arguments. */
7871 	[INDIRECT_ACTION_CREATE_ID] = {
7872 		.name = "action_id",
7873 		.help = "specify a indirect action id to create",
7874 		.next = NEXT(next_ia_create_attr,
7875 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7876 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
7877 	},
7878 	[ACTION_INDIRECT] = {
7879 		.name = "indirect",
7880 		.help = "apply indirect action by id",
7881 		.priv = PRIV_ACTION(INDIRECT, 0),
7882 		.next = NEXT(next_ia),
7883 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7884 		.call = parse_vc,
7885 	},
7886 	[ACTION_INDIRECT_LIST] = {
7887 		.name = "indirect_list",
7888 		.help = "apply indirect list action by id",
7889 		.priv = PRIV_ACTION(INDIRECT_LIST,
7890 				    sizeof(struct
7891 					   rte_flow_action_indirect_list)),
7892 		.next = NEXT(next_ial),
7893 		.call = parse_vc,
7894 	},
7895 	[ACTION_INDIRECT_LIST_HANDLE] = {
7896 		.name = "handle",
7897 		.help = "indirect list handle",
7898 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_HANDLE)),
7899 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7900 	},
7901 	[ACTION_INDIRECT_LIST_CONF] = {
7902 		.name = "conf",
7903 		.help = "indirect list configuration",
7904 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_CONF)),
7905 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7906 	},
7907 	[INDIRECT_LIST_ACTION_ID2PTR_HANDLE] = {
7908 		.type = "UNSIGNED",
7909 		.help = "unsigned integer value",
7910 		.call = parse_indlst_id2ptr,
7911 		.comp = comp_none,
7912 	},
7913 	[INDIRECT_LIST_ACTION_ID2PTR_CONF] = {
7914 		.type = "UNSIGNED",
7915 		.help = "unsigned integer value",
7916 		.call = parse_indlst_id2ptr,
7917 		.comp = comp_none,
7918 	},
7919 	[ACTION_SHARED_INDIRECT] = {
7920 		.name = "shared_indirect",
7921 		.help = "apply indirect action by id and port",
7922 		.priv = PRIV_ACTION(INDIRECT, 0),
7923 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_PORT)),
7924 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t)),
7925 			     ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7926 		.call = parse_vc,
7927 	},
7928 	[INDIRECT_ACTION_PORT] = {
7929 		.name = "{indirect_action_port}",
7930 		.type = "INDIRECT_ACTION_PORT",
7931 		.help = "indirect action port",
7932 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
7933 		.call = parse_ia_port,
7934 		.comp = comp_none,
7935 	},
7936 	[INDIRECT_ACTION_ID2PTR] = {
7937 		.name = "{action_id}",
7938 		.type = "INDIRECT_ACTION_ID",
7939 		.help = "indirect action id",
7940 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7941 		.call = parse_ia_id2ptr,
7942 		.comp = comp_none,
7943 	},
7944 	[INDIRECT_ACTION_INGRESS] = {
7945 		.name = "ingress",
7946 		.help = "affect rule to ingress",
7947 		.next = NEXT(next_ia_create_attr),
7948 		.call = parse_ia,
7949 	},
7950 	[INDIRECT_ACTION_EGRESS] = {
7951 		.name = "egress",
7952 		.help = "affect rule to egress",
7953 		.next = NEXT(next_ia_create_attr),
7954 		.call = parse_ia,
7955 	},
7956 	[INDIRECT_ACTION_TRANSFER] = {
7957 		.name = "transfer",
7958 		.help = "affect rule to transfer",
7959 		.next = NEXT(next_ia_create_attr),
7960 		.call = parse_ia,
7961 	},
7962 	[INDIRECT_ACTION_SPEC] = {
7963 		.name = "action",
7964 		.help = "specify action to create indirect handle",
7965 		.next = NEXT(next_action),
7966 	},
7967 	[INDIRECT_ACTION_LIST] = {
7968 		.name = "list",
7969 		.help = "specify actions for indirect handle list",
7970 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
7971 		.call = parse_ia,
7972 	},
7973 	[INDIRECT_ACTION_FLOW_CONF] = {
7974 		.name = "flow_conf",
7975 		.help = "specify actions configuration for indirect handle list",
7976 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
7977 		.call = parse_ia,
7978 	},
7979 	[ACTION_POL_G] = {
7980 		.name = "g_actions",
7981 		.help = "submit a list of associated actions for green",
7982 		.next = NEXT(next_action),
7983 		.call = parse_mp,
7984 	},
7985 	[ACTION_POL_Y] = {
7986 		.name = "y_actions",
7987 		.help = "submit a list of associated actions for yellow",
7988 		.next = NEXT(next_action),
7989 	},
7990 	[ACTION_POL_R] = {
7991 		.name = "r_actions",
7992 		.help = "submit a list of associated actions for red",
7993 		.next = NEXT(next_action),
7994 	},
7995 	[ACTION_QUOTA_CREATE] = {
7996 		.name = "quota_create",
7997 		.help = "create quota action",
7998 		.priv = PRIV_ACTION(QUOTA,
7999 				    sizeof(struct rte_flow_action_quota)),
8000 		.next = NEXT(action_quota_create),
8001 		.call = parse_vc
8002 	},
8003 	[ACTION_QUOTA_CREATE_LIMIT] = {
8004 		.name = "limit",
8005 		.help = "quota limit",
8006 		.next = NEXT(action_quota_create, NEXT_ENTRY(COMMON_UNSIGNED)),
8007 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, quota)),
8008 		.call = parse_vc_conf
8009 	},
8010 	[ACTION_QUOTA_CREATE_MODE] = {
8011 		.name = "mode",
8012 		.help = "quota mode",
8013 		.next = NEXT(action_quota_create,
8014 			     NEXT_ENTRY(ACTION_QUOTA_CREATE_MODE_NAME)),
8015 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, mode)),
8016 		.call = parse_vc_conf
8017 	},
8018 	[ACTION_QUOTA_CREATE_MODE_NAME] = {
8019 		.name = "mode_name",
8020 		.help = "quota mode name",
8021 		.call = parse_quota_mode_name,
8022 		.comp = comp_quota_mode_name
8023 	},
8024 	[ACTION_QUOTA_QU] = {
8025 		.name = "quota_update",
8026 		.help = "update quota action",
8027 		.priv = PRIV_ACTION(QUOTA,
8028 				    sizeof(struct rte_flow_update_quota)),
8029 		.next = NEXT(action_quota_update),
8030 		.call = parse_vc
8031 	},
8032 	[ACTION_QUOTA_QU_LIMIT] = {
8033 		.name = "limit",
8034 		.help = "quota limit",
8035 		.next = NEXT(action_quota_update, NEXT_ENTRY(COMMON_UNSIGNED)),
8036 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, quota)),
8037 		.call = parse_vc_conf
8038 	},
8039 	[ACTION_QUOTA_QU_UPDATE_OP] = {
8040 		.name = "update_op",
8041 		.help = "query update op SET|ADD",
8042 		.next = NEXT(action_quota_update,
8043 			     NEXT_ENTRY(ACTION_QUOTA_QU_UPDATE_OP_NAME)),
8044 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, op)),
8045 		.call = parse_vc_conf
8046 	},
8047 	[ACTION_QUOTA_QU_UPDATE_OP_NAME] = {
8048 		.name = "update_op_name",
8049 		.help = "quota update op name",
8050 		.call = parse_quota_update_name,
8051 		.comp = comp_quota_update_name
8052 	},
8053 
8054 	/* Top-level command. */
8055 	[ADD] = {
8056 		.name = "add",
8057 		.type = "port meter policy {port_id} {arg}",
8058 		.help = "add port meter policy",
8059 		.next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
8060 		.call = parse_init,
8061 	},
8062 	/* Sub-level commands. */
8063 	[ITEM_POL_PORT] = {
8064 		.name = "port",
8065 		.help = "add port meter policy",
8066 		.next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
8067 	},
8068 	[ITEM_POL_METER] = {
8069 		.name = "meter",
8070 		.help = "add port meter policy",
8071 		.next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
8072 	},
8073 	[ITEM_POL_POLICY] = {
8074 		.name = "policy",
8075 		.help = "add port meter policy",
8076 		.next = NEXT(NEXT_ENTRY(ACTION_POL_R),
8077 				NEXT_ENTRY(ACTION_POL_Y),
8078 				NEXT_ENTRY(ACTION_POL_G),
8079 				NEXT_ENTRY(COMMON_POLICY_ID),
8080 				NEXT_ENTRY(COMMON_PORT_ID)),
8081 		.args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
8082 				ARGS_ENTRY(struct buffer, port)),
8083 		.call = parse_mp,
8084 	},
8085 	[ITEM_AGGR_AFFINITY] = {
8086 		.name = "aggr_affinity",
8087 		.help = "match on the aggregated port receiving the packets",
8088 		.priv = PRIV_ITEM(AGGR_AFFINITY,
8089 				  sizeof(struct rte_flow_item_aggr_affinity)),
8090 		.next = NEXT(item_aggr_affinity),
8091 		.call = parse_vc,
8092 	},
8093 	[ITEM_AGGR_AFFINITY_VALUE] = {
8094 		.name = "affinity",
8095 		.help = "aggregated affinity value",
8096 		.next = NEXT(item_aggr_affinity, NEXT_ENTRY(COMMON_UNSIGNED),
8097 			     item_param),
8098 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_aggr_affinity,
8099 					affinity)),
8100 	},
8101 	[ITEM_TX_QUEUE] = {
8102 		.name = "tx_queue",
8103 		.help = "match on the tx queue of send packet",
8104 		.priv = PRIV_ITEM(TX_QUEUE,
8105 				  sizeof(struct rte_flow_item_tx_queue)),
8106 		.next = NEXT(item_tx_queue),
8107 		.call = parse_vc,
8108 	},
8109 	[ITEM_TX_QUEUE_VALUE] = {
8110 		.name = "tx_queue_value",
8111 		.help = "tx queue value",
8112 		.next = NEXT(item_tx_queue, NEXT_ENTRY(COMMON_UNSIGNED),
8113 			     item_param),
8114 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tx_queue,
8115 					tx_queue)),
8116 	},
8117 };
8118 
8119 /** Remove and return last entry from argument stack. */
8120 static const struct arg *
8121 pop_args(struct context *ctx)
8122 {
8123 	return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
8124 }
8125 
8126 /** Add entry on top of the argument stack. */
8127 static int
8128 push_args(struct context *ctx, const struct arg *arg)
8129 {
8130 	if (ctx->args_num == CTX_STACK_SIZE)
8131 		return -1;
8132 	ctx->args[ctx->args_num++] = arg;
8133 	return 0;
8134 }
8135 
8136 /** Spread value into buffer according to bit-mask. */
8137 static size_t
8138 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
8139 {
8140 	uint32_t i = arg->size;
8141 	uint32_t end = 0;
8142 	int sub = 1;
8143 	int add = 0;
8144 	size_t len = 0;
8145 
8146 	if (!arg->mask)
8147 		return 0;
8148 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8149 	if (!arg->hton) {
8150 		i = 0;
8151 		end = arg->size;
8152 		sub = 0;
8153 		add = 1;
8154 	}
8155 #endif
8156 	while (i != end) {
8157 		unsigned int shift = 0;
8158 		uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
8159 
8160 		for (shift = 0; arg->mask[i] >> shift; ++shift) {
8161 			if (!(arg->mask[i] & (1 << shift)))
8162 				continue;
8163 			++len;
8164 			if (!dst)
8165 				continue;
8166 			*buf &= ~(1 << shift);
8167 			*buf |= (val & 1) << shift;
8168 			val >>= 1;
8169 		}
8170 		i += add;
8171 	}
8172 	return len;
8173 }
8174 
8175 /** Compare a string with a partial one of a given length. */
8176 static int
8177 strcmp_partial(const char *full, const char *partial, size_t partial_len)
8178 {
8179 	int r = strncmp(full, partial, partial_len);
8180 
8181 	if (r)
8182 		return r;
8183 	if (strlen(full) <= partial_len)
8184 		return 0;
8185 	return full[partial_len];
8186 }
8187 
8188 /**
8189  * Parse a prefix length and generate a bit-mask.
8190  *
8191  * Last argument (ctx->args) is retrieved to determine mask size, storage
8192  * location and whether the result must use network byte ordering.
8193  */
8194 static int
8195 parse_prefix(struct context *ctx, const struct token *token,
8196 	     const char *str, unsigned int len,
8197 	     void *buf, unsigned int size)
8198 {
8199 	const struct arg *arg = pop_args(ctx);
8200 	static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
8201 	char *end;
8202 	uintmax_t u;
8203 	unsigned int bytes;
8204 	unsigned int extra;
8205 
8206 	(void)token;
8207 	/* Argument is expected. */
8208 	if (!arg)
8209 		return -1;
8210 	errno = 0;
8211 	u = strtoumax(str, &end, 0);
8212 	if (errno || (size_t)(end - str) != len)
8213 		goto error;
8214 	if (arg->mask) {
8215 		uintmax_t v = 0;
8216 
8217 		extra = arg_entry_bf_fill(NULL, 0, arg);
8218 		if (u > extra)
8219 			goto error;
8220 		if (!ctx->object)
8221 			return len;
8222 		extra -= u;
8223 		while (u--)
8224 			(v <<= 1, v |= 1);
8225 		v <<= extra;
8226 		if (!arg_entry_bf_fill(ctx->object, v, arg) ||
8227 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
8228 			goto error;
8229 		return len;
8230 	}
8231 	bytes = u / 8;
8232 	extra = u % 8;
8233 	size = arg->size;
8234 	if (bytes > size || bytes + !!extra > size)
8235 		goto error;
8236 	if (!ctx->object)
8237 		return len;
8238 	buf = (uint8_t *)ctx->object + arg->offset;
8239 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8240 	if (!arg->hton) {
8241 		memset((uint8_t *)buf + size - bytes, 0xff, bytes);
8242 		memset(buf, 0x00, size - bytes);
8243 		if (extra)
8244 			((uint8_t *)buf)[size - bytes - 1] = conv[extra];
8245 	} else
8246 #endif
8247 	{
8248 		memset(buf, 0xff, bytes);
8249 		memset((uint8_t *)buf + bytes, 0x00, size - bytes);
8250 		if (extra)
8251 			((uint8_t *)buf)[bytes] = conv[extra];
8252 	}
8253 	if (ctx->objmask)
8254 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8255 	return len;
8256 error:
8257 	push_args(ctx, arg);
8258 	return -1;
8259 }
8260 
8261 /** Default parsing function for token name matching. */
8262 static int
8263 parse_default(struct context *ctx, const struct token *token,
8264 	      const char *str, unsigned int len,
8265 	      void *buf, unsigned int size)
8266 {
8267 	(void)ctx;
8268 	(void)buf;
8269 	(void)size;
8270 	if (strcmp_partial(token->name, str, len))
8271 		return -1;
8272 	return len;
8273 }
8274 
8275 /** Parse flow command, initialize output buffer for subsequent tokens. */
8276 static int
8277 parse_init(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 
8283 	/* Token name must match. */
8284 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8285 		return -1;
8286 	/* Nothing else to do if there is no buffer. */
8287 	if (!out)
8288 		return len;
8289 	/* Make sure buffer is large enough. */
8290 	if (size < sizeof(*out))
8291 		return -1;
8292 	/* Initialize buffer. */
8293 	memset(out, 0x00, sizeof(*out));
8294 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
8295 	ctx->objdata = 0;
8296 	ctx->object = out;
8297 	ctx->objmask = NULL;
8298 	return len;
8299 }
8300 
8301 /** Parse tokens for indirect action commands. */
8302 static int
8303 parse_ia(struct context *ctx, const struct token *token,
8304 	 const char *str, unsigned int len,
8305 	 void *buf, unsigned int size)
8306 {
8307 	struct buffer *out = buf;
8308 
8309 	/* Token name must match. */
8310 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8311 		return -1;
8312 	/* Nothing else to do if there is no buffer. */
8313 	if (!out)
8314 		return len;
8315 	if (!out->command) {
8316 		if (ctx->curr != INDIRECT_ACTION)
8317 			return -1;
8318 		if (sizeof(*out) > size)
8319 			return -1;
8320 		out->command = ctx->curr;
8321 		ctx->objdata = 0;
8322 		ctx->object = out;
8323 		ctx->objmask = NULL;
8324 		out->args.vc.data = (uint8_t *)out + size;
8325 		return len;
8326 	}
8327 	switch (ctx->curr) {
8328 	case INDIRECT_ACTION_CREATE:
8329 	case INDIRECT_ACTION_UPDATE:
8330 	case INDIRECT_ACTION_QUERY_UPDATE:
8331 		out->args.vc.actions =
8332 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8333 					       sizeof(double));
8334 		out->args.vc.attr.group = UINT32_MAX;
8335 		/* fallthrough */
8336 	case INDIRECT_ACTION_QUERY:
8337 		out->command = ctx->curr;
8338 		ctx->objdata = 0;
8339 		ctx->object = out;
8340 		ctx->objmask = NULL;
8341 		return len;
8342 	case INDIRECT_ACTION_EGRESS:
8343 		out->args.vc.attr.egress = 1;
8344 		return len;
8345 	case INDIRECT_ACTION_INGRESS:
8346 		out->args.vc.attr.ingress = 1;
8347 		return len;
8348 	case INDIRECT_ACTION_TRANSFER:
8349 		out->args.vc.attr.transfer = 1;
8350 		return len;
8351 	case INDIRECT_ACTION_QU_MODE:
8352 		return len;
8353 	case INDIRECT_ACTION_LIST:
8354 		out->command = INDIRECT_ACTION_LIST_CREATE;
8355 		return len;
8356 	case INDIRECT_ACTION_FLOW_CONF:
8357 		out->command = INDIRECT_ACTION_FLOW_CONF_CREATE;
8358 		return len;
8359 	default:
8360 		return -1;
8361 	}
8362 }
8363 
8364 
8365 /** Parse tokens for indirect action destroy command. */
8366 static int
8367 parse_ia_destroy(struct context *ctx, const struct token *token,
8368 		 const char *str, unsigned int len,
8369 		 void *buf, unsigned int size)
8370 {
8371 	struct buffer *out = buf;
8372 	uint32_t *action_id;
8373 
8374 	/* Token name must match. */
8375 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8376 		return -1;
8377 	/* Nothing else to do if there is no buffer. */
8378 	if (!out)
8379 		return len;
8380 	if (!out->command || out->command == INDIRECT_ACTION) {
8381 		if (ctx->curr != INDIRECT_ACTION_DESTROY)
8382 			return -1;
8383 		if (sizeof(*out) > size)
8384 			return -1;
8385 		out->command = ctx->curr;
8386 		ctx->objdata = 0;
8387 		ctx->object = out;
8388 		ctx->objmask = NULL;
8389 		out->args.ia_destroy.action_id =
8390 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8391 					       sizeof(double));
8392 		return len;
8393 	}
8394 	action_id = out->args.ia_destroy.action_id
8395 		    + out->args.ia_destroy.action_id_n++;
8396 	if ((uint8_t *)action_id > (uint8_t *)out + size)
8397 		return -1;
8398 	ctx->objdata = 0;
8399 	ctx->object = action_id;
8400 	ctx->objmask = NULL;
8401 	return len;
8402 }
8403 
8404 /** Parse tokens for indirect action commands. */
8405 static int
8406 parse_qia(struct context *ctx, const struct token *token,
8407 	  const char *str, unsigned int len,
8408 	  void *buf, unsigned int size)
8409 {
8410 	struct buffer *out = buf;
8411 
8412 	/* Token name must match. */
8413 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8414 		return -1;
8415 	/* Nothing else to do if there is no buffer. */
8416 	if (!out)
8417 		return len;
8418 	if (!out->command) {
8419 		if (ctx->curr != QUEUE)
8420 			return -1;
8421 		if (sizeof(*out) > size)
8422 			return -1;
8423 		out->args.vc.data = (uint8_t *)out + size;
8424 		return len;
8425 	}
8426 	switch (ctx->curr) {
8427 	case QUEUE_INDIRECT_ACTION:
8428 		return len;
8429 	case QUEUE_INDIRECT_ACTION_CREATE:
8430 	case QUEUE_INDIRECT_ACTION_UPDATE:
8431 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
8432 		out->args.vc.actions =
8433 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8434 					       sizeof(double));
8435 		out->args.vc.attr.group = UINT32_MAX;
8436 		/* fallthrough */
8437 	case QUEUE_INDIRECT_ACTION_QUERY:
8438 		out->command = ctx->curr;
8439 		ctx->objdata = 0;
8440 		ctx->object = out;
8441 		ctx->objmask = NULL;
8442 		return len;
8443 	case QUEUE_INDIRECT_ACTION_EGRESS:
8444 		out->args.vc.attr.egress = 1;
8445 		return len;
8446 	case QUEUE_INDIRECT_ACTION_INGRESS:
8447 		out->args.vc.attr.ingress = 1;
8448 		return len;
8449 	case QUEUE_INDIRECT_ACTION_TRANSFER:
8450 		out->args.vc.attr.transfer = 1;
8451 		return len;
8452 	case QUEUE_INDIRECT_ACTION_CREATE_POSTPONE:
8453 		return len;
8454 	case QUEUE_INDIRECT_ACTION_QU_MODE:
8455 		return len;
8456 	case QUEUE_INDIRECT_ACTION_LIST:
8457 		out->command = QUEUE_INDIRECT_ACTION_LIST_CREATE;
8458 		return len;
8459 	default:
8460 		return -1;
8461 	}
8462 }
8463 
8464 /** Parse tokens for indirect action destroy command. */
8465 static int
8466 parse_qia_destroy(struct context *ctx, const struct token *token,
8467 		  const char *str, unsigned int len,
8468 		  void *buf, unsigned int size)
8469 {
8470 	struct buffer *out = buf;
8471 	uint32_t *action_id;
8472 
8473 	/* Token name must match. */
8474 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8475 		return -1;
8476 	/* Nothing else to do if there is no buffer. */
8477 	if (!out)
8478 		return len;
8479 	if (!out->command || out->command == QUEUE) {
8480 		if (ctx->curr != QUEUE_INDIRECT_ACTION_DESTROY)
8481 			return -1;
8482 		if (sizeof(*out) > size)
8483 			return -1;
8484 		out->command = ctx->curr;
8485 		ctx->objdata = 0;
8486 		ctx->object = out;
8487 		ctx->objmask = NULL;
8488 		out->args.ia_destroy.action_id =
8489 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8490 					       sizeof(double));
8491 		return len;
8492 	}
8493 	switch (ctx->curr) {
8494 	case QUEUE_INDIRECT_ACTION:
8495 		out->command = ctx->curr;
8496 		ctx->objdata = 0;
8497 		ctx->object = out;
8498 		ctx->objmask = NULL;
8499 		return len;
8500 	case QUEUE_INDIRECT_ACTION_DESTROY_ID:
8501 		action_id = out->args.ia_destroy.action_id
8502 				+ out->args.ia_destroy.action_id_n++;
8503 		if ((uint8_t *)action_id > (uint8_t *)out + size)
8504 			return -1;
8505 		ctx->objdata = 0;
8506 		ctx->object = action_id;
8507 		ctx->objmask = NULL;
8508 		return len;
8509 	case QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE:
8510 		return len;
8511 	default:
8512 		return -1;
8513 	}
8514 }
8515 
8516 /** Parse tokens for meter policy action commands. */
8517 static int
8518 parse_mp(struct context *ctx, const struct token *token,
8519 	const char *str, unsigned int len,
8520 	void *buf, unsigned int size)
8521 {
8522 	struct buffer *out = buf;
8523 
8524 	/* Token name must match. */
8525 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8526 		return -1;
8527 	/* Nothing else to do if there is no buffer. */
8528 	if (!out)
8529 		return len;
8530 	if (!out->command) {
8531 		if (ctx->curr != ITEM_POL_POLICY)
8532 			return -1;
8533 		if (sizeof(*out) > size)
8534 			return -1;
8535 		out->command = ctx->curr;
8536 		ctx->objdata = 0;
8537 		ctx->object = out;
8538 		ctx->objmask = NULL;
8539 		out->args.vc.data = (uint8_t *)out + size;
8540 		return len;
8541 	}
8542 	switch (ctx->curr) {
8543 	case ACTION_POL_G:
8544 		out->args.vc.actions =
8545 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8546 					sizeof(double));
8547 		out->command = ctx->curr;
8548 		ctx->objdata = 0;
8549 		ctx->object = out;
8550 		ctx->objmask = NULL;
8551 		return len;
8552 	default:
8553 		return -1;
8554 	}
8555 }
8556 
8557 /** Parse tokens for validate/create commands. */
8558 static int
8559 parse_vc(struct context *ctx, const struct token *token,
8560 	 const char *str, unsigned int len,
8561 	 void *buf, unsigned int size)
8562 {
8563 	struct buffer *out = buf;
8564 	uint8_t *data;
8565 	uint32_t data_size;
8566 
8567 	/* Token name must match. */
8568 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8569 		return -1;
8570 	/* Nothing else to do if there is no buffer. */
8571 	if (!out)
8572 		return len;
8573 	if (!out->command) {
8574 		if (ctx->curr != VALIDATE && ctx->curr != CREATE &&
8575 		    ctx->curr != PATTERN_TEMPLATE_CREATE &&
8576 		    ctx->curr != ACTIONS_TEMPLATE_CREATE &&
8577 		    ctx->curr != UPDATE)
8578 			return -1;
8579 		if (ctx->curr == UPDATE)
8580 			out->args.vc.pattern =
8581 				(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8582 						       sizeof(double));
8583 		if (sizeof(*out) > size)
8584 			return -1;
8585 		out->command = ctx->curr;
8586 		ctx->objdata = 0;
8587 		ctx->object = out;
8588 		ctx->objmask = NULL;
8589 		out->args.vc.data = (uint8_t *)out + size;
8590 		return len;
8591 	}
8592 	ctx->objdata = 0;
8593 	switch (ctx->curr) {
8594 	default:
8595 		ctx->object = &out->args.vc.attr;
8596 		break;
8597 	case VC_TUNNEL_SET:
8598 	case VC_TUNNEL_MATCH:
8599 		ctx->object = &out->args.vc.tunnel_ops;
8600 		break;
8601 	case VC_USER_ID:
8602 		ctx->object = out;
8603 		break;
8604 	}
8605 	ctx->objmask = NULL;
8606 	switch (ctx->curr) {
8607 	case VC_GROUP:
8608 	case VC_PRIORITY:
8609 	case VC_USER_ID:
8610 		return len;
8611 	case VC_TUNNEL_SET:
8612 		out->args.vc.tunnel_ops.enabled = 1;
8613 		out->args.vc.tunnel_ops.actions = 1;
8614 		return len;
8615 	case VC_TUNNEL_MATCH:
8616 		out->args.vc.tunnel_ops.enabled = 1;
8617 		out->args.vc.tunnel_ops.items = 1;
8618 		return len;
8619 	case VC_INGRESS:
8620 		out->args.vc.attr.ingress = 1;
8621 		return len;
8622 	case VC_EGRESS:
8623 		out->args.vc.attr.egress = 1;
8624 		return len;
8625 	case VC_TRANSFER:
8626 		out->args.vc.attr.transfer = 1;
8627 		return len;
8628 	case ITEM_PATTERN:
8629 		out->args.vc.pattern =
8630 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8631 					       sizeof(double));
8632 		ctx->object = out->args.vc.pattern;
8633 		ctx->objmask = NULL;
8634 		return len;
8635 	case ITEM_END:
8636 		if ((out->command == VALIDATE || out->command == CREATE) &&
8637 		    ctx->last)
8638 			return -1;
8639 		if (out->command == PATTERN_TEMPLATE_CREATE &&
8640 		    !ctx->last)
8641 			return -1;
8642 		break;
8643 	case ACTIONS:
8644 		out->args.vc.actions = out->args.vc.pattern ?
8645 			(void *)RTE_ALIGN_CEIL((uintptr_t)
8646 					       (out->args.vc.pattern +
8647 						out->args.vc.pattern_n),
8648 					       sizeof(double)) :
8649 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8650 					       sizeof(double));
8651 		ctx->object = out->args.vc.actions;
8652 		ctx->objmask = NULL;
8653 		return len;
8654 	case VC_IS_USER_ID:
8655 		out->args.vc.user_id = true;
8656 		return len;
8657 	default:
8658 		if (!token->priv)
8659 			return -1;
8660 		break;
8661 	}
8662 	if (!out->args.vc.actions) {
8663 		const struct parse_item_priv *priv = token->priv;
8664 		struct rte_flow_item *item =
8665 			out->args.vc.pattern + out->args.vc.pattern_n;
8666 
8667 		data_size = priv->size * 3; /* spec, last, mask */
8668 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8669 					       (out->args.vc.data - data_size),
8670 					       sizeof(double));
8671 		if ((uint8_t *)item + sizeof(*item) > data)
8672 			return -1;
8673 		*item = (struct rte_flow_item){
8674 			.type = priv->type,
8675 		};
8676 		++out->args.vc.pattern_n;
8677 		ctx->object = item;
8678 		ctx->objmask = NULL;
8679 	} else {
8680 		const struct parse_action_priv *priv = token->priv;
8681 		struct rte_flow_action *action =
8682 			out->args.vc.actions + out->args.vc.actions_n;
8683 
8684 		data_size = priv->size; /* configuration */
8685 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8686 					       (out->args.vc.data - data_size),
8687 					       sizeof(double));
8688 		if ((uint8_t *)action + sizeof(*action) > data)
8689 			return -1;
8690 		*action = (struct rte_flow_action){
8691 			.type = priv->type,
8692 			.conf = data_size ? data : NULL,
8693 		};
8694 		++out->args.vc.actions_n;
8695 		ctx->object = action;
8696 		ctx->objmask = NULL;
8697 	}
8698 	memset(data, 0, data_size);
8699 	out->args.vc.data = data;
8700 	ctx->objdata = data_size;
8701 	return len;
8702 }
8703 
8704 /** Parse pattern item parameter type. */
8705 static int
8706 parse_vc_spec(struct context *ctx, const struct token *token,
8707 	      const char *str, unsigned int len,
8708 	      void *buf, unsigned int size)
8709 {
8710 	struct buffer *out = buf;
8711 	struct rte_flow_item *item;
8712 	uint32_t data_size;
8713 	int index;
8714 	int objmask = 0;
8715 
8716 	(void)size;
8717 	/* Token name must match. */
8718 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8719 		return -1;
8720 	/* Parse parameter types. */
8721 	switch (ctx->curr) {
8722 		static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
8723 
8724 	case ITEM_PARAM_IS:
8725 		index = 0;
8726 		objmask = 1;
8727 		break;
8728 	case ITEM_PARAM_SPEC:
8729 		index = 0;
8730 		break;
8731 	case ITEM_PARAM_LAST:
8732 		index = 1;
8733 		break;
8734 	case ITEM_PARAM_PREFIX:
8735 		/* Modify next token to expect a prefix. */
8736 		if (ctx->next_num < 2)
8737 			return -1;
8738 		ctx->next[ctx->next_num - 2] = prefix;
8739 		/* Fall through. */
8740 	case ITEM_PARAM_MASK:
8741 		index = 2;
8742 		break;
8743 	default:
8744 		return -1;
8745 	}
8746 	/* Nothing else to do if there is no buffer. */
8747 	if (!out)
8748 		return len;
8749 	if (!out->args.vc.pattern_n)
8750 		return -1;
8751 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8752 	data_size = ctx->objdata / 3; /* spec, last, mask */
8753 	/* Point to selected object. */
8754 	ctx->object = out->args.vc.data + (data_size * index);
8755 	if (objmask) {
8756 		ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
8757 		item->mask = ctx->objmask;
8758 	} else
8759 		ctx->objmask = NULL;
8760 	/* Update relevant item pointer. */
8761 	*((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
8762 		ctx->object;
8763 	return len;
8764 }
8765 
8766 /** Parse action configuration field. */
8767 static int
8768 parse_vc_conf(struct context *ctx, const struct token *token,
8769 	      const char *str, unsigned int len,
8770 	      void *buf, unsigned int size)
8771 {
8772 	struct buffer *out = buf;
8773 
8774 	(void)size;
8775 	/* Token name must match. */
8776 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8777 		return -1;
8778 	/* Nothing else to do if there is no buffer. */
8779 	if (!out)
8780 		return len;
8781 	/* Point to selected object. */
8782 	ctx->object = out->args.vc.data;
8783 	ctx->objmask = NULL;
8784 	return len;
8785 }
8786 
8787 /** Parse action configuration field. */
8788 static int
8789 parse_vc_conf_timeout(struct context *ctx, const struct token *token,
8790 		      const char *str, unsigned int len,
8791 		      void *buf, unsigned int size)
8792 {
8793 	struct buffer *out = buf;
8794 	struct rte_flow_update_age *update;
8795 
8796 	(void)size;
8797 	if (ctx->curr != ACTION_AGE_UPDATE_TIMEOUT)
8798 		return -1;
8799 	/* Token name must match. */
8800 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8801 		return -1;
8802 	/* Nothing else to do if there is no buffer. */
8803 	if (!out)
8804 		return len;
8805 	/* Point to selected object. */
8806 	ctx->object = out->args.vc.data;
8807 	ctx->objmask = NULL;
8808 	/* Update the timeout is valid. */
8809 	update = (struct rte_flow_update_age *)out->args.vc.data;
8810 	update->timeout_valid = 1;
8811 	return len;
8812 }
8813 
8814 /** Parse eCPRI common header type field. */
8815 static int
8816 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
8817 			 const char *str, unsigned int len,
8818 			 void *buf, unsigned int size)
8819 {
8820 	struct rte_flow_item_ecpri *ecpri;
8821 	struct rte_flow_item_ecpri *ecpri_mask;
8822 	struct rte_flow_item *item;
8823 	uint32_t data_size;
8824 	uint8_t msg_type;
8825 	struct buffer *out = buf;
8826 	const struct arg *arg;
8827 
8828 	(void)size;
8829 	/* Token name must match. */
8830 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8831 		return -1;
8832 	switch (ctx->curr) {
8833 	case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
8834 		msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
8835 		break;
8836 	case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
8837 		msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
8838 		break;
8839 	case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
8840 		msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
8841 		break;
8842 	default:
8843 		return -1;
8844 	}
8845 	if (!ctx->object)
8846 		return len;
8847 	arg = pop_args(ctx);
8848 	if (!arg)
8849 		return -1;
8850 	ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
8851 	ecpri->hdr.common.type = msg_type;
8852 	data_size = ctx->objdata / 3; /* spec, last, mask */
8853 	ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
8854 						    (data_size * 2));
8855 	ecpri_mask->hdr.common.type = 0xFF;
8856 	if (arg->hton) {
8857 		ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
8858 		ecpri_mask->hdr.common.u32 =
8859 				rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
8860 	}
8861 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8862 	item->spec = ecpri;
8863 	item->mask = ecpri_mask;
8864 	return len;
8865 }
8866 
8867 /** Parse L2TPv2 common header type field. */
8868 static int
8869 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
8870 			 const char *str, unsigned int len,
8871 			 void *buf, unsigned int size)
8872 {
8873 	struct rte_flow_item_l2tpv2 *l2tpv2;
8874 	struct rte_flow_item_l2tpv2 *l2tpv2_mask;
8875 	struct rte_flow_item *item;
8876 	uint32_t data_size;
8877 	uint16_t msg_type = 0;
8878 	struct buffer *out = buf;
8879 	const struct arg *arg;
8880 
8881 	(void)size;
8882 	/* Token name must match. */
8883 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8884 		return -1;
8885 	switch (ctx->curr) {
8886 	case ITEM_L2TPV2_TYPE_DATA:
8887 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
8888 		break;
8889 	case ITEM_L2TPV2_TYPE_DATA_L:
8890 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
8891 		break;
8892 	case ITEM_L2TPV2_TYPE_DATA_S:
8893 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
8894 		break;
8895 	case ITEM_L2TPV2_TYPE_DATA_O:
8896 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
8897 		break;
8898 	case ITEM_L2TPV2_TYPE_DATA_L_S:
8899 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
8900 		break;
8901 	case ITEM_L2TPV2_TYPE_CTRL:
8902 		msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
8903 		break;
8904 	default:
8905 		return -1;
8906 	}
8907 	if (!ctx->object)
8908 		return len;
8909 	arg = pop_args(ctx);
8910 	if (!arg)
8911 		return -1;
8912 	l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
8913 	l2tpv2->hdr.common.flags_version |= msg_type;
8914 	data_size = ctx->objdata / 3; /* spec, last, mask */
8915 	l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
8916 						    (data_size * 2));
8917 	l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
8918 	if (arg->hton) {
8919 		l2tpv2->hdr.common.flags_version =
8920 			rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
8921 		l2tpv2_mask->hdr.common.flags_version =
8922 		    rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
8923 	}
8924 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8925 	item->spec = l2tpv2;
8926 	item->mask = l2tpv2_mask;
8927 	return len;
8928 }
8929 
8930 /** Parse operation for compare match item. */
8931 static int
8932 parse_vc_compare_op(struct context *ctx, const struct token *token,
8933 			 const char *str, unsigned int len, void *buf,
8934 			 unsigned int size)
8935 {
8936 	struct rte_flow_item_compare *compare_item;
8937 	unsigned int i;
8938 
8939 	(void)token;
8940 	(void)buf;
8941 	(void)size;
8942 	if (ctx->curr != ITEM_COMPARE_OP_VALUE)
8943 		return -1;
8944 	for (i = 0; compare_ops[i]; ++i)
8945 		if (!strcmp_partial(compare_ops[i], str, len))
8946 			break;
8947 	if (!compare_ops[i])
8948 		return -1;
8949 	if (!ctx->object)
8950 		return len;
8951 	compare_item = ctx->object;
8952 	compare_item->operation = (enum rte_flow_item_compare_op)i;
8953 	return len;
8954 }
8955 
8956 /** Parse id for compare match item. */
8957 static int
8958 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
8959 			  const char *str, unsigned int len, void *buf,
8960 			  unsigned int size)
8961 {
8962 	struct rte_flow_item_compare *compare_item;
8963 	unsigned int i;
8964 
8965 	(void)token;
8966 	(void)buf;
8967 	(void)size;
8968 	if (ctx->curr != ITEM_COMPARE_FIELD_A_TYPE_VALUE &&
8969 		ctx->curr != ITEM_COMPARE_FIELD_B_TYPE_VALUE)
8970 		return -1;
8971 	for (i = 0; flow_field_ids[i]; ++i)
8972 		if (!strcmp_partial(flow_field_ids[i], str, len))
8973 			break;
8974 	if (!flow_field_ids[i])
8975 		return -1;
8976 	if (!ctx->object)
8977 		return len;
8978 	compare_item = ctx->object;
8979 	if (ctx->curr == ITEM_COMPARE_FIELD_A_TYPE_VALUE)
8980 		compare_item->a.field = (enum rte_flow_field_id)i;
8981 	else
8982 		compare_item->b.field = (enum rte_flow_field_id)i;
8983 	return len;
8984 }
8985 
8986 /** Parse level for compare match item. */
8987 static int
8988 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
8989 			     const char *str, unsigned int len, void *buf,
8990 			     unsigned int size)
8991 {
8992 	struct rte_flow_item_compare *compare_item;
8993 	struct flex_item *fp = NULL;
8994 	uint32_t val;
8995 	struct buffer *out = buf;
8996 	char *end;
8997 
8998 	(void)token;
8999 	(void)size;
9000 	if (ctx->curr != ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
9001 		ctx->curr != ITEM_COMPARE_FIELD_B_LEVEL_VALUE)
9002 		return -1;
9003 	if (!ctx->object)
9004 		return len;
9005 	compare_item = ctx->object;
9006 	errno = 0;
9007 	val = strtoumax(str, &end, 0);
9008 	if (errno || (size_t)(end - str) != len)
9009 		return -1;
9010 	/* No need to validate action template mask value */
9011 	if (out->args.vc.masks) {
9012 		if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE)
9013 			compare_item->a.level = val;
9014 		else
9015 			compare_item->b.level = val;
9016 		return len;
9017 	}
9018 	if ((ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
9019 		compare_item->a.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
9020 		(ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE &&
9021 		compare_item->b.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
9022 		if (val >= FLEX_MAX_PARSERS_NUM) {
9023 			printf("Bad flex item handle\n");
9024 			return -1;
9025 		}
9026 		fp = flex_items[ctx->port][val];
9027 		if (!fp) {
9028 			printf("Bad flex item handle\n");
9029 			return -1;
9030 		}
9031 	}
9032 	if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE) {
9033 		if (compare_item->a.field != RTE_FLOW_FIELD_FLEX_ITEM)
9034 			compare_item->a.level = val;
9035 		else
9036 			compare_item->a.flex_handle = fp->flex_handle;
9037 	} else if (ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE) {
9038 		if (compare_item->b.field != RTE_FLOW_FIELD_FLEX_ITEM)
9039 			compare_item->b.level = val;
9040 		else
9041 			compare_item->b.flex_handle = fp->flex_handle;
9042 	}
9043 	return len;
9044 }
9045 
9046 /** Parse meter color action type. */
9047 static int
9048 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
9049 				const char *str, unsigned int len,
9050 				void *buf, unsigned int size)
9051 {
9052 	struct rte_flow_action *action_data;
9053 	struct rte_flow_action_meter_color *conf;
9054 	enum rte_color color;
9055 
9056 	(void)buf;
9057 	(void)size;
9058 	/* Token name must match. */
9059 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9060 		return -1;
9061 	switch (ctx->curr) {
9062 	case ACTION_METER_COLOR_GREEN:
9063 		color = RTE_COLOR_GREEN;
9064 	break;
9065 	case ACTION_METER_COLOR_YELLOW:
9066 		color = RTE_COLOR_YELLOW;
9067 	break;
9068 	case ACTION_METER_COLOR_RED:
9069 		color = RTE_COLOR_RED;
9070 	break;
9071 	default:
9072 		return -1;
9073 	}
9074 
9075 	if (!ctx->object)
9076 		return len;
9077 	action_data = ctx->object;
9078 	conf = (struct rte_flow_action_meter_color *)
9079 					(uintptr_t)(action_data->conf);
9080 	conf->color = color;
9081 	return len;
9082 }
9083 
9084 /** Parse RSS action. */
9085 static int
9086 parse_vc_action_rss(struct context *ctx, const struct token *token,
9087 		    const char *str, unsigned int len,
9088 		    void *buf, unsigned int size)
9089 {
9090 	struct buffer *out = buf;
9091 	struct rte_flow_action *action;
9092 	struct action_rss_data *action_rss_data;
9093 	unsigned int i;
9094 	int ret;
9095 
9096 	ret = parse_vc(ctx, token, str, len, buf, size);
9097 	if (ret < 0)
9098 		return ret;
9099 	/* Nothing else to do if there is no buffer. */
9100 	if (!out)
9101 		return ret;
9102 	if (!out->args.vc.actions_n)
9103 		return -1;
9104 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9105 	/* Point to selected object. */
9106 	ctx->object = out->args.vc.data;
9107 	ctx->objmask = NULL;
9108 	/* Set up default configuration. */
9109 	action_rss_data = ctx->object;
9110 	*action_rss_data = (struct action_rss_data){
9111 		.conf = (struct rte_flow_action_rss){
9112 			.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
9113 			.level = 0,
9114 			.types = rss_hf,
9115 			.key_len = 0,
9116 			.queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
9117 			.key = NULL,
9118 			.queue = action_rss_data->queue,
9119 		},
9120 		.queue = { 0 },
9121 	};
9122 	for (i = 0; i < action_rss_data->conf.queue_num; ++i)
9123 		action_rss_data->queue[i] = i;
9124 	action->conf = &action_rss_data->conf;
9125 	return ret;
9126 }
9127 
9128 /**
9129  * Parse func field for RSS action.
9130  *
9131  * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
9132  * ACTION_RSS_FUNC_* index that called this function.
9133  */
9134 static int
9135 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
9136 			 const char *str, unsigned int len,
9137 			 void *buf, unsigned int size)
9138 {
9139 	struct action_rss_data *action_rss_data;
9140 	enum rte_eth_hash_function func;
9141 
9142 	(void)buf;
9143 	(void)size;
9144 	/* Token name must match. */
9145 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9146 		return -1;
9147 	switch (ctx->curr) {
9148 	case ACTION_RSS_FUNC_DEFAULT:
9149 		func = RTE_ETH_HASH_FUNCTION_DEFAULT;
9150 		break;
9151 	case ACTION_RSS_FUNC_TOEPLITZ:
9152 		func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
9153 		break;
9154 	case ACTION_RSS_FUNC_SIMPLE_XOR:
9155 		func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
9156 		break;
9157 	case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
9158 		func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
9159 		break;
9160 	default:
9161 		return -1;
9162 	}
9163 	if (!ctx->object)
9164 		return len;
9165 	action_rss_data = ctx->object;
9166 	action_rss_data->conf.func = func;
9167 	return len;
9168 }
9169 
9170 /**
9171  * Parse type field for RSS action.
9172  *
9173  * Valid tokens are type field names and the "end" token.
9174  */
9175 static int
9176 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
9177 			  const char *str, unsigned int len,
9178 			  void *buf, unsigned int size)
9179 {
9180 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
9181 	struct action_rss_data *action_rss_data;
9182 	unsigned int i;
9183 
9184 	(void)token;
9185 	(void)buf;
9186 	(void)size;
9187 	if (ctx->curr != ACTION_RSS_TYPE)
9188 		return -1;
9189 	if (!(ctx->objdata >> 16) && ctx->object) {
9190 		action_rss_data = ctx->object;
9191 		action_rss_data->conf.types = 0;
9192 	}
9193 	if (!strcmp_partial("end", str, len)) {
9194 		ctx->objdata &= 0xffff;
9195 		return len;
9196 	}
9197 	for (i = 0; rss_type_table[i].str; ++i)
9198 		if (!strcmp_partial(rss_type_table[i].str, str, len))
9199 			break;
9200 	if (!rss_type_table[i].str)
9201 		return -1;
9202 	ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
9203 	/* Repeat token. */
9204 	if (ctx->next_num == RTE_DIM(ctx->next))
9205 		return -1;
9206 	ctx->next[ctx->next_num++] = next;
9207 	if (!ctx->object)
9208 		return len;
9209 	action_rss_data = ctx->object;
9210 	action_rss_data->conf.types |= rss_type_table[i].rss_type;
9211 	return len;
9212 }
9213 
9214 /**
9215  * Parse queue field for RSS action.
9216  *
9217  * Valid tokens are queue indices and the "end" token.
9218  */
9219 static int
9220 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
9221 			  const char *str, unsigned int len,
9222 			  void *buf, unsigned int size)
9223 {
9224 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
9225 	struct action_rss_data *action_rss_data;
9226 	const struct arg *arg;
9227 	int ret;
9228 	int i;
9229 
9230 	(void)token;
9231 	(void)buf;
9232 	(void)size;
9233 	if (ctx->curr != ACTION_RSS_QUEUE)
9234 		return -1;
9235 	i = ctx->objdata >> 16;
9236 	if (!strcmp_partial("end", str, len)) {
9237 		ctx->objdata &= 0xffff;
9238 		goto end;
9239 	}
9240 	if (i >= ACTION_RSS_QUEUE_NUM)
9241 		return -1;
9242 	arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
9243 			     i * sizeof(action_rss_data->queue[i]),
9244 			     sizeof(action_rss_data->queue[i]));
9245 	if (push_args(ctx, arg))
9246 		return -1;
9247 	ret = parse_int(ctx, token, str, len, NULL, 0);
9248 	if (ret < 0) {
9249 		pop_args(ctx);
9250 		return -1;
9251 	}
9252 	++i;
9253 	ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
9254 	/* Repeat token. */
9255 	if (ctx->next_num == RTE_DIM(ctx->next))
9256 		return -1;
9257 	ctx->next[ctx->next_num++] = next;
9258 end:
9259 	if (!ctx->object)
9260 		return len;
9261 	action_rss_data = ctx->object;
9262 	action_rss_data->conf.queue_num = i;
9263 	action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
9264 	return len;
9265 }
9266 
9267 /** Setup VXLAN encap configuration. */
9268 static int
9269 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
9270 {
9271 	/* Set up default configuration. */
9272 	*action_vxlan_encap_data = (struct action_vxlan_encap_data){
9273 		.conf = (struct rte_flow_action_vxlan_encap){
9274 			.definition = action_vxlan_encap_data->items,
9275 		},
9276 		.items = {
9277 			{
9278 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9279 				.spec = &action_vxlan_encap_data->item_eth,
9280 				.mask = &rte_flow_item_eth_mask,
9281 			},
9282 			{
9283 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9284 				.spec = &action_vxlan_encap_data->item_vlan,
9285 				.mask = &rte_flow_item_vlan_mask,
9286 			},
9287 			{
9288 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9289 				.spec = &action_vxlan_encap_data->item_ipv4,
9290 				.mask = &rte_flow_item_ipv4_mask,
9291 			},
9292 			{
9293 				.type = RTE_FLOW_ITEM_TYPE_UDP,
9294 				.spec = &action_vxlan_encap_data->item_udp,
9295 				.mask = &rte_flow_item_udp_mask,
9296 			},
9297 			{
9298 				.type = RTE_FLOW_ITEM_TYPE_VXLAN,
9299 				.spec = &action_vxlan_encap_data->item_vxlan,
9300 				.mask = &rte_flow_item_vxlan_mask,
9301 			},
9302 			{
9303 				.type = RTE_FLOW_ITEM_TYPE_END,
9304 			},
9305 		},
9306 		.item_eth.hdr.ether_type = 0,
9307 		.item_vlan = {
9308 			.hdr.vlan_tci = vxlan_encap_conf.vlan_tci,
9309 			.hdr.eth_proto = 0,
9310 		},
9311 		.item_ipv4.hdr = {
9312 			.src_addr = vxlan_encap_conf.ipv4_src,
9313 			.dst_addr = vxlan_encap_conf.ipv4_dst,
9314 		},
9315 		.item_udp.hdr = {
9316 			.src_port = vxlan_encap_conf.udp_src,
9317 			.dst_port = vxlan_encap_conf.udp_dst,
9318 		},
9319 		.item_vxlan.hdr.flags = 0,
9320 	};
9321 	memcpy(action_vxlan_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9322 	       vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9323 	memcpy(action_vxlan_encap_data->item_eth.hdr.src_addr.addr_bytes,
9324 	       vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9325 	if (!vxlan_encap_conf.select_ipv4) {
9326 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
9327 		       &vxlan_encap_conf.ipv6_src,
9328 		       sizeof(vxlan_encap_conf.ipv6_src));
9329 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
9330 		       &vxlan_encap_conf.ipv6_dst,
9331 		       sizeof(vxlan_encap_conf.ipv6_dst));
9332 		action_vxlan_encap_data->items[2] = (struct rte_flow_item){
9333 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9334 			.spec = &action_vxlan_encap_data->item_ipv6,
9335 			.mask = &rte_flow_item_ipv6_mask,
9336 		};
9337 	}
9338 	if (!vxlan_encap_conf.select_vlan)
9339 		action_vxlan_encap_data->items[1].type =
9340 			RTE_FLOW_ITEM_TYPE_VOID;
9341 	if (vxlan_encap_conf.select_tos_ttl) {
9342 		if (vxlan_encap_conf.select_ipv4) {
9343 			static struct rte_flow_item_ipv4 ipv4_mask_tos;
9344 
9345 			memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
9346 			       sizeof(ipv4_mask_tos));
9347 			ipv4_mask_tos.hdr.type_of_service = 0xff;
9348 			ipv4_mask_tos.hdr.time_to_live = 0xff;
9349 			action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
9350 					vxlan_encap_conf.ip_tos;
9351 			action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
9352 					vxlan_encap_conf.ip_ttl;
9353 			action_vxlan_encap_data->items[2].mask =
9354 							&ipv4_mask_tos;
9355 		} else {
9356 			static struct rte_flow_item_ipv6 ipv6_mask_tos;
9357 
9358 			memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
9359 			       sizeof(ipv6_mask_tos));
9360 			ipv6_mask_tos.hdr.vtc_flow |=
9361 				RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
9362 			ipv6_mask_tos.hdr.hop_limits = 0xff;
9363 			action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
9364 				rte_cpu_to_be_32
9365 					((uint32_t)vxlan_encap_conf.ip_tos <<
9366 					 RTE_IPV6_HDR_TC_SHIFT);
9367 			action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
9368 					vxlan_encap_conf.ip_ttl;
9369 			action_vxlan_encap_data->items[2].mask =
9370 							&ipv6_mask_tos;
9371 		}
9372 	}
9373 	memcpy(action_vxlan_encap_data->item_vxlan.hdr.vni, vxlan_encap_conf.vni,
9374 	       RTE_DIM(vxlan_encap_conf.vni));
9375 	return 0;
9376 }
9377 
9378 /** Parse VXLAN encap action. */
9379 static int
9380 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
9381 			    const char *str, unsigned int len,
9382 			    void *buf, unsigned int size)
9383 {
9384 	struct buffer *out = buf;
9385 	struct rte_flow_action *action;
9386 	struct action_vxlan_encap_data *action_vxlan_encap_data;
9387 	int ret;
9388 
9389 	ret = parse_vc(ctx, token, str, len, buf, size);
9390 	if (ret < 0)
9391 		return ret;
9392 	/* Nothing else to do if there is no buffer. */
9393 	if (!out)
9394 		return ret;
9395 	if (!out->args.vc.actions_n)
9396 		return -1;
9397 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9398 	/* Point to selected object. */
9399 	ctx->object = out->args.vc.data;
9400 	ctx->objmask = NULL;
9401 	action_vxlan_encap_data = ctx->object;
9402 	parse_setup_vxlan_encap_data(action_vxlan_encap_data);
9403 	action->conf = &action_vxlan_encap_data->conf;
9404 	return ret;
9405 }
9406 
9407 /** Setup NVGRE encap configuration. */
9408 static int
9409 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
9410 {
9411 	/* Set up default configuration. */
9412 	*action_nvgre_encap_data = (struct action_nvgre_encap_data){
9413 		.conf = (struct rte_flow_action_nvgre_encap){
9414 			.definition = action_nvgre_encap_data->items,
9415 		},
9416 		.items = {
9417 			{
9418 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9419 				.spec = &action_nvgre_encap_data->item_eth,
9420 				.mask = &rte_flow_item_eth_mask,
9421 			},
9422 			{
9423 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9424 				.spec = &action_nvgre_encap_data->item_vlan,
9425 				.mask = &rte_flow_item_vlan_mask,
9426 			},
9427 			{
9428 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9429 				.spec = &action_nvgre_encap_data->item_ipv4,
9430 				.mask = &rte_flow_item_ipv4_mask,
9431 			},
9432 			{
9433 				.type = RTE_FLOW_ITEM_TYPE_NVGRE,
9434 				.spec = &action_nvgre_encap_data->item_nvgre,
9435 				.mask = &rte_flow_item_nvgre_mask,
9436 			},
9437 			{
9438 				.type = RTE_FLOW_ITEM_TYPE_END,
9439 			},
9440 		},
9441 		.item_eth.hdr.ether_type = 0,
9442 		.item_vlan = {
9443 			.hdr.vlan_tci = nvgre_encap_conf.vlan_tci,
9444 			.hdr.eth_proto = 0,
9445 		},
9446 		.item_ipv4.hdr = {
9447 		       .src_addr = nvgre_encap_conf.ipv4_src,
9448 		       .dst_addr = nvgre_encap_conf.ipv4_dst,
9449 		},
9450 		.item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
9451 		.item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
9452 		.item_nvgre.flow_id = 0,
9453 	};
9454 	memcpy(action_nvgre_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9455 	       nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9456 	memcpy(action_nvgre_encap_data->item_eth.hdr.src_addr.addr_bytes,
9457 	       nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9458 	if (!nvgre_encap_conf.select_ipv4) {
9459 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
9460 		       &nvgre_encap_conf.ipv6_src,
9461 		       sizeof(nvgre_encap_conf.ipv6_src));
9462 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
9463 		       &nvgre_encap_conf.ipv6_dst,
9464 		       sizeof(nvgre_encap_conf.ipv6_dst));
9465 		action_nvgre_encap_data->items[2] = (struct rte_flow_item){
9466 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9467 			.spec = &action_nvgre_encap_data->item_ipv6,
9468 			.mask = &rte_flow_item_ipv6_mask,
9469 		};
9470 	}
9471 	if (!nvgre_encap_conf.select_vlan)
9472 		action_nvgre_encap_data->items[1].type =
9473 			RTE_FLOW_ITEM_TYPE_VOID;
9474 	memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
9475 	       RTE_DIM(nvgre_encap_conf.tni));
9476 	return 0;
9477 }
9478 
9479 /** Parse NVGRE encap action. */
9480 static int
9481 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
9482 			    const char *str, unsigned int len,
9483 			    void *buf, unsigned int size)
9484 {
9485 	struct buffer *out = buf;
9486 	struct rte_flow_action *action;
9487 	struct action_nvgre_encap_data *action_nvgre_encap_data;
9488 	int ret;
9489 
9490 	ret = parse_vc(ctx, token, str, len, buf, size);
9491 	if (ret < 0)
9492 		return ret;
9493 	/* Nothing else to do if there is no buffer. */
9494 	if (!out)
9495 		return ret;
9496 	if (!out->args.vc.actions_n)
9497 		return -1;
9498 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9499 	/* Point to selected object. */
9500 	ctx->object = out->args.vc.data;
9501 	ctx->objmask = NULL;
9502 	action_nvgre_encap_data = ctx->object;
9503 	parse_setup_nvgre_encap_data(action_nvgre_encap_data);
9504 	action->conf = &action_nvgre_encap_data->conf;
9505 	return ret;
9506 }
9507 
9508 /** Parse l2 encap action. */
9509 static int
9510 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
9511 			 const char *str, unsigned int len,
9512 			 void *buf, unsigned int size)
9513 {
9514 	struct buffer *out = buf;
9515 	struct rte_flow_action *action;
9516 	struct action_raw_encap_data *action_encap_data;
9517 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9518 	struct rte_flow_item_vlan vlan = {
9519 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9520 		.hdr.eth_proto = 0,
9521 	};
9522 	uint8_t *header;
9523 	int ret;
9524 
9525 	ret = parse_vc(ctx, token, str, len, buf, size);
9526 	if (ret < 0)
9527 		return ret;
9528 	/* Nothing else to do if there is no buffer. */
9529 	if (!out)
9530 		return ret;
9531 	if (!out->args.vc.actions_n)
9532 		return -1;
9533 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9534 	/* Point to selected object. */
9535 	ctx->object = out->args.vc.data;
9536 	ctx->objmask = NULL;
9537 	/* Copy the headers to the buffer. */
9538 	action_encap_data = ctx->object;
9539 	*action_encap_data = (struct action_raw_encap_data) {
9540 		.conf = (struct rte_flow_action_raw_encap){
9541 			.data = action_encap_data->data,
9542 		},
9543 		.data = {},
9544 	};
9545 	header = action_encap_data->data;
9546 	if (l2_encap_conf.select_vlan)
9547 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9548 	else if (l2_encap_conf.select_ipv4)
9549 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9550 	else
9551 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9552 	memcpy(eth.hdr.dst_addr.addr_bytes,
9553 	       l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9554 	memcpy(eth.hdr.src_addr.addr_bytes,
9555 	       l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9556 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9557 	header += sizeof(struct rte_ether_hdr);
9558 	if (l2_encap_conf.select_vlan) {
9559 		if (l2_encap_conf.select_ipv4)
9560 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9561 		else
9562 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9563 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9564 		header += sizeof(struct rte_vlan_hdr);
9565 	}
9566 	action_encap_data->conf.size = header -
9567 		action_encap_data->data;
9568 	action->conf = &action_encap_data->conf;
9569 	return ret;
9570 }
9571 
9572 /** Parse l2 decap action. */
9573 static int
9574 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
9575 			 const char *str, unsigned int len,
9576 			 void *buf, unsigned int size)
9577 {
9578 	struct buffer *out = buf;
9579 	struct rte_flow_action *action;
9580 	struct action_raw_decap_data *action_decap_data;
9581 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9582 	struct rte_flow_item_vlan vlan = {
9583 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9584 		.hdr.eth_proto = 0,
9585 	};
9586 	uint8_t *header;
9587 	int ret;
9588 
9589 	ret = parse_vc(ctx, token, str, len, buf, size);
9590 	if (ret < 0)
9591 		return ret;
9592 	/* Nothing else to do if there is no buffer. */
9593 	if (!out)
9594 		return ret;
9595 	if (!out->args.vc.actions_n)
9596 		return -1;
9597 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9598 	/* Point to selected object. */
9599 	ctx->object = out->args.vc.data;
9600 	ctx->objmask = NULL;
9601 	/* Copy the headers to the buffer. */
9602 	action_decap_data = ctx->object;
9603 	*action_decap_data = (struct action_raw_decap_data) {
9604 		.conf = (struct rte_flow_action_raw_decap){
9605 			.data = action_decap_data->data,
9606 		},
9607 		.data = {},
9608 	};
9609 	header = action_decap_data->data;
9610 	if (l2_decap_conf.select_vlan)
9611 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9612 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9613 	header += sizeof(struct rte_ether_hdr);
9614 	if (l2_decap_conf.select_vlan) {
9615 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9616 		header += sizeof(struct rte_vlan_hdr);
9617 	}
9618 	action_decap_data->conf.size = header -
9619 		action_decap_data->data;
9620 	action->conf = &action_decap_data->conf;
9621 	return ret;
9622 }
9623 
9624 #define ETHER_TYPE_MPLS_UNICAST 0x8847
9625 
9626 /** Parse MPLSOGRE encap action. */
9627 static int
9628 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
9629 			       const char *str, unsigned int len,
9630 			       void *buf, unsigned int size)
9631 {
9632 	struct buffer *out = buf;
9633 	struct rte_flow_action *action;
9634 	struct action_raw_encap_data *action_encap_data;
9635 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9636 	struct rte_flow_item_vlan vlan = {
9637 		.hdr.vlan_tci = mplsogre_encap_conf.vlan_tci,
9638 		.hdr.eth_proto = 0,
9639 	};
9640 	struct rte_flow_item_ipv4 ipv4 = {
9641 		.hdr =  {
9642 			.src_addr = mplsogre_encap_conf.ipv4_src,
9643 			.dst_addr = mplsogre_encap_conf.ipv4_dst,
9644 			.next_proto_id = IPPROTO_GRE,
9645 			.version_ihl = RTE_IPV4_VHL_DEF,
9646 			.time_to_live = IPDEFTTL,
9647 		},
9648 	};
9649 	struct rte_flow_item_ipv6 ipv6 = {
9650 		.hdr =  {
9651 			.proto = IPPROTO_GRE,
9652 			.hop_limits = IPDEFTTL,
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 		.ttl = 0,
9660 	};
9661 	uint8_t *header;
9662 	int ret;
9663 
9664 	ret = parse_vc(ctx, token, str, len, buf, size);
9665 	if (ret < 0)
9666 		return ret;
9667 	/* Nothing else to do if there is no buffer. */
9668 	if (!out)
9669 		return ret;
9670 	if (!out->args.vc.actions_n)
9671 		return -1;
9672 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9673 	/* Point to selected object. */
9674 	ctx->object = out->args.vc.data;
9675 	ctx->objmask = NULL;
9676 	/* Copy the headers to the buffer. */
9677 	action_encap_data = ctx->object;
9678 	*action_encap_data = (struct action_raw_encap_data) {
9679 		.conf = (struct rte_flow_action_raw_encap){
9680 			.data = action_encap_data->data,
9681 		},
9682 		.data = {},
9683 		.preserve = {},
9684 	};
9685 	header = action_encap_data->data;
9686 	if (mplsogre_encap_conf.select_vlan)
9687 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9688 	else if (mplsogre_encap_conf.select_ipv4)
9689 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9690 	else
9691 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9692 	memcpy(eth.hdr.dst_addr.addr_bytes,
9693 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9694 	memcpy(eth.hdr.src_addr.addr_bytes,
9695 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9696 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9697 	header += sizeof(struct rte_ether_hdr);
9698 	if (mplsogre_encap_conf.select_vlan) {
9699 		if (mplsogre_encap_conf.select_ipv4)
9700 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9701 		else
9702 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9703 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9704 		header += sizeof(struct rte_vlan_hdr);
9705 	}
9706 	if (mplsogre_encap_conf.select_ipv4) {
9707 		memcpy(header, &ipv4, sizeof(ipv4));
9708 		header += sizeof(ipv4);
9709 	} else {
9710 		memcpy(&ipv6.hdr.src_addr,
9711 		       &mplsogre_encap_conf.ipv6_src,
9712 		       sizeof(mplsogre_encap_conf.ipv6_src));
9713 		memcpy(&ipv6.hdr.dst_addr,
9714 		       &mplsogre_encap_conf.ipv6_dst,
9715 		       sizeof(mplsogre_encap_conf.ipv6_dst));
9716 		memcpy(header, &ipv6, sizeof(ipv6));
9717 		header += sizeof(ipv6);
9718 	}
9719 	memcpy(header, &gre, sizeof(gre));
9720 	header += sizeof(gre);
9721 	memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
9722 	       RTE_DIM(mplsogre_encap_conf.label));
9723 	mpls.label_tc_s[2] |= 0x1;
9724 	memcpy(header, &mpls, sizeof(mpls));
9725 	header += sizeof(mpls);
9726 	action_encap_data->conf.size = header -
9727 		action_encap_data->data;
9728 	action->conf = &action_encap_data->conf;
9729 	return ret;
9730 }
9731 
9732 /** Parse MPLSOGRE decap action. */
9733 static int
9734 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
9735 			       const char *str, unsigned int len,
9736 			       void *buf, unsigned int size)
9737 {
9738 	struct buffer *out = buf;
9739 	struct rte_flow_action *action;
9740 	struct action_raw_decap_data *action_decap_data;
9741 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9742 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
9743 	struct rte_flow_item_ipv4 ipv4 = {
9744 		.hdr =  {
9745 			.next_proto_id = IPPROTO_GRE,
9746 		},
9747 	};
9748 	struct rte_flow_item_ipv6 ipv6 = {
9749 		.hdr =  {
9750 			.proto = IPPROTO_GRE,
9751 		},
9752 	};
9753 	struct rte_flow_item_gre gre = {
9754 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
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_decap_data = ctx->object;
9774 	*action_decap_data = (struct action_raw_decap_data) {
9775 		.conf = (struct rte_flow_action_raw_decap){
9776 			.data = action_decap_data->data,
9777 		},
9778 		.data = {},
9779 	};
9780 	header = action_decap_data->data;
9781 	if (mplsogre_decap_conf.select_vlan)
9782 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9783 	else if (mplsogre_encap_conf.select_ipv4)
9784 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9785 	else
9786 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9787 	memcpy(eth.hdr.dst_addr.addr_bytes,
9788 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9789 	memcpy(eth.hdr.src_addr.addr_bytes,
9790 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9791 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9792 	header += sizeof(struct rte_ether_hdr);
9793 	if (mplsogre_encap_conf.select_vlan) {
9794 		if (mplsogre_encap_conf.select_ipv4)
9795 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9796 		else
9797 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9798 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9799 		header += sizeof(struct rte_vlan_hdr);
9800 	}
9801 	if (mplsogre_encap_conf.select_ipv4) {
9802 		memcpy(header, &ipv4, sizeof(ipv4));
9803 		header += sizeof(ipv4);
9804 	} else {
9805 		memcpy(header, &ipv6, sizeof(ipv6));
9806 		header += sizeof(ipv6);
9807 	}
9808 	memcpy(header, &gre, sizeof(gre));
9809 	header += sizeof(gre);
9810 	memset(&mpls, 0, sizeof(mpls));
9811 	memcpy(header, &mpls, sizeof(mpls));
9812 	header += sizeof(mpls);
9813 	action_decap_data->conf.size = header -
9814 		action_decap_data->data;
9815 	action->conf = &action_decap_data->conf;
9816 	return ret;
9817 }
9818 
9819 /** Parse MPLSOUDP encap action. */
9820 static int
9821 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
9822 			       const char *str, unsigned int len,
9823 			       void *buf, unsigned int size)
9824 {
9825 	struct buffer *out = buf;
9826 	struct rte_flow_action *action;
9827 	struct action_raw_encap_data *action_encap_data;
9828 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9829 	struct rte_flow_item_vlan vlan = {
9830 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9831 		.hdr.eth_proto = 0,
9832 	};
9833 	struct rte_flow_item_ipv4 ipv4 = {
9834 		.hdr =  {
9835 			.src_addr = mplsoudp_encap_conf.ipv4_src,
9836 			.dst_addr = mplsoudp_encap_conf.ipv4_dst,
9837 			.next_proto_id = IPPROTO_UDP,
9838 			.version_ihl = RTE_IPV4_VHL_DEF,
9839 			.time_to_live = IPDEFTTL,
9840 		},
9841 	};
9842 	struct rte_flow_item_ipv6 ipv6 = {
9843 		.hdr =  {
9844 			.proto = IPPROTO_UDP,
9845 			.hop_limits = IPDEFTTL,
9846 		},
9847 	};
9848 	struct rte_flow_item_udp udp = {
9849 		.hdr = {
9850 			.src_port = mplsoudp_encap_conf.udp_src,
9851 			.dst_port = mplsoudp_encap_conf.udp_dst,
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_encap_data = ctx->object;
9872 	*action_encap_data = (struct action_raw_encap_data) {
9873 		.conf = (struct rte_flow_action_raw_encap){
9874 			.data = action_encap_data->data,
9875 		},
9876 		.data = {},
9877 		.preserve = {},
9878 	};
9879 	header = action_encap_data->data;
9880 	if (mplsoudp_encap_conf.select_vlan)
9881 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9882 	else if (mplsoudp_encap_conf.select_ipv4)
9883 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9884 	else
9885 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9886 	memcpy(eth.hdr.dst_addr.addr_bytes,
9887 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9888 	memcpy(eth.hdr.src_addr.addr_bytes,
9889 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9890 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9891 	header += sizeof(struct rte_ether_hdr);
9892 	if (mplsoudp_encap_conf.select_vlan) {
9893 		if (mplsoudp_encap_conf.select_ipv4)
9894 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9895 		else
9896 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9897 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9898 		header += sizeof(struct rte_vlan_hdr);
9899 	}
9900 	if (mplsoudp_encap_conf.select_ipv4) {
9901 		memcpy(header, &ipv4, sizeof(ipv4));
9902 		header += sizeof(ipv4);
9903 	} else {
9904 		memcpy(&ipv6.hdr.src_addr,
9905 		       &mplsoudp_encap_conf.ipv6_src,
9906 		       sizeof(mplsoudp_encap_conf.ipv6_src));
9907 		memcpy(&ipv6.hdr.dst_addr,
9908 		       &mplsoudp_encap_conf.ipv6_dst,
9909 		       sizeof(mplsoudp_encap_conf.ipv6_dst));
9910 		memcpy(header, &ipv6, sizeof(ipv6));
9911 		header += sizeof(ipv6);
9912 	}
9913 	memcpy(header, &udp, sizeof(udp));
9914 	header += sizeof(udp);
9915 	memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
9916 	       RTE_DIM(mplsoudp_encap_conf.label));
9917 	mpls.label_tc_s[2] |= 0x1;
9918 	memcpy(header, &mpls, sizeof(mpls));
9919 	header += sizeof(mpls);
9920 	action_encap_data->conf.size = header -
9921 		action_encap_data->data;
9922 	action->conf = &action_encap_data->conf;
9923 	return ret;
9924 }
9925 
9926 /** Parse MPLSOUDP decap action. */
9927 static int
9928 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
9929 			       const char *str, unsigned int len,
9930 			       void *buf, unsigned int size)
9931 {
9932 	struct buffer *out = buf;
9933 	struct rte_flow_action *action;
9934 	struct action_raw_decap_data *action_decap_data;
9935 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9936 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
9937 	struct rte_flow_item_ipv4 ipv4 = {
9938 		.hdr =  {
9939 			.next_proto_id = IPPROTO_UDP,
9940 		},
9941 	};
9942 	struct rte_flow_item_ipv6 ipv6 = {
9943 		.hdr =  {
9944 			.proto = IPPROTO_UDP,
9945 		},
9946 	};
9947 	struct rte_flow_item_udp udp = {
9948 		.hdr = {
9949 			.dst_port = rte_cpu_to_be_16(6635),
9950 		},
9951 	};
9952 	struct rte_flow_item_mpls mpls;
9953 	uint8_t *header;
9954 	int ret;
9955 
9956 	ret = parse_vc(ctx, token, str, len, buf, size);
9957 	if (ret < 0)
9958 		return ret;
9959 	/* Nothing else to do if there is no buffer. */
9960 	if (!out)
9961 		return ret;
9962 	if (!out->args.vc.actions_n)
9963 		return -1;
9964 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9965 	/* Point to selected object. */
9966 	ctx->object = out->args.vc.data;
9967 	ctx->objmask = NULL;
9968 	/* Copy the headers to the buffer. */
9969 	action_decap_data = ctx->object;
9970 	*action_decap_data = (struct action_raw_decap_data) {
9971 		.conf = (struct rte_flow_action_raw_decap){
9972 			.data = action_decap_data->data,
9973 		},
9974 		.data = {},
9975 	};
9976 	header = action_decap_data->data;
9977 	if (mplsoudp_decap_conf.select_vlan)
9978 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9979 	else if (mplsoudp_encap_conf.select_ipv4)
9980 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9981 	else
9982 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9983 	memcpy(eth.hdr.dst_addr.addr_bytes,
9984 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9985 	memcpy(eth.hdr.src_addr.addr_bytes,
9986 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9987 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9988 	header += sizeof(struct rte_ether_hdr);
9989 	if (mplsoudp_encap_conf.select_vlan) {
9990 		if (mplsoudp_encap_conf.select_ipv4)
9991 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9992 		else
9993 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9994 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9995 		header += sizeof(struct rte_vlan_hdr);
9996 	}
9997 	if (mplsoudp_encap_conf.select_ipv4) {
9998 		memcpy(header, &ipv4, sizeof(ipv4));
9999 		header += sizeof(ipv4);
10000 	} else {
10001 		memcpy(header, &ipv6, sizeof(ipv6));
10002 		header += sizeof(ipv6);
10003 	}
10004 	memcpy(header, &udp, sizeof(udp));
10005 	header += sizeof(udp);
10006 	memset(&mpls, 0, sizeof(mpls));
10007 	memcpy(header, &mpls, sizeof(mpls));
10008 	header += sizeof(mpls);
10009 	action_decap_data->conf.size = header -
10010 		action_decap_data->data;
10011 	action->conf = &action_decap_data->conf;
10012 	return ret;
10013 }
10014 
10015 static int
10016 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
10017 				const char *str, unsigned int len, void *buf,
10018 				unsigned int size)
10019 {
10020 	struct action_raw_decap_data *action_raw_decap_data;
10021 	struct rte_flow_action *action;
10022 	const struct arg *arg;
10023 	struct buffer *out = buf;
10024 	int ret;
10025 	uint16_t idx;
10026 
10027 	RTE_SET_USED(token);
10028 	RTE_SET_USED(buf);
10029 	RTE_SET_USED(size);
10030 	arg = ARGS_ENTRY_ARB_BOUNDED
10031 		(offsetof(struct action_raw_decap_data, idx),
10032 		 sizeof(((struct action_raw_decap_data *)0)->idx),
10033 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
10034 	if (push_args(ctx, arg))
10035 		return -1;
10036 	ret = parse_int(ctx, token, str, len, NULL, 0);
10037 	if (ret < 0) {
10038 		pop_args(ctx);
10039 		return -1;
10040 	}
10041 	if (!ctx->object)
10042 		return len;
10043 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10044 	action_raw_decap_data = ctx->object;
10045 	idx = action_raw_decap_data->idx;
10046 	action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
10047 	action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
10048 	action->conf = &action_raw_decap_data->conf;
10049 	return len;
10050 }
10051 
10052 
10053 static int
10054 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
10055 				const char *str, unsigned int len, void *buf,
10056 				unsigned int size)
10057 {
10058 	struct action_raw_encap_data *action_raw_encap_data;
10059 	struct rte_flow_action *action;
10060 	const struct arg *arg;
10061 	struct buffer *out = buf;
10062 	int ret;
10063 	uint16_t idx;
10064 
10065 	RTE_SET_USED(token);
10066 	RTE_SET_USED(buf);
10067 	RTE_SET_USED(size);
10068 	if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
10069 		return -1;
10070 	arg = ARGS_ENTRY_ARB_BOUNDED
10071 		(offsetof(struct action_raw_encap_data, idx),
10072 		 sizeof(((struct action_raw_encap_data *)0)->idx),
10073 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
10074 	if (push_args(ctx, arg))
10075 		return -1;
10076 	ret = parse_int(ctx, token, str, len, NULL, 0);
10077 	if (ret < 0) {
10078 		pop_args(ctx);
10079 		return -1;
10080 	}
10081 	if (!ctx->object)
10082 		return len;
10083 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10084 	action_raw_encap_data = ctx->object;
10085 	idx = action_raw_encap_data->idx;
10086 	action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
10087 	action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
10088 	action_raw_encap_data->conf.preserve = NULL;
10089 	action->conf = &action_raw_encap_data->conf;
10090 	return len;
10091 }
10092 
10093 static int
10094 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
10095 			  const char *str, unsigned int len, void *buf,
10096 			  unsigned int size)
10097 {
10098 	struct buffer *out = buf;
10099 	int ret;
10100 
10101 	ret = parse_vc(ctx, token, str, len, buf, size);
10102 	if (ret < 0)
10103 		return ret;
10104 	/* Nothing else to do if there is no buffer. */
10105 	if (!out)
10106 		return ret;
10107 	if (!out->args.vc.actions_n)
10108 		return -1;
10109 	/* Point to selected object. */
10110 	ctx->object = out->args.vc.data;
10111 	ctx->objmask = NULL;
10112 	return ret;
10113 }
10114 
10115 static int
10116 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
10117 			  const char *str, unsigned int len, void *buf,
10118 			  unsigned int size)
10119 {
10120 	struct buffer *out = buf;
10121 	struct rte_flow_action *action;
10122 	struct action_raw_decap_data *action_raw_decap_data = NULL;
10123 	int ret;
10124 
10125 	ret = parse_vc(ctx, token, str, len, buf, size);
10126 	if (ret < 0)
10127 		return ret;
10128 	/* Nothing else to do if there is no buffer. */
10129 	if (!out)
10130 		return ret;
10131 	if (!out->args.vc.actions_n)
10132 		return -1;
10133 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10134 	/* Point to selected object. */
10135 	ctx->object = out->args.vc.data;
10136 	ctx->objmask = NULL;
10137 	/* Copy the headers to the buffer. */
10138 	action_raw_decap_data = ctx->object;
10139 	action_raw_decap_data->conf.data = raw_decap_confs[0].data;
10140 	action_raw_decap_data->conf.size = raw_decap_confs[0].size;
10141 	action->conf = &action_raw_decap_data->conf;
10142 	return ret;
10143 }
10144 
10145 static int
10146 parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
10147 				const char *str, unsigned int len, void *buf,
10148 				unsigned int size)
10149 {
10150 	struct buffer *out = buf;
10151 	struct rte_flow_action *action;
10152 	struct action_ipv6_ext_remove_data *ipv6_ext_remove_data = NULL;
10153 	int ret;
10154 
10155 	ret = parse_vc(ctx, token, str, len, buf, size);
10156 	if (ret < 0)
10157 		return ret;
10158 	/* Nothing else to do if there is no buffer. */
10159 	if (!out)
10160 		return ret;
10161 	if (!out->args.vc.actions_n)
10162 		return -1;
10163 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10164 	/* Point to selected object. */
10165 	ctx->object = out->args.vc.data;
10166 	ctx->objmask = NULL;
10167 	/* Copy the headers to the buffer. */
10168 	ipv6_ext_remove_data = ctx->object;
10169 	ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[0].type;
10170 	action->conf = &ipv6_ext_remove_data->conf;
10171 	return ret;
10172 }
10173 
10174 static int
10175 parse_vc_action_ipv6_ext_remove_index(struct context *ctx, const struct token *token,
10176 				      const char *str, unsigned int len, void *buf,
10177 				      unsigned int size)
10178 {
10179 	struct action_ipv6_ext_remove_data *action_ipv6_ext_remove_data;
10180 	struct rte_flow_action *action;
10181 	const struct arg *arg;
10182 	struct buffer *out = buf;
10183 	int ret;
10184 	uint16_t idx;
10185 
10186 	RTE_SET_USED(token);
10187 	RTE_SET_USED(buf);
10188 	RTE_SET_USED(size);
10189 	arg = ARGS_ENTRY_ARB_BOUNDED
10190 		(offsetof(struct action_ipv6_ext_remove_data, idx),
10191 		 sizeof(((struct action_ipv6_ext_remove_data *)0)->idx),
10192 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10193 	if (push_args(ctx, arg))
10194 		return -1;
10195 	ret = parse_int(ctx, token, str, len, NULL, 0);
10196 	if (ret < 0) {
10197 		pop_args(ctx);
10198 		return -1;
10199 	}
10200 	if (!ctx->object)
10201 		return len;
10202 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10203 	action_ipv6_ext_remove_data = ctx->object;
10204 	idx = action_ipv6_ext_remove_data->idx;
10205 	action_ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[idx].type;
10206 	action->conf = &action_ipv6_ext_remove_data->conf;
10207 	return len;
10208 }
10209 
10210 static int
10211 parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
10212 			      const char *str, unsigned int len, void *buf,
10213 			      unsigned int size)
10214 {
10215 	struct buffer *out = buf;
10216 	struct rte_flow_action *action;
10217 	struct action_ipv6_ext_push_data *ipv6_ext_push_data = NULL;
10218 	int ret;
10219 
10220 	ret = parse_vc(ctx, token, str, len, buf, size);
10221 	if (ret < 0)
10222 		return ret;
10223 	/* Nothing else to do if there is no buffer. */
10224 	if (!out)
10225 		return ret;
10226 	if (!out->args.vc.actions_n)
10227 		return -1;
10228 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10229 	/* Point to selected object. */
10230 	ctx->object = out->args.vc.data;
10231 	ctx->objmask = NULL;
10232 	/* Copy the headers to the buffer. */
10233 	ipv6_ext_push_data = ctx->object;
10234 	ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[0].type;
10235 	ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[0].data;
10236 	ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[0].size;
10237 	action->conf = &ipv6_ext_push_data->conf;
10238 	return ret;
10239 }
10240 
10241 static int
10242 parse_vc_action_ipv6_ext_push_index(struct context *ctx, const struct token *token,
10243 				    const char *str, unsigned int len, void *buf,
10244 				    unsigned int size)
10245 {
10246 	struct action_ipv6_ext_push_data *action_ipv6_ext_push_data;
10247 	struct rte_flow_action *action;
10248 	const struct arg *arg;
10249 	struct buffer *out = buf;
10250 	int ret;
10251 	uint16_t idx;
10252 
10253 	RTE_SET_USED(token);
10254 	RTE_SET_USED(buf);
10255 	RTE_SET_USED(size);
10256 	arg = ARGS_ENTRY_ARB_BOUNDED
10257 		(offsetof(struct action_ipv6_ext_push_data, idx),
10258 		 sizeof(((struct action_ipv6_ext_push_data *)0)->idx),
10259 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10260 	if (push_args(ctx, arg))
10261 		return -1;
10262 	ret = parse_int(ctx, token, str, len, NULL, 0);
10263 	if (ret < 0) {
10264 		pop_args(ctx);
10265 		return -1;
10266 	}
10267 	if (!ctx->object)
10268 		return len;
10269 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10270 	action_ipv6_ext_push_data = ctx->object;
10271 	idx = action_ipv6_ext_push_data->idx;
10272 	action_ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[idx].type;
10273 	action_ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[idx].size;
10274 	action_ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[idx].data;
10275 	action->conf = &action_ipv6_ext_push_data->conf;
10276 	return len;
10277 }
10278 
10279 static int
10280 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
10281 			 const char *str, unsigned int len, void *buf,
10282 			 unsigned int size)
10283 {
10284 	int ret;
10285 
10286 	ret = parse_vc(ctx, token, str, len, buf, size);
10287 	if (ret < 0)
10288 		return ret;
10289 	ret = rte_flow_dynf_metadata_register();
10290 	if (ret < 0)
10291 		return -1;
10292 	return len;
10293 }
10294 
10295 static int
10296 parse_vc_action_sample(struct context *ctx, const struct token *token,
10297 			 const char *str, unsigned int len, void *buf,
10298 			 unsigned int size)
10299 {
10300 	struct buffer *out = buf;
10301 	struct rte_flow_action *action;
10302 	struct action_sample_data *action_sample_data = NULL;
10303 	static struct rte_flow_action end_action = {
10304 		RTE_FLOW_ACTION_TYPE_END, 0
10305 	};
10306 	int ret;
10307 
10308 	ret = parse_vc(ctx, token, str, len, buf, size);
10309 	if (ret < 0)
10310 		return ret;
10311 	/* Nothing else to do if there is no buffer. */
10312 	if (!out)
10313 		return ret;
10314 	if (!out->args.vc.actions_n)
10315 		return -1;
10316 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10317 	/* Point to selected object. */
10318 	ctx->object = out->args.vc.data;
10319 	ctx->objmask = NULL;
10320 	/* Copy the headers to the buffer. */
10321 	action_sample_data = ctx->object;
10322 	action_sample_data->conf.actions = &end_action;
10323 	action->conf = &action_sample_data->conf;
10324 	return ret;
10325 }
10326 
10327 static int
10328 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
10329 				const char *str, unsigned int len, void *buf,
10330 				unsigned int size)
10331 {
10332 	struct action_sample_data *action_sample_data;
10333 	struct rte_flow_action *action;
10334 	const struct arg *arg;
10335 	struct buffer *out = buf;
10336 	int ret;
10337 	uint16_t idx;
10338 
10339 	RTE_SET_USED(token);
10340 	RTE_SET_USED(buf);
10341 	RTE_SET_USED(size);
10342 	if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
10343 		return -1;
10344 	arg = ARGS_ENTRY_ARB_BOUNDED
10345 		(offsetof(struct action_sample_data, idx),
10346 		 sizeof(((struct action_sample_data *)0)->idx),
10347 		 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
10348 	if (push_args(ctx, arg))
10349 		return -1;
10350 	ret = parse_int(ctx, token, str, len, NULL, 0);
10351 	if (ret < 0) {
10352 		pop_args(ctx);
10353 		return -1;
10354 	}
10355 	if (!ctx->object)
10356 		return len;
10357 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10358 	action_sample_data = ctx->object;
10359 	idx = action_sample_data->idx;
10360 	action_sample_data->conf.actions = raw_sample_confs[idx].data;
10361 	action->conf = &action_sample_data->conf;
10362 	return len;
10363 }
10364 
10365 /** Parse operation for modify_field command. */
10366 static int
10367 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
10368 			 const char *str, unsigned int len, void *buf,
10369 			 unsigned int size)
10370 {
10371 	struct rte_flow_action_modify_field *action_modify_field;
10372 	unsigned int i;
10373 
10374 	(void)token;
10375 	(void)buf;
10376 	(void)size;
10377 	if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
10378 		return -1;
10379 	for (i = 0; modify_field_ops[i]; ++i)
10380 		if (!strcmp_partial(modify_field_ops[i], str, len))
10381 			break;
10382 	if (!modify_field_ops[i])
10383 		return -1;
10384 	if (!ctx->object)
10385 		return len;
10386 	action_modify_field = ctx->object;
10387 	action_modify_field->operation = (enum rte_flow_modify_op)i;
10388 	return len;
10389 }
10390 
10391 /** Parse id for modify_field command. */
10392 static int
10393 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
10394 			 const char *str, unsigned int len, void *buf,
10395 			 unsigned int size)
10396 {
10397 	struct rte_flow_action_modify_field *action_modify_field;
10398 	unsigned int i;
10399 
10400 	(void)token;
10401 	(void)buf;
10402 	(void)size;
10403 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
10404 		ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
10405 		return -1;
10406 	for (i = 0; flow_field_ids[i]; ++i)
10407 		if (!strcmp_partial(flow_field_ids[i], str, len))
10408 			break;
10409 	if (!flow_field_ids[i])
10410 		return -1;
10411 	if (!ctx->object)
10412 		return len;
10413 	action_modify_field = ctx->object;
10414 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
10415 		action_modify_field->dst.field = (enum rte_flow_field_id)i;
10416 	else
10417 		action_modify_field->src.field = (enum rte_flow_field_id)i;
10418 	return len;
10419 }
10420 
10421 /** Parse level for modify_field command. */
10422 static int
10423 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
10424 			 const char *str, unsigned int len, void *buf,
10425 			 unsigned int size)
10426 {
10427 	struct rte_flow_action_modify_field *action;
10428 	struct flex_item *fp = NULL;
10429 	uint32_t val;
10430 	struct buffer *out = buf;
10431 	char *end;
10432 
10433 	(void)token;
10434 	(void)size;
10435 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10436 		ctx->curr != ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)
10437 		return -1;
10438 	if (!ctx->object)
10439 		return len;
10440 	action = ctx->object;
10441 	errno = 0;
10442 	val = strtoumax(str, &end, 0);
10443 	if (errno || (size_t)(end - str) != len)
10444 		return -1;
10445 	/* No need to validate action template mask value */
10446 	if (out->args.vc.masks) {
10447 		if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)
10448 			action->dst.level = val;
10449 		else
10450 			action->src.level = val;
10451 		return len;
10452 	}
10453 	if ((ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10454 		action->dst.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
10455 		(ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE &&
10456 		action->src.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
10457 		if (val >= FLEX_MAX_PARSERS_NUM) {
10458 			printf("Bad flex item handle\n");
10459 			return -1;
10460 		}
10461 		fp = flex_items[ctx->port][val];
10462 		if (!fp) {
10463 			printf("Bad flex item handle\n");
10464 			return -1;
10465 		}
10466 	}
10467 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE) {
10468 		if (action->dst.field != RTE_FLOW_FIELD_FLEX_ITEM)
10469 			action->dst.level = val;
10470 		else
10471 			action->dst.flex_handle = fp->flex_handle;
10472 	} else if (ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE) {
10473 		if (action->src.field != RTE_FLOW_FIELD_FLEX_ITEM)
10474 			action->src.level = val;
10475 		else
10476 			action->src.flex_handle = fp->flex_handle;
10477 	}
10478 	return len;
10479 }
10480 
10481 /** Parse the conntrack update, not a rte_flow_action. */
10482 static int
10483 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
10484 			 const char *str, unsigned int len, void *buf,
10485 			 unsigned int size)
10486 {
10487 	struct buffer *out = buf;
10488 	struct rte_flow_modify_conntrack *ct_modify = NULL;
10489 
10490 	(void)size;
10491 	if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
10492 	    ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
10493 		return -1;
10494 	/* Token name must match. */
10495 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10496 		return -1;
10497 	/* Nothing else to do if there is no buffer. */
10498 	if (!out)
10499 		return len;
10500 	ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
10501 	if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
10502 		ct_modify->new_ct.is_original_dir =
10503 				conntrack_context.is_original_dir;
10504 		ct_modify->direction = 1;
10505 	} else {
10506 		uint32_t old_dir;
10507 
10508 		old_dir = ct_modify->new_ct.is_original_dir;
10509 		memcpy(&ct_modify->new_ct, &conntrack_context,
10510 		       sizeof(conntrack_context));
10511 		ct_modify->new_ct.is_original_dir = old_dir;
10512 		ct_modify->state = 1;
10513 	}
10514 	return len;
10515 }
10516 
10517 /** Parse tokens for destroy command. */
10518 static int
10519 parse_destroy(struct context *ctx, const struct token *token,
10520 	      const char *str, unsigned int len,
10521 	      void *buf, unsigned int size)
10522 {
10523 	struct buffer *out = buf;
10524 
10525 	/* Token name must match. */
10526 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10527 		return -1;
10528 	/* Nothing else to do if there is no buffer. */
10529 	if (!out)
10530 		return len;
10531 	if (!out->command) {
10532 		if (ctx->curr != DESTROY)
10533 			return -1;
10534 		if (sizeof(*out) > size)
10535 			return -1;
10536 		out->command = ctx->curr;
10537 		ctx->objdata = 0;
10538 		ctx->object = out;
10539 		ctx->objmask = NULL;
10540 		out->args.destroy.rule =
10541 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10542 					       sizeof(double));
10543 		return len;
10544 	}
10545 	if (ctx->curr == DESTROY_IS_USER_ID) {
10546 		out->args.destroy.is_user_id = true;
10547 		return len;
10548 	}
10549 	if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
10550 	     sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
10551 		return -1;
10552 	ctx->objdata = 0;
10553 	ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
10554 	ctx->objmask = NULL;
10555 	return len;
10556 }
10557 
10558 /** Parse tokens for flush command. */
10559 static int
10560 parse_flush(struct context *ctx, const struct token *token,
10561 	    const char *str, unsigned int len,
10562 	    void *buf, unsigned int size)
10563 {
10564 	struct buffer *out = buf;
10565 
10566 	/* Token name must match. */
10567 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10568 		return -1;
10569 	/* Nothing else to do if there is no buffer. */
10570 	if (!out)
10571 		return len;
10572 	if (!out->command) {
10573 		if (ctx->curr != FLUSH)
10574 			return -1;
10575 		if (sizeof(*out) > size)
10576 			return -1;
10577 		out->command = ctx->curr;
10578 		ctx->objdata = 0;
10579 		ctx->object = out;
10580 		ctx->objmask = NULL;
10581 	}
10582 	return len;
10583 }
10584 
10585 /** Parse tokens for dump command. */
10586 static int
10587 parse_dump(struct context *ctx, const struct token *token,
10588 	    const char *str, unsigned int len,
10589 	    void *buf, unsigned int size)
10590 {
10591 	struct buffer *out = buf;
10592 
10593 	/* Token name must match. */
10594 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10595 		return -1;
10596 	/* Nothing else to do if there is no buffer. */
10597 	if (!out)
10598 		return len;
10599 	if (!out->command) {
10600 		if (ctx->curr != DUMP)
10601 			return -1;
10602 		if (sizeof(*out) > size)
10603 			return -1;
10604 		out->command = ctx->curr;
10605 		ctx->objdata = 0;
10606 		ctx->object = out;
10607 		ctx->objmask = NULL;
10608 		return len;
10609 	}
10610 	switch (ctx->curr) {
10611 	case DUMP_ALL:
10612 	case DUMP_ONE:
10613 		out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
10614 		out->command = ctx->curr;
10615 		ctx->objdata = 0;
10616 		ctx->object = out;
10617 		ctx->objmask = NULL;
10618 		return len;
10619 	case DUMP_IS_USER_ID:
10620 		out->args.dump.is_user_id = true;
10621 		return len;
10622 	default:
10623 		return -1;
10624 	}
10625 }
10626 
10627 /** Parse tokens for query command. */
10628 static int
10629 parse_query(struct context *ctx, const struct token *token,
10630 	    const char *str, unsigned int len,
10631 	    void *buf, unsigned int size)
10632 {
10633 	struct buffer *out = buf;
10634 
10635 	/* Token name must match. */
10636 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10637 		return -1;
10638 	/* Nothing else to do if there is no buffer. */
10639 	if (!out)
10640 		return len;
10641 	if (!out->command) {
10642 		if (ctx->curr != QUERY)
10643 			return -1;
10644 		if (sizeof(*out) > size)
10645 			return -1;
10646 		out->command = ctx->curr;
10647 		ctx->objdata = 0;
10648 		ctx->object = out;
10649 		ctx->objmask = NULL;
10650 	}
10651 	if (ctx->curr == QUERY_IS_USER_ID) {
10652 		out->args.query.is_user_id = true;
10653 		return len;
10654 	}
10655 	return len;
10656 }
10657 
10658 /** Parse action names. */
10659 static int
10660 parse_action(struct context *ctx, const struct token *token,
10661 	     const char *str, unsigned int len,
10662 	     void *buf, unsigned int size)
10663 {
10664 	struct buffer *out = buf;
10665 	const struct arg *arg = pop_args(ctx);
10666 	unsigned int i;
10667 
10668 	(void)size;
10669 	/* Argument is expected. */
10670 	if (!arg)
10671 		return -1;
10672 	/* Parse action name. */
10673 	for (i = 0; next_action[i]; ++i) {
10674 		const struct parse_action_priv *priv;
10675 
10676 		token = &token_list[next_action[i]];
10677 		if (strcmp_partial(token->name, str, len))
10678 			continue;
10679 		priv = token->priv;
10680 		if (!priv)
10681 			goto error;
10682 		if (out)
10683 			memcpy((uint8_t *)ctx->object + arg->offset,
10684 			       &priv->type,
10685 			       arg->size);
10686 		return len;
10687 	}
10688 error:
10689 	push_args(ctx, arg);
10690 	return -1;
10691 }
10692 
10693 /** Parse tokens for list command. */
10694 static int
10695 parse_list(struct context *ctx, const struct token *token,
10696 	   const char *str, unsigned int len,
10697 	   void *buf, unsigned int size)
10698 {
10699 	struct buffer *out = buf;
10700 
10701 	/* Token name must match. */
10702 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10703 		return -1;
10704 	/* Nothing else to do if there is no buffer. */
10705 	if (!out)
10706 		return len;
10707 	if (!out->command) {
10708 		if (ctx->curr != LIST)
10709 			return -1;
10710 		if (sizeof(*out) > size)
10711 			return -1;
10712 		out->command = ctx->curr;
10713 		ctx->objdata = 0;
10714 		ctx->object = out;
10715 		ctx->objmask = NULL;
10716 		out->args.list.group =
10717 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10718 					       sizeof(double));
10719 		return len;
10720 	}
10721 	if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
10722 	     sizeof(*out->args.list.group)) > (uint8_t *)out + size)
10723 		return -1;
10724 	ctx->objdata = 0;
10725 	ctx->object = out->args.list.group + out->args.list.group_n++;
10726 	ctx->objmask = NULL;
10727 	return len;
10728 }
10729 
10730 /** Parse tokens for list all aged flows command. */
10731 static int
10732 parse_aged(struct context *ctx, const struct token *token,
10733 	   const char *str, unsigned int len,
10734 	   void *buf, unsigned int size)
10735 {
10736 	struct buffer *out = buf;
10737 
10738 	/* Token name must match. */
10739 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10740 		return -1;
10741 	/* Nothing else to do if there is no buffer. */
10742 	if (!out)
10743 		return len;
10744 	if (!out->command || out->command == QUEUE) {
10745 		if (ctx->curr != AGED && ctx->curr != QUEUE_AGED)
10746 			return -1;
10747 		if (sizeof(*out) > size)
10748 			return -1;
10749 		out->command = ctx->curr;
10750 		ctx->objdata = 0;
10751 		ctx->object = out;
10752 		ctx->objmask = NULL;
10753 	}
10754 	if (ctx->curr == AGED_DESTROY)
10755 		out->args.aged.destroy = 1;
10756 	return len;
10757 }
10758 
10759 /** Parse tokens for isolate command. */
10760 static int
10761 parse_isolate(struct context *ctx, const struct token *token,
10762 	      const char *str, unsigned int len,
10763 	      void *buf, unsigned int size)
10764 {
10765 	struct buffer *out = buf;
10766 
10767 	/* Token name must match. */
10768 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10769 		return -1;
10770 	/* Nothing else to do if there is no buffer. */
10771 	if (!out)
10772 		return len;
10773 	if (!out->command) {
10774 		if (ctx->curr != ISOLATE)
10775 			return -1;
10776 		if (sizeof(*out) > size)
10777 			return -1;
10778 		out->command = ctx->curr;
10779 		ctx->objdata = 0;
10780 		ctx->object = out;
10781 		ctx->objmask = NULL;
10782 	}
10783 	return len;
10784 }
10785 
10786 /** Parse tokens for info/configure command. */
10787 static int
10788 parse_configure(struct context *ctx, const struct token *token,
10789 		const char *str, unsigned int len,
10790 		void *buf, unsigned int size)
10791 {
10792 	struct buffer *out = buf;
10793 
10794 	/* Token name must match. */
10795 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10796 		return -1;
10797 	/* Nothing else to do if there is no buffer. */
10798 	if (!out)
10799 		return len;
10800 	if (!out->command) {
10801 		if (ctx->curr != INFO && ctx->curr != CONFIGURE)
10802 			return -1;
10803 		if (sizeof(*out) > size)
10804 			return -1;
10805 		out->command = ctx->curr;
10806 		ctx->objdata = 0;
10807 		ctx->object = out;
10808 		ctx->objmask = NULL;
10809 	}
10810 	return len;
10811 }
10812 
10813 /** Parse tokens for template create command. */
10814 static int
10815 parse_template(struct context *ctx, const struct token *token,
10816 	       const char *str, unsigned int len,
10817 	       void *buf, unsigned int size)
10818 {
10819 	struct buffer *out = buf;
10820 
10821 	/* Token name must match. */
10822 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10823 		return -1;
10824 	/* Nothing else to do if there is no buffer. */
10825 	if (!out)
10826 		return len;
10827 	if (!out->command) {
10828 		if (ctx->curr != PATTERN_TEMPLATE &&
10829 		    ctx->curr != ACTIONS_TEMPLATE)
10830 			return -1;
10831 		if (sizeof(*out) > size)
10832 			return -1;
10833 		out->command = ctx->curr;
10834 		ctx->objdata = 0;
10835 		ctx->object = out;
10836 		ctx->objmask = NULL;
10837 		out->args.vc.data = (uint8_t *)out + size;
10838 		return len;
10839 	}
10840 	switch (ctx->curr) {
10841 	case PATTERN_TEMPLATE_CREATE:
10842 		out->args.vc.pattern =
10843 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10844 					       sizeof(double));
10845 		out->args.vc.pat_templ_id = UINT32_MAX;
10846 		out->command = ctx->curr;
10847 		ctx->objdata = 0;
10848 		ctx->object = out;
10849 		ctx->objmask = NULL;
10850 		return len;
10851 	case PATTERN_TEMPLATE_EGRESS:
10852 		out->args.vc.attr.egress = 1;
10853 		return len;
10854 	case PATTERN_TEMPLATE_INGRESS:
10855 		out->args.vc.attr.ingress = 1;
10856 		return len;
10857 	case PATTERN_TEMPLATE_TRANSFER:
10858 		out->args.vc.attr.transfer = 1;
10859 		return len;
10860 	case ACTIONS_TEMPLATE_CREATE:
10861 		out->args.vc.act_templ_id = UINT32_MAX;
10862 		out->command = ctx->curr;
10863 		ctx->objdata = 0;
10864 		ctx->object = out;
10865 		ctx->objmask = NULL;
10866 		return len;
10867 	case ACTIONS_TEMPLATE_SPEC:
10868 		out->args.vc.actions =
10869 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10870 					       sizeof(double));
10871 		ctx->object = out->args.vc.actions;
10872 		ctx->objmask = NULL;
10873 		return len;
10874 	case ACTIONS_TEMPLATE_MASK:
10875 		out->args.vc.masks =
10876 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10877 					       (out->args.vc.actions +
10878 						out->args.vc.actions_n),
10879 					       sizeof(double));
10880 		ctx->object = out->args.vc.masks;
10881 		ctx->objmask = NULL;
10882 		return len;
10883 	case ACTIONS_TEMPLATE_EGRESS:
10884 		out->args.vc.attr.egress = 1;
10885 		return len;
10886 	case ACTIONS_TEMPLATE_INGRESS:
10887 		out->args.vc.attr.ingress = 1;
10888 		return len;
10889 	case ACTIONS_TEMPLATE_TRANSFER:
10890 		out->args.vc.attr.transfer = 1;
10891 		return len;
10892 	default:
10893 		return -1;
10894 	}
10895 }
10896 
10897 /** Parse tokens for template destroy command. */
10898 static int
10899 parse_template_destroy(struct context *ctx, const struct token *token,
10900 		       const char *str, unsigned int len,
10901 		       void *buf, unsigned int size)
10902 {
10903 	struct buffer *out = buf;
10904 	uint32_t *template_id;
10905 
10906 	/* Token name must match. */
10907 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10908 		return -1;
10909 	/* Nothing else to do if there is no buffer. */
10910 	if (!out)
10911 		return len;
10912 	if (!out->command ||
10913 		out->command == PATTERN_TEMPLATE ||
10914 		out->command == ACTIONS_TEMPLATE) {
10915 		if (ctx->curr != PATTERN_TEMPLATE_DESTROY &&
10916 			ctx->curr != ACTIONS_TEMPLATE_DESTROY)
10917 			return -1;
10918 		if (sizeof(*out) > size)
10919 			return -1;
10920 		out->command = ctx->curr;
10921 		ctx->objdata = 0;
10922 		ctx->object = out;
10923 		ctx->objmask = NULL;
10924 		out->args.templ_destroy.template_id =
10925 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10926 					       sizeof(double));
10927 		return len;
10928 	}
10929 	template_id = out->args.templ_destroy.template_id
10930 		    + out->args.templ_destroy.template_id_n++;
10931 	if ((uint8_t *)template_id > (uint8_t *)out + size)
10932 		return -1;
10933 	ctx->objdata = 0;
10934 	ctx->object = template_id;
10935 	ctx->objmask = NULL;
10936 	return len;
10937 }
10938 
10939 /** Parse tokens for table create command. */
10940 static int
10941 parse_table(struct context *ctx, const struct token *token,
10942 	    const char *str, unsigned int len,
10943 	    void *buf, unsigned int size)
10944 {
10945 	struct buffer *out = buf;
10946 	uint32_t *template_id;
10947 
10948 	/* Token name must match. */
10949 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10950 		return -1;
10951 	/* Nothing else to do if there is no buffer. */
10952 	if (!out)
10953 		return len;
10954 	if (!out->command) {
10955 		if (ctx->curr != TABLE)
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 		return len;
10964 	}
10965 	switch (ctx->curr) {
10966 	case TABLE_CREATE:
10967 	case TABLE_RESIZE:
10968 		out->command = ctx->curr;
10969 		ctx->objdata = 0;
10970 		ctx->object = out;
10971 		ctx->objmask = NULL;
10972 		out->args.table.id = UINT32_MAX;
10973 		return len;
10974 	case TABLE_PATTERN_TEMPLATE:
10975 		out->args.table.pat_templ_id =
10976 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10977 					       sizeof(double));
10978 		template_id = out->args.table.pat_templ_id
10979 				+ out->args.table.pat_templ_id_n++;
10980 		if ((uint8_t *)template_id > (uint8_t *)out + size)
10981 			return -1;
10982 		ctx->objdata = 0;
10983 		ctx->object = template_id;
10984 		ctx->objmask = NULL;
10985 		return len;
10986 	case TABLE_ACTIONS_TEMPLATE:
10987 		out->args.table.act_templ_id =
10988 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10989 					       (out->args.table.pat_templ_id +
10990 						out->args.table.pat_templ_id_n),
10991 					       sizeof(double));
10992 		template_id = out->args.table.act_templ_id
10993 				+ out->args.table.act_templ_id_n++;
10994 		if ((uint8_t *)template_id > (uint8_t *)out + size)
10995 			return -1;
10996 		ctx->objdata = 0;
10997 		ctx->object = template_id;
10998 		ctx->objmask = NULL;
10999 		return len;
11000 	case TABLE_INGRESS:
11001 		out->args.table.attr.flow_attr.ingress = 1;
11002 		return len;
11003 	case TABLE_EGRESS:
11004 		out->args.table.attr.flow_attr.egress = 1;
11005 		return len;
11006 	case TABLE_TRANSFER:
11007 		out->args.table.attr.flow_attr.transfer = 1;
11008 		return len;
11009 	case TABLE_TRANSFER_WIRE_ORIG:
11010 		if (!out->args.table.attr.flow_attr.transfer)
11011 			return -1;
11012 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_WIRE_ORIG;
11013 		return len;
11014 	case TABLE_TRANSFER_VPORT_ORIG:
11015 		if (!out->args.table.attr.flow_attr.transfer)
11016 			return -1;
11017 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_VPORT_ORIG;
11018 		return len;
11019 	case TABLE_RESIZABLE:
11020 		out->args.table.attr.specialize |=
11021 			RTE_FLOW_TABLE_SPECIALIZE_RESIZABLE;
11022 		return len;
11023 	case TABLE_RULES_NUMBER:
11024 		ctx->objdata = 0;
11025 		ctx->object = out;
11026 		ctx->objmask = NULL;
11027 		return len;
11028 	case TABLE_RESIZE_ID:
11029 	case TABLE_RESIZE_RULES_NUMBER:
11030 		return len;
11031 	default:
11032 		return -1;
11033 	}
11034 }
11035 
11036 /** Parse tokens for table destroy command. */
11037 static int
11038 parse_table_destroy(struct context *ctx, const struct token *token,
11039 		    const char *str, unsigned int len,
11040 		    void *buf, unsigned int size)
11041 {
11042 	struct buffer *out = buf;
11043 	uint32_t *table_id;
11044 
11045 	/* Token name must match. */
11046 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11047 		return -1;
11048 	/* Nothing else to do if there is no buffer. */
11049 	if (!out)
11050 		return len;
11051 	if (!out->command || out->command == TABLE) {
11052 		if (ctx->curr != TABLE_DESTROY &&
11053 		    ctx->curr != TABLE_RESIZE_COMPLETE)
11054 			return -1;
11055 		if (sizeof(*out) > size)
11056 			return -1;
11057 		out->command = ctx->curr;
11058 		ctx->objdata = 0;
11059 		ctx->object = out;
11060 		ctx->objmask = NULL;
11061 		out->args.table_destroy.table_id =
11062 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11063 					       sizeof(double));
11064 		return len;
11065 	}
11066 	table_id = out->args.table_destroy.table_id
11067 		    + out->args.table_destroy.table_id_n++;
11068 	if ((uint8_t *)table_id > (uint8_t *)out + size)
11069 		return -1;
11070 	ctx->objdata = 0;
11071 	ctx->object = table_id;
11072 	ctx->objmask = NULL;
11073 	return len;
11074 }
11075 
11076 /** Parse tokens for queue create commands. */
11077 static int
11078 parse_qo(struct context *ctx, const struct token *token,
11079 	 const char *str, unsigned int len,
11080 	 void *buf, unsigned int size)
11081 {
11082 	struct buffer *out = buf;
11083 
11084 	/* Token name must match. */
11085 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11086 		return -1;
11087 	/* Nothing else to do if there is no buffer. */
11088 	if (!out)
11089 		return len;
11090 	if (!out->command) {
11091 		if (ctx->curr != QUEUE)
11092 			return -1;
11093 		if (sizeof(*out) > size)
11094 			return -1;
11095 		out->command = ctx->curr;
11096 		ctx->objdata = 0;
11097 		ctx->object = out;
11098 		ctx->objmask = NULL;
11099 		out->args.vc.data = (uint8_t *)out + size;
11100 		return len;
11101 	}
11102 	switch (ctx->curr) {
11103 	case QUEUE_CREATE:
11104 	case QUEUE_UPDATE:
11105 		out->command = ctx->curr;
11106 		ctx->objdata = 0;
11107 		ctx->object = out;
11108 		ctx->objmask = NULL;
11109 		out->args.vc.rule_id = UINT32_MAX;
11110 		return len;
11111 	case QUEUE_TEMPLATE_TABLE:
11112 	case QUEUE_PATTERN_TEMPLATE:
11113 	case QUEUE_ACTIONS_TEMPLATE:
11114 	case QUEUE_CREATE_POSTPONE:
11115 	case QUEUE_RULE_ID:
11116 	case QUEUE_UPDATE_ID:
11117 		return len;
11118 	case ITEM_PATTERN:
11119 		out->args.vc.pattern =
11120 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11121 					       sizeof(double));
11122 		ctx->object = out->args.vc.pattern;
11123 		ctx->objmask = NULL;
11124 		return len;
11125 	case ACTIONS:
11126 		out->args.vc.actions =
11127 			(void *)RTE_ALIGN_CEIL((uintptr_t)
11128 					       (out->args.vc.pattern +
11129 						out->args.vc.pattern_n),
11130 					       sizeof(double));
11131 		ctx->object = out->args.vc.actions;
11132 		ctx->objmask = NULL;
11133 		return len;
11134 	default:
11135 		return -1;
11136 	}
11137 }
11138 
11139 /** Parse tokens for queue destroy command. */
11140 static int
11141 parse_qo_destroy(struct context *ctx, const struct token *token,
11142 		 const char *str, unsigned int len,
11143 		 void *buf, unsigned int size)
11144 {
11145 	struct buffer *out = buf;
11146 	uint64_t *flow_id;
11147 
11148 	/* Token name must match. */
11149 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11150 		return -1;
11151 	/* Nothing else to do if there is no buffer. */
11152 	if (!out)
11153 		return len;
11154 	if (!out->command || out->command == QUEUE) {
11155 		if (ctx->curr != QUEUE_DESTROY &&
11156 		    ctx->curr != QUEUE_FLOW_UPDATE_RESIZED)
11157 			return -1;
11158 		if (sizeof(*out) > size)
11159 			return -1;
11160 		out->command = ctx->curr;
11161 		ctx->objdata = 0;
11162 		ctx->object = out;
11163 		ctx->objmask = NULL;
11164 		out->args.destroy.rule =
11165 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11166 					       sizeof(double));
11167 		return len;
11168 	}
11169 	switch (ctx->curr) {
11170 	case QUEUE_DESTROY_ID:
11171 		flow_id = out->args.destroy.rule
11172 				+ out->args.destroy.rule_n++;
11173 		if ((uint8_t *)flow_id > (uint8_t *)out + size)
11174 			return -1;
11175 		ctx->objdata = 0;
11176 		ctx->object = flow_id;
11177 		ctx->objmask = NULL;
11178 		return len;
11179 	case QUEUE_DESTROY_POSTPONE:
11180 		return len;
11181 	default:
11182 		return -1;
11183 	}
11184 }
11185 
11186 /** Parse tokens for push queue command. */
11187 static int
11188 parse_push(struct context *ctx, const struct token *token,
11189 	   const char *str, unsigned int len,
11190 	   void *buf, unsigned int size)
11191 {
11192 	struct buffer *out = buf;
11193 
11194 	/* Token name must match. */
11195 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11196 		return -1;
11197 	/* Nothing else to do if there is no buffer. */
11198 	if (!out)
11199 		return len;
11200 	if (!out->command) {
11201 		if (ctx->curr != PUSH)
11202 			return -1;
11203 		if (sizeof(*out) > size)
11204 			return -1;
11205 		out->command = ctx->curr;
11206 		ctx->objdata = 0;
11207 		ctx->object = out;
11208 		ctx->objmask = NULL;
11209 		out->args.vc.data = (uint8_t *)out + size;
11210 	}
11211 	return len;
11212 }
11213 
11214 /** Parse tokens for pull command. */
11215 static int
11216 parse_pull(struct context *ctx, const struct token *token,
11217 	   const char *str, unsigned int len,
11218 	   void *buf, unsigned int size)
11219 {
11220 	struct buffer *out = buf;
11221 
11222 	/* Token name must match. */
11223 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11224 		return -1;
11225 	/* Nothing else to do if there is no buffer. */
11226 	if (!out)
11227 		return len;
11228 	if (!out->command) {
11229 		if (ctx->curr != PULL)
11230 			return -1;
11231 		if (sizeof(*out) > size)
11232 			return -1;
11233 		out->command = ctx->curr;
11234 		ctx->objdata = 0;
11235 		ctx->object = out;
11236 		ctx->objmask = NULL;
11237 		out->args.vc.data = (uint8_t *)out + size;
11238 	}
11239 	return len;
11240 }
11241 
11242 /** Parse tokens for hash calculation commands. */
11243 static int
11244 parse_hash(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) {
11257 		if (ctx->curr != HASH)
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 		out->args.vc.data = (uint8_t *)out + size;
11266 		return len;
11267 	}
11268 	switch (ctx->curr) {
11269 	case HASH_CALC_TABLE:
11270 	case HASH_CALC_PATTERN_INDEX:
11271 		return len;
11272 	case ITEM_PATTERN:
11273 		out->args.vc.pattern =
11274 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11275 					       sizeof(double));
11276 		ctx->object = out->args.vc.pattern;
11277 		ctx->objmask = NULL;
11278 		return len;
11279 	case HASH_CALC_ENCAP:
11280 		out->args.vc.encap_hash = 1;
11281 		return len;
11282 	case ENCAP_HASH_FIELD_SRC_PORT:
11283 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_SRC_PORT;
11284 		return len;
11285 	case ENCAP_HASH_FIELD_GRE_FLOW_ID:
11286 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_NVGRE_FLOW_ID;
11287 		return len;
11288 	default:
11289 		return -1;
11290 	}
11291 }
11292 
11293 static int
11294 parse_group(struct context *ctx, const struct token *token,
11295 	    const char *str, unsigned int len,
11296 	    void *buf, unsigned int size)
11297 {
11298 	struct buffer *out = buf;
11299 
11300 	/* Token name must match. */
11301 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11302 		return -1;
11303 	/* Nothing else to do if there is no buffer. */
11304 	if (!out)
11305 		return len;
11306 	if (!out->command) {
11307 		if (ctx->curr != FLOW_GROUP)
11308 			return -1;
11309 		if (sizeof(*out) > size)
11310 			return -1;
11311 		out->command = ctx->curr;
11312 		ctx->objdata = 0;
11313 		ctx->object = out;
11314 		ctx->objmask = NULL;
11315 		out->args.vc.data = (uint8_t *)out + size;
11316 		return len;
11317 	}
11318 	switch (ctx->curr) {
11319 	case GROUP_INGRESS:
11320 		out->args.vc.attr.ingress = 1;
11321 		return len;
11322 	case GROUP_EGRESS:
11323 		out->args.vc.attr.egress = 1;
11324 		return len;
11325 	case GROUP_TRANSFER:
11326 		out->args.vc.attr.transfer = 1;
11327 		return len;
11328 	case GROUP_SET_MISS_ACTIONS:
11329 		out->command = ctx->curr;
11330 		ctx->objdata = 0;
11331 		ctx->object = out;
11332 		ctx->objmask = NULL;
11333 		out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11334 							       sizeof(double));
11335 		return len;
11336 	default:
11337 		return -1;
11338 	}
11339 }
11340 
11341 static int
11342 parse_flex(struct context *ctx, const struct token *token,
11343 	     const char *str, unsigned int len,
11344 	     void *buf, unsigned int size)
11345 {
11346 	struct buffer *out = buf;
11347 
11348 	/* Token name must match. */
11349 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11350 		return -1;
11351 	/* Nothing else to do if there is no buffer. */
11352 	if (!out)
11353 		return len;
11354 	if (out->command == ZERO) {
11355 		if (ctx->curr != FLEX)
11356 			return -1;
11357 		if (sizeof(*out) > size)
11358 			return -1;
11359 		out->command = ctx->curr;
11360 		ctx->objdata = 0;
11361 		ctx->object = out;
11362 		ctx->objmask = NULL;
11363 	} else {
11364 		switch (ctx->curr) {
11365 		default:
11366 			break;
11367 		case FLEX_ITEM_INIT:
11368 		case FLEX_ITEM_CREATE:
11369 		case FLEX_ITEM_DESTROY:
11370 			out->command = ctx->curr;
11371 			break;
11372 		}
11373 	}
11374 
11375 	return len;
11376 }
11377 
11378 static int
11379 parse_tunnel(struct context *ctx, const struct token *token,
11380 	     const char *str, unsigned int len,
11381 	     void *buf, unsigned int size)
11382 {
11383 	struct buffer *out = buf;
11384 
11385 	/* Token name must match. */
11386 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11387 		return -1;
11388 	/* Nothing else to do if there is no buffer. */
11389 	if (!out)
11390 		return len;
11391 	if (!out->command) {
11392 		if (ctx->curr != TUNNEL)
11393 			return -1;
11394 		if (sizeof(*out) > size)
11395 			return -1;
11396 		out->command = ctx->curr;
11397 		ctx->objdata = 0;
11398 		ctx->object = out;
11399 		ctx->objmask = NULL;
11400 	} else {
11401 		switch (ctx->curr) {
11402 		default:
11403 			break;
11404 		case TUNNEL_CREATE:
11405 		case TUNNEL_DESTROY:
11406 		case TUNNEL_LIST:
11407 			out->command = ctx->curr;
11408 			break;
11409 		case TUNNEL_CREATE_TYPE:
11410 		case TUNNEL_DESTROY_ID:
11411 			ctx->object = &out->args.vc.tunnel_ops;
11412 			break;
11413 		}
11414 	}
11415 
11416 	return len;
11417 }
11418 
11419 /**
11420  * Parse signed/unsigned integers 8 to 64-bit long.
11421  *
11422  * Last argument (ctx->args) is retrieved to determine integer type and
11423  * storage location.
11424  */
11425 static int
11426 parse_int(struct context *ctx, const struct token *token,
11427 	  const char *str, unsigned int len,
11428 	  void *buf, unsigned int size)
11429 {
11430 	const struct arg *arg = pop_args(ctx);
11431 	uintmax_t u;
11432 	char *end;
11433 
11434 	(void)token;
11435 	/* Argument is expected. */
11436 	if (!arg)
11437 		return -1;
11438 	errno = 0;
11439 	u = arg->sign ?
11440 		(uintmax_t)strtoimax(str, &end, 0) :
11441 		strtoumax(str, &end, 0);
11442 	if (errno || (size_t)(end - str) != len)
11443 		goto error;
11444 	if (arg->bounded &&
11445 	    ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
11446 			    (intmax_t)u > (intmax_t)arg->max)) ||
11447 	     (!arg->sign && (u < arg->min || u > arg->max))))
11448 		goto error;
11449 	if (!ctx->object)
11450 		return len;
11451 	if (arg->mask) {
11452 		if (!arg_entry_bf_fill(ctx->object, u, arg) ||
11453 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
11454 			goto error;
11455 		return len;
11456 	}
11457 	buf = (uint8_t *)ctx->object + arg->offset;
11458 	size = arg->size;
11459 	if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
11460 		return -1;
11461 objmask:
11462 	switch (size) {
11463 	case sizeof(uint8_t):
11464 		*(uint8_t *)buf = u;
11465 		break;
11466 	case sizeof(uint16_t):
11467 		*(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
11468 		break;
11469 	case sizeof(uint8_t [3]):
11470 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
11471 		if (!arg->hton) {
11472 			((uint8_t *)buf)[0] = u;
11473 			((uint8_t *)buf)[1] = u >> 8;
11474 			((uint8_t *)buf)[2] = u >> 16;
11475 			break;
11476 		}
11477 #endif
11478 		((uint8_t *)buf)[0] = u >> 16;
11479 		((uint8_t *)buf)[1] = u >> 8;
11480 		((uint8_t *)buf)[2] = u;
11481 		break;
11482 	case sizeof(uint32_t):
11483 		*(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
11484 		break;
11485 	case sizeof(uint64_t):
11486 		*(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
11487 		break;
11488 	default:
11489 		goto error;
11490 	}
11491 	if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
11492 		u = -1;
11493 		buf = (uint8_t *)ctx->objmask + arg->offset;
11494 		goto objmask;
11495 	}
11496 	return len;
11497 error:
11498 	push_args(ctx, arg);
11499 	return -1;
11500 }
11501 
11502 /**
11503  * Parse a string.
11504  *
11505  * Three arguments (ctx->args) are retrieved from the stack to store data,
11506  * its actual length and address (in that order).
11507  */
11508 static int
11509 parse_string(struct context *ctx, const struct token *token,
11510 	     const char *str, unsigned int len,
11511 	     void *buf, unsigned int size)
11512 {
11513 	const struct arg *arg_data = pop_args(ctx);
11514 	const struct arg *arg_len = pop_args(ctx);
11515 	const struct arg *arg_addr = pop_args(ctx);
11516 	char tmp[16]; /* Ought to be enough. */
11517 	int ret;
11518 
11519 	/* Arguments are expected. */
11520 	if (!arg_data)
11521 		return -1;
11522 	if (!arg_len) {
11523 		push_args(ctx, arg_data);
11524 		return -1;
11525 	}
11526 	if (!arg_addr) {
11527 		push_args(ctx, arg_len);
11528 		push_args(ctx, arg_data);
11529 		return -1;
11530 	}
11531 	size = arg_data->size;
11532 	/* Bit-mask fill is not supported. */
11533 	if (arg_data->mask || size < len)
11534 		goto error;
11535 	if (!ctx->object)
11536 		return len;
11537 	/* Let parse_int() fill length information first. */
11538 	ret = snprintf(tmp, sizeof(tmp), "%u", len);
11539 	if (ret < 0)
11540 		goto error;
11541 	push_args(ctx, arg_len);
11542 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11543 	if (ret < 0) {
11544 		pop_args(ctx);
11545 		goto error;
11546 	}
11547 	buf = (uint8_t *)ctx->object + arg_data->offset;
11548 	/* Output buffer is not necessarily NUL-terminated. */
11549 	memcpy(buf, str, len);
11550 	memset((uint8_t *)buf + len, 0x00, size - len);
11551 	if (ctx->objmask)
11552 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11553 	/* Save address if requested. */
11554 	if (arg_addr->size) {
11555 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11556 		       (void *[]){
11557 			(uint8_t *)ctx->object + arg_data->offset
11558 		       },
11559 		       arg_addr->size);
11560 		if (ctx->objmask)
11561 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11562 			       (void *[]){
11563 				(uint8_t *)ctx->objmask + arg_data->offset
11564 			       },
11565 			       arg_addr->size);
11566 	}
11567 	return len;
11568 error:
11569 	push_args(ctx, arg_addr);
11570 	push_args(ctx, arg_len);
11571 	push_args(ctx, arg_data);
11572 	return -1;
11573 }
11574 
11575 static int
11576 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
11577 {
11578 	const uint8_t *head = dst;
11579 	uint32_t left;
11580 
11581 	if (*size == 0)
11582 		return -1;
11583 
11584 	left = *size;
11585 
11586 	/* Convert chars to bytes */
11587 	while (left) {
11588 		char tmp[3], *end = tmp;
11589 		uint32_t read_lim = left & 1 ? 1 : 2;
11590 
11591 		snprintf(tmp, read_lim + 1, "%s", src);
11592 		*dst = strtoul(tmp, &end, 16);
11593 		if (*end) {
11594 			*dst = 0;
11595 			*size = (uint32_t)(dst - head);
11596 			return -1;
11597 		}
11598 		left -= read_lim;
11599 		src += read_lim;
11600 		dst++;
11601 	}
11602 	*dst = 0;
11603 	*size = (uint32_t)(dst - head);
11604 	return 0;
11605 }
11606 
11607 static int
11608 parse_hex(struct context *ctx, const struct token *token,
11609 		const char *str, unsigned int len,
11610 		void *buf, unsigned int size)
11611 {
11612 	const struct arg *arg_data = pop_args(ctx);
11613 	const struct arg *arg_len = pop_args(ctx);
11614 	const struct arg *arg_addr = pop_args(ctx);
11615 	char tmp[16]; /* Ought to be enough. */
11616 	int ret;
11617 	unsigned int hexlen = len;
11618 	unsigned int length = 256;
11619 	uint8_t hex_tmp[length];
11620 
11621 	/* Arguments are expected. */
11622 	if (!arg_data)
11623 		return -1;
11624 	if (!arg_len) {
11625 		push_args(ctx, arg_data);
11626 		return -1;
11627 	}
11628 	if (!arg_addr) {
11629 		push_args(ctx, arg_len);
11630 		push_args(ctx, arg_data);
11631 		return -1;
11632 	}
11633 	size = arg_data->size;
11634 	/* Bit-mask fill is not supported. */
11635 	if (arg_data->mask)
11636 		goto error;
11637 	if (!ctx->object)
11638 		return len;
11639 
11640 	/* translate bytes string to array. */
11641 	if (str[0] == '0' && ((str[1] == 'x') ||
11642 			(str[1] == 'X'))) {
11643 		str += 2;
11644 		hexlen -= 2;
11645 	}
11646 	if (hexlen > length)
11647 		goto error;
11648 	ret = parse_hex_string(str, hex_tmp, &hexlen);
11649 	if (ret < 0)
11650 		goto error;
11651 	/* Check the converted binary fits into data buffer. */
11652 	if (hexlen > size)
11653 		goto error;
11654 	/* Let parse_int() fill length information first. */
11655 	ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
11656 	if (ret < 0)
11657 		goto error;
11658 	/* Save length if requested. */
11659 	if (arg_len->size) {
11660 		push_args(ctx, arg_len);
11661 		ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11662 		if (ret < 0) {
11663 			pop_args(ctx);
11664 			goto error;
11665 		}
11666 	}
11667 	buf = (uint8_t *)ctx->object + arg_data->offset;
11668 	/* Output buffer is not necessarily NUL-terminated. */
11669 	memcpy(buf, hex_tmp, hexlen);
11670 	memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
11671 	if (ctx->objmask)
11672 		memset((uint8_t *)ctx->objmask + arg_data->offset,
11673 					0xff, hexlen);
11674 	/* Save address if requested. */
11675 	if (arg_addr->size) {
11676 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11677 		       (void *[]){
11678 			(uint8_t *)ctx->object + arg_data->offset
11679 		       },
11680 		       arg_addr->size);
11681 		if (ctx->objmask)
11682 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11683 			       (void *[]){
11684 				(uint8_t *)ctx->objmask + arg_data->offset
11685 			       },
11686 			       arg_addr->size);
11687 	}
11688 	return len;
11689 error:
11690 	push_args(ctx, arg_addr);
11691 	push_args(ctx, arg_len);
11692 	push_args(ctx, arg_data);
11693 	return -1;
11694 
11695 }
11696 
11697 /**
11698  * Parse a zero-ended string.
11699  */
11700 static int
11701 parse_string0(struct context *ctx, const struct token *token __rte_unused,
11702 	     const char *str, unsigned int len,
11703 	     void *buf, unsigned int size)
11704 {
11705 	const struct arg *arg_data = pop_args(ctx);
11706 
11707 	/* Arguments are expected. */
11708 	if (!arg_data)
11709 		return -1;
11710 	size = arg_data->size;
11711 	/* Bit-mask fill is not supported. */
11712 	if (arg_data->mask || size < len + 1)
11713 		goto error;
11714 	if (!ctx->object)
11715 		return len;
11716 	buf = (uint8_t *)ctx->object + arg_data->offset;
11717 	strncpy(buf, str, len);
11718 	if (ctx->objmask)
11719 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11720 	return len;
11721 error:
11722 	push_args(ctx, arg_data);
11723 	return -1;
11724 }
11725 
11726 /**
11727  * Parse a MAC address.
11728  *
11729  * Last argument (ctx->args) is retrieved to determine storage size and
11730  * location.
11731  */
11732 static int
11733 parse_mac_addr(struct context *ctx, const struct token *token,
11734 	       const char *str, unsigned int len,
11735 	       void *buf, unsigned int size)
11736 {
11737 	const struct arg *arg = pop_args(ctx);
11738 	struct rte_ether_addr tmp;
11739 	int ret;
11740 
11741 	(void)token;
11742 	/* Argument is expected. */
11743 	if (!arg)
11744 		return -1;
11745 	size = arg->size;
11746 	/* Bit-mask fill is not supported. */
11747 	if (arg->mask || size != sizeof(tmp))
11748 		goto error;
11749 	/* Only network endian is supported. */
11750 	if (!arg->hton)
11751 		goto error;
11752 	ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
11753 	if (ret < 0 || (unsigned int)ret != len)
11754 		goto error;
11755 	if (!ctx->object)
11756 		return len;
11757 	buf = (uint8_t *)ctx->object + arg->offset;
11758 	memcpy(buf, &tmp, size);
11759 	if (ctx->objmask)
11760 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11761 	return len;
11762 error:
11763 	push_args(ctx, arg);
11764 	return -1;
11765 }
11766 
11767 /**
11768  * Parse an IPv4 address.
11769  *
11770  * Last argument (ctx->args) is retrieved to determine storage size and
11771  * location.
11772  */
11773 static int
11774 parse_ipv4_addr(struct context *ctx, const struct token *token,
11775 		const char *str, unsigned int len,
11776 		void *buf, unsigned int size)
11777 {
11778 	const struct arg *arg = pop_args(ctx);
11779 	char str2[len + 1];
11780 	struct in_addr tmp;
11781 	int ret;
11782 
11783 	/* Argument is expected. */
11784 	if (!arg)
11785 		return -1;
11786 	size = arg->size;
11787 	/* Bit-mask fill is not supported. */
11788 	if (arg->mask || size != sizeof(tmp))
11789 		goto error;
11790 	/* Only network endian is supported. */
11791 	if (!arg->hton)
11792 		goto error;
11793 	memcpy(str2, str, len);
11794 	str2[len] = '\0';
11795 	ret = inet_pton(AF_INET, str2, &tmp);
11796 	if (ret != 1) {
11797 		/* Attempt integer parsing. */
11798 		push_args(ctx, arg);
11799 		return parse_int(ctx, token, str, len, buf, size);
11800 	}
11801 	if (!ctx->object)
11802 		return len;
11803 	buf = (uint8_t *)ctx->object + arg->offset;
11804 	memcpy(buf, &tmp, size);
11805 	if (ctx->objmask)
11806 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11807 	return len;
11808 error:
11809 	push_args(ctx, arg);
11810 	return -1;
11811 }
11812 
11813 /**
11814  * Parse an IPv6 address.
11815  *
11816  * Last argument (ctx->args) is retrieved to determine storage size and
11817  * location.
11818  */
11819 static int
11820 parse_ipv6_addr(struct context *ctx, const struct token *token,
11821 		const char *str, unsigned int len,
11822 		void *buf, unsigned int size)
11823 {
11824 	const struct arg *arg = pop_args(ctx);
11825 	char str2[len + 1];
11826 	struct in6_addr tmp;
11827 	int ret;
11828 
11829 	(void)token;
11830 	/* Argument is expected. */
11831 	if (!arg)
11832 		return -1;
11833 	size = arg->size;
11834 	/* Bit-mask fill is not supported. */
11835 	if (arg->mask || size != sizeof(tmp))
11836 		goto error;
11837 	/* Only network endian is supported. */
11838 	if (!arg->hton)
11839 		goto error;
11840 	memcpy(str2, str, len);
11841 	str2[len] = '\0';
11842 	ret = inet_pton(AF_INET6, str2, &tmp);
11843 	if (ret != 1)
11844 		goto error;
11845 	if (!ctx->object)
11846 		return len;
11847 	buf = (uint8_t *)ctx->object + arg->offset;
11848 	memcpy(buf, &tmp, size);
11849 	if (ctx->objmask)
11850 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11851 	return len;
11852 error:
11853 	push_args(ctx, arg);
11854 	return -1;
11855 }
11856 
11857 /** Boolean values (even indices stand for false). */
11858 static const char *const boolean_name[] = {
11859 	"0", "1",
11860 	"false", "true",
11861 	"no", "yes",
11862 	"N", "Y",
11863 	"off", "on",
11864 	NULL,
11865 };
11866 
11867 /**
11868  * Parse a boolean value.
11869  *
11870  * Last argument (ctx->args) is retrieved to determine storage size and
11871  * location.
11872  */
11873 static int
11874 parse_boolean(struct context *ctx, const struct token *token,
11875 	      const char *str, unsigned int len,
11876 	      void *buf, unsigned int size)
11877 {
11878 	const struct arg *arg = pop_args(ctx);
11879 	unsigned int i;
11880 	int ret;
11881 
11882 	/* Argument is expected. */
11883 	if (!arg)
11884 		return -1;
11885 	for (i = 0; boolean_name[i]; ++i)
11886 		if (!strcmp_partial(boolean_name[i], str, len))
11887 			break;
11888 	/* Process token as integer. */
11889 	if (boolean_name[i])
11890 		str = i & 1 ? "1" : "0";
11891 	push_args(ctx, arg);
11892 	ret = parse_int(ctx, token, str, strlen(str), buf, size);
11893 	return ret > 0 ? (int)len : ret;
11894 }
11895 
11896 /** Parse port and update context. */
11897 static int
11898 parse_port(struct context *ctx, const struct token *token,
11899 	   const char *str, unsigned int len,
11900 	   void *buf, unsigned int size)
11901 {
11902 	struct buffer *out = &(struct buffer){ .port = 0 };
11903 	int ret;
11904 
11905 	if (buf)
11906 		out = buf;
11907 	else {
11908 		ctx->objdata = 0;
11909 		ctx->object = out;
11910 		ctx->objmask = NULL;
11911 		size = sizeof(*out);
11912 	}
11913 	ret = parse_int(ctx, token, str, len, out, size);
11914 	if (ret >= 0)
11915 		ctx->port = out->port;
11916 	if (!buf)
11917 		ctx->object = NULL;
11918 	return ret;
11919 }
11920 
11921 /** Parse tokens for shared indirect actions. */
11922 static int
11923 parse_ia_port(struct context *ctx, const struct token *token,
11924 	      const char *str, unsigned int len,
11925 	      void *buf, unsigned int size)
11926 {
11927 	struct rte_flow_action *action = ctx->object;
11928 	uint32_t id;
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 indirect action */
11941 	if (action)
11942 		action->conf = (void *)(uintptr_t)id;
11943 	return ret;
11944 }
11945 
11946 static int
11947 parse_ia_id2ptr(struct context *ctx, const struct token *token,
11948 		const char *str, unsigned int len,
11949 		void *buf, unsigned int size)
11950 {
11951 	struct rte_flow_action *action = ctx->object;
11952 	uint32_t id;
11953 	int ret;
11954 
11955 	(void)buf;
11956 	(void)size;
11957 	ctx->objdata = 0;
11958 	ctx->object = &id;
11959 	ctx->objmask = NULL;
11960 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11961 	ctx->object = action;
11962 	if (ret != (int)len)
11963 		return ret;
11964 	/* set indirect action */
11965 	if (action) {
11966 		portid_t port_id = ctx->port;
11967 		if (ctx->prev == INDIRECT_ACTION_PORT)
11968 			port_id = (portid_t)(uintptr_t)action->conf;
11969 		action->conf = port_action_handle_get_by_id(port_id, id);
11970 		ret = (action->conf) ? ret : -1;
11971 	}
11972 	return ret;
11973 }
11974 
11975 static int
11976 parse_indlst_id2ptr(struct context *ctx, const struct token *token,
11977 		    const char *str, unsigned int len,
11978 		    __rte_unused void *buf, __rte_unused unsigned int size)
11979 {
11980 	struct rte_flow_action *action = ctx->object;
11981 	struct rte_flow_action_indirect_list *action_conf;
11982 	const struct indlst_conf *indlst_conf;
11983 	uint32_t id;
11984 	int ret;
11985 
11986 	ctx->objdata = 0;
11987 	ctx->object = &id;
11988 	ctx->objmask = NULL;
11989 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11990 	ctx->object = action;
11991 	if (ret != (int)len)
11992 		return ret;
11993 
11994 	/* set handle and conf */
11995 	if (action) {
11996 		action_conf = (void *)(uintptr_t)action->conf;
11997 		action_conf->conf = NULL;
11998 		switch (ctx->curr) {
11999 		case INDIRECT_LIST_ACTION_ID2PTR_HANDLE:
12000 		action_conf->handle = (typeof(action_conf->handle))
12001 					port_action_handle_get_by_id(ctx->port, id);
12002 			if (!action_conf->handle) {
12003 				printf("no indirect list handle for id %u\n", id);
12004 				return -1;
12005 			}
12006 			break;
12007 		case INDIRECT_LIST_ACTION_ID2PTR_CONF:
12008 			indlst_conf = indirect_action_list_conf_get(id);
12009 			if (!indlst_conf)
12010 				return -1;
12011 			action_conf->conf = (const void **)indlst_conf->conf;
12012 			break;
12013 		default:
12014 			break;
12015 		}
12016 	}
12017 	return ret;
12018 }
12019 
12020 static int
12021 parse_meter_profile_id2ptr(struct context *ctx, const struct token *token,
12022 		const char *str, unsigned int len,
12023 		void *buf, unsigned int size)
12024 {
12025 	struct rte_flow_action *action = ctx->object;
12026 	struct rte_flow_action_meter_mark *meter;
12027 	struct rte_flow_meter_profile *profile = NULL;
12028 	uint32_t id = 0;
12029 	int ret;
12030 
12031 	(void)buf;
12032 	(void)size;
12033 	ctx->objdata = 0;
12034 	ctx->object = &id;
12035 	ctx->objmask = NULL;
12036 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12037 	ctx->object = action;
12038 	if (ret != (int)len)
12039 		return ret;
12040 	/* set meter profile */
12041 	if (action) {
12042 		meter = (struct rte_flow_action_meter_mark *)
12043 			(uintptr_t)(action->conf);
12044 		profile = port_meter_profile_get_by_id(ctx->port, id);
12045 		meter->profile = profile;
12046 		ret = (profile) ? ret : -1;
12047 	}
12048 	return ret;
12049 }
12050 
12051 static int
12052 parse_meter_policy_id2ptr(struct context *ctx, const struct token *token,
12053 		const char *str, unsigned int len,
12054 		void *buf, unsigned int size)
12055 {
12056 	struct rte_flow_action *action = ctx->object;
12057 	struct rte_flow_action_meter_mark *meter;
12058 	struct rte_flow_meter_policy *policy = NULL;
12059 	uint32_t id = 0;
12060 	int ret;
12061 
12062 	(void)buf;
12063 	(void)size;
12064 	ctx->objdata = 0;
12065 	ctx->object = &id;
12066 	ctx->objmask = NULL;
12067 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12068 	ctx->object = action;
12069 	if (ret != (int)len)
12070 		return ret;
12071 	/* set meter policy */
12072 	if (action) {
12073 		meter = (struct rte_flow_action_meter_mark *)
12074 			(uintptr_t)(action->conf);
12075 		policy = port_meter_policy_get_by_id(ctx->port, id);
12076 		meter->policy = policy;
12077 		ret = (policy) ? ret : -1;
12078 	}
12079 	return ret;
12080 }
12081 
12082 /** Parse set command, initialize output buffer for subsequent tokens. */
12083 static int
12084 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
12085 			  const char *str, unsigned int len,
12086 			  void *buf, unsigned int size)
12087 {
12088 	struct buffer *out = buf;
12089 
12090 	/* Token name must match. */
12091 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12092 		return -1;
12093 	/* Nothing else to do if there is no buffer. */
12094 	if (!out)
12095 		return len;
12096 	/* Make sure buffer is large enough. */
12097 	if (size < sizeof(*out))
12098 		return -1;
12099 	ctx->objdata = 0;
12100 	ctx->objmask = NULL;
12101 	ctx->object = out;
12102 	if (!out->command)
12103 		return -1;
12104 	out->command = ctx->curr;
12105 	/* For encap/decap we need is pattern */
12106 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12107 						       sizeof(double));
12108 	return len;
12109 }
12110 
12111 /** Parse set command, initialize output buffer for subsequent tokens. */
12112 static int
12113 parse_set_sample_action(struct context *ctx, const struct token *token,
12114 			  const char *str, unsigned int len,
12115 			  void *buf, unsigned int size)
12116 {
12117 	struct buffer *out = buf;
12118 
12119 	/* Token name must match. */
12120 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12121 		return -1;
12122 	/* Nothing else to do if there is no buffer. */
12123 	if (!out)
12124 		return len;
12125 	/* Make sure buffer is large enough. */
12126 	if (size < sizeof(*out))
12127 		return -1;
12128 	ctx->objdata = 0;
12129 	ctx->objmask = NULL;
12130 	ctx->object = out;
12131 	if (!out->command)
12132 		return -1;
12133 	out->command = ctx->curr;
12134 	/* For sampler we need is actions */
12135 	out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12136 						       sizeof(double));
12137 	return len;
12138 }
12139 
12140 /** Parse set command, initialize output buffer for subsequent tokens. */
12141 static int
12142 parse_set_ipv6_ext_action(struct context *ctx, const struct token *token,
12143 			  const char *str, unsigned int len,
12144 			  void *buf, unsigned int size)
12145 {
12146 	struct buffer *out = buf;
12147 
12148 	/* Token name must match. */
12149 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12150 		return -1;
12151 	/* Nothing else to do if there is no buffer. */
12152 	if (!out)
12153 		return len;
12154 	/* Make sure buffer is large enough. */
12155 	if (size < sizeof(*out))
12156 		return -1;
12157 	ctx->objdata = 0;
12158 	ctx->objmask = NULL;
12159 	ctx->object = out;
12160 	if (!out->command)
12161 		return -1;
12162 	out->command = ctx->curr;
12163 	/* For ipv6_ext_push/remove we need is pattern */
12164 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12165 						       sizeof(double));
12166 	return len;
12167 }
12168 
12169 /**
12170  * Parse set raw_encap/raw_decap command,
12171  * initialize output buffer for subsequent tokens.
12172  */
12173 static int
12174 parse_set_init(struct context *ctx, const struct token *token,
12175 	       const char *str, unsigned int len,
12176 	       void *buf, unsigned int size)
12177 {
12178 	struct buffer *out = buf;
12179 
12180 	/* Token name must match. */
12181 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12182 		return -1;
12183 	/* Nothing else to do if there is no buffer. */
12184 	if (!out)
12185 		return len;
12186 	/* Make sure buffer is large enough. */
12187 	if (size < sizeof(*out))
12188 		return -1;
12189 	/* Initialize buffer. */
12190 	memset(out, 0x00, sizeof(*out));
12191 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
12192 	ctx->objdata = 0;
12193 	ctx->object = out;
12194 	ctx->objmask = NULL;
12195 	if (!out->command) {
12196 		if (ctx->curr != SET)
12197 			return -1;
12198 		if (sizeof(*out) > size)
12199 			return -1;
12200 		out->command = ctx->curr;
12201 		out->args.vc.data = (uint8_t *)out + size;
12202 		ctx->object  = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12203 						       sizeof(double));
12204 	}
12205 	return len;
12206 }
12207 
12208 /*
12209  * Replace testpmd handles in a flex flow item with real values.
12210  */
12211 static int
12212 parse_flex_handle(struct context *ctx, const struct token *token,
12213 		  const char *str, unsigned int len,
12214 		  void *buf, unsigned int size)
12215 {
12216 	struct rte_flow_item_flex *spec, *mask;
12217 	const struct rte_flow_item_flex *src_spec, *src_mask;
12218 	const struct arg *arg = pop_args(ctx);
12219 	uint32_t offset;
12220 	uint16_t handle;
12221 	int ret;
12222 
12223 	if (!arg) {
12224 		printf("Bad environment\n");
12225 		return -1;
12226 	}
12227 	offset = arg->offset;
12228 	push_args(ctx, arg);
12229 	ret = parse_int(ctx, token, str, len, buf, size);
12230 	if (ret <= 0 || !ctx->object)
12231 		return ret;
12232 	if (ctx->port >= RTE_MAX_ETHPORTS) {
12233 		printf("Bad port\n");
12234 		return -1;
12235 	}
12236 	if (offset == offsetof(struct rte_flow_item_flex, handle)) {
12237 		const struct flex_item *fp;
12238 		spec = ctx->object;
12239 		handle = (uint16_t)(uintptr_t)spec->handle;
12240 		if (handle >= FLEX_MAX_PARSERS_NUM) {
12241 			printf("Bad flex item handle\n");
12242 			return -1;
12243 		}
12244 		fp = flex_items[ctx->port][handle];
12245 		if (!fp) {
12246 			printf("Bad flex item handle\n");
12247 			return -1;
12248 		}
12249 		spec->handle = fp->flex_handle;
12250 		mask = spec + 2; /* spec, last, mask */
12251 		mask->handle = fp->flex_handle;
12252 	} else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
12253 		handle = (uint16_t)(uintptr_t)
12254 			((struct rte_flow_item_flex *)ctx->object)->pattern;
12255 		if (handle >= FLEX_MAX_PATTERNS_NUM) {
12256 			printf("Bad pattern handle\n");
12257 			return -1;
12258 		}
12259 		src_spec = &flex_patterns[handle].spec;
12260 		src_mask = &flex_patterns[handle].mask;
12261 		spec = ctx->object;
12262 		mask = spec + 2; /* spec, last, mask */
12263 		/* fill flow rule spec and mask parameters */
12264 		spec->length = src_spec->length;
12265 		spec->pattern = src_spec->pattern;
12266 		mask->length = src_mask->length;
12267 		mask->pattern = src_mask->pattern;
12268 	} else {
12269 		printf("Bad arguments - unknown flex item offset\n");
12270 		return -1;
12271 	}
12272 	return ret;
12273 }
12274 
12275 /** Parse Meter color name */
12276 static int
12277 parse_meter_color(struct context *ctx, const struct token *token,
12278 		  const char *str, unsigned int len, void *buf,
12279 		  unsigned int size)
12280 {
12281 	struct rte_flow_item_meter_color *meter_color;
12282 	unsigned int i;
12283 
12284 	(void)token;
12285 	(void)buf;
12286 	(void)size;
12287 	for (i = 0; meter_colors[i]; ++i)
12288 		if (!strcmp_partial(meter_colors[i], str, len))
12289 			break;
12290 	if (!meter_colors[i])
12291 		return -1;
12292 	if (!ctx->object)
12293 		return len;
12294 	meter_color = ctx->object;
12295 	meter_color->color = (enum rte_color)i;
12296 	return len;
12297 }
12298 
12299 /** Parse Insertion Table Type name */
12300 static int
12301 parse_insertion_table_type(struct context *ctx, const struct token *token,
12302 			   const char *str, unsigned int len, void *buf,
12303 			   unsigned int size)
12304 {
12305 	const struct arg *arg = pop_args(ctx);
12306 	unsigned int i;
12307 	char tmp[2];
12308 	int ret;
12309 
12310 	(void)size;
12311 	/* Argument is expected. */
12312 	if (!arg)
12313 		return -1;
12314 	for (i = 0; table_insertion_types[i]; ++i)
12315 		if (!strcmp_partial(table_insertion_types[i], str, len))
12316 			break;
12317 	if (!table_insertion_types[i])
12318 		return -1;
12319 	push_args(ctx, arg);
12320 	snprintf(tmp, sizeof(tmp), "%u", i);
12321 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12322 	return ret > 0 ? (int)len : ret;
12323 }
12324 
12325 /** Parse Hash Calculation Table Type name */
12326 static int
12327 parse_hash_table_type(struct context *ctx, const struct token *token,
12328 		      const char *str, unsigned int len, void *buf,
12329 		      unsigned int size)
12330 {
12331 	const struct arg *arg = pop_args(ctx);
12332 	unsigned int i;
12333 	char tmp[2];
12334 	int ret;
12335 
12336 	(void)size;
12337 	/* Argument is expected. */
12338 	if (!arg)
12339 		return -1;
12340 	for (i = 0; table_hash_funcs[i]; ++i)
12341 		if (!strcmp_partial(table_hash_funcs[i], str, len))
12342 			break;
12343 	if (!table_hash_funcs[i])
12344 		return -1;
12345 	push_args(ctx, arg);
12346 	snprintf(tmp, sizeof(tmp), "%u", i);
12347 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12348 	return ret > 0 ? (int)len : ret;
12349 }
12350 
12351 static int
12352 parse_name_to_index(struct context *ctx, const struct token *token,
12353 		    const char *str, unsigned int len, void *buf,
12354 		    unsigned int size,
12355 		    const char *const names[], size_t names_size, uint32_t *dst)
12356 {
12357 	int ret;
12358 	uint32_t i;
12359 
12360 	RTE_SET_USED(token);
12361 	RTE_SET_USED(buf);
12362 	RTE_SET_USED(size);
12363 	if (!ctx->object)
12364 		return len;
12365 	for (i = 0; i < names_size; i++) {
12366 		if (!names[i])
12367 			continue;
12368 		ret = strcmp_partial(names[i], str,
12369 				     RTE_MIN(len, strlen(names[i])));
12370 		if (!ret) {
12371 			*dst = i;
12372 			return len;
12373 		}
12374 	}
12375 	return -1;
12376 }
12377 
12378 static const char *const quota_mode_names[] = {
12379 	NULL,
12380 	[RTE_FLOW_QUOTA_MODE_PACKET] = "packet",
12381 	[RTE_FLOW_QUOTA_MODE_L2] = "l2",
12382 	[RTE_FLOW_QUOTA_MODE_L3] = "l3"
12383 };
12384 
12385 static const char *const quota_state_names[] = {
12386 	[RTE_FLOW_QUOTA_STATE_PASS] = "pass",
12387 	[RTE_FLOW_QUOTA_STATE_BLOCK] = "block"
12388 };
12389 
12390 static const char *const quota_update_names[] = {
12391 	[RTE_FLOW_UPDATE_QUOTA_SET] = "set",
12392 	[RTE_FLOW_UPDATE_QUOTA_ADD] = "add"
12393 };
12394 
12395 static const char *const query_update_mode_names[] = {
12396 	[RTE_FLOW_QU_QUERY_FIRST] = "query_first",
12397 	[RTE_FLOW_QU_UPDATE_FIRST] = "update_first"
12398 };
12399 
12400 static int
12401 parse_quota_state_name(struct context *ctx, const struct token *token,
12402 		       const char *str, unsigned int len, void *buf,
12403 		       unsigned int size)
12404 {
12405 	struct rte_flow_item_quota *quota = ctx->object;
12406 
12407 	return parse_name_to_index(ctx, token, str, len, buf, size,
12408 				   quota_state_names,
12409 				   RTE_DIM(quota_state_names),
12410 				   (uint32_t *)&quota->state);
12411 }
12412 
12413 static int
12414 parse_quota_mode_name(struct context *ctx, const struct token *token,
12415 		      const char *str, unsigned int len, void *buf,
12416 		      unsigned int size)
12417 {
12418 	struct rte_flow_action_quota *quota = ctx->object;
12419 
12420 	return parse_name_to_index(ctx, token, str, len, buf, size,
12421 				   quota_mode_names,
12422 				   RTE_DIM(quota_mode_names),
12423 				   (uint32_t *)&quota->mode);
12424 }
12425 
12426 static int
12427 parse_quota_update_name(struct context *ctx, const struct token *token,
12428 			const char *str, unsigned int len, void *buf,
12429 			unsigned int size)
12430 {
12431 	struct rte_flow_update_quota *update = ctx->object;
12432 
12433 	return parse_name_to_index(ctx, token, str, len, buf, size,
12434 				   quota_update_names,
12435 				   RTE_DIM(quota_update_names),
12436 				   (uint32_t *)&update->op);
12437 }
12438 
12439 static int
12440 parse_qu_mode_name(struct context *ctx, const struct token *token,
12441 		   const char *str, unsigned int len, void *buf,
12442 		   unsigned int size)
12443 {
12444 	struct buffer *out = ctx->object;
12445 
12446 	return parse_name_to_index(ctx, token, str, len, buf, size,
12447 				   query_update_mode_names,
12448 				   RTE_DIM(query_update_mode_names),
12449 				   (uint32_t *)&out->args.ia.qu_mode);
12450 }
12451 
12452 /** No completion. */
12453 static int
12454 comp_none(struct context *ctx, const struct token *token,
12455 	  unsigned int ent, char *buf, unsigned int size)
12456 {
12457 	(void)ctx;
12458 	(void)token;
12459 	(void)ent;
12460 	(void)buf;
12461 	(void)size;
12462 	return 0;
12463 }
12464 
12465 /** Complete boolean values. */
12466 static int
12467 comp_boolean(struct context *ctx, const struct token *token,
12468 	     unsigned int ent, char *buf, unsigned int size)
12469 {
12470 	unsigned int i;
12471 
12472 	(void)ctx;
12473 	(void)token;
12474 	for (i = 0; boolean_name[i]; ++i)
12475 		if (buf && i == ent)
12476 			return strlcpy(buf, boolean_name[i], size);
12477 	if (buf)
12478 		return -1;
12479 	return i;
12480 }
12481 
12482 /** Complete action names. */
12483 static int
12484 comp_action(struct context *ctx, const struct token *token,
12485 	    unsigned int ent, char *buf, unsigned int size)
12486 {
12487 	unsigned int i;
12488 
12489 	(void)ctx;
12490 	(void)token;
12491 	for (i = 0; next_action[i]; ++i)
12492 		if (buf && i == ent)
12493 			return strlcpy(buf, token_list[next_action[i]].name,
12494 				       size);
12495 	if (buf)
12496 		return -1;
12497 	return i;
12498 }
12499 
12500 /** Complete available ports. */
12501 static int
12502 comp_port(struct context *ctx, const struct token *token,
12503 	  unsigned int ent, char *buf, unsigned int size)
12504 {
12505 	unsigned int i = 0;
12506 	portid_t p;
12507 
12508 	(void)ctx;
12509 	(void)token;
12510 	RTE_ETH_FOREACH_DEV(p) {
12511 		if (buf && i == ent)
12512 			return snprintf(buf, size, "%u", p);
12513 		++i;
12514 	}
12515 	if (buf)
12516 		return -1;
12517 	return i;
12518 }
12519 
12520 /** Complete available rule IDs. */
12521 static int
12522 comp_rule_id(struct context *ctx, const struct token *token,
12523 	     unsigned int ent, char *buf, unsigned int size)
12524 {
12525 	unsigned int i = 0;
12526 	struct rte_port *port;
12527 	struct port_flow *pf;
12528 
12529 	(void)token;
12530 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12531 	    ctx->port == (portid_t)RTE_PORT_ALL)
12532 		return -1;
12533 	port = &ports[ctx->port];
12534 	for (pf = port->flow_list; pf != NULL; pf = pf->next) {
12535 		if (buf && i == ent)
12536 			return snprintf(buf, size, "%"PRIu64, pf->id);
12537 		++i;
12538 	}
12539 	if (buf)
12540 		return -1;
12541 	return i;
12542 }
12543 
12544 /** Complete operation for compare match item. */
12545 static int
12546 comp_set_compare_op(struct context *ctx, const struct token *token,
12547 		    unsigned int ent, char *buf, unsigned int size)
12548 {
12549 	RTE_SET_USED(ctx);
12550 	RTE_SET_USED(token);
12551 	if (!buf)
12552 		return RTE_DIM(compare_ops);
12553 	if (ent < RTE_DIM(compare_ops) - 1)
12554 		return strlcpy(buf, compare_ops[ent], size);
12555 	return -1;
12556 }
12557 
12558 /** Complete field id for compare match item. */
12559 static int
12560 comp_set_compare_field_id(struct context *ctx, const struct token *token,
12561 			  unsigned int ent, char *buf, unsigned int size)
12562 {
12563 	const char *name;
12564 
12565 	RTE_SET_USED(token);
12566 	if (!buf)
12567 		return RTE_DIM(flow_field_ids);
12568 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12569 		return -1;
12570 	name = flow_field_ids[ent];
12571 	if (ctx->curr == ITEM_COMPARE_FIELD_B_TYPE ||
12572 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12573 		return strlcpy(buf, name, size);
12574 	return -1;
12575 }
12576 
12577 /** Complete type field for RSS action. */
12578 static int
12579 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
12580 			unsigned int ent, char *buf, unsigned int size)
12581 {
12582 	unsigned int i;
12583 
12584 	(void)ctx;
12585 	(void)token;
12586 	for (i = 0; rss_type_table[i].str; ++i)
12587 		;
12588 	if (!buf)
12589 		return i + 1;
12590 	if (ent < i)
12591 		return strlcpy(buf, rss_type_table[ent].str, size);
12592 	if (ent == i)
12593 		return snprintf(buf, size, "end");
12594 	return -1;
12595 }
12596 
12597 /** Complete queue field for RSS action. */
12598 static int
12599 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
12600 			 unsigned int ent, char *buf, unsigned int size)
12601 {
12602 	(void)ctx;
12603 	(void)token;
12604 	if (!buf)
12605 		return nb_rxq + 1;
12606 	if (ent < nb_rxq)
12607 		return snprintf(buf, size, "%u", ent);
12608 	if (ent == nb_rxq)
12609 		return snprintf(buf, size, "end");
12610 	return -1;
12611 }
12612 
12613 /** Complete index number for set raw_encap/raw_decap commands. */
12614 static int
12615 comp_set_raw_index(struct context *ctx, const struct token *token,
12616 		   unsigned int ent, char *buf, unsigned int size)
12617 {
12618 	uint16_t idx = 0;
12619 	uint16_t nb = 0;
12620 
12621 	RTE_SET_USED(ctx);
12622 	RTE_SET_USED(token);
12623 	for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
12624 		if (buf && idx == ent)
12625 			return snprintf(buf, size, "%u", idx);
12626 		++nb;
12627 	}
12628 	return nb;
12629 }
12630 
12631 /** Complete index number for set raw_ipv6_ext_push/ipv6_ext_remove commands. */
12632 static int
12633 comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
12634 			unsigned int ent, char *buf, unsigned int size)
12635 {
12636 	uint16_t idx = 0;
12637 	uint16_t nb = 0;
12638 
12639 	RTE_SET_USED(ctx);
12640 	RTE_SET_USED(token);
12641 	for (idx = 0; idx < IPV6_EXT_PUSH_CONFS_MAX_NUM; ++idx) {
12642 		if (buf && idx == ent)
12643 			return snprintf(buf, size, "%u", idx);
12644 		++nb;
12645 	}
12646 	return nb;
12647 }
12648 
12649 /** Complete index number for set raw_encap/raw_decap commands. */
12650 static int
12651 comp_set_sample_index(struct context *ctx, const struct token *token,
12652 		   unsigned int ent, char *buf, unsigned int size)
12653 {
12654 	uint16_t idx = 0;
12655 	uint16_t nb = 0;
12656 
12657 	RTE_SET_USED(ctx);
12658 	RTE_SET_USED(token);
12659 	for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
12660 		if (buf && idx == ent)
12661 			return snprintf(buf, size, "%u", idx);
12662 		++nb;
12663 	}
12664 	return nb;
12665 }
12666 
12667 /** Complete operation for modify_field command. */
12668 static int
12669 comp_set_modify_field_op(struct context *ctx, const struct token *token,
12670 		   unsigned int ent, char *buf, unsigned int size)
12671 {
12672 	RTE_SET_USED(ctx);
12673 	RTE_SET_USED(token);
12674 	if (!buf)
12675 		return RTE_DIM(modify_field_ops);
12676 	if (ent < RTE_DIM(modify_field_ops) - 1)
12677 		return strlcpy(buf, modify_field_ops[ent], size);
12678 	return -1;
12679 }
12680 
12681 /** Complete field id for modify_field command. */
12682 static int
12683 comp_set_modify_field_id(struct context *ctx, const struct token *token,
12684 		   unsigned int ent, char *buf, unsigned int size)
12685 {
12686 	const char *name;
12687 
12688 	RTE_SET_USED(token);
12689 	if (!buf)
12690 		return RTE_DIM(flow_field_ids);
12691 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12692 		return -1;
12693 	name = flow_field_ids[ent];
12694 	if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
12695 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12696 		return strlcpy(buf, name, size);
12697 	return -1;
12698 }
12699 
12700 /** Complete available pattern template IDs. */
12701 static int
12702 comp_pattern_template_id(struct context *ctx, const struct token *token,
12703 			 unsigned int ent, char *buf, unsigned int size)
12704 {
12705 	unsigned int i = 0;
12706 	struct rte_port *port;
12707 	struct port_template *pt;
12708 
12709 	(void)token;
12710 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12711 	    ctx->port == (portid_t)RTE_PORT_ALL)
12712 		return -1;
12713 	port = &ports[ctx->port];
12714 	for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) {
12715 		if (buf && i == ent)
12716 			return snprintf(buf, size, "%u", pt->id);
12717 		++i;
12718 	}
12719 	if (buf)
12720 		return -1;
12721 	return i;
12722 }
12723 
12724 /** Complete available actions template IDs. */
12725 static int
12726 comp_actions_template_id(struct context *ctx, const struct token *token,
12727 			 unsigned int ent, char *buf, unsigned int size)
12728 {
12729 	unsigned int i = 0;
12730 	struct rte_port *port;
12731 	struct port_template *pt;
12732 
12733 	(void)token;
12734 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12735 	    ctx->port == (portid_t)RTE_PORT_ALL)
12736 		return -1;
12737 	port = &ports[ctx->port];
12738 	for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) {
12739 		if (buf && i == ent)
12740 			return snprintf(buf, size, "%u", pt->id);
12741 		++i;
12742 	}
12743 	if (buf)
12744 		return -1;
12745 	return i;
12746 }
12747 
12748 /** Complete available table IDs. */
12749 static int
12750 comp_table_id(struct context *ctx, const struct token *token,
12751 	      unsigned int ent, char *buf, unsigned int size)
12752 {
12753 	unsigned int i = 0;
12754 	struct rte_port *port;
12755 	struct port_table *pt;
12756 
12757 	(void)token;
12758 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12759 	    ctx->port == (portid_t)RTE_PORT_ALL)
12760 		return -1;
12761 	port = &ports[ctx->port];
12762 	for (pt = port->table_list; pt != NULL; pt = pt->next) {
12763 		if (buf && i == ent)
12764 			return snprintf(buf, size, "%u", pt->id);
12765 		++i;
12766 	}
12767 	if (buf)
12768 		return -1;
12769 	return i;
12770 }
12771 
12772 /** Complete available queue IDs. */
12773 static int
12774 comp_queue_id(struct context *ctx, const struct token *token,
12775 	      unsigned int ent, char *buf, unsigned int size)
12776 {
12777 	unsigned int i = 0;
12778 	struct rte_port *port;
12779 
12780 	(void)token;
12781 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12782 	    ctx->port == (portid_t)RTE_PORT_ALL)
12783 		return -1;
12784 	port = &ports[ctx->port];
12785 	for (i = 0; i < port->queue_nb; i++) {
12786 		if (buf && i == ent)
12787 			return snprintf(buf, size, "%u", i);
12788 	}
12789 	if (buf)
12790 		return -1;
12791 	return i;
12792 }
12793 
12794 static int
12795 comp_names_to_index(struct context *ctx, const struct token *token,
12796 		    unsigned int ent, char *buf, unsigned int size,
12797 		    const char *const names[], size_t names_size)
12798 {
12799 	RTE_SET_USED(ctx);
12800 	RTE_SET_USED(token);
12801 	if (!buf)
12802 		return names_size;
12803 	if (names[ent] && ent < names_size)
12804 		return rte_strscpy(buf, names[ent], size);
12805 	return -1;
12806 
12807 }
12808 
12809 /** Complete available Meter colors. */
12810 static int
12811 comp_meter_color(struct context *ctx, const struct token *token,
12812 		 unsigned int ent, char *buf, unsigned int size)
12813 {
12814 	RTE_SET_USED(ctx);
12815 	RTE_SET_USED(token);
12816 	if (!buf)
12817 		return RTE_DIM(meter_colors);
12818 	if (ent < RTE_DIM(meter_colors) - 1)
12819 		return strlcpy(buf, meter_colors[ent], size);
12820 	return -1;
12821 }
12822 
12823 /** Complete available Insertion Table types. */
12824 static int
12825 comp_insertion_table_type(struct context *ctx, const struct token *token,
12826 			  unsigned int ent, char *buf, unsigned int size)
12827 {
12828 	RTE_SET_USED(ctx);
12829 	RTE_SET_USED(token);
12830 	if (!buf)
12831 		return RTE_DIM(table_insertion_types);
12832 	if (ent < RTE_DIM(table_insertion_types) - 1)
12833 		return rte_strscpy(buf, table_insertion_types[ent], size);
12834 	return -1;
12835 }
12836 
12837 /** Complete available Hash Calculation Table types. */
12838 static int
12839 comp_hash_table_type(struct context *ctx, const struct token *token,
12840 		     unsigned int ent, char *buf, unsigned int size)
12841 {
12842 	RTE_SET_USED(ctx);
12843 	RTE_SET_USED(token);
12844 	if (!buf)
12845 		return RTE_DIM(table_hash_funcs);
12846 	if (ent < RTE_DIM(table_hash_funcs) - 1)
12847 		return rte_strscpy(buf, table_hash_funcs[ent], size);
12848 	return -1;
12849 }
12850 
12851 static int
12852 comp_quota_state_name(struct context *ctx, const struct token *token,
12853 		      unsigned int ent, char *buf, unsigned int size)
12854 {
12855 	return comp_names_to_index(ctx, token, ent, buf, size,
12856 				   quota_state_names,
12857 				   RTE_DIM(quota_state_names));
12858 }
12859 
12860 static int
12861 comp_quota_mode_name(struct context *ctx, const struct token *token,
12862 		     unsigned int ent, char *buf, unsigned int size)
12863 {
12864 	return comp_names_to_index(ctx, token, ent, buf, size,
12865 				   quota_mode_names,
12866 				   RTE_DIM(quota_mode_names));
12867 }
12868 
12869 static int
12870 comp_quota_update_name(struct context *ctx, const struct token *token,
12871 		       unsigned int ent, char *buf, unsigned int size)
12872 {
12873 	return comp_names_to_index(ctx, token, ent, buf, size,
12874 				   quota_update_names,
12875 				   RTE_DIM(quota_update_names));
12876 }
12877 
12878 static int
12879 comp_qu_mode_name(struct context *ctx, const struct token *token,
12880 		  unsigned int ent, char *buf, unsigned int size)
12881 {
12882 	return comp_names_to_index(ctx, token, ent, buf, size,
12883 				   query_update_mode_names,
12884 				   RTE_DIM(query_update_mode_names));
12885 }
12886 
12887 /** Internal context. */
12888 static struct context cmd_flow_context;
12889 
12890 /** Global parser instance (cmdline API). */
12891 cmdline_parse_inst_t cmd_flow;
12892 cmdline_parse_inst_t cmd_set_raw;
12893 
12894 /** Initialize context. */
12895 static void
12896 cmd_flow_context_init(struct context *ctx)
12897 {
12898 	/* A full memset() is not necessary. */
12899 	ctx->curr = ZERO;
12900 	ctx->prev = ZERO;
12901 	ctx->next_num = 0;
12902 	ctx->args_num = 0;
12903 	ctx->eol = 0;
12904 	ctx->last = 0;
12905 	ctx->port = 0;
12906 	ctx->objdata = 0;
12907 	ctx->object = NULL;
12908 	ctx->objmask = NULL;
12909 }
12910 
12911 /** Parse a token (cmdline API). */
12912 static int
12913 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
12914 	       unsigned int size)
12915 {
12916 	struct context *ctx = &cmd_flow_context;
12917 	const struct token *token;
12918 	const enum index *list;
12919 	int len;
12920 	int i;
12921 
12922 	(void)hdr;
12923 	token = &token_list[ctx->curr];
12924 	/* Check argument length. */
12925 	ctx->eol = 0;
12926 	ctx->last = 1;
12927 	for (len = 0; src[len]; ++len)
12928 		if (src[len] == '#' || isspace(src[len]))
12929 			break;
12930 	if (!len)
12931 		return -1;
12932 	/* Last argument and EOL detection. */
12933 	for (i = len; src[i]; ++i)
12934 		if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
12935 			break;
12936 		else if (!isspace(src[i])) {
12937 			ctx->last = 0;
12938 			break;
12939 		}
12940 	for (; src[i]; ++i)
12941 		if (src[i] == '\r' || src[i] == '\n') {
12942 			ctx->eol = 1;
12943 			break;
12944 		}
12945 	/* Initialize context if necessary. */
12946 	if (!ctx->next_num) {
12947 		if (!token->next)
12948 			return 0;
12949 		ctx->next[ctx->next_num++] = token->next[0];
12950 	}
12951 	/* Process argument through candidates. */
12952 	ctx->prev = ctx->curr;
12953 	list = ctx->next[ctx->next_num - 1];
12954 	for (i = 0; list[i]; ++i) {
12955 		const struct token *next = &token_list[list[i]];
12956 		int tmp;
12957 
12958 		ctx->curr = list[i];
12959 		if (next->call)
12960 			tmp = next->call(ctx, next, src, len, result, size);
12961 		else
12962 			tmp = parse_default(ctx, next, src, len, result, size);
12963 		if (tmp == -1 || tmp != len)
12964 			continue;
12965 		token = next;
12966 		break;
12967 	}
12968 	if (!list[i])
12969 		return -1;
12970 	--ctx->next_num;
12971 	/* Push subsequent tokens if any. */
12972 	if (token->next)
12973 		for (i = 0; token->next[i]; ++i) {
12974 			if (ctx->next_num == RTE_DIM(ctx->next))
12975 				return -1;
12976 			ctx->next[ctx->next_num++] = token->next[i];
12977 		}
12978 	/* Push arguments if any. */
12979 	if (token->args)
12980 		for (i = 0; token->args[i]; ++i) {
12981 			if (ctx->args_num == RTE_DIM(ctx->args))
12982 				return -1;
12983 			ctx->args[ctx->args_num++] = token->args[i];
12984 		}
12985 	return len;
12986 }
12987 
12988 int
12989 flow_parse(const char *src, void *result, unsigned int size,
12990 	   struct rte_flow_attr **attr,
12991 	   struct rte_flow_item **pattern, struct rte_flow_action **actions)
12992 {
12993 	int ret;
12994 	struct context saved_flow_ctx = cmd_flow_context;
12995 
12996 	cmd_flow_context_init(&cmd_flow_context);
12997 	do {
12998 		ret = cmd_flow_parse(NULL, src, result, size);
12999 		if (ret > 0) {
13000 			src += ret;
13001 			while (isspace(*src))
13002 				src++;
13003 		}
13004 	} while (ret > 0 && strlen(src));
13005 	cmd_flow_context = saved_flow_ctx;
13006 	*attr = &((struct buffer *)result)->args.vc.attr;
13007 	*pattern = ((struct buffer *)result)->args.vc.pattern;
13008 	*actions = ((struct buffer *)result)->args.vc.actions;
13009 	return (ret >= 0 && !strlen(src)) ? 0 : -1;
13010 }
13011 
13012 /** Return number of completion entries (cmdline API). */
13013 static int
13014 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
13015 {
13016 	struct context *ctx = &cmd_flow_context;
13017 	const struct token *token = &token_list[ctx->curr];
13018 	const enum index *list;
13019 	int i;
13020 
13021 	(void)hdr;
13022 	/* Count number of tokens in current list. */
13023 	if (ctx->next_num)
13024 		list = ctx->next[ctx->next_num - 1];
13025 	else
13026 		list = token->next[0];
13027 	for (i = 0; list[i]; ++i)
13028 		;
13029 	if (!i)
13030 		return 0;
13031 	/*
13032 	 * If there is a single token, use its completion callback, otherwise
13033 	 * return the number of entries.
13034 	 */
13035 	token = &token_list[list[0]];
13036 	if (i == 1 && token->comp) {
13037 		/* Save index for cmd_flow_get_help(). */
13038 		ctx->prev = list[0];
13039 		return token->comp(ctx, token, 0, NULL, 0);
13040 	}
13041 	return i;
13042 }
13043 
13044 /** Return a completion entry (cmdline API). */
13045 static int
13046 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
13047 			  char *dst, unsigned int size)
13048 {
13049 	struct context *ctx = &cmd_flow_context;
13050 	const struct token *token = &token_list[ctx->curr];
13051 	const enum index *list;
13052 	int i;
13053 
13054 	(void)hdr;
13055 	/* Count number of tokens in current list. */
13056 	if (ctx->next_num)
13057 		list = ctx->next[ctx->next_num - 1];
13058 	else
13059 		list = token->next[0];
13060 	for (i = 0; list[i]; ++i)
13061 		;
13062 	if (!i)
13063 		return -1;
13064 	/* If there is a single token, use its completion callback. */
13065 	token = &token_list[list[0]];
13066 	if (i == 1 && token->comp) {
13067 		/* Save index for cmd_flow_get_help(). */
13068 		ctx->prev = list[0];
13069 		return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
13070 	}
13071 	/* Otherwise make sure the index is valid and use defaults. */
13072 	if (index >= i)
13073 		return -1;
13074 	token = &token_list[list[index]];
13075 	strlcpy(dst, token->name, size);
13076 	/* Save index for cmd_flow_get_help(). */
13077 	ctx->prev = list[index];
13078 	return 0;
13079 }
13080 
13081 /** Populate help strings for current token (cmdline API). */
13082 static int
13083 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
13084 {
13085 	struct context *ctx = &cmd_flow_context;
13086 	const struct token *token = &token_list[ctx->prev];
13087 
13088 	(void)hdr;
13089 	if (!size)
13090 		return -1;
13091 	/* Set token type and update global help with details. */
13092 	strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
13093 	if (token->help)
13094 		cmd_flow.help_str = token->help;
13095 	else
13096 		cmd_flow.help_str = token->name;
13097 	return 0;
13098 }
13099 
13100 /** Token definition template (cmdline API). */
13101 static struct cmdline_token_hdr cmd_flow_token_hdr = {
13102 	.ops = &(struct cmdline_token_ops){
13103 		.parse = cmd_flow_parse,
13104 		.complete_get_nb = cmd_flow_complete_get_nb,
13105 		.complete_get_elt = cmd_flow_complete_get_elt,
13106 		.get_help = cmd_flow_get_help,
13107 	},
13108 	.offset = 0,
13109 };
13110 
13111 /** Populate the next dynamic token. */
13112 static void
13113 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
13114 	     cmdline_parse_token_hdr_t **hdr_inst)
13115 {
13116 	struct context *ctx = &cmd_flow_context;
13117 
13118 	/* Always reinitialize context before requesting the first token. */
13119 	if (!(hdr_inst - cmd_flow.tokens))
13120 		cmd_flow_context_init(ctx);
13121 	/* Return NULL when no more tokens are expected. */
13122 	if (!ctx->next_num && ctx->curr) {
13123 		*hdr = NULL;
13124 		return;
13125 	}
13126 	/* Determine if command should end here. */
13127 	if (ctx->eol && ctx->last && ctx->next_num) {
13128 		const enum index *list = ctx->next[ctx->next_num - 1];
13129 		int i;
13130 
13131 		for (i = 0; list[i]; ++i) {
13132 			if (list[i] != END)
13133 				continue;
13134 			*hdr = NULL;
13135 			return;
13136 		}
13137 	}
13138 	*hdr = &cmd_flow_token_hdr;
13139 }
13140 
13141 static SLIST_HEAD(, indlst_conf) indlst_conf_head =
13142 	SLIST_HEAD_INITIALIZER();
13143 
13144 static void
13145 indirect_action_flow_conf_create(const struct buffer *in)
13146 {
13147 	int len, ret;
13148 	uint32_t i;
13149 	struct indlst_conf *indlst_conf = NULL;
13150 	size_t base = RTE_ALIGN(sizeof(*indlst_conf), 8);
13151 	struct rte_flow_action *src = in->args.vc.actions;
13152 
13153 	if (!in->args.vc.actions_n)
13154 		goto end;
13155 	len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, src, NULL);
13156 	if (len <= 0)
13157 		goto end;
13158 	len = RTE_ALIGN(len, 16);
13159 
13160 	indlst_conf = calloc(1, base + len +
13161 			     in->args.vc.actions_n * sizeof(uintptr_t));
13162 	if (!indlst_conf)
13163 		goto end;
13164 	indlst_conf->id = in->args.vc.attr.group;
13165 	indlst_conf->conf_num = in->args.vc.actions_n - 1;
13166 	indlst_conf->actions = RTE_PTR_ADD(indlst_conf, base);
13167 	ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, indlst_conf->actions,
13168 			    len, src, NULL);
13169 	if (ret <= 0) {
13170 		free(indlst_conf);
13171 		indlst_conf = NULL;
13172 		goto end;
13173 	}
13174 	indlst_conf->conf = RTE_PTR_ADD(indlst_conf, base + len);
13175 	for (i = 0; i < indlst_conf->conf_num; i++)
13176 		indlst_conf->conf[i] = indlst_conf->actions[i].conf;
13177 	SLIST_INSERT_HEAD(&indlst_conf_head, indlst_conf, next);
13178 end:
13179 	if (indlst_conf)
13180 		printf("created indirect action list configuration %u\n",
13181 		       in->args.vc.attr.group);
13182 	else
13183 		printf("cannot create indirect action list configuration %u\n",
13184 		       in->args.vc.attr.group);
13185 }
13186 
13187 static const struct indlst_conf *
13188 indirect_action_list_conf_get(uint32_t conf_id)
13189 {
13190 	const struct indlst_conf *conf;
13191 
13192 	SLIST_FOREACH(conf, &indlst_conf_head, next) {
13193 		if (conf->id == conf_id)
13194 			return conf;
13195 	}
13196 	return NULL;
13197 }
13198 
13199 /** Dispatch parsed buffer to function calls. */
13200 static void
13201 cmd_flow_parsed(const struct buffer *in)
13202 {
13203 	switch (in->command) {
13204 	case INFO:
13205 		port_flow_get_info(in->port);
13206 		break;
13207 	case CONFIGURE:
13208 		port_flow_configure(in->port,
13209 				    &in->args.configure.port_attr,
13210 				    in->args.configure.nb_queue,
13211 				    &in->args.configure.queue_attr);
13212 		break;
13213 	case PATTERN_TEMPLATE_CREATE:
13214 		port_flow_pattern_template_create(in->port,
13215 				in->args.vc.pat_templ_id,
13216 				&((const struct rte_flow_pattern_template_attr) {
13217 					.relaxed_matching = in->args.vc.attr.reserved,
13218 					.ingress = in->args.vc.attr.ingress,
13219 					.egress = in->args.vc.attr.egress,
13220 					.transfer = in->args.vc.attr.transfer,
13221 				}),
13222 				in->args.vc.pattern);
13223 		break;
13224 	case PATTERN_TEMPLATE_DESTROY:
13225 		port_flow_pattern_template_destroy(in->port,
13226 				in->args.templ_destroy.template_id_n,
13227 				in->args.templ_destroy.template_id);
13228 		break;
13229 	case ACTIONS_TEMPLATE_CREATE:
13230 		port_flow_actions_template_create(in->port,
13231 				in->args.vc.act_templ_id,
13232 				&((const struct rte_flow_actions_template_attr) {
13233 					.ingress = in->args.vc.attr.ingress,
13234 					.egress = in->args.vc.attr.egress,
13235 					.transfer = in->args.vc.attr.transfer,
13236 				}),
13237 				in->args.vc.actions,
13238 				in->args.vc.masks);
13239 		break;
13240 	case ACTIONS_TEMPLATE_DESTROY:
13241 		port_flow_actions_template_destroy(in->port,
13242 				in->args.templ_destroy.template_id_n,
13243 				in->args.templ_destroy.template_id);
13244 		break;
13245 	case TABLE_CREATE:
13246 		port_flow_template_table_create(in->port, in->args.table.id,
13247 			&in->args.table.attr, in->args.table.pat_templ_id_n,
13248 			in->args.table.pat_templ_id, in->args.table.act_templ_id_n,
13249 			in->args.table.act_templ_id);
13250 		break;
13251 	case TABLE_DESTROY:
13252 		port_flow_template_table_destroy(in->port,
13253 					in->args.table_destroy.table_id_n,
13254 					in->args.table_destroy.table_id);
13255 		break;
13256 	case TABLE_RESIZE_COMPLETE:
13257 		port_flow_template_table_resize_complete
13258 			(in->port, in->args.table_destroy.table_id[0]);
13259 		break;
13260 	case GROUP_SET_MISS_ACTIONS:
13261 		port_queue_group_set_miss_actions(in->port, &in->args.vc.attr,
13262 						  in->args.vc.actions);
13263 		break;
13264 	case TABLE_RESIZE:
13265 		port_flow_template_table_resize(in->port, in->args.table.id,
13266 						in->args.table.attr.nb_flows);
13267 		break;
13268 	case QUEUE_CREATE:
13269 		port_queue_flow_create(in->port, in->queue, in->postpone,
13270 			in->args.vc.table_id, in->args.vc.rule_id,
13271 			in->args.vc.pat_templ_id, in->args.vc.act_templ_id,
13272 			in->args.vc.pattern, in->args.vc.actions);
13273 		break;
13274 	case QUEUE_DESTROY:
13275 		port_queue_flow_destroy(in->port, in->queue, in->postpone,
13276 					in->args.destroy.rule_n,
13277 					in->args.destroy.rule);
13278 		break;
13279 	case QUEUE_FLOW_UPDATE_RESIZED:
13280 		port_queue_flow_update_resized(in->port, in->queue,
13281 					       in->postpone,
13282 					       in->args.destroy.rule[0]);
13283 		break;
13284 	case QUEUE_UPDATE:
13285 		port_queue_flow_update(in->port, in->queue, in->postpone,
13286 				in->args.vc.rule_id, in->args.vc.act_templ_id,
13287 				in->args.vc.actions);
13288 		break;
13289 	case PUSH:
13290 		port_queue_flow_push(in->port, in->queue);
13291 		break;
13292 	case PULL:
13293 		port_queue_flow_pull(in->port, in->queue);
13294 		break;
13295 	case HASH:
13296 		if (!in->args.vc.encap_hash)
13297 			port_flow_hash_calc(in->port, in->args.vc.table_id,
13298 					    in->args.vc.pat_templ_id,
13299 					    in->args.vc.pattern);
13300 		else
13301 			port_flow_hash_calc_encap(in->port, in->args.vc.field,
13302 						  in->args.vc.pattern);
13303 		break;
13304 	case QUEUE_AGED:
13305 		port_queue_flow_aged(in->port, in->queue,
13306 				     in->args.aged.destroy);
13307 		break;
13308 	case QUEUE_INDIRECT_ACTION_CREATE:
13309 	case QUEUE_INDIRECT_ACTION_LIST_CREATE:
13310 		port_queue_action_handle_create(
13311 				in->port, in->queue, in->postpone,
13312 				in->args.vc.attr.group,
13313 				in->command == QUEUE_INDIRECT_ACTION_LIST_CREATE,
13314 				&((const struct rte_flow_indir_action_conf) {
13315 					.ingress = in->args.vc.attr.ingress,
13316 					.egress = in->args.vc.attr.egress,
13317 					.transfer = in->args.vc.attr.transfer,
13318 				}),
13319 				in->args.vc.actions);
13320 		break;
13321 	case QUEUE_INDIRECT_ACTION_DESTROY:
13322 		port_queue_action_handle_destroy(in->port,
13323 					   in->queue, in->postpone,
13324 					   in->args.ia_destroy.action_id_n,
13325 					   in->args.ia_destroy.action_id);
13326 		break;
13327 	case QUEUE_INDIRECT_ACTION_UPDATE:
13328 		port_queue_action_handle_update(in->port,
13329 						in->queue, in->postpone,
13330 						in->args.vc.attr.group,
13331 						in->args.vc.actions);
13332 		break;
13333 	case QUEUE_INDIRECT_ACTION_QUERY:
13334 		port_queue_action_handle_query(in->port,
13335 					       in->queue, in->postpone,
13336 					       in->args.ia.action_id);
13337 		break;
13338 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
13339 		port_queue_action_handle_query_update(in->port, in->queue,
13340 						      in->postpone,
13341 						      in->args.ia.action_id,
13342 						      in->args.ia.qu_mode,
13343 						      in->args.vc.actions);
13344 		break;
13345 	case INDIRECT_ACTION_CREATE:
13346 	case INDIRECT_ACTION_LIST_CREATE:
13347 		port_action_handle_create(
13348 				in->port, in->args.vc.attr.group,
13349 				in->command == INDIRECT_ACTION_LIST_CREATE,
13350 				&((const struct rte_flow_indir_action_conf) {
13351 					.ingress = in->args.vc.attr.ingress,
13352 					.egress = in->args.vc.attr.egress,
13353 					.transfer = in->args.vc.attr.transfer,
13354 				}),
13355 				in->args.vc.actions);
13356 		break;
13357 	case INDIRECT_ACTION_FLOW_CONF_CREATE:
13358 		indirect_action_flow_conf_create(in);
13359 		break;
13360 	case INDIRECT_ACTION_DESTROY:
13361 		port_action_handle_destroy(in->port,
13362 					   in->args.ia_destroy.action_id_n,
13363 					   in->args.ia_destroy.action_id);
13364 		break;
13365 	case INDIRECT_ACTION_UPDATE:
13366 		port_action_handle_update(in->port, in->args.vc.attr.group,
13367 					  in->args.vc.actions);
13368 		break;
13369 	case INDIRECT_ACTION_QUERY:
13370 		port_action_handle_query(in->port, in->args.ia.action_id);
13371 		break;
13372 	case INDIRECT_ACTION_QUERY_UPDATE:
13373 		port_action_handle_query_update(in->port,
13374 						in->args.ia.action_id,
13375 						in->args.ia.qu_mode,
13376 						in->args.vc.actions);
13377 		break;
13378 	case VALIDATE:
13379 		port_flow_validate(in->port, &in->args.vc.attr,
13380 				   in->args.vc.pattern, in->args.vc.actions,
13381 				   &in->args.vc.tunnel_ops);
13382 		break;
13383 	case CREATE:
13384 		port_flow_create(in->port, &in->args.vc.attr,
13385 				 in->args.vc.pattern, in->args.vc.actions,
13386 				 &in->args.vc.tunnel_ops, in->args.vc.user_id);
13387 		break;
13388 	case DESTROY:
13389 		port_flow_destroy(in->port, in->args.destroy.rule_n,
13390 				  in->args.destroy.rule,
13391 				  in->args.destroy.is_user_id);
13392 		break;
13393 	case UPDATE:
13394 		port_flow_update(in->port, in->args.vc.rule_id,
13395 				 in->args.vc.actions, in->args.vc.user_id);
13396 		break;
13397 	case FLUSH:
13398 		port_flow_flush(in->port);
13399 		break;
13400 	case DUMP_ONE:
13401 	case DUMP_ALL:
13402 		port_flow_dump(in->port, in->args.dump.mode,
13403 				in->args.dump.rule, in->args.dump.file,
13404 				in->args.dump.is_user_id);
13405 		break;
13406 	case QUERY:
13407 		port_flow_query(in->port, in->args.query.rule,
13408 				&in->args.query.action,
13409 				in->args.query.is_user_id);
13410 		break;
13411 	case LIST:
13412 		port_flow_list(in->port, in->args.list.group_n,
13413 			       in->args.list.group);
13414 		break;
13415 	case ISOLATE:
13416 		port_flow_isolate(in->port, in->args.isolate.set);
13417 		break;
13418 	case AGED:
13419 		port_flow_aged(in->port, in->args.aged.destroy);
13420 		break;
13421 	case TUNNEL_CREATE:
13422 		port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
13423 		break;
13424 	case TUNNEL_DESTROY:
13425 		port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
13426 		break;
13427 	case TUNNEL_LIST:
13428 		port_flow_tunnel_list(in->port);
13429 		break;
13430 	case ACTION_POL_G:
13431 		port_meter_policy_add(in->port, in->args.policy.policy_id,
13432 					in->args.vc.actions);
13433 		break;
13434 	case FLEX_ITEM_CREATE:
13435 		flex_item_create(in->port, in->args.flex.token,
13436 				 in->args.flex.filename);
13437 		break;
13438 	case FLEX_ITEM_DESTROY:
13439 		flex_item_destroy(in->port, in->args.flex.token);
13440 		break;
13441 	default:
13442 		break;
13443 	}
13444 	fflush(stdout);
13445 }
13446 
13447 /** Token generator and output processing callback (cmdline API). */
13448 static void
13449 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
13450 {
13451 	if (cl == NULL)
13452 		cmd_flow_tok(arg0, arg2);
13453 	else
13454 		cmd_flow_parsed(arg0);
13455 }
13456 
13457 /** Global parser instance (cmdline API). */
13458 cmdline_parse_inst_t cmd_flow = {
13459 	.f = cmd_flow_cb,
13460 	.data = NULL, /**< Unused. */
13461 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
13462 	.tokens = {
13463 		NULL,
13464 	}, /**< Tokens are returned by cmd_flow_tok(). */
13465 };
13466 
13467 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
13468 
13469 static void
13470 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
13471 {
13472 	struct rte_ipv4_hdr *ipv4;
13473 	struct rte_ether_hdr *eth;
13474 	struct rte_ipv6_hdr *ipv6;
13475 	struct rte_vxlan_hdr *vxlan;
13476 	struct rte_vxlan_gpe_hdr *gpe;
13477 	struct rte_flow_item_nvgre *nvgre;
13478 	uint32_t ipv6_vtc_flow;
13479 
13480 	switch (item->type) {
13481 	case RTE_FLOW_ITEM_TYPE_ETH:
13482 		eth = (struct rte_ether_hdr *)buf;
13483 		if (next_proto)
13484 			eth->ether_type = rte_cpu_to_be_16(next_proto);
13485 		break;
13486 	case RTE_FLOW_ITEM_TYPE_IPV4:
13487 		ipv4 = (struct rte_ipv4_hdr *)buf;
13488 		if (!ipv4->version_ihl)
13489 			ipv4->version_ihl = RTE_IPV4_VHL_DEF;
13490 		if (next_proto && ipv4->next_proto_id == 0)
13491 			ipv4->next_proto_id = (uint8_t)next_proto;
13492 		break;
13493 	case RTE_FLOW_ITEM_TYPE_IPV6:
13494 		ipv6 = (struct rte_ipv6_hdr *)buf;
13495 		if (next_proto && ipv6->proto == 0)
13496 			ipv6->proto = (uint8_t)next_proto;
13497 		ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
13498 		ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
13499 		ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
13500 		ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
13501 		break;
13502 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13503 		vxlan = (struct rte_vxlan_hdr *)buf;
13504 		vxlan->vx_flags = 0x08;
13505 		break;
13506 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13507 		gpe = (struct rte_vxlan_gpe_hdr *)buf;
13508 		gpe->vx_flags = 0x0C;
13509 		break;
13510 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13511 		nvgre = (struct rte_flow_item_nvgre *)buf;
13512 		nvgre->protocol = rte_cpu_to_be_16(0x6558);
13513 		nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
13514 		break;
13515 	default:
13516 		break;
13517 	}
13518 }
13519 
13520 /** Helper of get item's default mask. */
13521 static const void *
13522 flow_item_default_mask(const struct rte_flow_item *item)
13523 {
13524 	const void *mask = NULL;
13525 	static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
13526 	static struct rte_flow_item_ipv6_routing_ext ipv6_routing_ext_default_mask = {
13527 		.hdr = {
13528 			.next_hdr = 0xff,
13529 			.type = 0xff,
13530 			.segments_left = 0xff,
13531 		},
13532 	};
13533 
13534 	switch (item->type) {
13535 	case RTE_FLOW_ITEM_TYPE_ANY:
13536 		mask = &rte_flow_item_any_mask;
13537 		break;
13538 	case RTE_FLOW_ITEM_TYPE_PORT_ID:
13539 		mask = &rte_flow_item_port_id_mask;
13540 		break;
13541 	case RTE_FLOW_ITEM_TYPE_RAW:
13542 		mask = &rte_flow_item_raw_mask;
13543 		break;
13544 	case RTE_FLOW_ITEM_TYPE_ETH:
13545 		mask = &rte_flow_item_eth_mask;
13546 		break;
13547 	case RTE_FLOW_ITEM_TYPE_VLAN:
13548 		mask = &rte_flow_item_vlan_mask;
13549 		break;
13550 	case RTE_FLOW_ITEM_TYPE_IPV4:
13551 		mask = &rte_flow_item_ipv4_mask;
13552 		break;
13553 	case RTE_FLOW_ITEM_TYPE_IPV6:
13554 		mask = &rte_flow_item_ipv6_mask;
13555 		break;
13556 	case RTE_FLOW_ITEM_TYPE_ICMP:
13557 		mask = &rte_flow_item_icmp_mask;
13558 		break;
13559 	case RTE_FLOW_ITEM_TYPE_UDP:
13560 		mask = &rte_flow_item_udp_mask;
13561 		break;
13562 	case RTE_FLOW_ITEM_TYPE_TCP:
13563 		mask = &rte_flow_item_tcp_mask;
13564 		break;
13565 	case RTE_FLOW_ITEM_TYPE_SCTP:
13566 		mask = &rte_flow_item_sctp_mask;
13567 		break;
13568 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13569 		mask = &rte_flow_item_vxlan_mask;
13570 		break;
13571 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13572 		mask = &rte_flow_item_vxlan_gpe_mask;
13573 		break;
13574 	case RTE_FLOW_ITEM_TYPE_E_TAG:
13575 		mask = &rte_flow_item_e_tag_mask;
13576 		break;
13577 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13578 		mask = &rte_flow_item_nvgre_mask;
13579 		break;
13580 	case RTE_FLOW_ITEM_TYPE_MPLS:
13581 		mask = &rte_flow_item_mpls_mask;
13582 		break;
13583 	case RTE_FLOW_ITEM_TYPE_GRE:
13584 		mask = &rte_flow_item_gre_mask;
13585 		break;
13586 	case RTE_FLOW_ITEM_TYPE_GRE_KEY:
13587 		mask = &gre_key_default_mask;
13588 		break;
13589 	case RTE_FLOW_ITEM_TYPE_META:
13590 		mask = &rte_flow_item_meta_mask;
13591 		break;
13592 	case RTE_FLOW_ITEM_TYPE_RANDOM:
13593 		mask = &rte_flow_item_random_mask;
13594 		break;
13595 	case RTE_FLOW_ITEM_TYPE_FUZZY:
13596 		mask = &rte_flow_item_fuzzy_mask;
13597 		break;
13598 	case RTE_FLOW_ITEM_TYPE_GTP:
13599 		mask = &rte_flow_item_gtp_mask;
13600 		break;
13601 	case RTE_FLOW_ITEM_TYPE_GTP_PSC:
13602 		mask = &rte_flow_item_gtp_psc_mask;
13603 		break;
13604 	case RTE_FLOW_ITEM_TYPE_GENEVE:
13605 		mask = &rte_flow_item_geneve_mask;
13606 		break;
13607 	case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
13608 		mask = &rte_flow_item_geneve_opt_mask;
13609 		break;
13610 	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
13611 		mask = &rte_flow_item_pppoe_proto_id_mask;
13612 		break;
13613 	case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
13614 		mask = &rte_flow_item_l2tpv3oip_mask;
13615 		break;
13616 	case RTE_FLOW_ITEM_TYPE_ESP:
13617 		mask = &rte_flow_item_esp_mask;
13618 		break;
13619 	case RTE_FLOW_ITEM_TYPE_AH:
13620 		mask = &rte_flow_item_ah_mask;
13621 		break;
13622 	case RTE_FLOW_ITEM_TYPE_PFCP:
13623 		mask = &rte_flow_item_pfcp_mask;
13624 		break;
13625 	case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
13626 	case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
13627 		mask = &rte_flow_item_ethdev_mask;
13628 		break;
13629 	case RTE_FLOW_ITEM_TYPE_L2TPV2:
13630 		mask = &rte_flow_item_l2tpv2_mask;
13631 		break;
13632 	case RTE_FLOW_ITEM_TYPE_PPP:
13633 		mask = &rte_flow_item_ppp_mask;
13634 		break;
13635 	case RTE_FLOW_ITEM_TYPE_METER_COLOR:
13636 		mask = &rte_flow_item_meter_color_mask;
13637 		break;
13638 	case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13639 		mask = &ipv6_routing_ext_default_mask;
13640 		break;
13641 	case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
13642 		mask = &rte_flow_item_aggr_affinity_mask;
13643 		break;
13644 	case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
13645 		mask = &rte_flow_item_tx_queue_mask;
13646 		break;
13647 	case RTE_FLOW_ITEM_TYPE_IB_BTH:
13648 		mask = &rte_flow_item_ib_bth_mask;
13649 		break;
13650 	case RTE_FLOW_ITEM_TYPE_PTYPE:
13651 		mask = &rte_flow_item_ptype_mask;
13652 		break;
13653 	default:
13654 		break;
13655 	}
13656 	return mask;
13657 }
13658 
13659 /** Dispatch parsed buffer to function calls. */
13660 static void
13661 cmd_set_ipv6_ext_parsed(const struct buffer *in)
13662 {
13663 	uint32_t n = in->args.vc.pattern_n;
13664 	int i = 0;
13665 	struct rte_flow_item *item = NULL;
13666 	size_t size = 0;
13667 	uint8_t *data = NULL;
13668 	uint8_t *type = NULL;
13669 	size_t *total_size = NULL;
13670 	uint16_t idx = in->port; /* We borrow port field as index */
13671 	struct rte_flow_item_ipv6_routing_ext *ext;
13672 	const struct rte_flow_item_ipv6_ext *ipv6_ext;
13673 
13674 	RTE_ASSERT(in->command == SET_IPV6_EXT_PUSH ||
13675 		   in->command == SET_IPV6_EXT_REMOVE);
13676 
13677 	if (in->command == SET_IPV6_EXT_REMOVE) {
13678 		if (n != 1 || in->args.vc.pattern->type !=
13679 		    RTE_FLOW_ITEM_TYPE_IPV6_EXT) {
13680 			fprintf(stderr, "Error - Not supported item\n");
13681 			return;
13682 		}
13683 		type = (uint8_t *)&ipv6_ext_remove_confs[idx].type;
13684 		item = in->args.vc.pattern;
13685 		ipv6_ext = item->spec;
13686 		*type = ipv6_ext->next_hdr;
13687 		return;
13688 	}
13689 
13690 	total_size = &ipv6_ext_push_confs[idx].size;
13691 	data = (uint8_t *)&ipv6_ext_push_confs[idx].data;
13692 	type = (uint8_t *)&ipv6_ext_push_confs[idx].type;
13693 
13694 	*total_size = 0;
13695 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13696 	for (i = n - 1 ; i >= 0; --i) {
13697 		item = in->args.vc.pattern + i;
13698 		switch (item->type) {
13699 		case RTE_FLOW_ITEM_TYPE_IPV6_EXT:
13700 			ipv6_ext = item->spec;
13701 			*type = ipv6_ext->next_hdr;
13702 			break;
13703 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13704 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13705 			if (!ext->hdr.hdr_len) {
13706 				size = sizeof(struct rte_ipv6_routing_ext) +
13707 				(ext->hdr.segments_left << 4);
13708 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
13709 				/* Indicate no TLV once SRH. */
13710 				if (ext->hdr.type == 4)
13711 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
13712 			} else {
13713 				size = sizeof(struct rte_ipv6_routing_ext) +
13714 				(ext->hdr.hdr_len << 3);
13715 			}
13716 			*total_size += size;
13717 			memcpy(data, ext, size);
13718 			break;
13719 		default:
13720 			fprintf(stderr, "Error - Not supported item\n");
13721 			goto error;
13722 		}
13723 	}
13724 	RTE_ASSERT((*total_size) <= ACTION_IPV6_EXT_PUSH_MAX_DATA);
13725 	return;
13726 error:
13727 	*total_size = 0;
13728 	memset(data, 0x00, ACTION_IPV6_EXT_PUSH_MAX_DATA);
13729 }
13730 
13731 /** Dispatch parsed buffer to function calls. */
13732 static void
13733 cmd_set_raw_parsed_sample(const struct buffer *in)
13734 {
13735 	uint32_t n = in->args.vc.actions_n;
13736 	uint32_t i = 0;
13737 	struct rte_flow_action *action = NULL;
13738 	struct rte_flow_action *data = NULL;
13739 	const struct rte_flow_action_rss *rss = NULL;
13740 	size_t size = 0;
13741 	uint16_t idx = in->port; /* We borrow port field as index */
13742 	uint32_t max_size = sizeof(struct rte_flow_action) *
13743 						ACTION_SAMPLE_ACTIONS_NUM;
13744 
13745 	RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
13746 	data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
13747 	memset(data, 0x00, max_size);
13748 	for (; i <= n - 1; i++) {
13749 		action = in->args.vc.actions + i;
13750 		if (action->type == RTE_FLOW_ACTION_TYPE_END)
13751 			break;
13752 		switch (action->type) {
13753 		case RTE_FLOW_ACTION_TYPE_MARK:
13754 			size = sizeof(struct rte_flow_action_mark);
13755 			rte_memcpy(&sample_mark[idx],
13756 				(const void *)action->conf, size);
13757 			action->conf = &sample_mark[idx];
13758 			break;
13759 		case RTE_FLOW_ACTION_TYPE_COUNT:
13760 			size = sizeof(struct rte_flow_action_count);
13761 			rte_memcpy(&sample_count[idx],
13762 				(const void *)action->conf, size);
13763 			action->conf = &sample_count[idx];
13764 			break;
13765 		case RTE_FLOW_ACTION_TYPE_QUEUE:
13766 			size = sizeof(struct rte_flow_action_queue);
13767 			rte_memcpy(&sample_queue[idx],
13768 				(const void *)action->conf, size);
13769 			action->conf = &sample_queue[idx];
13770 			break;
13771 		case RTE_FLOW_ACTION_TYPE_RSS:
13772 			size = sizeof(struct rte_flow_action_rss);
13773 			rss = action->conf;
13774 			rte_memcpy(&sample_rss_data[idx].conf,
13775 				   (const void *)rss, size);
13776 			if (rss->key_len && rss->key) {
13777 				sample_rss_data[idx].conf.key =
13778 						sample_rss_data[idx].key;
13779 				rte_memcpy((void *)((uintptr_t)
13780 					   sample_rss_data[idx].conf.key),
13781 					   (const void *)rss->key,
13782 					   sizeof(uint8_t) * rss->key_len);
13783 			}
13784 			if (rss->queue_num && rss->queue) {
13785 				sample_rss_data[idx].conf.queue =
13786 						sample_rss_data[idx].queue;
13787 				rte_memcpy((void *)((uintptr_t)
13788 					   sample_rss_data[idx].conf.queue),
13789 					   (const void *)rss->queue,
13790 					   sizeof(uint16_t) * rss->queue_num);
13791 			}
13792 			action->conf = &sample_rss_data[idx].conf;
13793 			break;
13794 		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
13795 			size = sizeof(struct rte_flow_action_raw_encap);
13796 			rte_memcpy(&sample_encap[idx],
13797 				(const void *)action->conf, size);
13798 			action->conf = &sample_encap[idx];
13799 			break;
13800 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
13801 			size = sizeof(struct rte_flow_action_port_id);
13802 			rte_memcpy(&sample_port_id[idx],
13803 				(const void *)action->conf, size);
13804 			action->conf = &sample_port_id[idx];
13805 			break;
13806 		case RTE_FLOW_ACTION_TYPE_PF:
13807 			break;
13808 		case RTE_FLOW_ACTION_TYPE_VF:
13809 			size = sizeof(struct rte_flow_action_vf);
13810 			rte_memcpy(&sample_vf[idx],
13811 					(const void *)action->conf, size);
13812 			action->conf = &sample_vf[idx];
13813 			break;
13814 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
13815 			size = sizeof(struct rte_flow_action_vxlan_encap);
13816 			parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
13817 			action->conf = &sample_vxlan_encap[idx].conf;
13818 			break;
13819 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
13820 			size = sizeof(struct rte_flow_action_nvgre_encap);
13821 			parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
13822 			action->conf = &sample_nvgre_encap[idx];
13823 			break;
13824 		case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
13825 			size = sizeof(struct rte_flow_action_ethdev);
13826 			rte_memcpy(&sample_port_representor[idx],
13827 					(const void *)action->conf, size);
13828 			action->conf = &sample_port_representor[idx];
13829 			break;
13830 		case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
13831 			size = sizeof(struct rte_flow_action_ethdev);
13832 			rte_memcpy(&sample_represented_port[idx],
13833 					(const void *)action->conf, size);
13834 			action->conf = &sample_represented_port[idx];
13835 			break;
13836 		default:
13837 			fprintf(stderr, "Error - Not supported action\n");
13838 			return;
13839 		}
13840 		rte_memcpy(data, action, sizeof(struct rte_flow_action));
13841 		data++;
13842 	}
13843 }
13844 
13845 /** Dispatch parsed buffer to function calls. */
13846 static void
13847 cmd_set_raw_parsed(const struct buffer *in)
13848 {
13849 	uint32_t n = in->args.vc.pattern_n;
13850 	int i = 0;
13851 	struct rte_flow_item *item = NULL;
13852 	size_t size = 0;
13853 	uint8_t *data = NULL;
13854 	uint8_t *data_tail = NULL;
13855 	size_t *total_size = NULL;
13856 	uint16_t upper_layer = 0;
13857 	uint16_t proto = 0;
13858 	uint16_t idx = in->port; /* We borrow port field as index */
13859 	int gtp_psc = -1; /* GTP PSC option index. */
13860 	const void *src_spec;
13861 
13862 	if (in->command == SET_SAMPLE_ACTIONS)
13863 		return cmd_set_raw_parsed_sample(in);
13864 	else if (in->command == SET_IPV6_EXT_PUSH ||
13865 		 in->command == SET_IPV6_EXT_REMOVE)
13866 		return cmd_set_ipv6_ext_parsed(in);
13867 	RTE_ASSERT(in->command == SET_RAW_ENCAP ||
13868 		   in->command == SET_RAW_DECAP);
13869 	if (in->command == SET_RAW_ENCAP) {
13870 		total_size = &raw_encap_confs[idx].size;
13871 		data = (uint8_t *)&raw_encap_confs[idx].data;
13872 	} else {
13873 		total_size = &raw_decap_confs[idx].size;
13874 		data = (uint8_t *)&raw_decap_confs[idx].data;
13875 	}
13876 	*total_size = 0;
13877 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13878 	/* process hdr from upper layer to low layer (L3/L4 -> L2). */
13879 	data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
13880 	for (i = n - 1 ; i >= 0; --i) {
13881 		const struct rte_flow_item_gtp *gtp;
13882 		const struct rte_flow_item_geneve_opt *opt;
13883 		struct rte_flow_item_ipv6_routing_ext *ext;
13884 
13885 		item = in->args.vc.pattern + i;
13886 		if (item->spec == NULL)
13887 			item->spec = flow_item_default_mask(item);
13888 		src_spec = item->spec;
13889 		switch (item->type) {
13890 		case RTE_FLOW_ITEM_TYPE_ETH:
13891 			size = sizeof(struct rte_ether_hdr);
13892 			break;
13893 		case RTE_FLOW_ITEM_TYPE_VLAN:
13894 			size = sizeof(struct rte_vlan_hdr);
13895 			proto = RTE_ETHER_TYPE_VLAN;
13896 			break;
13897 		case RTE_FLOW_ITEM_TYPE_IPV4:
13898 			size = sizeof(struct rte_ipv4_hdr);
13899 			proto = RTE_ETHER_TYPE_IPV4;
13900 			break;
13901 		case RTE_FLOW_ITEM_TYPE_IPV6:
13902 			size = sizeof(struct rte_ipv6_hdr);
13903 			proto = RTE_ETHER_TYPE_IPV6;
13904 			break;
13905 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13906 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13907 			if (!ext->hdr.hdr_len) {
13908 				size = sizeof(struct rte_ipv6_routing_ext) +
13909 					(ext->hdr.segments_left << 4);
13910 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
13911 				/* SRv6 without TLV. */
13912 				if (ext->hdr.type == RTE_IPV6_SRCRT_TYPE_4)
13913 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
13914 			} else {
13915 				size = sizeof(struct rte_ipv6_routing_ext) +
13916 					(ext->hdr.hdr_len << 3);
13917 			}
13918 			proto = IPPROTO_ROUTING;
13919 			break;
13920 		case RTE_FLOW_ITEM_TYPE_UDP:
13921 			size = sizeof(struct rte_udp_hdr);
13922 			proto = 0x11;
13923 			break;
13924 		case RTE_FLOW_ITEM_TYPE_TCP:
13925 			size = sizeof(struct rte_tcp_hdr);
13926 			proto = 0x06;
13927 			break;
13928 		case RTE_FLOW_ITEM_TYPE_VXLAN:
13929 			size = sizeof(struct rte_vxlan_hdr);
13930 			break;
13931 		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13932 			size = sizeof(struct rte_vxlan_gpe_hdr);
13933 			break;
13934 		case RTE_FLOW_ITEM_TYPE_GRE:
13935 			size = sizeof(struct rte_gre_hdr);
13936 			proto = 0x2F;
13937 			break;
13938 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
13939 			size = sizeof(rte_be32_t);
13940 			proto = 0x0;
13941 			break;
13942 		case RTE_FLOW_ITEM_TYPE_MPLS:
13943 			size = sizeof(struct rte_mpls_hdr);
13944 			proto = 0x0;
13945 			break;
13946 		case RTE_FLOW_ITEM_TYPE_NVGRE:
13947 			size = sizeof(struct rte_flow_item_nvgre);
13948 			proto = 0x2F;
13949 			break;
13950 		case RTE_FLOW_ITEM_TYPE_GENEVE:
13951 			size = sizeof(struct rte_geneve_hdr);
13952 			break;
13953 		case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
13954 			opt = (const struct rte_flow_item_geneve_opt *)
13955 								item->spec;
13956 			size = offsetof(struct rte_flow_item_geneve_opt,
13957 					option_len) + sizeof(uint8_t);
13958 			if (opt->option_len && opt->data) {
13959 				*total_size += opt->option_len *
13960 					       sizeof(uint32_t);
13961 				rte_memcpy(data_tail - (*total_size),
13962 					   opt->data,
13963 					   opt->option_len * sizeof(uint32_t));
13964 			}
13965 			break;
13966 		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
13967 			size = sizeof(rte_be32_t);
13968 			proto = 0x73;
13969 			break;
13970 		case RTE_FLOW_ITEM_TYPE_ESP:
13971 			size = sizeof(struct rte_esp_hdr);
13972 			proto = 0x32;
13973 			break;
13974 		case RTE_FLOW_ITEM_TYPE_AH:
13975 			size = sizeof(struct rte_flow_item_ah);
13976 			proto = 0x33;
13977 			break;
13978 		case RTE_FLOW_ITEM_TYPE_GTP:
13979 			if (gtp_psc < 0) {
13980 				size = sizeof(struct rte_gtp_hdr);
13981 				break;
13982 			}
13983 			if (gtp_psc != i + 1) {
13984 				fprintf(stderr,
13985 					"Error - GTP PSC does not follow GTP\n");
13986 				goto error;
13987 			}
13988 			gtp = item->spec;
13989 			if (gtp->hdr.s == 1 || gtp->hdr.pn == 1) {
13990 				/* Only E flag should be set. */
13991 				fprintf(stderr,
13992 					"Error - GTP unsupported flags\n");
13993 				goto error;
13994 			} else {
13995 				struct rte_gtp_hdr_ext_word ext_word = {
13996 					.next_ext = 0x85
13997 				};
13998 
13999 				/* We have to add GTP header extra word. */
14000 				*total_size += sizeof(ext_word);
14001 				rte_memcpy(data_tail - (*total_size),
14002 					   &ext_word, sizeof(ext_word));
14003 			}
14004 			size = sizeof(struct rte_gtp_hdr);
14005 			break;
14006 		case RTE_FLOW_ITEM_TYPE_GTP_PSC:
14007 			if (gtp_psc >= 0) {
14008 				fprintf(stderr,
14009 					"Error - Multiple GTP PSC items\n");
14010 				goto error;
14011 			} else {
14012 				const struct rte_flow_item_gtp_psc
14013 					*opt = item->spec;
14014 				struct rte_gtp_psc_generic_hdr *hdr;
14015 				size_t hdr_size = RTE_ALIGN(sizeof(*hdr),
14016 							 sizeof(int32_t));
14017 
14018 				*total_size += hdr_size;
14019 				hdr = (typeof(hdr))(data_tail - (*total_size));
14020 				memset(hdr, 0, hdr_size);
14021 				*hdr = opt->hdr;
14022 				hdr->ext_hdr_len = 1;
14023 				gtp_psc = i;
14024 				size = 0;
14025 			}
14026 			break;
14027 		case RTE_FLOW_ITEM_TYPE_PFCP:
14028 			size = sizeof(struct rte_flow_item_pfcp);
14029 			break;
14030 		case RTE_FLOW_ITEM_TYPE_FLEX:
14031 			if (item->spec != NULL) {
14032 				size = ((const struct rte_flow_item_flex *)item->spec)->length;
14033 				src_spec = ((const struct rte_flow_item_flex *)item->spec)->pattern;
14034 			} else {
14035 				size = 0;
14036 				src_spec = NULL;
14037 			}
14038 			break;
14039 		case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
14040 			size = 0;
14041 			if (item->spec) {
14042 				const struct rte_flow_item_gre_opt
14043 					*opt = item->spec;
14044 				if (opt->checksum_rsvd.checksum) {
14045 					*total_size +=
14046 						sizeof(opt->checksum_rsvd);
14047 					rte_memcpy(data_tail - (*total_size),
14048 						   &opt->checksum_rsvd,
14049 						   sizeof(opt->checksum_rsvd));
14050 				}
14051 				if (opt->key.key) {
14052 					*total_size += sizeof(opt->key.key);
14053 					rte_memcpy(data_tail - (*total_size),
14054 						   &opt->key.key,
14055 						   sizeof(opt->key.key));
14056 				}
14057 				if (opt->sequence.sequence) {
14058 					*total_size += sizeof(opt->sequence.sequence);
14059 					rte_memcpy(data_tail - (*total_size),
14060 						   &opt->sequence.sequence,
14061 						   sizeof(opt->sequence.sequence));
14062 				}
14063 			}
14064 			proto = 0x2F;
14065 			break;
14066 		default:
14067 			fprintf(stderr, "Error - Not supported item\n");
14068 			goto error;
14069 		}
14070 		if (size) {
14071 			*total_size += size;
14072 			rte_memcpy(data_tail - (*total_size), src_spec, size);
14073 			/* update some fields which cannot be set by cmdline */
14074 			update_fields((data_tail - (*total_size)), item,
14075 				      upper_layer);
14076 			upper_layer = proto;
14077 		}
14078 	}
14079 	if (verbose_level & 0x1)
14080 		printf("total data size is %zu\n", (*total_size));
14081 	RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
14082 	memmove(data, (data_tail - (*total_size)), *total_size);
14083 	return;
14084 
14085 error:
14086 	*total_size = 0;
14087 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
14088 }
14089 
14090 /** Populate help strings for current token (cmdline API). */
14091 static int
14092 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
14093 		     unsigned int size)
14094 {
14095 	struct context *ctx = &cmd_flow_context;
14096 	const struct token *token = &token_list[ctx->prev];
14097 
14098 	(void)hdr;
14099 	if (!size)
14100 		return -1;
14101 	/* Set token type and update global help with details. */
14102 	snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
14103 	if (token->help)
14104 		cmd_set_raw.help_str = token->help;
14105 	else
14106 		cmd_set_raw.help_str = token->name;
14107 	return 0;
14108 }
14109 
14110 /** Token definition template (cmdline API). */
14111 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
14112 	.ops = &(struct cmdline_token_ops){
14113 		.parse = cmd_flow_parse,
14114 		.complete_get_nb = cmd_flow_complete_get_nb,
14115 		.complete_get_elt = cmd_flow_complete_get_elt,
14116 		.get_help = cmd_set_raw_get_help,
14117 	},
14118 	.offset = 0,
14119 };
14120 
14121 /** Populate the next dynamic token. */
14122 static void
14123 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
14124 	     cmdline_parse_token_hdr_t **hdr_inst)
14125 {
14126 	struct context *ctx = &cmd_flow_context;
14127 
14128 	/* Always reinitialize context before requesting the first token. */
14129 	if (!(hdr_inst - cmd_set_raw.tokens)) {
14130 		cmd_flow_context_init(ctx);
14131 		ctx->curr = START_SET;
14132 	}
14133 	/* Return NULL when no more tokens are expected. */
14134 	if (!ctx->next_num && (ctx->curr != START_SET)) {
14135 		*hdr = NULL;
14136 		return;
14137 	}
14138 	/* Determine if command should end here. */
14139 	if (ctx->eol && ctx->last && ctx->next_num) {
14140 		const enum index *list = ctx->next[ctx->next_num - 1];
14141 		int i;
14142 
14143 		for (i = 0; list[i]; ++i) {
14144 			if (list[i] != END)
14145 				continue;
14146 			*hdr = NULL;
14147 			return;
14148 		}
14149 	}
14150 	*hdr = &cmd_set_raw_token_hdr;
14151 }
14152 
14153 /** Token generator and output processing callback (cmdline API). */
14154 static void
14155 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
14156 {
14157 	if (cl == NULL)
14158 		cmd_set_raw_tok(arg0, arg2);
14159 	else
14160 		cmd_set_raw_parsed(arg0);
14161 }
14162 
14163 /** Global parser instance (cmdline API). */
14164 cmdline_parse_inst_t cmd_set_raw = {
14165 	.f = cmd_set_raw_cb,
14166 	.data = NULL, /**< Unused. */
14167 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
14168 	.tokens = {
14169 		NULL,
14170 	}, /**< Tokens are returned by cmd_flow_tok(). */
14171 };
14172 
14173 /* *** display raw_encap/raw_decap buf */
14174 struct cmd_show_set_raw_result {
14175 	cmdline_fixed_string_t cmd_show;
14176 	cmdline_fixed_string_t cmd_what;
14177 	cmdline_fixed_string_t cmd_all;
14178 	uint16_t cmd_index;
14179 };
14180 
14181 static void
14182 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
14183 {
14184 	struct cmd_show_set_raw_result *res = parsed_result;
14185 	uint16_t index = res->cmd_index;
14186 	uint8_t all = 0;
14187 	uint8_t *raw_data = NULL;
14188 	size_t raw_size = 0;
14189 	char title[16] = {0};
14190 
14191 	RTE_SET_USED(cl);
14192 	RTE_SET_USED(data);
14193 	if (!strcmp(res->cmd_all, "all")) {
14194 		all = 1;
14195 		index = 0;
14196 	} else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
14197 		fprintf(stderr, "index should be 0-%u\n",
14198 			RAW_ENCAP_CONFS_MAX_NUM - 1);
14199 		return;
14200 	}
14201 	do {
14202 		if (!strcmp(res->cmd_what, "raw_encap")) {
14203 			raw_data = (uint8_t *)&raw_encap_confs[index].data;
14204 			raw_size = raw_encap_confs[index].size;
14205 			snprintf(title, 16, "\nindex: %u", index);
14206 			rte_hexdump(stdout, title, raw_data, raw_size);
14207 		} else {
14208 			raw_data = (uint8_t *)&raw_decap_confs[index].data;
14209 			raw_size = raw_decap_confs[index].size;
14210 			snprintf(title, 16, "\nindex: %u", index);
14211 			rte_hexdump(stdout, title, raw_data, raw_size);
14212 		}
14213 	} while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
14214 }
14215 
14216 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
14217 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14218 			cmd_show, "show");
14219 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
14220 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14221 			cmd_what, "raw_encap#raw_decap");
14222 static cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
14223 	TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
14224 			cmd_index, RTE_UINT16);
14225 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
14226 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14227 			cmd_all, "all");
14228 cmdline_parse_inst_t cmd_show_set_raw = {
14229 	.f = cmd_show_set_raw_parsed,
14230 	.data = NULL,
14231 	.help_str = "show <raw_encap|raw_decap> <index>",
14232 	.tokens = {
14233 		(void *)&cmd_show_set_raw_cmd_show,
14234 		(void *)&cmd_show_set_raw_cmd_what,
14235 		(void *)&cmd_show_set_raw_cmd_index,
14236 		NULL,
14237 	},
14238 };
14239 cmdline_parse_inst_t cmd_show_set_raw_all = {
14240 	.f = cmd_show_set_raw_parsed,
14241 	.data = NULL,
14242 	.help_str = "show <raw_encap|raw_decap> all",
14243 	.tokens = {
14244 		(void *)&cmd_show_set_raw_cmd_show,
14245 		(void *)&cmd_show_set_raw_cmd_what,
14246 		(void *)&cmd_show_set_raw_cmd_all,
14247 		NULL,
14248 	},
14249 };
14250