xref: /dpdk/app/test-pmd/cmdline_flow.c (revision 1ec9a3afeb51465b23a2d4734bddd0c39581406b)
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 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
5867 			     item_param),
5868 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
5869 	},
5870 	[ITEM_PORT_REPRESENTOR] = {
5871 		.name = "port_representor",
5872 		.help = "match traffic entering the embedded switch from the given ethdev",
5873 		.priv = PRIV_ITEM(PORT_REPRESENTOR,
5874 				  sizeof(struct rte_flow_item_ethdev)),
5875 		.next = NEXT(item_port_representor),
5876 		.call = parse_vc,
5877 	},
5878 	[ITEM_PORT_REPRESENTOR_PORT_ID] = {
5879 		.name = "port_id",
5880 		.help = "ethdev port ID",
5881 		.next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
5882 			     item_param),
5883 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5884 	},
5885 	[ITEM_REPRESENTED_PORT] = {
5886 		.name = "represented_port",
5887 		.help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
5888 		.priv = PRIV_ITEM(REPRESENTED_PORT,
5889 				  sizeof(struct rte_flow_item_ethdev)),
5890 		.next = NEXT(item_represented_port),
5891 		.call = parse_vc,
5892 	},
5893 	[ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
5894 		.name = "ethdev_port_id",
5895 		.help = "ethdev port ID",
5896 		.next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
5897 			     item_param),
5898 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5899 	},
5900 	[ITEM_FLEX] = {
5901 		.name = "flex",
5902 		.help = "match flex header",
5903 		.priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
5904 		.next = NEXT(item_flex),
5905 		.call = parse_vc,
5906 	},
5907 	[ITEM_FLEX_ITEM_HANDLE] = {
5908 		.name = "item",
5909 		.help = "flex item handle",
5910 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5911 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5912 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
5913 	},
5914 	[ITEM_FLEX_PATTERN_HANDLE] = {
5915 		.name = "pattern",
5916 		.help = "flex pattern handle",
5917 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5918 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5919 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
5920 	},
5921 	[ITEM_L2TPV2] = {
5922 		.name = "l2tpv2",
5923 		.help = "match L2TPv2 header",
5924 		.priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
5925 		.next = NEXT(item_l2tpv2),
5926 		.call = parse_vc,
5927 	},
5928 	[ITEM_L2TPV2_TYPE] = {
5929 		.name = "type",
5930 		.help = "type of l2tpv2",
5931 		.next = NEXT(item_l2tpv2_type),
5932 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
5933 	},
5934 	[ITEM_L2TPV2_TYPE_DATA] = {
5935 		.name = "data",
5936 		.help = "Type #7: data message without any options",
5937 		.next = NEXT(item_l2tpv2_type_data),
5938 		.call = parse_vc_item_l2tpv2_type,
5939 	},
5940 	[ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
5941 		.name = "tunnel_id",
5942 		.help = "tunnel identifier",
5943 		.next = NEXT(item_l2tpv2_type_data,
5944 			     NEXT_ENTRY(COMMON_UNSIGNED),
5945 			     item_param),
5946 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5947 					     hdr.type7.tunnel_id)),
5948 	},
5949 	[ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
5950 		.name = "session_id",
5951 		.help = "session identifier",
5952 		.next = NEXT(item_l2tpv2_type_data,
5953 			     NEXT_ENTRY(COMMON_UNSIGNED),
5954 			     item_param),
5955 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5956 					     hdr.type7.session_id)),
5957 	},
5958 	[ITEM_L2TPV2_TYPE_DATA_L] = {
5959 		.name = "data_l",
5960 		.help = "Type #6: data message with length option",
5961 		.next = NEXT(item_l2tpv2_type_data_l),
5962 		.call = parse_vc_item_l2tpv2_type,
5963 	},
5964 	[ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
5965 		.name = "length",
5966 		.help = "message length",
5967 		.next = NEXT(item_l2tpv2_type_data_l,
5968 			     NEXT_ENTRY(COMMON_UNSIGNED),
5969 			     item_param),
5970 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5971 					     hdr.type6.length)),
5972 	},
5973 	[ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
5974 		.name = "tunnel_id",
5975 		.help = "tunnel identifier",
5976 		.next = NEXT(item_l2tpv2_type_data_l,
5977 			     NEXT_ENTRY(COMMON_UNSIGNED),
5978 			     item_param),
5979 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5980 					     hdr.type6.tunnel_id)),
5981 	},
5982 	[ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
5983 		.name = "session_id",
5984 		.help = "session identifier",
5985 		.next = NEXT(item_l2tpv2_type_data_l,
5986 			     NEXT_ENTRY(COMMON_UNSIGNED),
5987 			     item_param),
5988 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5989 					     hdr.type6.session_id)),
5990 	},
5991 	[ITEM_L2TPV2_TYPE_DATA_S] = {
5992 		.name = "data_s",
5993 		.help = "Type #5: data message with ns, nr option",
5994 		.next = NEXT(item_l2tpv2_type_data_s),
5995 		.call = parse_vc_item_l2tpv2_type,
5996 	},
5997 	[ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
5998 		.name = "tunnel_id",
5999 		.help = "tunnel identifier",
6000 		.next = NEXT(item_l2tpv2_type_data_s,
6001 			     NEXT_ENTRY(COMMON_UNSIGNED),
6002 			     item_param),
6003 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6004 					     hdr.type5.tunnel_id)),
6005 	},
6006 	[ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
6007 		.name = "session_id",
6008 		.help = "session identifier",
6009 		.next = NEXT(item_l2tpv2_type_data_s,
6010 			     NEXT_ENTRY(COMMON_UNSIGNED),
6011 			     item_param),
6012 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6013 					     hdr.type5.session_id)),
6014 	},
6015 	[ITEM_L2TPV2_MSG_DATA_S_NS] = {
6016 		.name = "ns",
6017 		.help = "sequence number for message",
6018 		.next = NEXT(item_l2tpv2_type_data_s,
6019 			     NEXT_ENTRY(COMMON_UNSIGNED),
6020 			     item_param),
6021 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6022 					     hdr.type5.ns)),
6023 	},
6024 	[ITEM_L2TPV2_MSG_DATA_S_NR] = {
6025 		.name = "nr",
6026 		.help = "sequence number for next receive message",
6027 		.next = NEXT(item_l2tpv2_type_data_s,
6028 			     NEXT_ENTRY(COMMON_UNSIGNED),
6029 			     item_param),
6030 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6031 					     hdr.type5.nr)),
6032 	},
6033 	[ITEM_L2TPV2_TYPE_DATA_O] = {
6034 		.name = "data_o",
6035 		.help = "Type #4: data message with offset option",
6036 		.next = NEXT(item_l2tpv2_type_data_o),
6037 		.call = parse_vc_item_l2tpv2_type,
6038 	},
6039 	[ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
6040 		.name = "tunnel_id",
6041 		.help = "tunnel identifier",
6042 		.next = NEXT(item_l2tpv2_type_data_o,
6043 			     NEXT_ENTRY(COMMON_UNSIGNED),
6044 			     item_param),
6045 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6046 					     hdr.type4.tunnel_id)),
6047 	},
6048 	[ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
6049 		.name = "session_id",
6050 		.help = "session identifier",
6051 		.next = NEXT(item_l2tpv2_type_data_o,
6052 			     NEXT_ENTRY(COMMON_UNSIGNED),
6053 			     item_param),
6054 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6055 					     hdr.type5.session_id)),
6056 	},
6057 	[ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
6058 		.name = "offset_size",
6059 		.help = "the size of offset padding",
6060 		.next = NEXT(item_l2tpv2_type_data_o,
6061 			     NEXT_ENTRY(COMMON_UNSIGNED),
6062 			     item_param),
6063 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6064 					     hdr.type4.offset_size)),
6065 	},
6066 	[ITEM_L2TPV2_TYPE_DATA_L_S] = {
6067 		.name = "data_l_s",
6068 		.help = "Type #3: data message contains length, ns, nr "
6069 			"options",
6070 		.next = NEXT(item_l2tpv2_type_data_l_s),
6071 		.call = parse_vc_item_l2tpv2_type,
6072 	},
6073 	[ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
6074 		.name = "length",
6075 		.help = "message length",
6076 		.next = NEXT(item_l2tpv2_type_data_l_s,
6077 			     NEXT_ENTRY(COMMON_UNSIGNED),
6078 			     item_param),
6079 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6080 					     hdr.type3.length)),
6081 	},
6082 	[ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
6083 		.name = "tunnel_id",
6084 		.help = "tunnel identifier",
6085 		.next = NEXT(item_l2tpv2_type_data_l_s,
6086 			     NEXT_ENTRY(COMMON_UNSIGNED),
6087 			     item_param),
6088 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6089 					     hdr.type3.tunnel_id)),
6090 	},
6091 	[ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
6092 		.name = "session_id",
6093 		.help = "session identifier",
6094 		.next = NEXT(item_l2tpv2_type_data_l_s,
6095 			     NEXT_ENTRY(COMMON_UNSIGNED),
6096 			     item_param),
6097 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6098 					     hdr.type3.session_id)),
6099 	},
6100 	[ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
6101 		.name = "ns",
6102 		.help = "sequence number for message",
6103 		.next = NEXT(item_l2tpv2_type_data_l_s,
6104 			     NEXT_ENTRY(COMMON_UNSIGNED),
6105 			     item_param),
6106 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6107 					     hdr.type3.ns)),
6108 	},
6109 	[ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
6110 		.name = "nr",
6111 		.help = "sequence number for next receive message",
6112 		.next = NEXT(item_l2tpv2_type_data_l_s,
6113 			     NEXT_ENTRY(COMMON_UNSIGNED),
6114 			     item_param),
6115 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6116 					     hdr.type3.nr)),
6117 	},
6118 	[ITEM_L2TPV2_TYPE_CTRL] = {
6119 		.name = "control",
6120 		.help = "Type #3: conrtol message contains length, ns, nr "
6121 			"options",
6122 		.next = NEXT(item_l2tpv2_type_ctrl),
6123 		.call = parse_vc_item_l2tpv2_type,
6124 	},
6125 	[ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
6126 		.name = "length",
6127 		.help = "message length",
6128 		.next = NEXT(item_l2tpv2_type_ctrl,
6129 			     NEXT_ENTRY(COMMON_UNSIGNED),
6130 			     item_param),
6131 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6132 					     hdr.type3.length)),
6133 	},
6134 	[ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
6135 		.name = "tunnel_id",
6136 		.help = "tunnel identifier",
6137 		.next = NEXT(item_l2tpv2_type_ctrl,
6138 			     NEXT_ENTRY(COMMON_UNSIGNED),
6139 			     item_param),
6140 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6141 					     hdr.type3.tunnel_id)),
6142 	},
6143 	[ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
6144 		.name = "session_id",
6145 		.help = "session identifier",
6146 		.next = NEXT(item_l2tpv2_type_ctrl,
6147 			     NEXT_ENTRY(COMMON_UNSIGNED),
6148 			     item_param),
6149 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6150 					     hdr.type3.session_id)),
6151 	},
6152 	[ITEM_L2TPV2_MSG_CTRL_NS] = {
6153 		.name = "ns",
6154 		.help = "sequence number for message",
6155 		.next = NEXT(item_l2tpv2_type_ctrl,
6156 			     NEXT_ENTRY(COMMON_UNSIGNED),
6157 			     item_param),
6158 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6159 					     hdr.type3.ns)),
6160 	},
6161 	[ITEM_L2TPV2_MSG_CTRL_NR] = {
6162 		.name = "nr",
6163 		.help = "sequence number for next receive message",
6164 		.next = NEXT(item_l2tpv2_type_ctrl,
6165 			     NEXT_ENTRY(COMMON_UNSIGNED),
6166 			     item_param),
6167 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6168 					     hdr.type3.nr)),
6169 	},
6170 	[ITEM_PPP] = {
6171 		.name = "ppp",
6172 		.help = "match PPP header",
6173 		.priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
6174 		.next = NEXT(item_ppp),
6175 		.call = parse_vc,
6176 	},
6177 	[ITEM_PPP_ADDR] = {
6178 		.name = "addr",
6179 		.help = "PPP address",
6180 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6181 			     item_param),
6182 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
6183 	},
6184 	[ITEM_PPP_CTRL] = {
6185 		.name = "ctrl",
6186 		.help = "PPP control",
6187 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6188 			     item_param),
6189 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
6190 	},
6191 	[ITEM_PPP_PROTO_ID] = {
6192 		.name = "proto_id",
6193 		.help = "PPP protocol identifier",
6194 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6195 			     item_param),
6196 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
6197 					hdr.proto_id)),
6198 	},
6199 	[ITEM_METER] = {
6200 		.name = "meter",
6201 		.help = "match meter color",
6202 		.priv = PRIV_ITEM(METER_COLOR,
6203 				  sizeof(struct rte_flow_item_meter_color)),
6204 		.next = NEXT(item_meter),
6205 		.call = parse_vc,
6206 	},
6207 	[ITEM_METER_COLOR] = {
6208 		.name = "color",
6209 		.help = "meter color",
6210 		.next = NEXT(item_meter,
6211 			     NEXT_ENTRY(ITEM_METER_COLOR_NAME),
6212 			     item_param),
6213 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_meter_color,
6214 					color)),
6215 	},
6216 	[ITEM_METER_COLOR_NAME] = {
6217 		.name = "color_name",
6218 		.help = "meter color name",
6219 		.call = parse_meter_color,
6220 		.comp = comp_meter_color,
6221 	},
6222 	[ITEM_QUOTA] = {
6223 		.name = "quota",
6224 		.help = "match quota",
6225 		.priv = PRIV_ITEM(QUOTA, sizeof(struct rte_flow_item_quota)),
6226 		.next = NEXT(item_quota),
6227 		.call = parse_vc
6228 	},
6229 	[ITEM_QUOTA_STATE] = {
6230 		.name = "quota_state",
6231 		.help = "quota state",
6232 		.next = NEXT(item_quota, NEXT_ENTRY(ITEM_QUOTA_STATE_NAME),
6233 			     NEXT_ENTRY(ITEM_PARAM_SPEC, ITEM_PARAM_MASK)),
6234 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_quota, state))
6235 	},
6236 	[ITEM_QUOTA_STATE_NAME] = {
6237 		.name = "state_name",
6238 		.help = "quota state name",
6239 		.call = parse_quota_state_name,
6240 		.comp = comp_quota_state_name
6241 	},
6242 	[ITEM_IB_BTH] = {
6243 		.name = "ib_bth",
6244 		.help = "match ib bth fields",
6245 		.priv = PRIV_ITEM(IB_BTH,
6246 				  sizeof(struct rte_flow_item_ib_bth)),
6247 		.next = NEXT(item_ib_bth),
6248 		.call = parse_vc,
6249 	},
6250 	[ITEM_IB_BTH_OPCODE] = {
6251 		.name = "opcode",
6252 		.help = "match ib bth opcode",
6253 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6254 				 item_param),
6255 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6256 						 hdr.opcode)),
6257 	},
6258 	[ITEM_IB_BTH_PKEY] = {
6259 		.name = "pkey",
6260 		.help = "partition key",
6261 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6262 				 item_param),
6263 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6264 						 hdr.pkey)),
6265 	},
6266 	[ITEM_IB_BTH_DST_QPN] = {
6267 		.name = "dst_qp",
6268 		.help = "destination qp",
6269 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6270 				 item_param),
6271 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6272 						 hdr.dst_qp)),
6273 	},
6274 	[ITEM_IB_BTH_PSN] = {
6275 		.name = "psn",
6276 		.help = "packet sequence number",
6277 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6278 				 item_param),
6279 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6280 						 hdr.psn)),
6281 	},
6282 	[ITEM_PTYPE] = {
6283 		.name = "ptype",
6284 		.help = "match L2/L3/L4 and tunnel information",
6285 		.priv = PRIV_ITEM(PTYPE,
6286 				  sizeof(struct rte_flow_item_ptype)),
6287 		.next = NEXT(item_ptype),
6288 		.call = parse_vc,
6289 	},
6290 	[ITEM_PTYPE_VALUE] = {
6291 		.name = "packet_type",
6292 		.help = "packet type as defined in rte_mbuf_ptype",
6293 		.next = NEXT(item_ptype, NEXT_ENTRY(COMMON_UNSIGNED),
6294 			     item_param),
6295 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ptype, packet_type)),
6296 	},
6297 	[ITEM_NSH] = {
6298 		.name = "nsh",
6299 		.help = "match NSH header",
6300 		.priv = PRIV_ITEM(NSH,
6301 				  sizeof(struct rte_flow_item_nsh)),
6302 		.next = NEXT(item_nsh),
6303 		.call = parse_vc,
6304 	},
6305 	[ITEM_COMPARE] = {
6306 		.name = "compare",
6307 		.help = "match with the comparison result",
6308 		.priv = PRIV_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
6309 		.next = NEXT(NEXT_ENTRY(ITEM_COMPARE_OP)),
6310 		.call = parse_vc,
6311 	},
6312 	[ITEM_COMPARE_OP] = {
6313 		.name = "op",
6314 		.help = "operation type",
6315 		.next = NEXT(item_compare_field,
6316 			NEXT_ENTRY(ITEM_COMPARE_OP_VALUE), item_param),
6317 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, operation)),
6318 	},
6319 	[ITEM_COMPARE_OP_VALUE] = {
6320 		.name = "{operation}",
6321 		.help = "operation type value",
6322 		.call = parse_vc_compare_op,
6323 		.comp = comp_set_compare_op,
6324 	},
6325 	[ITEM_COMPARE_FIELD_A_TYPE] = {
6326 		.name = "a_type",
6327 		.help = "compared field type",
6328 		.next = NEXT(compare_field_a,
6329 			NEXT_ENTRY(ITEM_COMPARE_FIELD_A_TYPE_VALUE), item_param),
6330 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.field)),
6331 	},
6332 	[ITEM_COMPARE_FIELD_A_TYPE_VALUE] = {
6333 		.name = "{a_type}",
6334 		.help = "compared field type value",
6335 		.call = parse_vc_compare_field_id,
6336 		.comp = comp_set_compare_field_id,
6337 	},
6338 	[ITEM_COMPARE_FIELD_A_LEVEL] = {
6339 		.name = "a_level",
6340 		.help = "compared field level",
6341 		.next = NEXT(compare_field_a,
6342 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_A_LEVEL_VALUE), item_param),
6343 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.level)),
6344 	},
6345 	[ITEM_COMPARE_FIELD_A_LEVEL_VALUE] = {
6346 		.name = "{a_level}",
6347 		.help = "compared field level value",
6348 		.call = parse_vc_compare_field_level,
6349 		.comp = comp_none,
6350 	},
6351 	[ITEM_COMPARE_FIELD_A_TAG_INDEX] = {
6352 		.name = "a_tag_index",
6353 		.help = "compared field tag array",
6354 		.next = NEXT(compare_field_a,
6355 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6356 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6357 					a.tag_index)),
6358 	},
6359 	[ITEM_COMPARE_FIELD_A_TYPE_ID] = {
6360 		.name = "a_type_id",
6361 		.help = "compared field type ID",
6362 		.next = NEXT(compare_field_a,
6363 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6364 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6365 					a.type)),
6366 	},
6367 	[ITEM_COMPARE_FIELD_A_CLASS_ID] = {
6368 		.name = "a_class",
6369 		.help = "compared field class ID",
6370 		.next = NEXT(compare_field_a,
6371 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6372 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6373 					     a.class_id)),
6374 	},
6375 	[ITEM_COMPARE_FIELD_A_OFFSET] = {
6376 		.name = "a_offset",
6377 		.help = "compared field bit offset",
6378 		.next = NEXT(compare_field_a,
6379 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6380 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6381 					a.offset)),
6382 	},
6383 	[ITEM_COMPARE_FIELD_B_TYPE] = {
6384 		.name = "b_type",
6385 		.help = "comparator field type",
6386 		.next = NEXT(compare_field_b,
6387 			NEXT_ENTRY(ITEM_COMPARE_FIELD_B_TYPE_VALUE), item_param),
6388 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6389 					b.field)),
6390 	},
6391 	[ITEM_COMPARE_FIELD_B_TYPE_VALUE] = {
6392 		.name = "{b_type}",
6393 		.help = "comparator field type value",
6394 		.call = parse_vc_compare_field_id,
6395 		.comp = comp_set_compare_field_id,
6396 	},
6397 	[ITEM_COMPARE_FIELD_B_LEVEL] = {
6398 		.name = "b_level",
6399 		.help = "comparator field level",
6400 		.next = NEXT(compare_field_b,
6401 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_B_LEVEL_VALUE), item_param),
6402 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6403 					b.level)),
6404 	},
6405 	[ITEM_COMPARE_FIELD_B_LEVEL_VALUE] = {
6406 		.name = "{b_level}",
6407 		.help = "comparator field level value",
6408 		.call = parse_vc_compare_field_level,
6409 		.comp = comp_none,
6410 	},
6411 	[ITEM_COMPARE_FIELD_B_TAG_INDEX] = {
6412 		.name = "b_tag_index",
6413 		.help = "comparator field tag array",
6414 		.next = NEXT(compare_field_b,
6415 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6416 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6417 					b.tag_index)),
6418 	},
6419 	[ITEM_COMPARE_FIELD_B_TYPE_ID] = {
6420 		.name = "b_type_id",
6421 		.help = "comparator field type ID",
6422 		.next = NEXT(compare_field_b,
6423 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6424 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6425 					b.type)),
6426 	},
6427 	[ITEM_COMPARE_FIELD_B_CLASS_ID] = {
6428 		.name = "b_class",
6429 		.help = "comparator field class ID",
6430 		.next = NEXT(compare_field_b,
6431 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6432 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6433 					     b.class_id)),
6434 	},
6435 	[ITEM_COMPARE_FIELD_B_OFFSET] = {
6436 		.name = "b_offset",
6437 		.help = "comparator field bit offset",
6438 		.next = NEXT(compare_field_b,
6439 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6440 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6441 					b.offset)),
6442 	},
6443 	[ITEM_COMPARE_FIELD_B_VALUE] = {
6444 		.name = "b_value",
6445 		.help = "comparator immediate value",
6446 		.next = NEXT(compare_field_b,
6447 			     NEXT_ENTRY(COMMON_HEX), item_param),
6448 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
6449 			     ARGS_ENTRY_ARB(0, 0),
6450 			     ARGS_ENTRY(struct rte_flow_item_compare,
6451 					b.value)),
6452 	},
6453 	[ITEM_COMPARE_FIELD_B_POINTER] = {
6454 		.name = "b_ptr",
6455 		.help = "pointer to comparator immediate value",
6456 		.next = NEXT(compare_field_b,
6457 			     NEXT_ENTRY(COMMON_HEX), item_param),
6458 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6459 					b.pvalue),
6460 			     ARGS_ENTRY_ARB(0, 0),
6461 			     ARGS_ENTRY_ARB
6462 				(sizeof(struct rte_flow_item_compare),
6463 				 FLOW_FIELD_PATTERN_SIZE)),
6464 	},
6465 	[ITEM_COMPARE_FIELD_WIDTH] = {
6466 		.name = "width",
6467 		.help = "number of bits to compare",
6468 		.next = NEXT(item_compare_field,
6469 			NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6470 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6471 					width)),
6472 	},
6473 
6474 	/* Validate/create actions. */
6475 	[ACTIONS] = {
6476 		.name = "actions",
6477 		.help = "submit a list of associated actions",
6478 		.next = NEXT(next_action),
6479 		.call = parse_vc,
6480 	},
6481 	[ACTION_NEXT] = {
6482 		.name = "/",
6483 		.help = "specify next action",
6484 		.next = NEXT(next_action),
6485 	},
6486 	[ACTION_END] = {
6487 		.name = "end",
6488 		.help = "end list of actions",
6489 		.priv = PRIV_ACTION(END, 0),
6490 		.call = parse_vc,
6491 	},
6492 	[ACTION_VOID] = {
6493 		.name = "void",
6494 		.help = "no-op action",
6495 		.priv = PRIV_ACTION(VOID, 0),
6496 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6497 		.call = parse_vc,
6498 	},
6499 	[ACTION_PASSTHRU] = {
6500 		.name = "passthru",
6501 		.help = "let subsequent rule process matched packets",
6502 		.priv = PRIV_ACTION(PASSTHRU, 0),
6503 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6504 		.call = parse_vc,
6505 	},
6506 	[ACTION_SKIP_CMAN] = {
6507 		.name = "skip_cman",
6508 		.help = "bypass cman on received packets",
6509 		.priv = PRIV_ACTION(SKIP_CMAN, 0),
6510 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6511 		.call = parse_vc,
6512 	},
6513 	[ACTION_JUMP] = {
6514 		.name = "jump",
6515 		.help = "redirect traffic to a given group",
6516 		.priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
6517 		.next = NEXT(action_jump),
6518 		.call = parse_vc,
6519 	},
6520 	[ACTION_JUMP_GROUP] = {
6521 		.name = "group",
6522 		.help = "group to redirect traffic to",
6523 		.next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
6524 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
6525 		.call = parse_vc_conf,
6526 	},
6527 	[ACTION_MARK] = {
6528 		.name = "mark",
6529 		.help = "attach 32 bit value to packets",
6530 		.priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
6531 		.next = NEXT(action_mark),
6532 		.call = parse_vc,
6533 	},
6534 	[ACTION_MARK_ID] = {
6535 		.name = "id",
6536 		.help = "32 bit value to return with packets",
6537 		.next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6538 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
6539 		.call = parse_vc_conf,
6540 	},
6541 	[ACTION_FLAG] = {
6542 		.name = "flag",
6543 		.help = "flag packets",
6544 		.priv = PRIV_ACTION(FLAG, 0),
6545 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6546 		.call = parse_vc,
6547 	},
6548 	[ACTION_QUEUE] = {
6549 		.name = "queue",
6550 		.help = "assign packets to a given queue index",
6551 		.priv = PRIV_ACTION(QUEUE,
6552 				    sizeof(struct rte_flow_action_queue)),
6553 		.next = NEXT(action_queue),
6554 		.call = parse_vc,
6555 	},
6556 	[ACTION_QUEUE_INDEX] = {
6557 		.name = "index",
6558 		.help = "queue index to use",
6559 		.next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
6560 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
6561 		.call = parse_vc_conf,
6562 	},
6563 	[ACTION_DROP] = {
6564 		.name = "drop",
6565 		.help = "drop packets (note: passthru has priority)",
6566 		.priv = PRIV_ACTION(DROP, 0),
6567 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6568 		.call = parse_vc,
6569 	},
6570 	[ACTION_COUNT] = {
6571 		.name = "count",
6572 		.help = "enable counters for this rule",
6573 		.priv = PRIV_ACTION(COUNT,
6574 				    sizeof(struct rte_flow_action_count)),
6575 		.next = NEXT(action_count),
6576 		.call = parse_vc,
6577 	},
6578 	[ACTION_COUNT_ID] = {
6579 		.name = "identifier",
6580 		.help = "counter identifier to use",
6581 		.next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
6582 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
6583 		.call = parse_vc_conf,
6584 	},
6585 	[ACTION_RSS] = {
6586 		.name = "rss",
6587 		.help = "spread packets among several queues",
6588 		.priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
6589 		.next = NEXT(action_rss),
6590 		.call = parse_vc_action_rss,
6591 	},
6592 	[ACTION_RSS_FUNC] = {
6593 		.name = "func",
6594 		.help = "RSS hash function to apply",
6595 		.next = NEXT(action_rss,
6596 			     NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
6597 					ACTION_RSS_FUNC_TOEPLITZ,
6598 					ACTION_RSS_FUNC_SIMPLE_XOR,
6599 					ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
6600 	},
6601 	[ACTION_RSS_FUNC_DEFAULT] = {
6602 		.name = "default",
6603 		.help = "default hash function",
6604 		.call = parse_vc_action_rss_func,
6605 	},
6606 	[ACTION_RSS_FUNC_TOEPLITZ] = {
6607 		.name = "toeplitz",
6608 		.help = "Toeplitz hash function",
6609 		.call = parse_vc_action_rss_func,
6610 	},
6611 	[ACTION_RSS_FUNC_SIMPLE_XOR] = {
6612 		.name = "simple_xor",
6613 		.help = "simple XOR hash function",
6614 		.call = parse_vc_action_rss_func,
6615 	},
6616 	[ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
6617 		.name = "symmetric_toeplitz",
6618 		.help = "Symmetric Toeplitz hash function",
6619 		.call = parse_vc_action_rss_func,
6620 	},
6621 	[ACTION_RSS_LEVEL] = {
6622 		.name = "level",
6623 		.help = "encapsulation level for \"types\"",
6624 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6625 		.args = ARGS(ARGS_ENTRY_ARB
6626 			     (offsetof(struct action_rss_data, conf) +
6627 			      offsetof(struct rte_flow_action_rss, level),
6628 			      sizeof(((struct rte_flow_action_rss *)0)->
6629 				     level))),
6630 	},
6631 	[ACTION_RSS_TYPES] = {
6632 		.name = "types",
6633 		.help = "specific RSS hash types",
6634 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
6635 	},
6636 	[ACTION_RSS_TYPE] = {
6637 		.name = "{type}",
6638 		.help = "RSS hash type",
6639 		.call = parse_vc_action_rss_type,
6640 		.comp = comp_vc_action_rss_type,
6641 	},
6642 	[ACTION_RSS_KEY] = {
6643 		.name = "key",
6644 		.help = "RSS hash key",
6645 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
6646 		.args = ARGS(ARGS_ENTRY_ARB
6647 			     (offsetof(struct action_rss_data, conf) +
6648 			      offsetof(struct rte_flow_action_rss, key),
6649 			      sizeof(((struct rte_flow_action_rss *)0)->key)),
6650 			     ARGS_ENTRY_ARB
6651 			     (offsetof(struct action_rss_data, conf) +
6652 			      offsetof(struct rte_flow_action_rss, key_len),
6653 			      sizeof(((struct rte_flow_action_rss *)0)->
6654 				     key_len)),
6655 			     ARGS_ENTRY(struct action_rss_data, key)),
6656 	},
6657 	[ACTION_RSS_KEY_LEN] = {
6658 		.name = "key_len",
6659 		.help = "RSS hash key length in bytes",
6660 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6661 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
6662 			     (offsetof(struct action_rss_data, conf) +
6663 			      offsetof(struct rte_flow_action_rss, key_len),
6664 			      sizeof(((struct rte_flow_action_rss *)0)->
6665 				     key_len),
6666 			      0,
6667 			      RSS_HASH_KEY_LENGTH)),
6668 	},
6669 	[ACTION_RSS_QUEUES] = {
6670 		.name = "queues",
6671 		.help = "queue indices to use",
6672 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
6673 		.call = parse_vc_conf,
6674 	},
6675 	[ACTION_RSS_QUEUE] = {
6676 		.name = "{queue}",
6677 		.help = "queue index",
6678 		.call = parse_vc_action_rss_queue,
6679 		.comp = comp_vc_action_rss_queue,
6680 	},
6681 	[ACTION_PF] = {
6682 		.name = "pf",
6683 		.help = "direct traffic to physical function",
6684 		.priv = PRIV_ACTION(PF, 0),
6685 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6686 		.call = parse_vc,
6687 	},
6688 	[ACTION_VF] = {
6689 		.name = "vf",
6690 		.help = "direct traffic to a virtual function ID",
6691 		.priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
6692 		.next = NEXT(action_vf),
6693 		.call = parse_vc,
6694 	},
6695 	[ACTION_VF_ORIGINAL] = {
6696 		.name = "original",
6697 		.help = "use original VF ID if possible",
6698 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
6699 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
6700 					   original, 1)),
6701 		.call = parse_vc_conf,
6702 	},
6703 	[ACTION_VF_ID] = {
6704 		.name = "id",
6705 		.help = "VF ID",
6706 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
6707 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
6708 		.call = parse_vc_conf,
6709 	},
6710 	[ACTION_PORT_ID] = {
6711 		.name = "port_id",
6712 		.help = "direct matching traffic to a given DPDK port ID",
6713 		.priv = PRIV_ACTION(PORT_ID,
6714 				    sizeof(struct rte_flow_action_port_id)),
6715 		.next = NEXT(action_port_id),
6716 		.call = parse_vc,
6717 	},
6718 	[ACTION_PORT_ID_ORIGINAL] = {
6719 		.name = "original",
6720 		.help = "use original DPDK port ID if possible",
6721 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
6722 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
6723 					   original, 1)),
6724 		.call = parse_vc_conf,
6725 	},
6726 	[ACTION_PORT_ID_ID] = {
6727 		.name = "id",
6728 		.help = "DPDK port ID",
6729 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
6730 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
6731 		.call = parse_vc_conf,
6732 	},
6733 	[ACTION_METER] = {
6734 		.name = "meter",
6735 		.help = "meter the directed packets at given id",
6736 		.priv = PRIV_ACTION(METER,
6737 				    sizeof(struct rte_flow_action_meter)),
6738 		.next = NEXT(action_meter),
6739 		.call = parse_vc,
6740 	},
6741 	[ACTION_METER_COLOR] = {
6742 		.name = "color",
6743 		.help = "meter color for the packets",
6744 		.priv = PRIV_ACTION(METER_COLOR,
6745 				sizeof(struct rte_flow_action_meter_color)),
6746 		.next = NEXT(action_meter_color),
6747 		.call = parse_vc,
6748 	},
6749 	[ACTION_METER_COLOR_TYPE] = {
6750 		.name = "type",
6751 		.help = "specific meter color",
6752 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
6753 				NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
6754 					ACTION_METER_COLOR_YELLOW,
6755 					ACTION_METER_COLOR_RED)),
6756 	},
6757 	[ACTION_METER_COLOR_GREEN] = {
6758 		.name = "green",
6759 		.help = "meter color green",
6760 		.call = parse_vc_action_meter_color_type,
6761 	},
6762 	[ACTION_METER_COLOR_YELLOW] = {
6763 		.name = "yellow",
6764 		.help = "meter color yellow",
6765 		.call = parse_vc_action_meter_color_type,
6766 	},
6767 	[ACTION_METER_COLOR_RED] = {
6768 		.name = "red",
6769 		.help = "meter color red",
6770 		.call = parse_vc_action_meter_color_type,
6771 	},
6772 	[ACTION_METER_ID] = {
6773 		.name = "mtr_id",
6774 		.help = "meter id to use",
6775 		.next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
6776 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
6777 		.call = parse_vc_conf,
6778 	},
6779 	[ACTION_METER_MARK] = {
6780 		.name = "meter_mark",
6781 		.help = "meter the directed packets using profile and policy",
6782 		.priv = PRIV_ACTION(METER_MARK,
6783 				    sizeof(struct rte_flow_action_meter_mark)),
6784 		.next = NEXT(action_meter_mark),
6785 		.call = parse_vc,
6786 	},
6787 	[ACTION_METER_PROFILE] = {
6788 		.name = "mtr_profile",
6789 		.help = "meter profile id to use",
6790 		.next = NEXT(NEXT_ENTRY(ACTION_METER_PROFILE_ID2PTR)),
6791 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6792 	},
6793 	[ACTION_METER_PROFILE_ID2PTR] = {
6794 		.name = "{mtr_profile_id}",
6795 		.type = "PROFILE_ID",
6796 		.help = "meter profile id",
6797 		.next = NEXT(action_meter_mark),
6798 		.call = parse_meter_profile_id2ptr,
6799 		.comp = comp_none,
6800 	},
6801 	[ACTION_METER_POLICY] = {
6802 		.name = "mtr_policy",
6803 		.help = "meter policy id to use",
6804 		.next = NEXT(NEXT_ENTRY(ACTION_METER_POLICY_ID2PTR)),
6805 		ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6806 	},
6807 	[ACTION_METER_POLICY_ID2PTR] = {
6808 		.name = "{mtr_policy_id}",
6809 		.type = "POLICY_ID",
6810 		.help = "meter policy id",
6811 		.next = NEXT(action_meter_mark),
6812 		.call = parse_meter_policy_id2ptr,
6813 		.comp = comp_none,
6814 	},
6815 	[ACTION_METER_COLOR_MODE] = {
6816 		.name = "mtr_color_mode",
6817 		.help = "meter color awareness mode",
6818 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6819 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, color_mode)),
6820 		.call = parse_vc_conf,
6821 	},
6822 	[ACTION_METER_STATE] = {
6823 		.name = "mtr_state",
6824 		.help = "meter state",
6825 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6826 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, state)),
6827 		.call = parse_vc_conf,
6828 	},
6829 	[ACTION_OF_DEC_NW_TTL] = {
6830 		.name = "of_dec_nw_ttl",
6831 		.help = "OpenFlow's OFPAT_DEC_NW_TTL",
6832 		.priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
6833 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6834 		.call = parse_vc,
6835 	},
6836 	[ACTION_OF_POP_VLAN] = {
6837 		.name = "of_pop_vlan",
6838 		.help = "OpenFlow's OFPAT_POP_VLAN",
6839 		.priv = PRIV_ACTION(OF_POP_VLAN, 0),
6840 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6841 		.call = parse_vc,
6842 	},
6843 	[ACTION_OF_PUSH_VLAN] = {
6844 		.name = "of_push_vlan",
6845 		.help = "OpenFlow's OFPAT_PUSH_VLAN",
6846 		.priv = PRIV_ACTION
6847 			(OF_PUSH_VLAN,
6848 			 sizeof(struct rte_flow_action_of_push_vlan)),
6849 		.next = NEXT(action_of_push_vlan),
6850 		.call = parse_vc,
6851 	},
6852 	[ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
6853 		.name = "ethertype",
6854 		.help = "EtherType",
6855 		.next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
6856 		.args = ARGS(ARGS_ENTRY_HTON
6857 			     (struct rte_flow_action_of_push_vlan,
6858 			      ethertype)),
6859 		.call = parse_vc_conf,
6860 	},
6861 	[ACTION_OF_SET_VLAN_VID] = {
6862 		.name = "of_set_vlan_vid",
6863 		.help = "OpenFlow's OFPAT_SET_VLAN_VID",
6864 		.priv = PRIV_ACTION
6865 			(OF_SET_VLAN_VID,
6866 			 sizeof(struct rte_flow_action_of_set_vlan_vid)),
6867 		.next = NEXT(action_of_set_vlan_vid),
6868 		.call = parse_vc,
6869 	},
6870 	[ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
6871 		.name = "vlan_vid",
6872 		.help = "VLAN id",
6873 		.next = NEXT(action_of_set_vlan_vid,
6874 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6875 		.args = ARGS(ARGS_ENTRY_HTON
6876 			     (struct rte_flow_action_of_set_vlan_vid,
6877 			      vlan_vid)),
6878 		.call = parse_vc_conf,
6879 	},
6880 	[ACTION_OF_SET_VLAN_PCP] = {
6881 		.name = "of_set_vlan_pcp",
6882 		.help = "OpenFlow's OFPAT_SET_VLAN_PCP",
6883 		.priv = PRIV_ACTION
6884 			(OF_SET_VLAN_PCP,
6885 			 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
6886 		.next = NEXT(action_of_set_vlan_pcp),
6887 		.call = parse_vc,
6888 	},
6889 	[ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
6890 		.name = "vlan_pcp",
6891 		.help = "VLAN priority",
6892 		.next = NEXT(action_of_set_vlan_pcp,
6893 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6894 		.args = ARGS(ARGS_ENTRY_HTON
6895 			     (struct rte_flow_action_of_set_vlan_pcp,
6896 			      vlan_pcp)),
6897 		.call = parse_vc_conf,
6898 	},
6899 	[ACTION_OF_POP_MPLS] = {
6900 		.name = "of_pop_mpls",
6901 		.help = "OpenFlow's OFPAT_POP_MPLS",
6902 		.priv = PRIV_ACTION(OF_POP_MPLS,
6903 				    sizeof(struct rte_flow_action_of_pop_mpls)),
6904 		.next = NEXT(action_of_pop_mpls),
6905 		.call = parse_vc,
6906 	},
6907 	[ACTION_OF_POP_MPLS_ETHERTYPE] = {
6908 		.name = "ethertype",
6909 		.help = "EtherType",
6910 		.next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6911 		.args = ARGS(ARGS_ENTRY_HTON
6912 			     (struct rte_flow_action_of_pop_mpls,
6913 			      ethertype)),
6914 		.call = parse_vc_conf,
6915 	},
6916 	[ACTION_OF_PUSH_MPLS] = {
6917 		.name = "of_push_mpls",
6918 		.help = "OpenFlow's OFPAT_PUSH_MPLS",
6919 		.priv = PRIV_ACTION
6920 			(OF_PUSH_MPLS,
6921 			 sizeof(struct rte_flow_action_of_push_mpls)),
6922 		.next = NEXT(action_of_push_mpls),
6923 		.call = parse_vc,
6924 	},
6925 	[ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
6926 		.name = "ethertype",
6927 		.help = "EtherType",
6928 		.next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6929 		.args = ARGS(ARGS_ENTRY_HTON
6930 			     (struct rte_flow_action_of_push_mpls,
6931 			      ethertype)),
6932 		.call = parse_vc_conf,
6933 	},
6934 	[ACTION_VXLAN_ENCAP] = {
6935 		.name = "vxlan_encap",
6936 		.help = "VXLAN encapsulation, uses configuration set by \"set"
6937 			" vxlan\"",
6938 		.priv = PRIV_ACTION(VXLAN_ENCAP,
6939 				    sizeof(struct action_vxlan_encap_data)),
6940 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6941 		.call = parse_vc_action_vxlan_encap,
6942 	},
6943 	[ACTION_VXLAN_DECAP] = {
6944 		.name = "vxlan_decap",
6945 		.help = "Performs a decapsulation action by stripping all"
6946 			" headers of the VXLAN tunnel network overlay from the"
6947 			" matched flow.",
6948 		.priv = PRIV_ACTION(VXLAN_DECAP, 0),
6949 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6950 		.call = parse_vc,
6951 	},
6952 	[ACTION_NVGRE_ENCAP] = {
6953 		.name = "nvgre_encap",
6954 		.help = "NVGRE encapsulation, uses configuration set by \"set"
6955 			" nvgre\"",
6956 		.priv = PRIV_ACTION(NVGRE_ENCAP,
6957 				    sizeof(struct action_nvgre_encap_data)),
6958 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6959 		.call = parse_vc_action_nvgre_encap,
6960 	},
6961 	[ACTION_NVGRE_DECAP] = {
6962 		.name = "nvgre_decap",
6963 		.help = "Performs a decapsulation action by stripping all"
6964 			" headers of the NVGRE tunnel network overlay from the"
6965 			" matched flow.",
6966 		.priv = PRIV_ACTION(NVGRE_DECAP, 0),
6967 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6968 		.call = parse_vc,
6969 	},
6970 	[ACTION_L2_ENCAP] = {
6971 		.name = "l2_encap",
6972 		.help = "l2 encap, uses configuration set by"
6973 			" \"set l2_encap\"",
6974 		.priv = PRIV_ACTION(RAW_ENCAP,
6975 				    sizeof(struct action_raw_encap_data)),
6976 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6977 		.call = parse_vc_action_l2_encap,
6978 	},
6979 	[ACTION_L2_DECAP] = {
6980 		.name = "l2_decap",
6981 		.help = "l2 decap, uses configuration set by"
6982 			" \"set l2_decap\"",
6983 		.priv = PRIV_ACTION(RAW_DECAP,
6984 				    sizeof(struct action_raw_decap_data)),
6985 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6986 		.call = parse_vc_action_l2_decap,
6987 	},
6988 	[ACTION_MPLSOGRE_ENCAP] = {
6989 		.name = "mplsogre_encap",
6990 		.help = "mplsogre encapsulation, uses configuration set by"
6991 			" \"set mplsogre_encap\"",
6992 		.priv = PRIV_ACTION(RAW_ENCAP,
6993 				    sizeof(struct action_raw_encap_data)),
6994 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6995 		.call = parse_vc_action_mplsogre_encap,
6996 	},
6997 	[ACTION_MPLSOGRE_DECAP] = {
6998 		.name = "mplsogre_decap",
6999 		.help = "mplsogre decapsulation, uses configuration set by"
7000 			" \"set mplsogre_decap\"",
7001 		.priv = PRIV_ACTION(RAW_DECAP,
7002 				    sizeof(struct action_raw_decap_data)),
7003 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7004 		.call = parse_vc_action_mplsogre_decap,
7005 	},
7006 	[ACTION_MPLSOUDP_ENCAP] = {
7007 		.name = "mplsoudp_encap",
7008 		.help = "mplsoudp encapsulation, uses configuration set by"
7009 			" \"set mplsoudp_encap\"",
7010 		.priv = PRIV_ACTION(RAW_ENCAP,
7011 				    sizeof(struct action_raw_encap_data)),
7012 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7013 		.call = parse_vc_action_mplsoudp_encap,
7014 	},
7015 	[ACTION_MPLSOUDP_DECAP] = {
7016 		.name = "mplsoudp_decap",
7017 		.help = "mplsoudp decapsulation, uses configuration set by"
7018 			" \"set mplsoudp_decap\"",
7019 		.priv = PRIV_ACTION(RAW_DECAP,
7020 				    sizeof(struct action_raw_decap_data)),
7021 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7022 		.call = parse_vc_action_mplsoudp_decap,
7023 	},
7024 	[ACTION_SET_IPV4_SRC] = {
7025 		.name = "set_ipv4_src",
7026 		.help = "Set a new IPv4 source address in the outermost"
7027 			" IPv4 header",
7028 		.priv = PRIV_ACTION(SET_IPV4_SRC,
7029 			sizeof(struct rte_flow_action_set_ipv4)),
7030 		.next = NEXT(action_set_ipv4_src),
7031 		.call = parse_vc,
7032 	},
7033 	[ACTION_SET_IPV4_SRC_IPV4_SRC] = {
7034 		.name = "ipv4_addr",
7035 		.help = "new IPv4 source address to set",
7036 		.next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
7037 		.args = ARGS(ARGS_ENTRY_HTON
7038 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
7039 		.call = parse_vc_conf,
7040 	},
7041 	[ACTION_SET_IPV4_DST] = {
7042 		.name = "set_ipv4_dst",
7043 		.help = "Set a new IPv4 destination address in the outermost"
7044 			" IPv4 header",
7045 		.priv = PRIV_ACTION(SET_IPV4_DST,
7046 			sizeof(struct rte_flow_action_set_ipv4)),
7047 		.next = NEXT(action_set_ipv4_dst),
7048 		.call = parse_vc,
7049 	},
7050 	[ACTION_SET_IPV4_DST_IPV4_DST] = {
7051 		.name = "ipv4_addr",
7052 		.help = "new IPv4 destination address to set",
7053 		.next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
7054 		.args = ARGS(ARGS_ENTRY_HTON
7055 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
7056 		.call = parse_vc_conf,
7057 	},
7058 	[ACTION_SET_IPV6_SRC] = {
7059 		.name = "set_ipv6_src",
7060 		.help = "Set a new IPv6 source address in the outermost"
7061 			" IPv6 header",
7062 		.priv = PRIV_ACTION(SET_IPV6_SRC,
7063 			sizeof(struct rte_flow_action_set_ipv6)),
7064 		.next = NEXT(action_set_ipv6_src),
7065 		.call = parse_vc,
7066 	},
7067 	[ACTION_SET_IPV6_SRC_IPV6_SRC] = {
7068 		.name = "ipv6_addr",
7069 		.help = "new IPv6 source address to set",
7070 		.next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
7071 		.args = ARGS(ARGS_ENTRY_HTON
7072 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
7073 		.call = parse_vc_conf,
7074 	},
7075 	[ACTION_SET_IPV6_DST] = {
7076 		.name = "set_ipv6_dst",
7077 		.help = "Set a new IPv6 destination address in the outermost"
7078 			" IPv6 header",
7079 		.priv = PRIV_ACTION(SET_IPV6_DST,
7080 			sizeof(struct rte_flow_action_set_ipv6)),
7081 		.next = NEXT(action_set_ipv6_dst),
7082 		.call = parse_vc,
7083 	},
7084 	[ACTION_SET_IPV6_DST_IPV6_DST] = {
7085 		.name = "ipv6_addr",
7086 		.help = "new IPv6 destination address to set",
7087 		.next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
7088 		.args = ARGS(ARGS_ENTRY_HTON
7089 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
7090 		.call = parse_vc_conf,
7091 	},
7092 	[ACTION_SET_TP_SRC] = {
7093 		.name = "set_tp_src",
7094 		.help = "set a new source port number in the outermost"
7095 			" TCP/UDP header",
7096 		.priv = PRIV_ACTION(SET_TP_SRC,
7097 			sizeof(struct rte_flow_action_set_tp)),
7098 		.next = NEXT(action_set_tp_src),
7099 		.call = parse_vc,
7100 	},
7101 	[ACTION_SET_TP_SRC_TP_SRC] = {
7102 		.name = "port",
7103 		.help = "new source port number to set",
7104 		.next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
7105 		.args = ARGS(ARGS_ENTRY_HTON
7106 			     (struct rte_flow_action_set_tp, port)),
7107 		.call = parse_vc_conf,
7108 	},
7109 	[ACTION_SET_TP_DST] = {
7110 		.name = "set_tp_dst",
7111 		.help = "set a new destination port number in the outermost"
7112 			" TCP/UDP header",
7113 		.priv = PRIV_ACTION(SET_TP_DST,
7114 			sizeof(struct rte_flow_action_set_tp)),
7115 		.next = NEXT(action_set_tp_dst),
7116 		.call = parse_vc,
7117 	},
7118 	[ACTION_SET_TP_DST_TP_DST] = {
7119 		.name = "port",
7120 		.help = "new destination port number to set",
7121 		.next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
7122 		.args = ARGS(ARGS_ENTRY_HTON
7123 			     (struct rte_flow_action_set_tp, port)),
7124 		.call = parse_vc_conf,
7125 	},
7126 	[ACTION_MAC_SWAP] = {
7127 		.name = "mac_swap",
7128 		.help = "Swap the source and destination MAC addresses"
7129 			" in the outermost Ethernet header",
7130 		.priv = PRIV_ACTION(MAC_SWAP, 0),
7131 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7132 		.call = parse_vc,
7133 	},
7134 	[ACTION_DEC_TTL] = {
7135 		.name = "dec_ttl",
7136 		.help = "decrease network TTL if available",
7137 		.priv = PRIV_ACTION(DEC_TTL, 0),
7138 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7139 		.call = parse_vc,
7140 	},
7141 	[ACTION_SET_TTL] = {
7142 		.name = "set_ttl",
7143 		.help = "set ttl value",
7144 		.priv = PRIV_ACTION(SET_TTL,
7145 			sizeof(struct rte_flow_action_set_ttl)),
7146 		.next = NEXT(action_set_ttl),
7147 		.call = parse_vc,
7148 	},
7149 	[ACTION_SET_TTL_TTL] = {
7150 		.name = "ttl_value",
7151 		.help = "new ttl value to set",
7152 		.next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
7153 		.args = ARGS(ARGS_ENTRY_HTON
7154 			     (struct rte_flow_action_set_ttl, ttl_value)),
7155 		.call = parse_vc_conf,
7156 	},
7157 	[ACTION_SET_MAC_SRC] = {
7158 		.name = "set_mac_src",
7159 		.help = "set source mac address",
7160 		.priv = PRIV_ACTION(SET_MAC_SRC,
7161 			sizeof(struct rte_flow_action_set_mac)),
7162 		.next = NEXT(action_set_mac_src),
7163 		.call = parse_vc,
7164 	},
7165 	[ACTION_SET_MAC_SRC_MAC_SRC] = {
7166 		.name = "mac_addr",
7167 		.help = "new source mac address",
7168 		.next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
7169 		.args = ARGS(ARGS_ENTRY_HTON
7170 			     (struct rte_flow_action_set_mac, mac_addr)),
7171 		.call = parse_vc_conf,
7172 	},
7173 	[ACTION_SET_MAC_DST] = {
7174 		.name = "set_mac_dst",
7175 		.help = "set destination mac address",
7176 		.priv = PRIV_ACTION(SET_MAC_DST,
7177 			sizeof(struct rte_flow_action_set_mac)),
7178 		.next = NEXT(action_set_mac_dst),
7179 		.call = parse_vc,
7180 	},
7181 	[ACTION_SET_MAC_DST_MAC_DST] = {
7182 		.name = "mac_addr",
7183 		.help = "new destination mac address to set",
7184 		.next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
7185 		.args = ARGS(ARGS_ENTRY_HTON
7186 			     (struct rte_flow_action_set_mac, mac_addr)),
7187 		.call = parse_vc_conf,
7188 	},
7189 	[ACTION_INC_TCP_SEQ] = {
7190 		.name = "inc_tcp_seq",
7191 		.help = "increase TCP sequence number",
7192 		.priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
7193 		.next = NEXT(action_inc_tcp_seq),
7194 		.call = parse_vc,
7195 	},
7196 	[ACTION_INC_TCP_SEQ_VALUE] = {
7197 		.name = "value",
7198 		.help = "the value to increase TCP sequence number by",
7199 		.next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7200 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7201 		.call = parse_vc_conf,
7202 	},
7203 	[ACTION_DEC_TCP_SEQ] = {
7204 		.name = "dec_tcp_seq",
7205 		.help = "decrease TCP sequence number",
7206 		.priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
7207 		.next = NEXT(action_dec_tcp_seq),
7208 		.call = parse_vc,
7209 	},
7210 	[ACTION_DEC_TCP_SEQ_VALUE] = {
7211 		.name = "value",
7212 		.help = "the value to decrease TCP sequence number by",
7213 		.next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7214 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7215 		.call = parse_vc_conf,
7216 	},
7217 	[ACTION_INC_TCP_ACK] = {
7218 		.name = "inc_tcp_ack",
7219 		.help = "increase TCP acknowledgment number",
7220 		.priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
7221 		.next = NEXT(action_inc_tcp_ack),
7222 		.call = parse_vc,
7223 	},
7224 	[ACTION_INC_TCP_ACK_VALUE] = {
7225 		.name = "value",
7226 		.help = "the value to increase TCP acknowledgment number by",
7227 		.next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7228 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7229 		.call = parse_vc_conf,
7230 	},
7231 	[ACTION_DEC_TCP_ACK] = {
7232 		.name = "dec_tcp_ack",
7233 		.help = "decrease TCP acknowledgment number",
7234 		.priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
7235 		.next = NEXT(action_dec_tcp_ack),
7236 		.call = parse_vc,
7237 	},
7238 	[ACTION_DEC_TCP_ACK_VALUE] = {
7239 		.name = "value",
7240 		.help = "the value to decrease TCP acknowledgment number by",
7241 		.next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7242 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7243 		.call = parse_vc_conf,
7244 	},
7245 	[ACTION_RAW_ENCAP] = {
7246 		.name = "raw_encap",
7247 		.help = "encapsulation data, defined by set raw_encap",
7248 		.priv = PRIV_ACTION(RAW_ENCAP,
7249 			sizeof(struct action_raw_encap_data)),
7250 		.next = NEXT(action_raw_encap),
7251 		.call = parse_vc_action_raw_encap,
7252 	},
7253 	[ACTION_RAW_ENCAP_SIZE] = {
7254 		.name = "size",
7255 		.help = "raw encap size",
7256 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7257 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7258 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_raw_encap, size)),
7259 		.call = parse_vc_conf,
7260 	},
7261 	[ACTION_RAW_ENCAP_INDEX] = {
7262 		.name = "index",
7263 		.help = "the index of raw_encap_confs",
7264 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
7265 	},
7266 	[ACTION_RAW_ENCAP_INDEX_VALUE] = {
7267 		.name = "{index}",
7268 		.type = "UNSIGNED",
7269 		.help = "unsigned integer value",
7270 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7271 		.call = parse_vc_action_raw_encap_index,
7272 		.comp = comp_set_raw_index,
7273 	},
7274 	[ACTION_RAW_DECAP] = {
7275 		.name = "raw_decap",
7276 		.help = "decapsulation data, defined by set raw_encap",
7277 		.priv = PRIV_ACTION(RAW_DECAP,
7278 			sizeof(struct action_raw_decap_data)),
7279 		.next = NEXT(action_raw_decap),
7280 		.call = parse_vc_action_raw_decap,
7281 	},
7282 	[ACTION_RAW_DECAP_INDEX] = {
7283 		.name = "index",
7284 		.help = "the index of raw_encap_confs",
7285 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
7286 	},
7287 	[ACTION_RAW_DECAP_INDEX_VALUE] = {
7288 		.name = "{index}",
7289 		.type = "UNSIGNED",
7290 		.help = "unsigned integer value",
7291 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7292 		.call = parse_vc_action_raw_decap_index,
7293 		.comp = comp_set_raw_index,
7294 	},
7295 	[ACTION_MODIFY_FIELD] = {
7296 		.name = "modify_field",
7297 		.help = "modify destination field with data from source field",
7298 		.priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
7299 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
7300 		.call = parse_vc,
7301 	},
7302 	[ACTION_MODIFY_FIELD_OP] = {
7303 		.name = "op",
7304 		.help = "operation type",
7305 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
7306 			NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
7307 		.call = parse_vc_conf,
7308 	},
7309 	[ACTION_MODIFY_FIELD_OP_VALUE] = {
7310 		.name = "{operation}",
7311 		.help = "operation type value",
7312 		.call = parse_vc_modify_field_op,
7313 		.comp = comp_set_modify_field_op,
7314 	},
7315 	[ACTION_MODIFY_FIELD_DST_TYPE] = {
7316 		.name = "dst_type",
7317 		.help = "destination field type",
7318 		.next = NEXT(action_modify_field_dst,
7319 			NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
7320 		.call = parse_vc_conf,
7321 	},
7322 	[ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
7323 		.name = "{dst_type}",
7324 		.help = "destination field type value",
7325 		.call = parse_vc_modify_field_id,
7326 		.comp = comp_set_modify_field_id,
7327 	},
7328 	[ACTION_MODIFY_FIELD_DST_LEVEL] = {
7329 		.name = "dst_level",
7330 		.help = "destination field level",
7331 		.next = NEXT(action_modify_field_dst,
7332 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)),
7333 		.call = parse_vc_conf,
7334 	},
7335 	[ACTION_MODIFY_FIELD_DST_LEVEL_VALUE] = {
7336 		.name = "{dst_level}",
7337 		.help = "destination field level value",
7338 		.call = parse_vc_modify_field_level,
7339 		.comp = comp_none,
7340 	},
7341 	[ACTION_MODIFY_FIELD_DST_TAG_INDEX] = {
7342 		.name = "dst_tag_index",
7343 		.help = "destination field tag array",
7344 		.next = NEXT(action_modify_field_dst,
7345 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7346 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7347 					dst.tag_index)),
7348 		.call = parse_vc_conf,
7349 	},
7350 	[ACTION_MODIFY_FIELD_DST_TYPE_ID] = {
7351 		.name = "dst_type_id",
7352 		.help = "destination field type ID",
7353 		.next = NEXT(action_modify_field_dst,
7354 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7355 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7356 					dst.type)),
7357 		.call = parse_vc_conf,
7358 	},
7359 	[ACTION_MODIFY_FIELD_DST_CLASS_ID] = {
7360 		.name = "dst_class",
7361 		.help = "destination field class ID",
7362 		.next = NEXT(action_modify_field_dst,
7363 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7364 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7365 					     dst.class_id)),
7366 		.call = parse_vc_conf,
7367 	},
7368 	[ACTION_MODIFY_FIELD_DST_OFFSET] = {
7369 		.name = "dst_offset",
7370 		.help = "destination field bit offset",
7371 		.next = NEXT(action_modify_field_dst,
7372 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7373 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7374 					dst.offset)),
7375 		.call = parse_vc_conf,
7376 	},
7377 	[ACTION_MODIFY_FIELD_SRC_TYPE] = {
7378 		.name = "src_type",
7379 		.help = "source field type",
7380 		.next = NEXT(action_modify_field_src,
7381 			NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
7382 		.call = parse_vc_conf,
7383 	},
7384 	[ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
7385 		.name = "{src_type}",
7386 		.help = "source field type value",
7387 		.call = parse_vc_modify_field_id,
7388 		.comp = comp_set_modify_field_id,
7389 	},
7390 	[ACTION_MODIFY_FIELD_SRC_LEVEL] = {
7391 		.name = "src_level",
7392 		.help = "source field level",
7393 		.next = NEXT(action_modify_field_src,
7394 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)),
7395 		.call = parse_vc_conf,
7396 	},
7397 	[ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE] = {
7398 		.name = "{src_level}",
7399 		.help = "source field level value",
7400 		.call = parse_vc_modify_field_level,
7401 		.comp = comp_none,
7402 	},
7403 	[ACTION_MODIFY_FIELD_SRC_TAG_INDEX] = {
7404 		.name = "src_tag_index",
7405 		.help = "source field tag array",
7406 		.next = NEXT(action_modify_field_src,
7407 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7408 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7409 					src.tag_index)),
7410 		.call = parse_vc_conf,
7411 	},
7412 	[ACTION_MODIFY_FIELD_SRC_TYPE_ID] = {
7413 		.name = "src_type_id",
7414 		.help = "source field type ID",
7415 		.next = NEXT(action_modify_field_src,
7416 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7417 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7418 					src.type)),
7419 		.call = parse_vc_conf,
7420 	},
7421 	[ACTION_MODIFY_FIELD_SRC_CLASS_ID] = {
7422 		.name = "src_class",
7423 		.help = "source field class ID",
7424 		.next = NEXT(action_modify_field_src,
7425 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7426 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7427 					     src.class_id)),
7428 		.call = parse_vc_conf,
7429 	},
7430 	[ACTION_MODIFY_FIELD_SRC_OFFSET] = {
7431 		.name = "src_offset",
7432 		.help = "source field bit offset",
7433 		.next = NEXT(action_modify_field_src,
7434 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7435 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7436 					src.offset)),
7437 		.call = parse_vc_conf,
7438 	},
7439 	[ACTION_MODIFY_FIELD_SRC_VALUE] = {
7440 		.name = "src_value",
7441 		.help = "source immediate value",
7442 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7443 			     NEXT_ENTRY(COMMON_HEX)),
7444 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
7445 			     ARGS_ENTRY_ARB(0, 0),
7446 			     ARGS_ENTRY(struct rte_flow_action_modify_field,
7447 					src.value)),
7448 		.call = parse_vc_conf,
7449 	},
7450 	[ACTION_MODIFY_FIELD_SRC_POINTER] = {
7451 		.name = "src_ptr",
7452 		.help = "pointer to source immediate value",
7453 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7454 			     NEXT_ENTRY(COMMON_HEX)),
7455 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7456 					src.pvalue),
7457 			     ARGS_ENTRY_ARB(0, 0),
7458 			     ARGS_ENTRY_ARB
7459 				(sizeof(struct rte_flow_action_modify_field),
7460 				 FLOW_FIELD_PATTERN_SIZE)),
7461 		.call = parse_vc_conf,
7462 	},
7463 	[ACTION_MODIFY_FIELD_WIDTH] = {
7464 		.name = "width",
7465 		.help = "number of bits to copy",
7466 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7467 			NEXT_ENTRY(COMMON_UNSIGNED)),
7468 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7469 					width)),
7470 		.call = parse_vc_conf,
7471 	},
7472 	[ACTION_SEND_TO_KERNEL] = {
7473 		.name = "send_to_kernel",
7474 		.help = "send packets to kernel",
7475 		.priv = PRIV_ACTION(SEND_TO_KERNEL, 0),
7476 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7477 		.call = parse_vc,
7478 	},
7479 	[ACTION_IPV6_EXT_REMOVE] = {
7480 		.name = "ipv6_ext_remove",
7481 		.help = "IPv6 extension type, defined by set ipv6_ext_remove",
7482 		.priv = PRIV_ACTION(IPV6_EXT_REMOVE,
7483 			sizeof(struct action_ipv6_ext_remove_data)),
7484 		.next = NEXT(action_ipv6_ext_remove),
7485 		.call = parse_vc_action_ipv6_ext_remove,
7486 	},
7487 	[ACTION_IPV6_EXT_REMOVE_INDEX] = {
7488 		.name = "index",
7489 		.help = "the index of ipv6_ext_remove",
7490 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_REMOVE_INDEX_VALUE)),
7491 	},
7492 	[ACTION_IPV6_EXT_REMOVE_INDEX_VALUE] = {
7493 		.name = "{index}",
7494 		.type = "UNSIGNED",
7495 		.help = "unsigned integer value",
7496 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7497 		.call = parse_vc_action_ipv6_ext_remove_index,
7498 		.comp = comp_set_ipv6_ext_index,
7499 	},
7500 	[ACTION_IPV6_EXT_PUSH] = {
7501 		.name = "ipv6_ext_push",
7502 		.help = "IPv6 extension data, defined by set ipv6_ext_push",
7503 		.priv = PRIV_ACTION(IPV6_EXT_PUSH,
7504 			sizeof(struct action_ipv6_ext_push_data)),
7505 		.next = NEXT(action_ipv6_ext_push),
7506 		.call = parse_vc_action_ipv6_ext_push,
7507 	},
7508 	[ACTION_IPV6_EXT_PUSH_INDEX] = {
7509 		.name = "index",
7510 		.help = "the index of ipv6_ext_push",
7511 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_PUSH_INDEX_VALUE)),
7512 	},
7513 	[ACTION_IPV6_EXT_PUSH_INDEX_VALUE] = {
7514 		.name = "{index}",
7515 		.type = "UNSIGNED",
7516 		.help = "unsigned integer value",
7517 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7518 		.call = parse_vc_action_ipv6_ext_push_index,
7519 		.comp = comp_set_ipv6_ext_index,
7520 	},
7521 	[ACTION_NAT64] = {
7522 		.name = "nat64",
7523 		.help = "NAT64 IP headers translation",
7524 		.priv = PRIV_ACTION(NAT64, sizeof(struct rte_flow_action_nat64)),
7525 		.next = NEXT(action_nat64),
7526 		.call = parse_vc,
7527 	},
7528 	[ACTION_NAT64_MODE] = {
7529 		.name = "type",
7530 		.help = "NAT64 translation type",
7531 		.next = NEXT(action_nat64, NEXT_ENTRY(COMMON_UNSIGNED)),
7532 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_nat64, type)),
7533 		.call = parse_vc_conf,
7534 	},
7535 	/* Top level command. */
7536 	[SET] = {
7537 		.name = "set",
7538 		.help = "set raw encap/decap/sample data",
7539 		.type = "set raw_encap|raw_decap <index> <pattern>"
7540 				" or set sample_actions <index> <action>",
7541 		.next = NEXT(NEXT_ENTRY
7542 			     (SET_RAW_ENCAP,
7543 			      SET_RAW_DECAP,
7544 			      SET_SAMPLE_ACTIONS,
7545 			      SET_IPV6_EXT_REMOVE,
7546 			      SET_IPV6_EXT_PUSH)),
7547 		.call = parse_set_init,
7548 	},
7549 	/* Sub-level commands. */
7550 	[SET_RAW_ENCAP] = {
7551 		.name = "raw_encap",
7552 		.help = "set raw encap data",
7553 		.next = NEXT(next_set_raw),
7554 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7555 				(offsetof(struct buffer, port),
7556 				 sizeof(((struct buffer *)0)->port),
7557 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7558 		.call = parse_set_raw_encap_decap,
7559 	},
7560 	[SET_RAW_DECAP] = {
7561 		.name = "raw_decap",
7562 		.help = "set raw decap data",
7563 		.next = NEXT(next_set_raw),
7564 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7565 				(offsetof(struct buffer, port),
7566 				 sizeof(((struct buffer *)0)->port),
7567 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7568 		.call = parse_set_raw_encap_decap,
7569 	},
7570 	[SET_RAW_INDEX] = {
7571 		.name = "{index}",
7572 		.type = "COMMON_UNSIGNED",
7573 		.help = "index of raw_encap/raw_decap data",
7574 		.next = NEXT(next_item),
7575 		.call = parse_port,
7576 	},
7577 	[SET_SAMPLE_INDEX] = {
7578 		.name = "{index}",
7579 		.type = "UNSIGNED",
7580 		.help = "index of sample actions",
7581 		.next = NEXT(next_action_sample),
7582 		.call = parse_port,
7583 	},
7584 	[SET_SAMPLE_ACTIONS] = {
7585 		.name = "sample_actions",
7586 		.help = "set sample actions list",
7587 		.next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
7588 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7589 				(offsetof(struct buffer, port),
7590 				 sizeof(((struct buffer *)0)->port),
7591 				 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
7592 		.call = parse_set_sample_action,
7593 	},
7594 	[SET_IPV6_EXT_PUSH] = {
7595 		.name = "ipv6_ext_push",
7596 		.help = "set IPv6 extension header",
7597 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7598 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7599 				(offsetof(struct buffer, port),
7600 				 sizeof(((struct buffer *)0)->port),
7601 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7602 		.call = parse_set_ipv6_ext_action,
7603 	},
7604 	[SET_IPV6_EXT_REMOVE] = {
7605 		.name = "ipv6_ext_remove",
7606 		.help = "set IPv6 extension header",
7607 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7608 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7609 				(offsetof(struct buffer, port),
7610 				 sizeof(((struct buffer *)0)->port),
7611 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7612 		.call = parse_set_ipv6_ext_action,
7613 	},
7614 	[SET_IPV6_EXT_INDEX] = {
7615 		.name = "{index}",
7616 		.type = "UNSIGNED",
7617 		.help = "index of ipv6 extension push/remove actions",
7618 		.next = NEXT(item_ipv6_push_ext),
7619 		.call = parse_port,
7620 	},
7621 	[ITEM_IPV6_PUSH_REMOVE_EXT] = {
7622 		.name = "ipv6_ext",
7623 		.help = "set IPv6 extension header",
7624 		.priv = PRIV_ITEM(IPV6_EXT,
7625 				  sizeof(struct rte_flow_item_ipv6_ext)),
7626 		.next = NEXT(item_ipv6_push_ext_type),
7627 		.call = parse_vc,
7628 	},
7629 	[ITEM_IPV6_PUSH_REMOVE_EXT_TYPE] = {
7630 		.name = "type",
7631 		.help = "set IPv6 extension type",
7632 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
7633 					     next_hdr)),
7634 		.next = NEXT(item_ipv6_push_ext_header, NEXT_ENTRY(COMMON_UNSIGNED),
7635 			     item_param),
7636 	},
7637 	[ACTION_SET_TAG] = {
7638 		.name = "set_tag",
7639 		.help = "set tag",
7640 		.priv = PRIV_ACTION(SET_TAG,
7641 			sizeof(struct rte_flow_action_set_tag)),
7642 		.next = NEXT(action_set_tag),
7643 		.call = parse_vc,
7644 	},
7645 	[ACTION_SET_TAG_INDEX] = {
7646 		.name = "index",
7647 		.help = "index of tag array",
7648 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7649 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
7650 		.call = parse_vc_conf,
7651 	},
7652 	[ACTION_SET_TAG_DATA] = {
7653 		.name = "data",
7654 		.help = "tag value",
7655 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7656 		.args = ARGS(ARGS_ENTRY
7657 			     (struct rte_flow_action_set_tag, data)),
7658 		.call = parse_vc_conf,
7659 	},
7660 	[ACTION_SET_TAG_MASK] = {
7661 		.name = "mask",
7662 		.help = "mask for tag value",
7663 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7664 		.args = ARGS(ARGS_ENTRY
7665 			     (struct rte_flow_action_set_tag, mask)),
7666 		.call = parse_vc_conf,
7667 	},
7668 	[ACTION_SET_META] = {
7669 		.name = "set_meta",
7670 		.help = "set metadata",
7671 		.priv = PRIV_ACTION(SET_META,
7672 			sizeof(struct rte_flow_action_set_meta)),
7673 		.next = NEXT(action_set_meta),
7674 		.call = parse_vc_action_set_meta,
7675 	},
7676 	[ACTION_SET_META_DATA] = {
7677 		.name = "data",
7678 		.help = "metadata value",
7679 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7680 		.args = ARGS(ARGS_ENTRY
7681 			     (struct rte_flow_action_set_meta, data)),
7682 		.call = parse_vc_conf,
7683 	},
7684 	[ACTION_SET_META_MASK] = {
7685 		.name = "mask",
7686 		.help = "mask for metadata value",
7687 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7688 		.args = ARGS(ARGS_ENTRY
7689 			     (struct rte_flow_action_set_meta, mask)),
7690 		.call = parse_vc_conf,
7691 	},
7692 	[ACTION_SET_IPV4_DSCP] = {
7693 		.name = "set_ipv4_dscp",
7694 		.help = "set DSCP value",
7695 		.priv = PRIV_ACTION(SET_IPV4_DSCP,
7696 			sizeof(struct rte_flow_action_set_dscp)),
7697 		.next = NEXT(action_set_ipv4_dscp),
7698 		.call = parse_vc,
7699 	},
7700 	[ACTION_SET_IPV4_DSCP_VALUE] = {
7701 		.name = "dscp_value",
7702 		.help = "new IPv4 DSCP value to set",
7703 		.next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7704 		.args = ARGS(ARGS_ENTRY
7705 			     (struct rte_flow_action_set_dscp, dscp)),
7706 		.call = parse_vc_conf,
7707 	},
7708 	[ACTION_SET_IPV6_DSCP] = {
7709 		.name = "set_ipv6_dscp",
7710 		.help = "set DSCP value",
7711 		.priv = PRIV_ACTION(SET_IPV6_DSCP,
7712 			sizeof(struct rte_flow_action_set_dscp)),
7713 		.next = NEXT(action_set_ipv6_dscp),
7714 		.call = parse_vc,
7715 	},
7716 	[ACTION_SET_IPV6_DSCP_VALUE] = {
7717 		.name = "dscp_value",
7718 		.help = "new IPv6 DSCP value to set",
7719 		.next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7720 		.args = ARGS(ARGS_ENTRY
7721 			     (struct rte_flow_action_set_dscp, dscp)),
7722 		.call = parse_vc_conf,
7723 	},
7724 	[ACTION_AGE] = {
7725 		.name = "age",
7726 		.help = "set a specific metadata header",
7727 		.next = NEXT(action_age),
7728 		.priv = PRIV_ACTION(AGE,
7729 			sizeof(struct rte_flow_action_age)),
7730 		.call = parse_vc,
7731 	},
7732 	[ACTION_AGE_TIMEOUT] = {
7733 		.name = "timeout",
7734 		.help = "flow age timeout value",
7735 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
7736 					   timeout, 24)),
7737 		.next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
7738 		.call = parse_vc_conf,
7739 	},
7740 	[ACTION_AGE_UPDATE] = {
7741 		.name = "age_update",
7742 		.help = "update aging parameter",
7743 		.next = NEXT(action_age_update),
7744 		.priv = PRIV_ACTION(AGE,
7745 				    sizeof(struct rte_flow_update_age)),
7746 		.call = parse_vc,
7747 	},
7748 	[ACTION_AGE_UPDATE_TIMEOUT] = {
7749 		.name = "timeout",
7750 		.help = "age timeout update value",
7751 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7752 					   timeout, 24)),
7753 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_UNSIGNED)),
7754 		.call = parse_vc_conf_timeout,
7755 	},
7756 	[ACTION_AGE_UPDATE_TOUCH] = {
7757 		.name = "touch",
7758 		.help = "this flow is touched",
7759 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_BOOLEAN)),
7760 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7761 					   touch, 1)),
7762 		.call = parse_vc_conf,
7763 	},
7764 	[ACTION_SAMPLE] = {
7765 		.name = "sample",
7766 		.help = "set a sample action",
7767 		.next = NEXT(action_sample),
7768 		.priv = PRIV_ACTION(SAMPLE,
7769 			sizeof(struct action_sample_data)),
7770 		.call = parse_vc_action_sample,
7771 	},
7772 	[ACTION_SAMPLE_RATIO] = {
7773 		.name = "ratio",
7774 		.help = "flow sample ratio value",
7775 		.next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
7776 		.args = ARGS(ARGS_ENTRY_ARB
7777 			     (offsetof(struct action_sample_data, conf) +
7778 			      offsetof(struct rte_flow_action_sample, ratio),
7779 			      sizeof(((struct rte_flow_action_sample *)0)->
7780 				     ratio))),
7781 	},
7782 	[ACTION_SAMPLE_INDEX] = {
7783 		.name = "index",
7784 		.help = "the index of sample actions list",
7785 		.next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
7786 	},
7787 	[ACTION_SAMPLE_INDEX_VALUE] = {
7788 		.name = "{index}",
7789 		.type = "COMMON_UNSIGNED",
7790 		.help = "unsigned integer value",
7791 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7792 		.call = parse_vc_action_sample_index,
7793 		.comp = comp_set_sample_index,
7794 	},
7795 	[ACTION_CONNTRACK] = {
7796 		.name = "conntrack",
7797 		.help = "create a conntrack object",
7798 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7799 		.priv = PRIV_ACTION(CONNTRACK,
7800 				    sizeof(struct rte_flow_action_conntrack)),
7801 		.call = parse_vc,
7802 	},
7803 	[ACTION_CONNTRACK_UPDATE] = {
7804 		.name = "conntrack_update",
7805 		.help = "update a conntrack object",
7806 		.next = NEXT(action_update_conntrack),
7807 		.priv = PRIV_ACTION(CONNTRACK,
7808 				    sizeof(struct rte_flow_modify_conntrack)),
7809 		.call = parse_vc,
7810 	},
7811 	[ACTION_CONNTRACK_UPDATE_DIR] = {
7812 		.name = "dir",
7813 		.help = "update a conntrack object direction",
7814 		.next = NEXT(action_update_conntrack),
7815 		.call = parse_vc_action_conntrack_update,
7816 	},
7817 	[ACTION_CONNTRACK_UPDATE_CTX] = {
7818 		.name = "ctx",
7819 		.help = "update a conntrack object context",
7820 		.next = NEXT(action_update_conntrack),
7821 		.call = parse_vc_action_conntrack_update,
7822 	},
7823 	[ACTION_PORT_REPRESENTOR] = {
7824 		.name = "port_representor",
7825 		.help = "at embedded switch level, send matching traffic to the given ethdev",
7826 		.priv = PRIV_ACTION(PORT_REPRESENTOR,
7827 				    sizeof(struct rte_flow_action_ethdev)),
7828 		.next = NEXT(action_port_representor),
7829 		.call = parse_vc,
7830 	},
7831 	[ACTION_PORT_REPRESENTOR_PORT_ID] = {
7832 		.name = "port_id",
7833 		.help = "ethdev port ID",
7834 		.next = NEXT(action_port_representor,
7835 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7836 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7837 					port_id)),
7838 		.call = parse_vc_conf,
7839 	},
7840 	[ACTION_REPRESENTED_PORT] = {
7841 		.name = "represented_port",
7842 		.help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
7843 		.priv = PRIV_ACTION(REPRESENTED_PORT,
7844 				sizeof(struct rte_flow_action_ethdev)),
7845 		.next = NEXT(action_represented_port),
7846 		.call = parse_vc,
7847 	},
7848 	[ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
7849 		.name = "ethdev_port_id",
7850 		.help = "ethdev port ID",
7851 		.next = NEXT(action_represented_port,
7852 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7853 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7854 					port_id)),
7855 		.call = parse_vc_conf,
7856 	},
7857 	/* Indirect action destroy arguments. */
7858 	[INDIRECT_ACTION_DESTROY_ID] = {
7859 		.name = "action_id",
7860 		.help = "specify a indirect action id to destroy",
7861 		.next = NEXT(next_ia_destroy_attr,
7862 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7863 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
7864 					    args.ia_destroy.action_id)),
7865 		.call = parse_ia_destroy,
7866 	},
7867 	/* Indirect action create arguments. */
7868 	[INDIRECT_ACTION_CREATE_ID] = {
7869 		.name = "action_id",
7870 		.help = "specify a indirect action id to create",
7871 		.next = NEXT(next_ia_create_attr,
7872 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7873 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
7874 	},
7875 	[ACTION_INDIRECT] = {
7876 		.name = "indirect",
7877 		.help = "apply indirect action by id",
7878 		.priv = PRIV_ACTION(INDIRECT, 0),
7879 		.next = NEXT(next_ia),
7880 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7881 		.call = parse_vc,
7882 	},
7883 	[ACTION_INDIRECT_LIST] = {
7884 		.name = "indirect_list",
7885 		.help = "apply indirect list action by id",
7886 		.priv = PRIV_ACTION(INDIRECT_LIST,
7887 				    sizeof(struct
7888 					   rte_flow_action_indirect_list)),
7889 		.next = NEXT(next_ial),
7890 		.call = parse_vc,
7891 	},
7892 	[ACTION_INDIRECT_LIST_HANDLE] = {
7893 		.name = "handle",
7894 		.help = "indirect list handle",
7895 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_HANDLE)),
7896 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7897 	},
7898 	[ACTION_INDIRECT_LIST_CONF] = {
7899 		.name = "conf",
7900 		.help = "indirect list configuration",
7901 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_CONF)),
7902 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7903 	},
7904 	[INDIRECT_LIST_ACTION_ID2PTR_HANDLE] = {
7905 		.type = "UNSIGNED",
7906 		.help = "unsigned integer value",
7907 		.call = parse_indlst_id2ptr,
7908 		.comp = comp_none,
7909 	},
7910 	[INDIRECT_LIST_ACTION_ID2PTR_CONF] = {
7911 		.type = "UNSIGNED",
7912 		.help = "unsigned integer value",
7913 		.call = parse_indlst_id2ptr,
7914 		.comp = comp_none,
7915 	},
7916 	[ACTION_SHARED_INDIRECT] = {
7917 		.name = "shared_indirect",
7918 		.help = "apply indirect action by id and port",
7919 		.priv = PRIV_ACTION(INDIRECT, 0),
7920 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_PORT)),
7921 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t)),
7922 			     ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7923 		.call = parse_vc,
7924 	},
7925 	[INDIRECT_ACTION_PORT] = {
7926 		.name = "{indirect_action_port}",
7927 		.type = "INDIRECT_ACTION_PORT",
7928 		.help = "indirect action port",
7929 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
7930 		.call = parse_ia_port,
7931 		.comp = comp_none,
7932 	},
7933 	[INDIRECT_ACTION_ID2PTR] = {
7934 		.name = "{action_id}",
7935 		.type = "INDIRECT_ACTION_ID",
7936 		.help = "indirect action id",
7937 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7938 		.call = parse_ia_id2ptr,
7939 		.comp = comp_none,
7940 	},
7941 	[INDIRECT_ACTION_INGRESS] = {
7942 		.name = "ingress",
7943 		.help = "affect rule to ingress",
7944 		.next = NEXT(next_ia_create_attr),
7945 		.call = parse_ia,
7946 	},
7947 	[INDIRECT_ACTION_EGRESS] = {
7948 		.name = "egress",
7949 		.help = "affect rule to egress",
7950 		.next = NEXT(next_ia_create_attr),
7951 		.call = parse_ia,
7952 	},
7953 	[INDIRECT_ACTION_TRANSFER] = {
7954 		.name = "transfer",
7955 		.help = "affect rule to transfer",
7956 		.next = NEXT(next_ia_create_attr),
7957 		.call = parse_ia,
7958 	},
7959 	[INDIRECT_ACTION_SPEC] = {
7960 		.name = "action",
7961 		.help = "specify action to create indirect handle",
7962 		.next = NEXT(next_action),
7963 	},
7964 	[INDIRECT_ACTION_LIST] = {
7965 		.name = "list",
7966 		.help = "specify actions for indirect handle list",
7967 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
7968 		.call = parse_ia,
7969 	},
7970 	[INDIRECT_ACTION_FLOW_CONF] = {
7971 		.name = "flow_conf",
7972 		.help = "specify actions configuration for indirect handle list",
7973 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
7974 		.call = parse_ia,
7975 	},
7976 	[ACTION_POL_G] = {
7977 		.name = "g_actions",
7978 		.help = "submit a list of associated actions for green",
7979 		.next = NEXT(next_action),
7980 		.call = parse_mp,
7981 	},
7982 	[ACTION_POL_Y] = {
7983 		.name = "y_actions",
7984 		.help = "submit a list of associated actions for yellow",
7985 		.next = NEXT(next_action),
7986 	},
7987 	[ACTION_POL_R] = {
7988 		.name = "r_actions",
7989 		.help = "submit a list of associated actions for red",
7990 		.next = NEXT(next_action),
7991 	},
7992 	[ACTION_QUOTA_CREATE] = {
7993 		.name = "quota_create",
7994 		.help = "create quota action",
7995 		.priv = PRIV_ACTION(QUOTA,
7996 				    sizeof(struct rte_flow_action_quota)),
7997 		.next = NEXT(action_quota_create),
7998 		.call = parse_vc
7999 	},
8000 	[ACTION_QUOTA_CREATE_LIMIT] = {
8001 		.name = "limit",
8002 		.help = "quota limit",
8003 		.next = NEXT(action_quota_create, NEXT_ENTRY(COMMON_UNSIGNED)),
8004 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, quota)),
8005 		.call = parse_vc_conf
8006 	},
8007 	[ACTION_QUOTA_CREATE_MODE] = {
8008 		.name = "mode",
8009 		.help = "quota mode",
8010 		.next = NEXT(action_quota_create,
8011 			     NEXT_ENTRY(ACTION_QUOTA_CREATE_MODE_NAME)),
8012 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, mode)),
8013 		.call = parse_vc_conf
8014 	},
8015 	[ACTION_QUOTA_CREATE_MODE_NAME] = {
8016 		.name = "mode_name",
8017 		.help = "quota mode name",
8018 		.call = parse_quota_mode_name,
8019 		.comp = comp_quota_mode_name
8020 	},
8021 	[ACTION_QUOTA_QU] = {
8022 		.name = "quota_update",
8023 		.help = "update quota action",
8024 		.priv = PRIV_ACTION(QUOTA,
8025 				    sizeof(struct rte_flow_update_quota)),
8026 		.next = NEXT(action_quota_update),
8027 		.call = parse_vc
8028 	},
8029 	[ACTION_QUOTA_QU_LIMIT] = {
8030 		.name = "limit",
8031 		.help = "quota limit",
8032 		.next = NEXT(action_quota_update, NEXT_ENTRY(COMMON_UNSIGNED)),
8033 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, quota)),
8034 		.call = parse_vc_conf
8035 	},
8036 	[ACTION_QUOTA_QU_UPDATE_OP] = {
8037 		.name = "update_op",
8038 		.help = "query update op SET|ADD",
8039 		.next = NEXT(action_quota_update,
8040 			     NEXT_ENTRY(ACTION_QUOTA_QU_UPDATE_OP_NAME)),
8041 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, op)),
8042 		.call = parse_vc_conf
8043 	},
8044 	[ACTION_QUOTA_QU_UPDATE_OP_NAME] = {
8045 		.name = "update_op_name",
8046 		.help = "quota update op name",
8047 		.call = parse_quota_update_name,
8048 		.comp = comp_quota_update_name
8049 	},
8050 
8051 	/* Top-level command. */
8052 	[ADD] = {
8053 		.name = "add",
8054 		.type = "port meter policy {port_id} {arg}",
8055 		.help = "add port meter policy",
8056 		.next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
8057 		.call = parse_init,
8058 	},
8059 	/* Sub-level commands. */
8060 	[ITEM_POL_PORT] = {
8061 		.name = "port",
8062 		.help = "add port meter policy",
8063 		.next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
8064 	},
8065 	[ITEM_POL_METER] = {
8066 		.name = "meter",
8067 		.help = "add port meter policy",
8068 		.next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
8069 	},
8070 	[ITEM_POL_POLICY] = {
8071 		.name = "policy",
8072 		.help = "add port meter policy",
8073 		.next = NEXT(NEXT_ENTRY(ACTION_POL_R),
8074 				NEXT_ENTRY(ACTION_POL_Y),
8075 				NEXT_ENTRY(ACTION_POL_G),
8076 				NEXT_ENTRY(COMMON_POLICY_ID),
8077 				NEXT_ENTRY(COMMON_PORT_ID)),
8078 		.args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
8079 				ARGS_ENTRY(struct buffer, port)),
8080 		.call = parse_mp,
8081 	},
8082 	[ITEM_AGGR_AFFINITY] = {
8083 		.name = "aggr_affinity",
8084 		.help = "match on the aggregated port receiving the packets",
8085 		.priv = PRIV_ITEM(AGGR_AFFINITY,
8086 				  sizeof(struct rte_flow_item_aggr_affinity)),
8087 		.next = NEXT(item_aggr_affinity),
8088 		.call = parse_vc,
8089 	},
8090 	[ITEM_AGGR_AFFINITY_VALUE] = {
8091 		.name = "affinity",
8092 		.help = "aggregated affinity value",
8093 		.next = NEXT(item_aggr_affinity, NEXT_ENTRY(COMMON_UNSIGNED),
8094 			     item_param),
8095 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_aggr_affinity,
8096 					affinity)),
8097 	},
8098 	[ITEM_TX_QUEUE] = {
8099 		.name = "tx_queue",
8100 		.help = "match on the tx queue of send packet",
8101 		.priv = PRIV_ITEM(TX_QUEUE,
8102 				  sizeof(struct rte_flow_item_tx_queue)),
8103 		.next = NEXT(item_tx_queue),
8104 		.call = parse_vc,
8105 	},
8106 	[ITEM_TX_QUEUE_VALUE] = {
8107 		.name = "tx_queue_value",
8108 		.help = "tx queue value",
8109 		.next = NEXT(item_tx_queue, NEXT_ENTRY(COMMON_UNSIGNED),
8110 			     item_param),
8111 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tx_queue,
8112 					tx_queue)),
8113 	},
8114 };
8115 
8116 /** Remove and return last entry from argument stack. */
8117 static const struct arg *
8118 pop_args(struct context *ctx)
8119 {
8120 	return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
8121 }
8122 
8123 /** Add entry on top of the argument stack. */
8124 static int
8125 push_args(struct context *ctx, const struct arg *arg)
8126 {
8127 	if (ctx->args_num == CTX_STACK_SIZE)
8128 		return -1;
8129 	ctx->args[ctx->args_num++] = arg;
8130 	return 0;
8131 }
8132 
8133 /** Spread value into buffer according to bit-mask. */
8134 static size_t
8135 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
8136 {
8137 	uint32_t i = arg->size;
8138 	uint32_t end = 0;
8139 	int sub = 1;
8140 	int add = 0;
8141 	size_t len = 0;
8142 
8143 	if (!arg->mask)
8144 		return 0;
8145 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8146 	if (!arg->hton) {
8147 		i = 0;
8148 		end = arg->size;
8149 		sub = 0;
8150 		add = 1;
8151 	}
8152 #endif
8153 	while (i != end) {
8154 		unsigned int shift = 0;
8155 		uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
8156 
8157 		for (shift = 0; arg->mask[i] >> shift; ++shift) {
8158 			if (!(arg->mask[i] & (1 << shift)))
8159 				continue;
8160 			++len;
8161 			if (!dst)
8162 				continue;
8163 			*buf &= ~(1 << shift);
8164 			*buf |= (val & 1) << shift;
8165 			val >>= 1;
8166 		}
8167 		i += add;
8168 	}
8169 	return len;
8170 }
8171 
8172 /** Compare a string with a partial one of a given length. */
8173 static int
8174 strcmp_partial(const char *full, const char *partial, size_t partial_len)
8175 {
8176 	int r = strncmp(full, partial, partial_len);
8177 
8178 	if (r)
8179 		return r;
8180 	if (strlen(full) <= partial_len)
8181 		return 0;
8182 	return full[partial_len];
8183 }
8184 
8185 /**
8186  * Parse a prefix length and generate a bit-mask.
8187  *
8188  * Last argument (ctx->args) is retrieved to determine mask size, storage
8189  * location and whether the result must use network byte ordering.
8190  */
8191 static int
8192 parse_prefix(struct context *ctx, const struct token *token,
8193 	     const char *str, unsigned int len,
8194 	     void *buf, unsigned int size)
8195 {
8196 	const struct arg *arg = pop_args(ctx);
8197 	static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
8198 	char *end;
8199 	uintmax_t u;
8200 	unsigned int bytes;
8201 	unsigned int extra;
8202 
8203 	(void)token;
8204 	/* Argument is expected. */
8205 	if (!arg)
8206 		return -1;
8207 	errno = 0;
8208 	u = strtoumax(str, &end, 0);
8209 	if (errno || (size_t)(end - str) != len)
8210 		goto error;
8211 	if (arg->mask) {
8212 		uintmax_t v = 0;
8213 
8214 		extra = arg_entry_bf_fill(NULL, 0, arg);
8215 		if (u > extra)
8216 			goto error;
8217 		if (!ctx->object)
8218 			return len;
8219 		extra -= u;
8220 		while (u--)
8221 			(v <<= 1, v |= 1);
8222 		v <<= extra;
8223 		if (!arg_entry_bf_fill(ctx->object, v, arg) ||
8224 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
8225 			goto error;
8226 		return len;
8227 	}
8228 	bytes = u / 8;
8229 	extra = u % 8;
8230 	size = arg->size;
8231 	if (bytes > size || bytes + !!extra > size)
8232 		goto error;
8233 	if (!ctx->object)
8234 		return len;
8235 	buf = (uint8_t *)ctx->object + arg->offset;
8236 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8237 	if (!arg->hton) {
8238 		memset((uint8_t *)buf + size - bytes, 0xff, bytes);
8239 		memset(buf, 0x00, size - bytes);
8240 		if (extra)
8241 			((uint8_t *)buf)[size - bytes - 1] = conv[extra];
8242 	} else
8243 #endif
8244 	{
8245 		memset(buf, 0xff, bytes);
8246 		memset((uint8_t *)buf + bytes, 0x00, size - bytes);
8247 		if (extra)
8248 			((uint8_t *)buf)[bytes] = conv[extra];
8249 	}
8250 	if (ctx->objmask)
8251 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8252 	return len;
8253 error:
8254 	push_args(ctx, arg);
8255 	return -1;
8256 }
8257 
8258 /** Default parsing function for token name matching. */
8259 static int
8260 parse_default(struct context *ctx, const struct token *token,
8261 	      const char *str, unsigned int len,
8262 	      void *buf, unsigned int size)
8263 {
8264 	(void)ctx;
8265 	(void)buf;
8266 	(void)size;
8267 	if (strcmp_partial(token->name, str, len))
8268 		return -1;
8269 	return len;
8270 }
8271 
8272 /** Parse flow command, initialize output buffer for subsequent tokens. */
8273 static int
8274 parse_init(struct context *ctx, const struct token *token,
8275 	   const char *str, unsigned int len,
8276 	   void *buf, unsigned int size)
8277 {
8278 	struct buffer *out = buf;
8279 
8280 	/* Token name must match. */
8281 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8282 		return -1;
8283 	/* Nothing else to do if there is no buffer. */
8284 	if (!out)
8285 		return len;
8286 	/* Make sure buffer is large enough. */
8287 	if (size < sizeof(*out))
8288 		return -1;
8289 	/* Initialize buffer. */
8290 	memset(out, 0x00, sizeof(*out));
8291 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
8292 	ctx->objdata = 0;
8293 	ctx->object = out;
8294 	ctx->objmask = NULL;
8295 	return len;
8296 }
8297 
8298 /** Parse tokens for indirect action commands. */
8299 static int
8300 parse_ia(struct context *ctx, const struct token *token,
8301 	 const char *str, unsigned int len,
8302 	 void *buf, unsigned int size)
8303 {
8304 	struct buffer *out = buf;
8305 
8306 	/* Token name must match. */
8307 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8308 		return -1;
8309 	/* Nothing else to do if there is no buffer. */
8310 	if (!out)
8311 		return len;
8312 	if (!out->command) {
8313 		if (ctx->curr != INDIRECT_ACTION)
8314 			return -1;
8315 		if (sizeof(*out) > size)
8316 			return -1;
8317 		out->command = ctx->curr;
8318 		ctx->objdata = 0;
8319 		ctx->object = out;
8320 		ctx->objmask = NULL;
8321 		out->args.vc.data = (uint8_t *)out + size;
8322 		return len;
8323 	}
8324 	switch (ctx->curr) {
8325 	case INDIRECT_ACTION_CREATE:
8326 	case INDIRECT_ACTION_UPDATE:
8327 	case INDIRECT_ACTION_QUERY_UPDATE:
8328 		out->args.vc.actions =
8329 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8330 					       sizeof(double));
8331 		out->args.vc.attr.group = UINT32_MAX;
8332 		/* fallthrough */
8333 	case INDIRECT_ACTION_QUERY:
8334 		out->command = ctx->curr;
8335 		ctx->objdata = 0;
8336 		ctx->object = out;
8337 		ctx->objmask = NULL;
8338 		return len;
8339 	case INDIRECT_ACTION_EGRESS:
8340 		out->args.vc.attr.egress = 1;
8341 		return len;
8342 	case INDIRECT_ACTION_INGRESS:
8343 		out->args.vc.attr.ingress = 1;
8344 		return len;
8345 	case INDIRECT_ACTION_TRANSFER:
8346 		out->args.vc.attr.transfer = 1;
8347 		return len;
8348 	case INDIRECT_ACTION_QU_MODE:
8349 		return len;
8350 	case INDIRECT_ACTION_LIST:
8351 		out->command = INDIRECT_ACTION_LIST_CREATE;
8352 		return len;
8353 	case INDIRECT_ACTION_FLOW_CONF:
8354 		out->command = INDIRECT_ACTION_FLOW_CONF_CREATE;
8355 		return len;
8356 	default:
8357 		return -1;
8358 	}
8359 }
8360 
8361 
8362 /** Parse tokens for indirect action destroy command. */
8363 static int
8364 parse_ia_destroy(struct context *ctx, const struct token *token,
8365 		 const char *str, unsigned int len,
8366 		 void *buf, unsigned int size)
8367 {
8368 	struct buffer *out = buf;
8369 	uint32_t *action_id;
8370 
8371 	/* Token name must match. */
8372 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8373 		return -1;
8374 	/* Nothing else to do if there is no buffer. */
8375 	if (!out)
8376 		return len;
8377 	if (!out->command || out->command == INDIRECT_ACTION) {
8378 		if (ctx->curr != INDIRECT_ACTION_DESTROY)
8379 			return -1;
8380 		if (sizeof(*out) > size)
8381 			return -1;
8382 		out->command = ctx->curr;
8383 		ctx->objdata = 0;
8384 		ctx->object = out;
8385 		ctx->objmask = NULL;
8386 		out->args.ia_destroy.action_id =
8387 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8388 					       sizeof(double));
8389 		return len;
8390 	}
8391 	action_id = out->args.ia_destroy.action_id
8392 		    + out->args.ia_destroy.action_id_n++;
8393 	if ((uint8_t *)action_id > (uint8_t *)out + size)
8394 		return -1;
8395 	ctx->objdata = 0;
8396 	ctx->object = action_id;
8397 	ctx->objmask = NULL;
8398 	return len;
8399 }
8400 
8401 /** Parse tokens for indirect action commands. */
8402 static int
8403 parse_qia(struct context *ctx, const struct token *token,
8404 	  const char *str, unsigned int len,
8405 	  void *buf, unsigned int size)
8406 {
8407 	struct buffer *out = buf;
8408 
8409 	/* Token name must match. */
8410 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8411 		return -1;
8412 	/* Nothing else to do if there is no buffer. */
8413 	if (!out)
8414 		return len;
8415 	if (!out->command) {
8416 		if (ctx->curr != QUEUE)
8417 			return -1;
8418 		if (sizeof(*out) > size)
8419 			return -1;
8420 		out->args.vc.data = (uint8_t *)out + size;
8421 		return len;
8422 	}
8423 	switch (ctx->curr) {
8424 	case QUEUE_INDIRECT_ACTION:
8425 		return len;
8426 	case QUEUE_INDIRECT_ACTION_CREATE:
8427 	case QUEUE_INDIRECT_ACTION_UPDATE:
8428 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
8429 		out->args.vc.actions =
8430 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8431 					       sizeof(double));
8432 		out->args.vc.attr.group = UINT32_MAX;
8433 		/* fallthrough */
8434 	case QUEUE_INDIRECT_ACTION_QUERY:
8435 		out->command = ctx->curr;
8436 		ctx->objdata = 0;
8437 		ctx->object = out;
8438 		ctx->objmask = NULL;
8439 		return len;
8440 	case QUEUE_INDIRECT_ACTION_EGRESS:
8441 		out->args.vc.attr.egress = 1;
8442 		return len;
8443 	case QUEUE_INDIRECT_ACTION_INGRESS:
8444 		out->args.vc.attr.ingress = 1;
8445 		return len;
8446 	case QUEUE_INDIRECT_ACTION_TRANSFER:
8447 		out->args.vc.attr.transfer = 1;
8448 		return len;
8449 	case QUEUE_INDIRECT_ACTION_CREATE_POSTPONE:
8450 		return len;
8451 	case QUEUE_INDIRECT_ACTION_QU_MODE:
8452 		return len;
8453 	case QUEUE_INDIRECT_ACTION_LIST:
8454 		out->command = QUEUE_INDIRECT_ACTION_LIST_CREATE;
8455 		return len;
8456 	default:
8457 		return -1;
8458 	}
8459 }
8460 
8461 /** Parse tokens for indirect action destroy command. */
8462 static int
8463 parse_qia_destroy(struct context *ctx, const struct token *token,
8464 		  const char *str, unsigned int len,
8465 		  void *buf, unsigned int size)
8466 {
8467 	struct buffer *out = buf;
8468 	uint32_t *action_id;
8469 
8470 	/* Token name must match. */
8471 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8472 		return -1;
8473 	/* Nothing else to do if there is no buffer. */
8474 	if (!out)
8475 		return len;
8476 	if (!out->command || out->command == QUEUE) {
8477 		if (ctx->curr != QUEUE_INDIRECT_ACTION_DESTROY)
8478 			return -1;
8479 		if (sizeof(*out) > size)
8480 			return -1;
8481 		out->command = ctx->curr;
8482 		ctx->objdata = 0;
8483 		ctx->object = out;
8484 		ctx->objmask = NULL;
8485 		out->args.ia_destroy.action_id =
8486 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8487 					       sizeof(double));
8488 		return len;
8489 	}
8490 	switch (ctx->curr) {
8491 	case QUEUE_INDIRECT_ACTION:
8492 		out->command = ctx->curr;
8493 		ctx->objdata = 0;
8494 		ctx->object = out;
8495 		ctx->objmask = NULL;
8496 		return len;
8497 	case QUEUE_INDIRECT_ACTION_DESTROY_ID:
8498 		action_id = out->args.ia_destroy.action_id
8499 				+ out->args.ia_destroy.action_id_n++;
8500 		if ((uint8_t *)action_id > (uint8_t *)out + size)
8501 			return -1;
8502 		ctx->objdata = 0;
8503 		ctx->object = action_id;
8504 		ctx->objmask = NULL;
8505 		return len;
8506 	case QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE:
8507 		return len;
8508 	default:
8509 		return -1;
8510 	}
8511 }
8512 
8513 /** Parse tokens for meter policy action commands. */
8514 static int
8515 parse_mp(struct context *ctx, const struct token *token,
8516 	const char *str, unsigned int len,
8517 	void *buf, unsigned int size)
8518 {
8519 	struct buffer *out = buf;
8520 
8521 	/* Token name must match. */
8522 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8523 		return -1;
8524 	/* Nothing else to do if there is no buffer. */
8525 	if (!out)
8526 		return len;
8527 	if (!out->command) {
8528 		if (ctx->curr != ITEM_POL_POLICY)
8529 			return -1;
8530 		if (sizeof(*out) > size)
8531 			return -1;
8532 		out->command = ctx->curr;
8533 		ctx->objdata = 0;
8534 		ctx->object = out;
8535 		ctx->objmask = NULL;
8536 		out->args.vc.data = (uint8_t *)out + size;
8537 		return len;
8538 	}
8539 	switch (ctx->curr) {
8540 	case ACTION_POL_G:
8541 		out->args.vc.actions =
8542 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8543 					sizeof(double));
8544 		out->command = ctx->curr;
8545 		ctx->objdata = 0;
8546 		ctx->object = out;
8547 		ctx->objmask = NULL;
8548 		return len;
8549 	default:
8550 		return -1;
8551 	}
8552 }
8553 
8554 /** Parse tokens for validate/create commands. */
8555 static int
8556 parse_vc(struct context *ctx, const struct token *token,
8557 	 const char *str, unsigned int len,
8558 	 void *buf, unsigned int size)
8559 {
8560 	struct buffer *out = buf;
8561 	uint8_t *data;
8562 	uint32_t data_size;
8563 
8564 	/* Token name must match. */
8565 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8566 		return -1;
8567 	/* Nothing else to do if there is no buffer. */
8568 	if (!out)
8569 		return len;
8570 	if (!out->command) {
8571 		if (ctx->curr != VALIDATE && ctx->curr != CREATE &&
8572 		    ctx->curr != PATTERN_TEMPLATE_CREATE &&
8573 		    ctx->curr != ACTIONS_TEMPLATE_CREATE &&
8574 		    ctx->curr != UPDATE)
8575 			return -1;
8576 		if (ctx->curr == UPDATE)
8577 			out->args.vc.pattern =
8578 				(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8579 						       sizeof(double));
8580 		if (sizeof(*out) > size)
8581 			return -1;
8582 		out->command = ctx->curr;
8583 		ctx->objdata = 0;
8584 		ctx->object = out;
8585 		ctx->objmask = NULL;
8586 		out->args.vc.data = (uint8_t *)out + size;
8587 		return len;
8588 	}
8589 	ctx->objdata = 0;
8590 	switch (ctx->curr) {
8591 	default:
8592 		ctx->object = &out->args.vc.attr;
8593 		break;
8594 	case VC_TUNNEL_SET:
8595 	case VC_TUNNEL_MATCH:
8596 		ctx->object = &out->args.vc.tunnel_ops;
8597 		break;
8598 	case VC_USER_ID:
8599 		ctx->object = out;
8600 		break;
8601 	}
8602 	ctx->objmask = NULL;
8603 	switch (ctx->curr) {
8604 	case VC_GROUP:
8605 	case VC_PRIORITY:
8606 	case VC_USER_ID:
8607 		return len;
8608 	case VC_TUNNEL_SET:
8609 		out->args.vc.tunnel_ops.enabled = 1;
8610 		out->args.vc.tunnel_ops.actions = 1;
8611 		return len;
8612 	case VC_TUNNEL_MATCH:
8613 		out->args.vc.tunnel_ops.enabled = 1;
8614 		out->args.vc.tunnel_ops.items = 1;
8615 		return len;
8616 	case VC_INGRESS:
8617 		out->args.vc.attr.ingress = 1;
8618 		return len;
8619 	case VC_EGRESS:
8620 		out->args.vc.attr.egress = 1;
8621 		return len;
8622 	case VC_TRANSFER:
8623 		out->args.vc.attr.transfer = 1;
8624 		return len;
8625 	case ITEM_PATTERN:
8626 		out->args.vc.pattern =
8627 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8628 					       sizeof(double));
8629 		ctx->object = out->args.vc.pattern;
8630 		ctx->objmask = NULL;
8631 		return len;
8632 	case ITEM_END:
8633 		if ((out->command == VALIDATE || out->command == CREATE) &&
8634 		    ctx->last)
8635 			return -1;
8636 		if (out->command == PATTERN_TEMPLATE_CREATE &&
8637 		    !ctx->last)
8638 			return -1;
8639 		break;
8640 	case ACTIONS:
8641 		out->args.vc.actions = out->args.vc.pattern ?
8642 			(void *)RTE_ALIGN_CEIL((uintptr_t)
8643 					       (out->args.vc.pattern +
8644 						out->args.vc.pattern_n),
8645 					       sizeof(double)) :
8646 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8647 					       sizeof(double));
8648 		ctx->object = out->args.vc.actions;
8649 		ctx->objmask = NULL;
8650 		return len;
8651 	case VC_IS_USER_ID:
8652 		out->args.vc.user_id = true;
8653 		return len;
8654 	default:
8655 		if (!token->priv)
8656 			return -1;
8657 		break;
8658 	}
8659 	if (!out->args.vc.actions) {
8660 		const struct parse_item_priv *priv = token->priv;
8661 		struct rte_flow_item *item =
8662 			out->args.vc.pattern + out->args.vc.pattern_n;
8663 
8664 		data_size = priv->size * 3; /* spec, last, mask */
8665 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8666 					       (out->args.vc.data - data_size),
8667 					       sizeof(double));
8668 		if ((uint8_t *)item + sizeof(*item) > data)
8669 			return -1;
8670 		*item = (struct rte_flow_item){
8671 			.type = priv->type,
8672 		};
8673 		++out->args.vc.pattern_n;
8674 		ctx->object = item;
8675 		ctx->objmask = NULL;
8676 	} else {
8677 		const struct parse_action_priv *priv = token->priv;
8678 		struct rte_flow_action *action =
8679 			out->args.vc.actions + out->args.vc.actions_n;
8680 
8681 		data_size = priv->size; /* configuration */
8682 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8683 					       (out->args.vc.data - data_size),
8684 					       sizeof(double));
8685 		if ((uint8_t *)action + sizeof(*action) > data)
8686 			return -1;
8687 		*action = (struct rte_flow_action){
8688 			.type = priv->type,
8689 			.conf = data_size ? data : NULL,
8690 		};
8691 		++out->args.vc.actions_n;
8692 		ctx->object = action;
8693 		ctx->objmask = NULL;
8694 	}
8695 	memset(data, 0, data_size);
8696 	out->args.vc.data = data;
8697 	ctx->objdata = data_size;
8698 	return len;
8699 }
8700 
8701 /** Parse pattern item parameter type. */
8702 static int
8703 parse_vc_spec(struct context *ctx, const struct token *token,
8704 	      const char *str, unsigned int len,
8705 	      void *buf, unsigned int size)
8706 {
8707 	struct buffer *out = buf;
8708 	struct rte_flow_item *item;
8709 	uint32_t data_size;
8710 	int index;
8711 	int objmask = 0;
8712 
8713 	(void)size;
8714 	/* Token name must match. */
8715 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8716 		return -1;
8717 	/* Parse parameter types. */
8718 	switch (ctx->curr) {
8719 		static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
8720 
8721 	case ITEM_PARAM_IS:
8722 		index = 0;
8723 		objmask = 1;
8724 		break;
8725 	case ITEM_PARAM_SPEC:
8726 		index = 0;
8727 		break;
8728 	case ITEM_PARAM_LAST:
8729 		index = 1;
8730 		break;
8731 	case ITEM_PARAM_PREFIX:
8732 		/* Modify next token to expect a prefix. */
8733 		if (ctx->next_num < 2)
8734 			return -1;
8735 		ctx->next[ctx->next_num - 2] = prefix;
8736 		/* Fall through. */
8737 	case ITEM_PARAM_MASK:
8738 		index = 2;
8739 		break;
8740 	default:
8741 		return -1;
8742 	}
8743 	/* Nothing else to do if there is no buffer. */
8744 	if (!out)
8745 		return len;
8746 	if (!out->args.vc.pattern_n)
8747 		return -1;
8748 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8749 	data_size = ctx->objdata / 3; /* spec, last, mask */
8750 	/* Point to selected object. */
8751 	ctx->object = out->args.vc.data + (data_size * index);
8752 	if (objmask) {
8753 		ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
8754 		item->mask = ctx->objmask;
8755 	} else
8756 		ctx->objmask = NULL;
8757 	/* Update relevant item pointer. */
8758 	*((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
8759 		ctx->object;
8760 	return len;
8761 }
8762 
8763 /** Parse action configuration field. */
8764 static int
8765 parse_vc_conf(struct context *ctx, const struct token *token,
8766 	      const char *str, unsigned int len,
8767 	      void *buf, unsigned int size)
8768 {
8769 	struct buffer *out = buf;
8770 
8771 	(void)size;
8772 	/* Token name must match. */
8773 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8774 		return -1;
8775 	/* Nothing else to do if there is no buffer. */
8776 	if (!out)
8777 		return len;
8778 	/* Point to selected object. */
8779 	ctx->object = out->args.vc.data;
8780 	ctx->objmask = NULL;
8781 	return len;
8782 }
8783 
8784 /** Parse action configuration field. */
8785 static int
8786 parse_vc_conf_timeout(struct context *ctx, const struct token *token,
8787 		      const char *str, unsigned int len,
8788 		      void *buf, unsigned int size)
8789 {
8790 	struct buffer *out = buf;
8791 	struct rte_flow_update_age *update;
8792 
8793 	(void)size;
8794 	if (ctx->curr != ACTION_AGE_UPDATE_TIMEOUT)
8795 		return -1;
8796 	/* Token name must match. */
8797 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8798 		return -1;
8799 	/* Nothing else to do if there is no buffer. */
8800 	if (!out)
8801 		return len;
8802 	/* Point to selected object. */
8803 	ctx->object = out->args.vc.data;
8804 	ctx->objmask = NULL;
8805 	/* Update the timeout is valid. */
8806 	update = (struct rte_flow_update_age *)out->args.vc.data;
8807 	update->timeout_valid = 1;
8808 	return len;
8809 }
8810 
8811 /** Parse eCPRI common header type field. */
8812 static int
8813 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
8814 			 const char *str, unsigned int len,
8815 			 void *buf, unsigned int size)
8816 {
8817 	struct rte_flow_item_ecpri *ecpri;
8818 	struct rte_flow_item_ecpri *ecpri_mask;
8819 	struct rte_flow_item *item;
8820 	uint32_t data_size;
8821 	uint8_t msg_type;
8822 	struct buffer *out = buf;
8823 	const struct arg *arg;
8824 
8825 	(void)size;
8826 	/* Token name must match. */
8827 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8828 		return -1;
8829 	switch (ctx->curr) {
8830 	case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
8831 		msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
8832 		break;
8833 	case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
8834 		msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
8835 		break;
8836 	case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
8837 		msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
8838 		break;
8839 	default:
8840 		return -1;
8841 	}
8842 	if (!ctx->object)
8843 		return len;
8844 	arg = pop_args(ctx);
8845 	if (!arg)
8846 		return -1;
8847 	ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
8848 	ecpri->hdr.common.type = msg_type;
8849 	data_size = ctx->objdata / 3; /* spec, last, mask */
8850 	ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
8851 						    (data_size * 2));
8852 	ecpri_mask->hdr.common.type = 0xFF;
8853 	if (arg->hton) {
8854 		ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
8855 		ecpri_mask->hdr.common.u32 =
8856 				rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
8857 	}
8858 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8859 	item->spec = ecpri;
8860 	item->mask = ecpri_mask;
8861 	return len;
8862 }
8863 
8864 /** Parse L2TPv2 common header type field. */
8865 static int
8866 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
8867 			 const char *str, unsigned int len,
8868 			 void *buf, unsigned int size)
8869 {
8870 	struct rte_flow_item_l2tpv2 *l2tpv2;
8871 	struct rte_flow_item_l2tpv2 *l2tpv2_mask;
8872 	struct rte_flow_item *item;
8873 	uint32_t data_size;
8874 	uint16_t msg_type = 0;
8875 	struct buffer *out = buf;
8876 	const struct arg *arg;
8877 
8878 	(void)size;
8879 	/* Token name must match. */
8880 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8881 		return -1;
8882 	switch (ctx->curr) {
8883 	case ITEM_L2TPV2_TYPE_DATA:
8884 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
8885 		break;
8886 	case ITEM_L2TPV2_TYPE_DATA_L:
8887 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
8888 		break;
8889 	case ITEM_L2TPV2_TYPE_DATA_S:
8890 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
8891 		break;
8892 	case ITEM_L2TPV2_TYPE_DATA_O:
8893 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
8894 		break;
8895 	case ITEM_L2TPV2_TYPE_DATA_L_S:
8896 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
8897 		break;
8898 	case ITEM_L2TPV2_TYPE_CTRL:
8899 		msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
8900 		break;
8901 	default:
8902 		return -1;
8903 	}
8904 	if (!ctx->object)
8905 		return len;
8906 	arg = pop_args(ctx);
8907 	if (!arg)
8908 		return -1;
8909 	l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
8910 	l2tpv2->hdr.common.flags_version |= msg_type;
8911 	data_size = ctx->objdata / 3; /* spec, last, mask */
8912 	l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
8913 						    (data_size * 2));
8914 	l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
8915 	if (arg->hton) {
8916 		l2tpv2->hdr.common.flags_version =
8917 			rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
8918 		l2tpv2_mask->hdr.common.flags_version =
8919 		    rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
8920 	}
8921 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8922 	item->spec = l2tpv2;
8923 	item->mask = l2tpv2_mask;
8924 	return len;
8925 }
8926 
8927 /** Parse operation for compare match item. */
8928 static int
8929 parse_vc_compare_op(struct context *ctx, const struct token *token,
8930 			 const char *str, unsigned int len, void *buf,
8931 			 unsigned int size)
8932 {
8933 	struct rte_flow_item_compare *compare_item;
8934 	unsigned int i;
8935 
8936 	(void)token;
8937 	(void)buf;
8938 	(void)size;
8939 	if (ctx->curr != ITEM_COMPARE_OP_VALUE)
8940 		return -1;
8941 	for (i = 0; compare_ops[i]; ++i)
8942 		if (!strcmp_partial(compare_ops[i], str, len))
8943 			break;
8944 	if (!compare_ops[i])
8945 		return -1;
8946 	if (!ctx->object)
8947 		return len;
8948 	compare_item = ctx->object;
8949 	compare_item->operation = (enum rte_flow_item_compare_op)i;
8950 	return len;
8951 }
8952 
8953 /** Parse id for compare match item. */
8954 static int
8955 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
8956 			  const char *str, unsigned int len, void *buf,
8957 			  unsigned int size)
8958 {
8959 	struct rte_flow_item_compare *compare_item;
8960 	unsigned int i;
8961 
8962 	(void)token;
8963 	(void)buf;
8964 	(void)size;
8965 	if (ctx->curr != ITEM_COMPARE_FIELD_A_TYPE_VALUE &&
8966 		ctx->curr != ITEM_COMPARE_FIELD_B_TYPE_VALUE)
8967 		return -1;
8968 	for (i = 0; flow_field_ids[i]; ++i)
8969 		if (!strcmp_partial(flow_field_ids[i], str, len))
8970 			break;
8971 	if (!flow_field_ids[i])
8972 		return -1;
8973 	if (!ctx->object)
8974 		return len;
8975 	compare_item = ctx->object;
8976 	if (ctx->curr == ITEM_COMPARE_FIELD_A_TYPE_VALUE)
8977 		compare_item->a.field = (enum rte_flow_field_id)i;
8978 	else
8979 		compare_item->b.field = (enum rte_flow_field_id)i;
8980 	return len;
8981 }
8982 
8983 /** Parse level for compare match item. */
8984 static int
8985 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
8986 			     const char *str, unsigned int len, void *buf,
8987 			     unsigned int size)
8988 {
8989 	struct rte_flow_item_compare *compare_item;
8990 	struct flex_item *fp = NULL;
8991 	uint32_t val;
8992 	struct buffer *out = buf;
8993 	char *end;
8994 
8995 	(void)token;
8996 	(void)size;
8997 	if (ctx->curr != ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
8998 		ctx->curr != ITEM_COMPARE_FIELD_B_LEVEL_VALUE)
8999 		return -1;
9000 	if (!ctx->object)
9001 		return len;
9002 	compare_item = ctx->object;
9003 	errno = 0;
9004 	val = strtoumax(str, &end, 0);
9005 	if (errno || (size_t)(end - str) != len)
9006 		return -1;
9007 	/* No need to validate action template mask value */
9008 	if (out->args.vc.masks) {
9009 		if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE)
9010 			compare_item->a.level = val;
9011 		else
9012 			compare_item->b.level = val;
9013 		return len;
9014 	}
9015 	if ((ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
9016 		compare_item->a.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
9017 		(ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE &&
9018 		compare_item->b.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
9019 		if (val >= FLEX_MAX_PARSERS_NUM) {
9020 			printf("Bad flex item handle\n");
9021 			return -1;
9022 		}
9023 		fp = flex_items[ctx->port][val];
9024 		if (!fp) {
9025 			printf("Bad flex item handle\n");
9026 			return -1;
9027 		}
9028 	}
9029 	if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE) {
9030 		if (compare_item->a.field != RTE_FLOW_FIELD_FLEX_ITEM)
9031 			compare_item->a.level = val;
9032 		else
9033 			compare_item->a.flex_handle = fp->flex_handle;
9034 	} else if (ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE) {
9035 		if (compare_item->b.field != RTE_FLOW_FIELD_FLEX_ITEM)
9036 			compare_item->b.level = val;
9037 		else
9038 			compare_item->b.flex_handle = fp->flex_handle;
9039 	}
9040 	return len;
9041 }
9042 
9043 /** Parse meter color action type. */
9044 static int
9045 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
9046 				const char *str, unsigned int len,
9047 				void *buf, unsigned int size)
9048 {
9049 	struct rte_flow_action *action_data;
9050 	struct rte_flow_action_meter_color *conf;
9051 	enum rte_color color;
9052 
9053 	(void)buf;
9054 	(void)size;
9055 	/* Token name must match. */
9056 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9057 		return -1;
9058 	switch (ctx->curr) {
9059 	case ACTION_METER_COLOR_GREEN:
9060 		color = RTE_COLOR_GREEN;
9061 	break;
9062 	case ACTION_METER_COLOR_YELLOW:
9063 		color = RTE_COLOR_YELLOW;
9064 	break;
9065 	case ACTION_METER_COLOR_RED:
9066 		color = RTE_COLOR_RED;
9067 	break;
9068 	default:
9069 		return -1;
9070 	}
9071 
9072 	if (!ctx->object)
9073 		return len;
9074 	action_data = ctx->object;
9075 	conf = (struct rte_flow_action_meter_color *)
9076 					(uintptr_t)(action_data->conf);
9077 	conf->color = color;
9078 	return len;
9079 }
9080 
9081 /** Parse RSS action. */
9082 static int
9083 parse_vc_action_rss(struct context *ctx, const struct token *token,
9084 		    const char *str, unsigned int len,
9085 		    void *buf, unsigned int size)
9086 {
9087 	struct buffer *out = buf;
9088 	struct rte_flow_action *action;
9089 	struct action_rss_data *action_rss_data;
9090 	unsigned int i;
9091 	int ret;
9092 
9093 	ret = parse_vc(ctx, token, str, len, buf, size);
9094 	if (ret < 0)
9095 		return ret;
9096 	/* Nothing else to do if there is no buffer. */
9097 	if (!out)
9098 		return ret;
9099 	if (!out->args.vc.actions_n)
9100 		return -1;
9101 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9102 	/* Point to selected object. */
9103 	ctx->object = out->args.vc.data;
9104 	ctx->objmask = NULL;
9105 	/* Set up default configuration. */
9106 	action_rss_data = ctx->object;
9107 	*action_rss_data = (struct action_rss_data){
9108 		.conf = (struct rte_flow_action_rss){
9109 			.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
9110 			.level = 0,
9111 			.types = rss_hf,
9112 			.key_len = 0,
9113 			.queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
9114 			.key = NULL,
9115 			.queue = action_rss_data->queue,
9116 		},
9117 		.queue = { 0 },
9118 	};
9119 	for (i = 0; i < action_rss_data->conf.queue_num; ++i)
9120 		action_rss_data->queue[i] = i;
9121 	action->conf = &action_rss_data->conf;
9122 	return ret;
9123 }
9124 
9125 /**
9126  * Parse func field for RSS action.
9127  *
9128  * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
9129  * ACTION_RSS_FUNC_* index that called this function.
9130  */
9131 static int
9132 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
9133 			 const char *str, unsigned int len,
9134 			 void *buf, unsigned int size)
9135 {
9136 	struct action_rss_data *action_rss_data;
9137 	enum rte_eth_hash_function func;
9138 
9139 	(void)buf;
9140 	(void)size;
9141 	/* Token name must match. */
9142 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9143 		return -1;
9144 	switch (ctx->curr) {
9145 	case ACTION_RSS_FUNC_DEFAULT:
9146 		func = RTE_ETH_HASH_FUNCTION_DEFAULT;
9147 		break;
9148 	case ACTION_RSS_FUNC_TOEPLITZ:
9149 		func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
9150 		break;
9151 	case ACTION_RSS_FUNC_SIMPLE_XOR:
9152 		func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
9153 		break;
9154 	case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
9155 		func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
9156 		break;
9157 	default:
9158 		return -1;
9159 	}
9160 	if (!ctx->object)
9161 		return len;
9162 	action_rss_data = ctx->object;
9163 	action_rss_data->conf.func = func;
9164 	return len;
9165 }
9166 
9167 /**
9168  * Parse type field for RSS action.
9169  *
9170  * Valid tokens are type field names and the "end" token.
9171  */
9172 static int
9173 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
9174 			  const char *str, unsigned int len,
9175 			  void *buf, unsigned int size)
9176 {
9177 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
9178 	struct action_rss_data *action_rss_data;
9179 	unsigned int i;
9180 
9181 	(void)token;
9182 	(void)buf;
9183 	(void)size;
9184 	if (ctx->curr != ACTION_RSS_TYPE)
9185 		return -1;
9186 	if (!(ctx->objdata >> 16) && ctx->object) {
9187 		action_rss_data = ctx->object;
9188 		action_rss_data->conf.types = 0;
9189 	}
9190 	if (!strcmp_partial("end", str, len)) {
9191 		ctx->objdata &= 0xffff;
9192 		return len;
9193 	}
9194 	for (i = 0; rss_type_table[i].str; ++i)
9195 		if (!strcmp_partial(rss_type_table[i].str, str, len))
9196 			break;
9197 	if (!rss_type_table[i].str)
9198 		return -1;
9199 	ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
9200 	/* Repeat token. */
9201 	if (ctx->next_num == RTE_DIM(ctx->next))
9202 		return -1;
9203 	ctx->next[ctx->next_num++] = next;
9204 	if (!ctx->object)
9205 		return len;
9206 	action_rss_data = ctx->object;
9207 	action_rss_data->conf.types |= rss_type_table[i].rss_type;
9208 	return len;
9209 }
9210 
9211 /**
9212  * Parse queue field for RSS action.
9213  *
9214  * Valid tokens are queue indices and the "end" token.
9215  */
9216 static int
9217 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
9218 			  const char *str, unsigned int len,
9219 			  void *buf, unsigned int size)
9220 {
9221 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
9222 	struct action_rss_data *action_rss_data;
9223 	const struct arg *arg;
9224 	int ret;
9225 	int i;
9226 
9227 	(void)token;
9228 	(void)buf;
9229 	(void)size;
9230 	if (ctx->curr != ACTION_RSS_QUEUE)
9231 		return -1;
9232 	i = ctx->objdata >> 16;
9233 	if (!strcmp_partial("end", str, len)) {
9234 		ctx->objdata &= 0xffff;
9235 		goto end;
9236 	}
9237 	if (i >= ACTION_RSS_QUEUE_NUM)
9238 		return -1;
9239 	arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
9240 			     i * sizeof(action_rss_data->queue[i]),
9241 			     sizeof(action_rss_data->queue[i]));
9242 	if (push_args(ctx, arg))
9243 		return -1;
9244 	ret = parse_int(ctx, token, str, len, NULL, 0);
9245 	if (ret < 0) {
9246 		pop_args(ctx);
9247 		return -1;
9248 	}
9249 	++i;
9250 	ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
9251 	/* Repeat token. */
9252 	if (ctx->next_num == RTE_DIM(ctx->next))
9253 		return -1;
9254 	ctx->next[ctx->next_num++] = next;
9255 end:
9256 	if (!ctx->object)
9257 		return len;
9258 	action_rss_data = ctx->object;
9259 	action_rss_data->conf.queue_num = i;
9260 	action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
9261 	return len;
9262 }
9263 
9264 /** Setup VXLAN encap configuration. */
9265 static int
9266 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
9267 {
9268 	/* Set up default configuration. */
9269 	*action_vxlan_encap_data = (struct action_vxlan_encap_data){
9270 		.conf = (struct rte_flow_action_vxlan_encap){
9271 			.definition = action_vxlan_encap_data->items,
9272 		},
9273 		.items = {
9274 			{
9275 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9276 				.spec = &action_vxlan_encap_data->item_eth,
9277 				.mask = &rte_flow_item_eth_mask,
9278 			},
9279 			{
9280 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9281 				.spec = &action_vxlan_encap_data->item_vlan,
9282 				.mask = &rte_flow_item_vlan_mask,
9283 			},
9284 			{
9285 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9286 				.spec = &action_vxlan_encap_data->item_ipv4,
9287 				.mask = &rte_flow_item_ipv4_mask,
9288 			},
9289 			{
9290 				.type = RTE_FLOW_ITEM_TYPE_UDP,
9291 				.spec = &action_vxlan_encap_data->item_udp,
9292 				.mask = &rte_flow_item_udp_mask,
9293 			},
9294 			{
9295 				.type = RTE_FLOW_ITEM_TYPE_VXLAN,
9296 				.spec = &action_vxlan_encap_data->item_vxlan,
9297 				.mask = &rte_flow_item_vxlan_mask,
9298 			},
9299 			{
9300 				.type = RTE_FLOW_ITEM_TYPE_END,
9301 			},
9302 		},
9303 		.item_eth.hdr.ether_type = 0,
9304 		.item_vlan = {
9305 			.hdr.vlan_tci = vxlan_encap_conf.vlan_tci,
9306 			.hdr.eth_proto = 0,
9307 		},
9308 		.item_ipv4.hdr = {
9309 			.src_addr = vxlan_encap_conf.ipv4_src,
9310 			.dst_addr = vxlan_encap_conf.ipv4_dst,
9311 		},
9312 		.item_udp.hdr = {
9313 			.src_port = vxlan_encap_conf.udp_src,
9314 			.dst_port = vxlan_encap_conf.udp_dst,
9315 		},
9316 		.item_vxlan.hdr.flags = 0,
9317 	};
9318 	memcpy(action_vxlan_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9319 	       vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9320 	memcpy(action_vxlan_encap_data->item_eth.hdr.src_addr.addr_bytes,
9321 	       vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9322 	if (!vxlan_encap_conf.select_ipv4) {
9323 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
9324 		       &vxlan_encap_conf.ipv6_src,
9325 		       sizeof(vxlan_encap_conf.ipv6_src));
9326 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
9327 		       &vxlan_encap_conf.ipv6_dst,
9328 		       sizeof(vxlan_encap_conf.ipv6_dst));
9329 		action_vxlan_encap_data->items[2] = (struct rte_flow_item){
9330 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9331 			.spec = &action_vxlan_encap_data->item_ipv6,
9332 			.mask = &rte_flow_item_ipv6_mask,
9333 		};
9334 	}
9335 	if (!vxlan_encap_conf.select_vlan)
9336 		action_vxlan_encap_data->items[1].type =
9337 			RTE_FLOW_ITEM_TYPE_VOID;
9338 	if (vxlan_encap_conf.select_tos_ttl) {
9339 		if (vxlan_encap_conf.select_ipv4) {
9340 			static struct rte_flow_item_ipv4 ipv4_mask_tos;
9341 
9342 			memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
9343 			       sizeof(ipv4_mask_tos));
9344 			ipv4_mask_tos.hdr.type_of_service = 0xff;
9345 			ipv4_mask_tos.hdr.time_to_live = 0xff;
9346 			action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
9347 					vxlan_encap_conf.ip_tos;
9348 			action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
9349 					vxlan_encap_conf.ip_ttl;
9350 			action_vxlan_encap_data->items[2].mask =
9351 							&ipv4_mask_tos;
9352 		} else {
9353 			static struct rte_flow_item_ipv6 ipv6_mask_tos;
9354 
9355 			memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
9356 			       sizeof(ipv6_mask_tos));
9357 			ipv6_mask_tos.hdr.vtc_flow |=
9358 				RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
9359 			ipv6_mask_tos.hdr.hop_limits = 0xff;
9360 			action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
9361 				rte_cpu_to_be_32
9362 					((uint32_t)vxlan_encap_conf.ip_tos <<
9363 					 RTE_IPV6_HDR_TC_SHIFT);
9364 			action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
9365 					vxlan_encap_conf.ip_ttl;
9366 			action_vxlan_encap_data->items[2].mask =
9367 							&ipv6_mask_tos;
9368 		}
9369 	}
9370 	memcpy(action_vxlan_encap_data->item_vxlan.hdr.vni, vxlan_encap_conf.vni,
9371 	       RTE_DIM(vxlan_encap_conf.vni));
9372 	return 0;
9373 }
9374 
9375 /** Parse VXLAN encap action. */
9376 static int
9377 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
9378 			    const char *str, unsigned int len,
9379 			    void *buf, unsigned int size)
9380 {
9381 	struct buffer *out = buf;
9382 	struct rte_flow_action *action;
9383 	struct action_vxlan_encap_data *action_vxlan_encap_data;
9384 	int ret;
9385 
9386 	ret = parse_vc(ctx, token, str, len, buf, size);
9387 	if (ret < 0)
9388 		return ret;
9389 	/* Nothing else to do if there is no buffer. */
9390 	if (!out)
9391 		return ret;
9392 	if (!out->args.vc.actions_n)
9393 		return -1;
9394 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9395 	/* Point to selected object. */
9396 	ctx->object = out->args.vc.data;
9397 	ctx->objmask = NULL;
9398 	action_vxlan_encap_data = ctx->object;
9399 	parse_setup_vxlan_encap_data(action_vxlan_encap_data);
9400 	action->conf = &action_vxlan_encap_data->conf;
9401 	return ret;
9402 }
9403 
9404 /** Setup NVGRE encap configuration. */
9405 static int
9406 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
9407 {
9408 	/* Set up default configuration. */
9409 	*action_nvgre_encap_data = (struct action_nvgre_encap_data){
9410 		.conf = (struct rte_flow_action_nvgre_encap){
9411 			.definition = action_nvgre_encap_data->items,
9412 		},
9413 		.items = {
9414 			{
9415 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9416 				.spec = &action_nvgre_encap_data->item_eth,
9417 				.mask = &rte_flow_item_eth_mask,
9418 			},
9419 			{
9420 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9421 				.spec = &action_nvgre_encap_data->item_vlan,
9422 				.mask = &rte_flow_item_vlan_mask,
9423 			},
9424 			{
9425 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9426 				.spec = &action_nvgre_encap_data->item_ipv4,
9427 				.mask = &rte_flow_item_ipv4_mask,
9428 			},
9429 			{
9430 				.type = RTE_FLOW_ITEM_TYPE_NVGRE,
9431 				.spec = &action_nvgre_encap_data->item_nvgre,
9432 				.mask = &rte_flow_item_nvgre_mask,
9433 			},
9434 			{
9435 				.type = RTE_FLOW_ITEM_TYPE_END,
9436 			},
9437 		},
9438 		.item_eth.hdr.ether_type = 0,
9439 		.item_vlan = {
9440 			.hdr.vlan_tci = nvgre_encap_conf.vlan_tci,
9441 			.hdr.eth_proto = 0,
9442 		},
9443 		.item_ipv4.hdr = {
9444 		       .src_addr = nvgre_encap_conf.ipv4_src,
9445 		       .dst_addr = nvgre_encap_conf.ipv4_dst,
9446 		},
9447 		.item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
9448 		.item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
9449 		.item_nvgre.flow_id = 0,
9450 	};
9451 	memcpy(action_nvgre_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9452 	       nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9453 	memcpy(action_nvgre_encap_data->item_eth.hdr.src_addr.addr_bytes,
9454 	       nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9455 	if (!nvgre_encap_conf.select_ipv4) {
9456 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
9457 		       &nvgre_encap_conf.ipv6_src,
9458 		       sizeof(nvgre_encap_conf.ipv6_src));
9459 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
9460 		       &nvgre_encap_conf.ipv6_dst,
9461 		       sizeof(nvgre_encap_conf.ipv6_dst));
9462 		action_nvgre_encap_data->items[2] = (struct rte_flow_item){
9463 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9464 			.spec = &action_nvgre_encap_data->item_ipv6,
9465 			.mask = &rte_flow_item_ipv6_mask,
9466 		};
9467 	}
9468 	if (!nvgre_encap_conf.select_vlan)
9469 		action_nvgre_encap_data->items[1].type =
9470 			RTE_FLOW_ITEM_TYPE_VOID;
9471 	memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
9472 	       RTE_DIM(nvgre_encap_conf.tni));
9473 	return 0;
9474 }
9475 
9476 /** Parse NVGRE encap action. */
9477 static int
9478 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
9479 			    const char *str, unsigned int len,
9480 			    void *buf, unsigned int size)
9481 {
9482 	struct buffer *out = buf;
9483 	struct rte_flow_action *action;
9484 	struct action_nvgre_encap_data *action_nvgre_encap_data;
9485 	int ret;
9486 
9487 	ret = parse_vc(ctx, token, str, len, buf, size);
9488 	if (ret < 0)
9489 		return ret;
9490 	/* Nothing else to do if there is no buffer. */
9491 	if (!out)
9492 		return ret;
9493 	if (!out->args.vc.actions_n)
9494 		return -1;
9495 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9496 	/* Point to selected object. */
9497 	ctx->object = out->args.vc.data;
9498 	ctx->objmask = NULL;
9499 	action_nvgre_encap_data = ctx->object;
9500 	parse_setup_nvgre_encap_data(action_nvgre_encap_data);
9501 	action->conf = &action_nvgre_encap_data->conf;
9502 	return ret;
9503 }
9504 
9505 /** Parse l2 encap action. */
9506 static int
9507 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
9508 			 const char *str, unsigned int len,
9509 			 void *buf, unsigned int size)
9510 {
9511 	struct buffer *out = buf;
9512 	struct rte_flow_action *action;
9513 	struct action_raw_encap_data *action_encap_data;
9514 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9515 	struct rte_flow_item_vlan vlan = {
9516 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9517 		.hdr.eth_proto = 0,
9518 	};
9519 	uint8_t *header;
9520 	int ret;
9521 
9522 	ret = parse_vc(ctx, token, str, len, buf, size);
9523 	if (ret < 0)
9524 		return ret;
9525 	/* Nothing else to do if there is no buffer. */
9526 	if (!out)
9527 		return ret;
9528 	if (!out->args.vc.actions_n)
9529 		return -1;
9530 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9531 	/* Point to selected object. */
9532 	ctx->object = out->args.vc.data;
9533 	ctx->objmask = NULL;
9534 	/* Copy the headers to the buffer. */
9535 	action_encap_data = ctx->object;
9536 	*action_encap_data = (struct action_raw_encap_data) {
9537 		.conf = (struct rte_flow_action_raw_encap){
9538 			.data = action_encap_data->data,
9539 		},
9540 		.data = {},
9541 	};
9542 	header = action_encap_data->data;
9543 	if (l2_encap_conf.select_vlan)
9544 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9545 	else if (l2_encap_conf.select_ipv4)
9546 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9547 	else
9548 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9549 	memcpy(eth.hdr.dst_addr.addr_bytes,
9550 	       l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9551 	memcpy(eth.hdr.src_addr.addr_bytes,
9552 	       l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9553 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9554 	header += sizeof(struct rte_ether_hdr);
9555 	if (l2_encap_conf.select_vlan) {
9556 		if (l2_encap_conf.select_ipv4)
9557 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9558 		else
9559 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9560 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9561 		header += sizeof(struct rte_vlan_hdr);
9562 	}
9563 	action_encap_data->conf.size = header -
9564 		action_encap_data->data;
9565 	action->conf = &action_encap_data->conf;
9566 	return ret;
9567 }
9568 
9569 /** Parse l2 decap action. */
9570 static int
9571 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
9572 			 const char *str, unsigned int len,
9573 			 void *buf, unsigned int size)
9574 {
9575 	struct buffer *out = buf;
9576 	struct rte_flow_action *action;
9577 	struct action_raw_decap_data *action_decap_data;
9578 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9579 	struct rte_flow_item_vlan vlan = {
9580 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9581 		.hdr.eth_proto = 0,
9582 	};
9583 	uint8_t *header;
9584 	int ret;
9585 
9586 	ret = parse_vc(ctx, token, str, len, buf, size);
9587 	if (ret < 0)
9588 		return ret;
9589 	/* Nothing else to do if there is no buffer. */
9590 	if (!out)
9591 		return ret;
9592 	if (!out->args.vc.actions_n)
9593 		return -1;
9594 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9595 	/* Point to selected object. */
9596 	ctx->object = out->args.vc.data;
9597 	ctx->objmask = NULL;
9598 	/* Copy the headers to the buffer. */
9599 	action_decap_data = ctx->object;
9600 	*action_decap_data = (struct action_raw_decap_data) {
9601 		.conf = (struct rte_flow_action_raw_decap){
9602 			.data = action_decap_data->data,
9603 		},
9604 		.data = {},
9605 	};
9606 	header = action_decap_data->data;
9607 	if (l2_decap_conf.select_vlan)
9608 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9609 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9610 	header += sizeof(struct rte_ether_hdr);
9611 	if (l2_decap_conf.select_vlan) {
9612 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9613 		header += sizeof(struct rte_vlan_hdr);
9614 	}
9615 	action_decap_data->conf.size = header -
9616 		action_decap_data->data;
9617 	action->conf = &action_decap_data->conf;
9618 	return ret;
9619 }
9620 
9621 #define ETHER_TYPE_MPLS_UNICAST 0x8847
9622 
9623 /** Parse MPLSOGRE encap action. */
9624 static int
9625 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
9626 			       const char *str, unsigned int len,
9627 			       void *buf, unsigned int size)
9628 {
9629 	struct buffer *out = buf;
9630 	struct rte_flow_action *action;
9631 	struct action_raw_encap_data *action_encap_data;
9632 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9633 	struct rte_flow_item_vlan vlan = {
9634 		.hdr.vlan_tci = mplsogre_encap_conf.vlan_tci,
9635 		.hdr.eth_proto = 0,
9636 	};
9637 	struct rte_flow_item_ipv4 ipv4 = {
9638 		.hdr =  {
9639 			.src_addr = mplsogre_encap_conf.ipv4_src,
9640 			.dst_addr = mplsogre_encap_conf.ipv4_dst,
9641 			.next_proto_id = IPPROTO_GRE,
9642 			.version_ihl = RTE_IPV4_VHL_DEF,
9643 			.time_to_live = IPDEFTTL,
9644 		},
9645 	};
9646 	struct rte_flow_item_ipv6 ipv6 = {
9647 		.hdr =  {
9648 			.proto = IPPROTO_GRE,
9649 			.hop_limits = IPDEFTTL,
9650 		},
9651 	};
9652 	struct rte_flow_item_gre gre = {
9653 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9654 	};
9655 	struct rte_flow_item_mpls mpls = {
9656 		.ttl = 0,
9657 	};
9658 	uint8_t *header;
9659 	int ret;
9660 
9661 	ret = parse_vc(ctx, token, str, len, buf, size);
9662 	if (ret < 0)
9663 		return ret;
9664 	/* Nothing else to do if there is no buffer. */
9665 	if (!out)
9666 		return ret;
9667 	if (!out->args.vc.actions_n)
9668 		return -1;
9669 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9670 	/* Point to selected object. */
9671 	ctx->object = out->args.vc.data;
9672 	ctx->objmask = NULL;
9673 	/* Copy the headers to the buffer. */
9674 	action_encap_data = ctx->object;
9675 	*action_encap_data = (struct action_raw_encap_data) {
9676 		.conf = (struct rte_flow_action_raw_encap){
9677 			.data = action_encap_data->data,
9678 		},
9679 		.data = {},
9680 		.preserve = {},
9681 	};
9682 	header = action_encap_data->data;
9683 	if (mplsogre_encap_conf.select_vlan)
9684 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9685 	else if (mplsogre_encap_conf.select_ipv4)
9686 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9687 	else
9688 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9689 	memcpy(eth.hdr.dst_addr.addr_bytes,
9690 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9691 	memcpy(eth.hdr.src_addr.addr_bytes,
9692 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9693 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9694 	header += sizeof(struct rte_ether_hdr);
9695 	if (mplsogre_encap_conf.select_vlan) {
9696 		if (mplsogre_encap_conf.select_ipv4)
9697 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9698 		else
9699 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9700 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9701 		header += sizeof(struct rte_vlan_hdr);
9702 	}
9703 	if (mplsogre_encap_conf.select_ipv4) {
9704 		memcpy(header, &ipv4, sizeof(ipv4));
9705 		header += sizeof(ipv4);
9706 	} else {
9707 		memcpy(&ipv6.hdr.src_addr,
9708 		       &mplsogre_encap_conf.ipv6_src,
9709 		       sizeof(mplsogre_encap_conf.ipv6_src));
9710 		memcpy(&ipv6.hdr.dst_addr,
9711 		       &mplsogre_encap_conf.ipv6_dst,
9712 		       sizeof(mplsogre_encap_conf.ipv6_dst));
9713 		memcpy(header, &ipv6, sizeof(ipv6));
9714 		header += sizeof(ipv6);
9715 	}
9716 	memcpy(header, &gre, sizeof(gre));
9717 	header += sizeof(gre);
9718 	memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
9719 	       RTE_DIM(mplsogre_encap_conf.label));
9720 	mpls.label_tc_s[2] |= 0x1;
9721 	memcpy(header, &mpls, sizeof(mpls));
9722 	header += sizeof(mpls);
9723 	action_encap_data->conf.size = header -
9724 		action_encap_data->data;
9725 	action->conf = &action_encap_data->conf;
9726 	return ret;
9727 }
9728 
9729 /** Parse MPLSOGRE decap action. */
9730 static int
9731 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
9732 			       const char *str, unsigned int len,
9733 			       void *buf, unsigned int size)
9734 {
9735 	struct buffer *out = buf;
9736 	struct rte_flow_action *action;
9737 	struct action_raw_decap_data *action_decap_data;
9738 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9739 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
9740 	struct rte_flow_item_ipv4 ipv4 = {
9741 		.hdr =  {
9742 			.next_proto_id = IPPROTO_GRE,
9743 		},
9744 	};
9745 	struct rte_flow_item_ipv6 ipv6 = {
9746 		.hdr =  {
9747 			.proto = IPPROTO_GRE,
9748 		},
9749 	};
9750 	struct rte_flow_item_gre gre = {
9751 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9752 	};
9753 	struct rte_flow_item_mpls mpls;
9754 	uint8_t *header;
9755 	int ret;
9756 
9757 	ret = parse_vc(ctx, token, str, len, buf, size);
9758 	if (ret < 0)
9759 		return ret;
9760 	/* Nothing else to do if there is no buffer. */
9761 	if (!out)
9762 		return ret;
9763 	if (!out->args.vc.actions_n)
9764 		return -1;
9765 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9766 	/* Point to selected object. */
9767 	ctx->object = out->args.vc.data;
9768 	ctx->objmask = NULL;
9769 	/* Copy the headers to the buffer. */
9770 	action_decap_data = ctx->object;
9771 	*action_decap_data = (struct action_raw_decap_data) {
9772 		.conf = (struct rte_flow_action_raw_decap){
9773 			.data = action_decap_data->data,
9774 		},
9775 		.data = {},
9776 	};
9777 	header = action_decap_data->data;
9778 	if (mplsogre_decap_conf.select_vlan)
9779 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9780 	else if (mplsogre_encap_conf.select_ipv4)
9781 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9782 	else
9783 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9784 	memcpy(eth.hdr.dst_addr.addr_bytes,
9785 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9786 	memcpy(eth.hdr.src_addr.addr_bytes,
9787 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9788 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9789 	header += sizeof(struct rte_ether_hdr);
9790 	if (mplsogre_encap_conf.select_vlan) {
9791 		if (mplsogre_encap_conf.select_ipv4)
9792 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9793 		else
9794 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9795 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9796 		header += sizeof(struct rte_vlan_hdr);
9797 	}
9798 	if (mplsogre_encap_conf.select_ipv4) {
9799 		memcpy(header, &ipv4, sizeof(ipv4));
9800 		header += sizeof(ipv4);
9801 	} else {
9802 		memcpy(header, &ipv6, sizeof(ipv6));
9803 		header += sizeof(ipv6);
9804 	}
9805 	memcpy(header, &gre, sizeof(gre));
9806 	header += sizeof(gre);
9807 	memset(&mpls, 0, sizeof(mpls));
9808 	memcpy(header, &mpls, sizeof(mpls));
9809 	header += sizeof(mpls);
9810 	action_decap_data->conf.size = header -
9811 		action_decap_data->data;
9812 	action->conf = &action_decap_data->conf;
9813 	return ret;
9814 }
9815 
9816 /** Parse MPLSOUDP encap action. */
9817 static int
9818 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
9819 			       const char *str, unsigned int len,
9820 			       void *buf, unsigned int size)
9821 {
9822 	struct buffer *out = buf;
9823 	struct rte_flow_action *action;
9824 	struct action_raw_encap_data *action_encap_data;
9825 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9826 	struct rte_flow_item_vlan vlan = {
9827 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9828 		.hdr.eth_proto = 0,
9829 	};
9830 	struct rte_flow_item_ipv4 ipv4 = {
9831 		.hdr =  {
9832 			.src_addr = mplsoudp_encap_conf.ipv4_src,
9833 			.dst_addr = mplsoudp_encap_conf.ipv4_dst,
9834 			.next_proto_id = IPPROTO_UDP,
9835 			.version_ihl = RTE_IPV4_VHL_DEF,
9836 			.time_to_live = IPDEFTTL,
9837 		},
9838 	};
9839 	struct rte_flow_item_ipv6 ipv6 = {
9840 		.hdr =  {
9841 			.proto = IPPROTO_UDP,
9842 			.hop_limits = IPDEFTTL,
9843 		},
9844 	};
9845 	struct rte_flow_item_udp udp = {
9846 		.hdr = {
9847 			.src_port = mplsoudp_encap_conf.udp_src,
9848 			.dst_port = mplsoudp_encap_conf.udp_dst,
9849 		},
9850 	};
9851 	struct rte_flow_item_mpls mpls;
9852 	uint8_t *header;
9853 	int ret;
9854 
9855 	ret = parse_vc(ctx, token, str, len, buf, size);
9856 	if (ret < 0)
9857 		return ret;
9858 	/* Nothing else to do if there is no buffer. */
9859 	if (!out)
9860 		return ret;
9861 	if (!out->args.vc.actions_n)
9862 		return -1;
9863 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9864 	/* Point to selected object. */
9865 	ctx->object = out->args.vc.data;
9866 	ctx->objmask = NULL;
9867 	/* Copy the headers to the buffer. */
9868 	action_encap_data = ctx->object;
9869 	*action_encap_data = (struct action_raw_encap_data) {
9870 		.conf = (struct rte_flow_action_raw_encap){
9871 			.data = action_encap_data->data,
9872 		},
9873 		.data = {},
9874 		.preserve = {},
9875 	};
9876 	header = action_encap_data->data;
9877 	if (mplsoudp_encap_conf.select_vlan)
9878 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9879 	else if (mplsoudp_encap_conf.select_ipv4)
9880 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9881 	else
9882 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9883 	memcpy(eth.hdr.dst_addr.addr_bytes,
9884 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9885 	memcpy(eth.hdr.src_addr.addr_bytes,
9886 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9887 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9888 	header += sizeof(struct rte_ether_hdr);
9889 	if (mplsoudp_encap_conf.select_vlan) {
9890 		if (mplsoudp_encap_conf.select_ipv4)
9891 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9892 		else
9893 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9894 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9895 		header += sizeof(struct rte_vlan_hdr);
9896 	}
9897 	if (mplsoudp_encap_conf.select_ipv4) {
9898 		memcpy(header, &ipv4, sizeof(ipv4));
9899 		header += sizeof(ipv4);
9900 	} else {
9901 		memcpy(&ipv6.hdr.src_addr,
9902 		       &mplsoudp_encap_conf.ipv6_src,
9903 		       sizeof(mplsoudp_encap_conf.ipv6_src));
9904 		memcpy(&ipv6.hdr.dst_addr,
9905 		       &mplsoudp_encap_conf.ipv6_dst,
9906 		       sizeof(mplsoudp_encap_conf.ipv6_dst));
9907 		memcpy(header, &ipv6, sizeof(ipv6));
9908 		header += sizeof(ipv6);
9909 	}
9910 	memcpy(header, &udp, sizeof(udp));
9911 	header += sizeof(udp);
9912 	memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
9913 	       RTE_DIM(mplsoudp_encap_conf.label));
9914 	mpls.label_tc_s[2] |= 0x1;
9915 	memcpy(header, &mpls, sizeof(mpls));
9916 	header += sizeof(mpls);
9917 	action_encap_data->conf.size = header -
9918 		action_encap_data->data;
9919 	action->conf = &action_encap_data->conf;
9920 	return ret;
9921 }
9922 
9923 /** Parse MPLSOUDP decap action. */
9924 static int
9925 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
9926 			       const char *str, unsigned int len,
9927 			       void *buf, unsigned int size)
9928 {
9929 	struct buffer *out = buf;
9930 	struct rte_flow_action *action;
9931 	struct action_raw_decap_data *action_decap_data;
9932 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9933 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
9934 	struct rte_flow_item_ipv4 ipv4 = {
9935 		.hdr =  {
9936 			.next_proto_id = IPPROTO_UDP,
9937 		},
9938 	};
9939 	struct rte_flow_item_ipv6 ipv6 = {
9940 		.hdr =  {
9941 			.proto = IPPROTO_UDP,
9942 		},
9943 	};
9944 	struct rte_flow_item_udp udp = {
9945 		.hdr = {
9946 			.dst_port = rte_cpu_to_be_16(6635),
9947 		},
9948 	};
9949 	struct rte_flow_item_mpls mpls;
9950 	uint8_t *header;
9951 	int ret;
9952 
9953 	ret = parse_vc(ctx, token, str, len, buf, size);
9954 	if (ret < 0)
9955 		return ret;
9956 	/* Nothing else to do if there is no buffer. */
9957 	if (!out)
9958 		return ret;
9959 	if (!out->args.vc.actions_n)
9960 		return -1;
9961 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9962 	/* Point to selected object. */
9963 	ctx->object = out->args.vc.data;
9964 	ctx->objmask = NULL;
9965 	/* Copy the headers to the buffer. */
9966 	action_decap_data = ctx->object;
9967 	*action_decap_data = (struct action_raw_decap_data) {
9968 		.conf = (struct rte_flow_action_raw_decap){
9969 			.data = action_decap_data->data,
9970 		},
9971 		.data = {},
9972 	};
9973 	header = action_decap_data->data;
9974 	if (mplsoudp_decap_conf.select_vlan)
9975 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9976 	else if (mplsoudp_encap_conf.select_ipv4)
9977 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9978 	else
9979 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9980 	memcpy(eth.hdr.dst_addr.addr_bytes,
9981 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9982 	memcpy(eth.hdr.src_addr.addr_bytes,
9983 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9984 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9985 	header += sizeof(struct rte_ether_hdr);
9986 	if (mplsoudp_encap_conf.select_vlan) {
9987 		if (mplsoudp_encap_conf.select_ipv4)
9988 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9989 		else
9990 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9991 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9992 		header += sizeof(struct rte_vlan_hdr);
9993 	}
9994 	if (mplsoudp_encap_conf.select_ipv4) {
9995 		memcpy(header, &ipv4, sizeof(ipv4));
9996 		header += sizeof(ipv4);
9997 	} else {
9998 		memcpy(header, &ipv6, sizeof(ipv6));
9999 		header += sizeof(ipv6);
10000 	}
10001 	memcpy(header, &udp, sizeof(udp));
10002 	header += sizeof(udp);
10003 	memset(&mpls, 0, sizeof(mpls));
10004 	memcpy(header, &mpls, sizeof(mpls));
10005 	header += sizeof(mpls);
10006 	action_decap_data->conf.size = header -
10007 		action_decap_data->data;
10008 	action->conf = &action_decap_data->conf;
10009 	return ret;
10010 }
10011 
10012 static int
10013 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
10014 				const char *str, unsigned int len, void *buf,
10015 				unsigned int size)
10016 {
10017 	struct action_raw_decap_data *action_raw_decap_data;
10018 	struct rte_flow_action *action;
10019 	const struct arg *arg;
10020 	struct buffer *out = buf;
10021 	int ret;
10022 	uint16_t idx;
10023 
10024 	RTE_SET_USED(token);
10025 	RTE_SET_USED(buf);
10026 	RTE_SET_USED(size);
10027 	arg = ARGS_ENTRY_ARB_BOUNDED
10028 		(offsetof(struct action_raw_decap_data, idx),
10029 		 sizeof(((struct action_raw_decap_data *)0)->idx),
10030 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
10031 	if (push_args(ctx, arg))
10032 		return -1;
10033 	ret = parse_int(ctx, token, str, len, NULL, 0);
10034 	if (ret < 0) {
10035 		pop_args(ctx);
10036 		return -1;
10037 	}
10038 	if (!ctx->object)
10039 		return len;
10040 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10041 	action_raw_decap_data = ctx->object;
10042 	idx = action_raw_decap_data->idx;
10043 	action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
10044 	action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
10045 	action->conf = &action_raw_decap_data->conf;
10046 	return len;
10047 }
10048 
10049 
10050 static int
10051 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
10052 				const char *str, unsigned int len, void *buf,
10053 				unsigned int size)
10054 {
10055 	struct action_raw_encap_data *action_raw_encap_data;
10056 	struct rte_flow_action *action;
10057 	const struct arg *arg;
10058 	struct buffer *out = buf;
10059 	int ret;
10060 	uint16_t idx;
10061 
10062 	RTE_SET_USED(token);
10063 	RTE_SET_USED(buf);
10064 	RTE_SET_USED(size);
10065 	if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
10066 		return -1;
10067 	arg = ARGS_ENTRY_ARB_BOUNDED
10068 		(offsetof(struct action_raw_encap_data, idx),
10069 		 sizeof(((struct action_raw_encap_data *)0)->idx),
10070 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
10071 	if (push_args(ctx, arg))
10072 		return -1;
10073 	ret = parse_int(ctx, token, str, len, NULL, 0);
10074 	if (ret < 0) {
10075 		pop_args(ctx);
10076 		return -1;
10077 	}
10078 	if (!ctx->object)
10079 		return len;
10080 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10081 	action_raw_encap_data = ctx->object;
10082 	idx = action_raw_encap_data->idx;
10083 	action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
10084 	action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
10085 	action_raw_encap_data->conf.preserve = NULL;
10086 	action->conf = &action_raw_encap_data->conf;
10087 	return len;
10088 }
10089 
10090 static int
10091 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
10092 			  const char *str, unsigned int len, void *buf,
10093 			  unsigned int size)
10094 {
10095 	struct buffer *out = buf;
10096 	int ret;
10097 
10098 	ret = parse_vc(ctx, token, str, len, buf, size);
10099 	if (ret < 0)
10100 		return ret;
10101 	/* Nothing else to do if there is no buffer. */
10102 	if (!out)
10103 		return ret;
10104 	if (!out->args.vc.actions_n)
10105 		return -1;
10106 	/* Point to selected object. */
10107 	ctx->object = out->args.vc.data;
10108 	ctx->objmask = NULL;
10109 	return ret;
10110 }
10111 
10112 static int
10113 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
10114 			  const char *str, unsigned int len, void *buf,
10115 			  unsigned int size)
10116 {
10117 	struct buffer *out = buf;
10118 	struct rte_flow_action *action;
10119 	struct action_raw_decap_data *action_raw_decap_data = NULL;
10120 	int ret;
10121 
10122 	ret = parse_vc(ctx, token, str, len, buf, size);
10123 	if (ret < 0)
10124 		return ret;
10125 	/* Nothing else to do if there is no buffer. */
10126 	if (!out)
10127 		return ret;
10128 	if (!out->args.vc.actions_n)
10129 		return -1;
10130 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10131 	/* Point to selected object. */
10132 	ctx->object = out->args.vc.data;
10133 	ctx->objmask = NULL;
10134 	/* Copy the headers to the buffer. */
10135 	action_raw_decap_data = ctx->object;
10136 	action_raw_decap_data->conf.data = raw_decap_confs[0].data;
10137 	action_raw_decap_data->conf.size = raw_decap_confs[0].size;
10138 	action->conf = &action_raw_decap_data->conf;
10139 	return ret;
10140 }
10141 
10142 static int
10143 parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
10144 				const char *str, unsigned int len, void *buf,
10145 				unsigned int size)
10146 {
10147 	struct buffer *out = buf;
10148 	struct rte_flow_action *action;
10149 	struct action_ipv6_ext_remove_data *ipv6_ext_remove_data = NULL;
10150 	int ret;
10151 
10152 	ret = parse_vc(ctx, token, str, len, buf, size);
10153 	if (ret < 0)
10154 		return ret;
10155 	/* Nothing else to do if there is no buffer. */
10156 	if (!out)
10157 		return ret;
10158 	if (!out->args.vc.actions_n)
10159 		return -1;
10160 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10161 	/* Point to selected object. */
10162 	ctx->object = out->args.vc.data;
10163 	ctx->objmask = NULL;
10164 	/* Copy the headers to the buffer. */
10165 	ipv6_ext_remove_data = ctx->object;
10166 	ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[0].type;
10167 	action->conf = &ipv6_ext_remove_data->conf;
10168 	return ret;
10169 }
10170 
10171 static int
10172 parse_vc_action_ipv6_ext_remove_index(struct context *ctx, const struct token *token,
10173 				      const char *str, unsigned int len, void *buf,
10174 				      unsigned int size)
10175 {
10176 	struct action_ipv6_ext_remove_data *action_ipv6_ext_remove_data;
10177 	struct rte_flow_action *action;
10178 	const struct arg *arg;
10179 	struct buffer *out = buf;
10180 	int ret;
10181 	uint16_t idx;
10182 
10183 	RTE_SET_USED(token);
10184 	RTE_SET_USED(buf);
10185 	RTE_SET_USED(size);
10186 	arg = ARGS_ENTRY_ARB_BOUNDED
10187 		(offsetof(struct action_ipv6_ext_remove_data, idx),
10188 		 sizeof(((struct action_ipv6_ext_remove_data *)0)->idx),
10189 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10190 	if (push_args(ctx, arg))
10191 		return -1;
10192 	ret = parse_int(ctx, token, str, len, NULL, 0);
10193 	if (ret < 0) {
10194 		pop_args(ctx);
10195 		return -1;
10196 	}
10197 	if (!ctx->object)
10198 		return len;
10199 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10200 	action_ipv6_ext_remove_data = ctx->object;
10201 	idx = action_ipv6_ext_remove_data->idx;
10202 	action_ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[idx].type;
10203 	action->conf = &action_ipv6_ext_remove_data->conf;
10204 	return len;
10205 }
10206 
10207 static int
10208 parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
10209 			      const char *str, unsigned int len, void *buf,
10210 			      unsigned int size)
10211 {
10212 	struct buffer *out = buf;
10213 	struct rte_flow_action *action;
10214 	struct action_ipv6_ext_push_data *ipv6_ext_push_data = NULL;
10215 	int ret;
10216 
10217 	ret = parse_vc(ctx, token, str, len, buf, size);
10218 	if (ret < 0)
10219 		return ret;
10220 	/* Nothing else to do if there is no buffer. */
10221 	if (!out)
10222 		return ret;
10223 	if (!out->args.vc.actions_n)
10224 		return -1;
10225 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10226 	/* Point to selected object. */
10227 	ctx->object = out->args.vc.data;
10228 	ctx->objmask = NULL;
10229 	/* Copy the headers to the buffer. */
10230 	ipv6_ext_push_data = ctx->object;
10231 	ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[0].type;
10232 	ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[0].data;
10233 	ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[0].size;
10234 	action->conf = &ipv6_ext_push_data->conf;
10235 	return ret;
10236 }
10237 
10238 static int
10239 parse_vc_action_ipv6_ext_push_index(struct context *ctx, const struct token *token,
10240 				    const char *str, unsigned int len, void *buf,
10241 				    unsigned int size)
10242 {
10243 	struct action_ipv6_ext_push_data *action_ipv6_ext_push_data;
10244 	struct rte_flow_action *action;
10245 	const struct arg *arg;
10246 	struct buffer *out = buf;
10247 	int ret;
10248 	uint16_t idx;
10249 
10250 	RTE_SET_USED(token);
10251 	RTE_SET_USED(buf);
10252 	RTE_SET_USED(size);
10253 	arg = ARGS_ENTRY_ARB_BOUNDED
10254 		(offsetof(struct action_ipv6_ext_push_data, idx),
10255 		 sizeof(((struct action_ipv6_ext_push_data *)0)->idx),
10256 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10257 	if (push_args(ctx, arg))
10258 		return -1;
10259 	ret = parse_int(ctx, token, str, len, NULL, 0);
10260 	if (ret < 0) {
10261 		pop_args(ctx);
10262 		return -1;
10263 	}
10264 	if (!ctx->object)
10265 		return len;
10266 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10267 	action_ipv6_ext_push_data = ctx->object;
10268 	idx = action_ipv6_ext_push_data->idx;
10269 	action_ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[idx].type;
10270 	action_ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[idx].size;
10271 	action_ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[idx].data;
10272 	action->conf = &action_ipv6_ext_push_data->conf;
10273 	return len;
10274 }
10275 
10276 static int
10277 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
10278 			 const char *str, unsigned int len, void *buf,
10279 			 unsigned int size)
10280 {
10281 	int ret;
10282 
10283 	ret = parse_vc(ctx, token, str, len, buf, size);
10284 	if (ret < 0)
10285 		return ret;
10286 	ret = rte_flow_dynf_metadata_register();
10287 	if (ret < 0)
10288 		return -1;
10289 	return len;
10290 }
10291 
10292 static int
10293 parse_vc_action_sample(struct context *ctx, const struct token *token,
10294 			 const char *str, unsigned int len, void *buf,
10295 			 unsigned int size)
10296 {
10297 	struct buffer *out = buf;
10298 	struct rte_flow_action *action;
10299 	struct action_sample_data *action_sample_data = NULL;
10300 	static struct rte_flow_action end_action = {
10301 		RTE_FLOW_ACTION_TYPE_END, 0
10302 	};
10303 	int ret;
10304 
10305 	ret = parse_vc(ctx, token, str, len, buf, size);
10306 	if (ret < 0)
10307 		return ret;
10308 	/* Nothing else to do if there is no buffer. */
10309 	if (!out)
10310 		return ret;
10311 	if (!out->args.vc.actions_n)
10312 		return -1;
10313 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10314 	/* Point to selected object. */
10315 	ctx->object = out->args.vc.data;
10316 	ctx->objmask = NULL;
10317 	/* Copy the headers to the buffer. */
10318 	action_sample_data = ctx->object;
10319 	action_sample_data->conf.actions = &end_action;
10320 	action->conf = &action_sample_data->conf;
10321 	return ret;
10322 }
10323 
10324 static int
10325 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
10326 				const char *str, unsigned int len, void *buf,
10327 				unsigned int size)
10328 {
10329 	struct action_sample_data *action_sample_data;
10330 	struct rte_flow_action *action;
10331 	const struct arg *arg;
10332 	struct buffer *out = buf;
10333 	int ret;
10334 	uint16_t idx;
10335 
10336 	RTE_SET_USED(token);
10337 	RTE_SET_USED(buf);
10338 	RTE_SET_USED(size);
10339 	if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
10340 		return -1;
10341 	arg = ARGS_ENTRY_ARB_BOUNDED
10342 		(offsetof(struct action_sample_data, idx),
10343 		 sizeof(((struct action_sample_data *)0)->idx),
10344 		 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
10345 	if (push_args(ctx, arg))
10346 		return -1;
10347 	ret = parse_int(ctx, token, str, len, NULL, 0);
10348 	if (ret < 0) {
10349 		pop_args(ctx);
10350 		return -1;
10351 	}
10352 	if (!ctx->object)
10353 		return len;
10354 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10355 	action_sample_data = ctx->object;
10356 	idx = action_sample_data->idx;
10357 	action_sample_data->conf.actions = raw_sample_confs[idx].data;
10358 	action->conf = &action_sample_data->conf;
10359 	return len;
10360 }
10361 
10362 /** Parse operation for modify_field command. */
10363 static int
10364 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
10365 			 const char *str, unsigned int len, void *buf,
10366 			 unsigned int size)
10367 {
10368 	struct rte_flow_action_modify_field *action_modify_field;
10369 	unsigned int i;
10370 
10371 	(void)token;
10372 	(void)buf;
10373 	(void)size;
10374 	if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
10375 		return -1;
10376 	for (i = 0; modify_field_ops[i]; ++i)
10377 		if (!strcmp_partial(modify_field_ops[i], str, len))
10378 			break;
10379 	if (!modify_field_ops[i])
10380 		return -1;
10381 	if (!ctx->object)
10382 		return len;
10383 	action_modify_field = ctx->object;
10384 	action_modify_field->operation = (enum rte_flow_modify_op)i;
10385 	return len;
10386 }
10387 
10388 /** Parse id for modify_field command. */
10389 static int
10390 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
10391 			 const char *str, unsigned int len, void *buf,
10392 			 unsigned int size)
10393 {
10394 	struct rte_flow_action_modify_field *action_modify_field;
10395 	unsigned int i;
10396 
10397 	(void)token;
10398 	(void)buf;
10399 	(void)size;
10400 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
10401 		ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
10402 		return -1;
10403 	for (i = 0; flow_field_ids[i]; ++i)
10404 		if (!strcmp_partial(flow_field_ids[i], str, len))
10405 			break;
10406 	if (!flow_field_ids[i])
10407 		return -1;
10408 	if (!ctx->object)
10409 		return len;
10410 	action_modify_field = ctx->object;
10411 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
10412 		action_modify_field->dst.field = (enum rte_flow_field_id)i;
10413 	else
10414 		action_modify_field->src.field = (enum rte_flow_field_id)i;
10415 	return len;
10416 }
10417 
10418 /** Parse level for modify_field command. */
10419 static int
10420 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
10421 			 const char *str, unsigned int len, void *buf,
10422 			 unsigned int size)
10423 {
10424 	struct rte_flow_action_modify_field *action;
10425 	struct flex_item *fp = NULL;
10426 	uint32_t val;
10427 	struct buffer *out = buf;
10428 	char *end;
10429 
10430 	(void)token;
10431 	(void)size;
10432 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10433 		ctx->curr != ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)
10434 		return -1;
10435 	if (!ctx->object)
10436 		return len;
10437 	action = ctx->object;
10438 	errno = 0;
10439 	val = strtoumax(str, &end, 0);
10440 	if (errno || (size_t)(end - str) != len)
10441 		return -1;
10442 	/* No need to validate action template mask value */
10443 	if (out->args.vc.masks) {
10444 		if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)
10445 			action->dst.level = val;
10446 		else
10447 			action->src.level = val;
10448 		return len;
10449 	}
10450 	if ((ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10451 		action->dst.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
10452 		(ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE &&
10453 		action->src.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
10454 		if (val >= FLEX_MAX_PARSERS_NUM) {
10455 			printf("Bad flex item handle\n");
10456 			return -1;
10457 		}
10458 		fp = flex_items[ctx->port][val];
10459 		if (!fp) {
10460 			printf("Bad flex item handle\n");
10461 			return -1;
10462 		}
10463 	}
10464 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE) {
10465 		if (action->dst.field != RTE_FLOW_FIELD_FLEX_ITEM)
10466 			action->dst.level = val;
10467 		else
10468 			action->dst.flex_handle = fp->flex_handle;
10469 	} else if (ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE) {
10470 		if (action->src.field != RTE_FLOW_FIELD_FLEX_ITEM)
10471 			action->src.level = val;
10472 		else
10473 			action->src.flex_handle = fp->flex_handle;
10474 	}
10475 	return len;
10476 }
10477 
10478 /** Parse the conntrack update, not a rte_flow_action. */
10479 static int
10480 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
10481 			 const char *str, unsigned int len, void *buf,
10482 			 unsigned int size)
10483 {
10484 	struct buffer *out = buf;
10485 	struct rte_flow_modify_conntrack *ct_modify = NULL;
10486 
10487 	(void)size;
10488 	if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
10489 	    ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
10490 		return -1;
10491 	/* Token name must match. */
10492 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10493 		return -1;
10494 	/* Nothing else to do if there is no buffer. */
10495 	if (!out)
10496 		return len;
10497 	ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
10498 	if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
10499 		ct_modify->new_ct.is_original_dir =
10500 				conntrack_context.is_original_dir;
10501 		ct_modify->direction = 1;
10502 	} else {
10503 		uint32_t old_dir;
10504 
10505 		old_dir = ct_modify->new_ct.is_original_dir;
10506 		memcpy(&ct_modify->new_ct, &conntrack_context,
10507 		       sizeof(conntrack_context));
10508 		ct_modify->new_ct.is_original_dir = old_dir;
10509 		ct_modify->state = 1;
10510 	}
10511 	return len;
10512 }
10513 
10514 /** Parse tokens for destroy command. */
10515 static int
10516 parse_destroy(struct context *ctx, const struct token *token,
10517 	      const char *str, unsigned int len,
10518 	      void *buf, unsigned int size)
10519 {
10520 	struct buffer *out = buf;
10521 
10522 	/* Token name must match. */
10523 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10524 		return -1;
10525 	/* Nothing else to do if there is no buffer. */
10526 	if (!out)
10527 		return len;
10528 	if (!out->command) {
10529 		if (ctx->curr != DESTROY)
10530 			return -1;
10531 		if (sizeof(*out) > size)
10532 			return -1;
10533 		out->command = ctx->curr;
10534 		ctx->objdata = 0;
10535 		ctx->object = out;
10536 		ctx->objmask = NULL;
10537 		out->args.destroy.rule =
10538 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10539 					       sizeof(double));
10540 		return len;
10541 	}
10542 	if (ctx->curr == DESTROY_IS_USER_ID) {
10543 		out->args.destroy.is_user_id = true;
10544 		return len;
10545 	}
10546 	if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
10547 	     sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
10548 		return -1;
10549 	ctx->objdata = 0;
10550 	ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
10551 	ctx->objmask = NULL;
10552 	return len;
10553 }
10554 
10555 /** Parse tokens for flush command. */
10556 static int
10557 parse_flush(struct context *ctx, const struct token *token,
10558 	    const char *str, unsigned int len,
10559 	    void *buf, unsigned int size)
10560 {
10561 	struct buffer *out = buf;
10562 
10563 	/* Token name must match. */
10564 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10565 		return -1;
10566 	/* Nothing else to do if there is no buffer. */
10567 	if (!out)
10568 		return len;
10569 	if (!out->command) {
10570 		if (ctx->curr != FLUSH)
10571 			return -1;
10572 		if (sizeof(*out) > size)
10573 			return -1;
10574 		out->command = ctx->curr;
10575 		ctx->objdata = 0;
10576 		ctx->object = out;
10577 		ctx->objmask = NULL;
10578 	}
10579 	return len;
10580 }
10581 
10582 /** Parse tokens for dump command. */
10583 static int
10584 parse_dump(struct context *ctx, const struct token *token,
10585 	    const char *str, unsigned int len,
10586 	    void *buf, unsigned int size)
10587 {
10588 	struct buffer *out = buf;
10589 
10590 	/* Token name must match. */
10591 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10592 		return -1;
10593 	/* Nothing else to do if there is no buffer. */
10594 	if (!out)
10595 		return len;
10596 	if (!out->command) {
10597 		if (ctx->curr != DUMP)
10598 			return -1;
10599 		if (sizeof(*out) > size)
10600 			return -1;
10601 		out->command = ctx->curr;
10602 		ctx->objdata = 0;
10603 		ctx->object = out;
10604 		ctx->objmask = NULL;
10605 		return len;
10606 	}
10607 	switch (ctx->curr) {
10608 	case DUMP_ALL:
10609 	case DUMP_ONE:
10610 		out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
10611 		out->command = ctx->curr;
10612 		ctx->objdata = 0;
10613 		ctx->object = out;
10614 		ctx->objmask = NULL;
10615 		return len;
10616 	case DUMP_IS_USER_ID:
10617 		out->args.dump.is_user_id = true;
10618 		return len;
10619 	default:
10620 		return -1;
10621 	}
10622 }
10623 
10624 /** Parse tokens for query command. */
10625 static int
10626 parse_query(struct context *ctx, const struct token *token,
10627 	    const char *str, unsigned int len,
10628 	    void *buf, unsigned int size)
10629 {
10630 	struct buffer *out = buf;
10631 
10632 	/* Token name must match. */
10633 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10634 		return -1;
10635 	/* Nothing else to do if there is no buffer. */
10636 	if (!out)
10637 		return len;
10638 	if (!out->command) {
10639 		if (ctx->curr != QUERY)
10640 			return -1;
10641 		if (sizeof(*out) > size)
10642 			return -1;
10643 		out->command = ctx->curr;
10644 		ctx->objdata = 0;
10645 		ctx->object = out;
10646 		ctx->objmask = NULL;
10647 	}
10648 	if (ctx->curr == QUERY_IS_USER_ID) {
10649 		out->args.query.is_user_id = true;
10650 		return len;
10651 	}
10652 	return len;
10653 }
10654 
10655 /** Parse action names. */
10656 static int
10657 parse_action(struct context *ctx, const struct token *token,
10658 	     const char *str, unsigned int len,
10659 	     void *buf, unsigned int size)
10660 {
10661 	struct buffer *out = buf;
10662 	const struct arg *arg = pop_args(ctx);
10663 	unsigned int i;
10664 
10665 	(void)size;
10666 	/* Argument is expected. */
10667 	if (!arg)
10668 		return -1;
10669 	/* Parse action name. */
10670 	for (i = 0; next_action[i]; ++i) {
10671 		const struct parse_action_priv *priv;
10672 
10673 		token = &token_list[next_action[i]];
10674 		if (strcmp_partial(token->name, str, len))
10675 			continue;
10676 		priv = token->priv;
10677 		if (!priv)
10678 			goto error;
10679 		if (out)
10680 			memcpy((uint8_t *)ctx->object + arg->offset,
10681 			       &priv->type,
10682 			       arg->size);
10683 		return len;
10684 	}
10685 error:
10686 	push_args(ctx, arg);
10687 	return -1;
10688 }
10689 
10690 /** Parse tokens for list command. */
10691 static int
10692 parse_list(struct context *ctx, const struct token *token,
10693 	   const char *str, unsigned int len,
10694 	   void *buf, unsigned int size)
10695 {
10696 	struct buffer *out = buf;
10697 
10698 	/* Token name must match. */
10699 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10700 		return -1;
10701 	/* Nothing else to do if there is no buffer. */
10702 	if (!out)
10703 		return len;
10704 	if (!out->command) {
10705 		if (ctx->curr != LIST)
10706 			return -1;
10707 		if (sizeof(*out) > size)
10708 			return -1;
10709 		out->command = ctx->curr;
10710 		ctx->objdata = 0;
10711 		ctx->object = out;
10712 		ctx->objmask = NULL;
10713 		out->args.list.group =
10714 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10715 					       sizeof(double));
10716 		return len;
10717 	}
10718 	if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
10719 	     sizeof(*out->args.list.group)) > (uint8_t *)out + size)
10720 		return -1;
10721 	ctx->objdata = 0;
10722 	ctx->object = out->args.list.group + out->args.list.group_n++;
10723 	ctx->objmask = NULL;
10724 	return len;
10725 }
10726 
10727 /** Parse tokens for list all aged flows command. */
10728 static int
10729 parse_aged(struct context *ctx, const struct token *token,
10730 	   const char *str, unsigned int len,
10731 	   void *buf, unsigned int size)
10732 {
10733 	struct buffer *out = buf;
10734 
10735 	/* Token name must match. */
10736 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10737 		return -1;
10738 	/* Nothing else to do if there is no buffer. */
10739 	if (!out)
10740 		return len;
10741 	if (!out->command || out->command == QUEUE) {
10742 		if (ctx->curr != AGED && ctx->curr != QUEUE_AGED)
10743 			return -1;
10744 		if (sizeof(*out) > size)
10745 			return -1;
10746 		out->command = ctx->curr;
10747 		ctx->objdata = 0;
10748 		ctx->object = out;
10749 		ctx->objmask = NULL;
10750 	}
10751 	if (ctx->curr == AGED_DESTROY)
10752 		out->args.aged.destroy = 1;
10753 	return len;
10754 }
10755 
10756 /** Parse tokens for isolate command. */
10757 static int
10758 parse_isolate(struct context *ctx, const struct token *token,
10759 	      const char *str, unsigned int len,
10760 	      void *buf, unsigned int size)
10761 {
10762 	struct buffer *out = buf;
10763 
10764 	/* Token name must match. */
10765 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10766 		return -1;
10767 	/* Nothing else to do if there is no buffer. */
10768 	if (!out)
10769 		return len;
10770 	if (!out->command) {
10771 		if (ctx->curr != ISOLATE)
10772 			return -1;
10773 		if (sizeof(*out) > size)
10774 			return -1;
10775 		out->command = ctx->curr;
10776 		ctx->objdata = 0;
10777 		ctx->object = out;
10778 		ctx->objmask = NULL;
10779 	}
10780 	return len;
10781 }
10782 
10783 /** Parse tokens for info/configure command. */
10784 static int
10785 parse_configure(struct context *ctx, const struct token *token,
10786 		const char *str, unsigned int len,
10787 		void *buf, unsigned int size)
10788 {
10789 	struct buffer *out = buf;
10790 
10791 	/* Token name must match. */
10792 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10793 		return -1;
10794 	/* Nothing else to do if there is no buffer. */
10795 	if (!out)
10796 		return len;
10797 	if (!out->command) {
10798 		if (ctx->curr != INFO && ctx->curr != CONFIGURE)
10799 			return -1;
10800 		if (sizeof(*out) > size)
10801 			return -1;
10802 		out->command = ctx->curr;
10803 		ctx->objdata = 0;
10804 		ctx->object = out;
10805 		ctx->objmask = NULL;
10806 	}
10807 	return len;
10808 }
10809 
10810 /** Parse tokens for template create command. */
10811 static int
10812 parse_template(struct context *ctx, const struct token *token,
10813 	       const char *str, unsigned int len,
10814 	       void *buf, unsigned int size)
10815 {
10816 	struct buffer *out = buf;
10817 
10818 	/* Token name must match. */
10819 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10820 		return -1;
10821 	/* Nothing else to do if there is no buffer. */
10822 	if (!out)
10823 		return len;
10824 	if (!out->command) {
10825 		if (ctx->curr != PATTERN_TEMPLATE &&
10826 		    ctx->curr != ACTIONS_TEMPLATE)
10827 			return -1;
10828 		if (sizeof(*out) > size)
10829 			return -1;
10830 		out->command = ctx->curr;
10831 		ctx->objdata = 0;
10832 		ctx->object = out;
10833 		ctx->objmask = NULL;
10834 		out->args.vc.data = (uint8_t *)out + size;
10835 		return len;
10836 	}
10837 	switch (ctx->curr) {
10838 	case PATTERN_TEMPLATE_CREATE:
10839 		out->args.vc.pattern =
10840 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10841 					       sizeof(double));
10842 		out->args.vc.pat_templ_id = UINT32_MAX;
10843 		out->command = ctx->curr;
10844 		ctx->objdata = 0;
10845 		ctx->object = out;
10846 		ctx->objmask = NULL;
10847 		return len;
10848 	case PATTERN_TEMPLATE_EGRESS:
10849 		out->args.vc.attr.egress = 1;
10850 		return len;
10851 	case PATTERN_TEMPLATE_INGRESS:
10852 		out->args.vc.attr.ingress = 1;
10853 		return len;
10854 	case PATTERN_TEMPLATE_TRANSFER:
10855 		out->args.vc.attr.transfer = 1;
10856 		return len;
10857 	case ACTIONS_TEMPLATE_CREATE:
10858 		out->args.vc.act_templ_id = UINT32_MAX;
10859 		out->command = ctx->curr;
10860 		ctx->objdata = 0;
10861 		ctx->object = out;
10862 		ctx->objmask = NULL;
10863 		return len;
10864 	case ACTIONS_TEMPLATE_SPEC:
10865 		out->args.vc.actions =
10866 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10867 					       sizeof(double));
10868 		ctx->object = out->args.vc.actions;
10869 		ctx->objmask = NULL;
10870 		return len;
10871 	case ACTIONS_TEMPLATE_MASK:
10872 		out->args.vc.masks =
10873 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10874 					       (out->args.vc.actions +
10875 						out->args.vc.actions_n),
10876 					       sizeof(double));
10877 		ctx->object = out->args.vc.masks;
10878 		ctx->objmask = NULL;
10879 		return len;
10880 	case ACTIONS_TEMPLATE_EGRESS:
10881 		out->args.vc.attr.egress = 1;
10882 		return len;
10883 	case ACTIONS_TEMPLATE_INGRESS:
10884 		out->args.vc.attr.ingress = 1;
10885 		return len;
10886 	case ACTIONS_TEMPLATE_TRANSFER:
10887 		out->args.vc.attr.transfer = 1;
10888 		return len;
10889 	default:
10890 		return -1;
10891 	}
10892 }
10893 
10894 /** Parse tokens for template destroy command. */
10895 static int
10896 parse_template_destroy(struct context *ctx, const struct token *token,
10897 		       const char *str, unsigned int len,
10898 		       void *buf, unsigned int size)
10899 {
10900 	struct buffer *out = buf;
10901 	uint32_t *template_id;
10902 
10903 	/* Token name must match. */
10904 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10905 		return -1;
10906 	/* Nothing else to do if there is no buffer. */
10907 	if (!out)
10908 		return len;
10909 	if (!out->command ||
10910 		out->command == PATTERN_TEMPLATE ||
10911 		out->command == ACTIONS_TEMPLATE) {
10912 		if (ctx->curr != PATTERN_TEMPLATE_DESTROY &&
10913 			ctx->curr != ACTIONS_TEMPLATE_DESTROY)
10914 			return -1;
10915 		if (sizeof(*out) > size)
10916 			return -1;
10917 		out->command = ctx->curr;
10918 		ctx->objdata = 0;
10919 		ctx->object = out;
10920 		ctx->objmask = NULL;
10921 		out->args.templ_destroy.template_id =
10922 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10923 					       sizeof(double));
10924 		return len;
10925 	}
10926 	template_id = out->args.templ_destroy.template_id
10927 		    + out->args.templ_destroy.template_id_n++;
10928 	if ((uint8_t *)template_id > (uint8_t *)out + size)
10929 		return -1;
10930 	ctx->objdata = 0;
10931 	ctx->object = template_id;
10932 	ctx->objmask = NULL;
10933 	return len;
10934 }
10935 
10936 /** Parse tokens for table create command. */
10937 static int
10938 parse_table(struct context *ctx, const struct token *token,
10939 	    const char *str, unsigned int len,
10940 	    void *buf, unsigned int size)
10941 {
10942 	struct buffer *out = buf;
10943 	uint32_t *template_id;
10944 
10945 	/* Token name must match. */
10946 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10947 		return -1;
10948 	/* Nothing else to do if there is no buffer. */
10949 	if (!out)
10950 		return len;
10951 	if (!out->command) {
10952 		if (ctx->curr != TABLE)
10953 			return -1;
10954 		if (sizeof(*out) > size)
10955 			return -1;
10956 		out->command = ctx->curr;
10957 		ctx->objdata = 0;
10958 		ctx->object = out;
10959 		ctx->objmask = NULL;
10960 		return len;
10961 	}
10962 	switch (ctx->curr) {
10963 	case TABLE_CREATE:
10964 	case TABLE_RESIZE:
10965 		out->command = ctx->curr;
10966 		ctx->objdata = 0;
10967 		ctx->object = out;
10968 		ctx->objmask = NULL;
10969 		out->args.table.id = UINT32_MAX;
10970 		return len;
10971 	case TABLE_PATTERN_TEMPLATE:
10972 		out->args.table.pat_templ_id =
10973 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10974 					       sizeof(double));
10975 		template_id = out->args.table.pat_templ_id
10976 				+ out->args.table.pat_templ_id_n++;
10977 		if ((uint8_t *)template_id > (uint8_t *)out + size)
10978 			return -1;
10979 		ctx->objdata = 0;
10980 		ctx->object = template_id;
10981 		ctx->objmask = NULL;
10982 		return len;
10983 	case TABLE_ACTIONS_TEMPLATE:
10984 		out->args.table.act_templ_id =
10985 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10986 					       (out->args.table.pat_templ_id +
10987 						out->args.table.pat_templ_id_n),
10988 					       sizeof(double));
10989 		template_id = out->args.table.act_templ_id
10990 				+ out->args.table.act_templ_id_n++;
10991 		if ((uint8_t *)template_id > (uint8_t *)out + size)
10992 			return -1;
10993 		ctx->objdata = 0;
10994 		ctx->object = template_id;
10995 		ctx->objmask = NULL;
10996 		return len;
10997 	case TABLE_INGRESS:
10998 		out->args.table.attr.flow_attr.ingress = 1;
10999 		return len;
11000 	case TABLE_EGRESS:
11001 		out->args.table.attr.flow_attr.egress = 1;
11002 		return len;
11003 	case TABLE_TRANSFER:
11004 		out->args.table.attr.flow_attr.transfer = 1;
11005 		return len;
11006 	case TABLE_TRANSFER_WIRE_ORIG:
11007 		if (!out->args.table.attr.flow_attr.transfer)
11008 			return -1;
11009 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_WIRE_ORIG;
11010 		return len;
11011 	case TABLE_TRANSFER_VPORT_ORIG:
11012 		if (!out->args.table.attr.flow_attr.transfer)
11013 			return -1;
11014 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_VPORT_ORIG;
11015 		return len;
11016 	case TABLE_RESIZABLE:
11017 		out->args.table.attr.specialize |=
11018 			RTE_FLOW_TABLE_SPECIALIZE_RESIZABLE;
11019 		return len;
11020 	case TABLE_RULES_NUMBER:
11021 		ctx->objdata = 0;
11022 		ctx->object = out;
11023 		ctx->objmask = NULL;
11024 		return len;
11025 	case TABLE_RESIZE_ID:
11026 	case TABLE_RESIZE_RULES_NUMBER:
11027 		return len;
11028 	default:
11029 		return -1;
11030 	}
11031 }
11032 
11033 /** Parse tokens for table destroy command. */
11034 static int
11035 parse_table_destroy(struct context *ctx, const struct token *token,
11036 		    const char *str, unsigned int len,
11037 		    void *buf, unsigned int size)
11038 {
11039 	struct buffer *out = buf;
11040 	uint32_t *table_id;
11041 
11042 	/* Token name must match. */
11043 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11044 		return -1;
11045 	/* Nothing else to do if there is no buffer. */
11046 	if (!out)
11047 		return len;
11048 	if (!out->command || out->command == TABLE) {
11049 		if (ctx->curr != TABLE_DESTROY &&
11050 		    ctx->curr != TABLE_RESIZE_COMPLETE)
11051 			return -1;
11052 		if (sizeof(*out) > size)
11053 			return -1;
11054 		out->command = ctx->curr;
11055 		ctx->objdata = 0;
11056 		ctx->object = out;
11057 		ctx->objmask = NULL;
11058 		out->args.table_destroy.table_id =
11059 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11060 					       sizeof(double));
11061 		return len;
11062 	}
11063 	table_id = out->args.table_destroy.table_id
11064 		    + out->args.table_destroy.table_id_n++;
11065 	if ((uint8_t *)table_id > (uint8_t *)out + size)
11066 		return -1;
11067 	ctx->objdata = 0;
11068 	ctx->object = table_id;
11069 	ctx->objmask = NULL;
11070 	return len;
11071 }
11072 
11073 /** Parse tokens for queue create commands. */
11074 static int
11075 parse_qo(struct context *ctx, const struct token *token,
11076 	 const char *str, unsigned int len,
11077 	 void *buf, unsigned int size)
11078 {
11079 	struct buffer *out = buf;
11080 
11081 	/* Token name must match. */
11082 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11083 		return -1;
11084 	/* Nothing else to do if there is no buffer. */
11085 	if (!out)
11086 		return len;
11087 	if (!out->command) {
11088 		if (ctx->curr != QUEUE)
11089 			return -1;
11090 		if (sizeof(*out) > size)
11091 			return -1;
11092 		out->command = ctx->curr;
11093 		ctx->objdata = 0;
11094 		ctx->object = out;
11095 		ctx->objmask = NULL;
11096 		out->args.vc.data = (uint8_t *)out + size;
11097 		return len;
11098 	}
11099 	switch (ctx->curr) {
11100 	case QUEUE_CREATE:
11101 	case QUEUE_UPDATE:
11102 		out->command = ctx->curr;
11103 		ctx->objdata = 0;
11104 		ctx->object = out;
11105 		ctx->objmask = NULL;
11106 		out->args.vc.rule_id = UINT32_MAX;
11107 		return len;
11108 	case QUEUE_TEMPLATE_TABLE:
11109 	case QUEUE_PATTERN_TEMPLATE:
11110 	case QUEUE_ACTIONS_TEMPLATE:
11111 	case QUEUE_CREATE_POSTPONE:
11112 	case QUEUE_RULE_ID:
11113 	case QUEUE_UPDATE_ID:
11114 		return len;
11115 	case ITEM_PATTERN:
11116 		out->args.vc.pattern =
11117 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11118 					       sizeof(double));
11119 		ctx->object = out->args.vc.pattern;
11120 		ctx->objmask = NULL;
11121 		return len;
11122 	case ACTIONS:
11123 		out->args.vc.actions =
11124 			(void *)RTE_ALIGN_CEIL((uintptr_t)
11125 					       (out->args.vc.pattern +
11126 						out->args.vc.pattern_n),
11127 					       sizeof(double));
11128 		ctx->object = out->args.vc.actions;
11129 		ctx->objmask = NULL;
11130 		return len;
11131 	default:
11132 		return -1;
11133 	}
11134 }
11135 
11136 /** Parse tokens for queue destroy command. */
11137 static int
11138 parse_qo_destroy(struct context *ctx, const struct token *token,
11139 		 const char *str, unsigned int len,
11140 		 void *buf, unsigned int size)
11141 {
11142 	struct buffer *out = buf;
11143 	uint64_t *flow_id;
11144 
11145 	/* Token name must match. */
11146 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11147 		return -1;
11148 	/* Nothing else to do if there is no buffer. */
11149 	if (!out)
11150 		return len;
11151 	if (!out->command || out->command == QUEUE) {
11152 		if (ctx->curr != QUEUE_DESTROY &&
11153 		    ctx->curr != QUEUE_FLOW_UPDATE_RESIZED)
11154 			return -1;
11155 		if (sizeof(*out) > size)
11156 			return -1;
11157 		out->command = ctx->curr;
11158 		ctx->objdata = 0;
11159 		ctx->object = out;
11160 		ctx->objmask = NULL;
11161 		out->args.destroy.rule =
11162 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11163 					       sizeof(double));
11164 		return len;
11165 	}
11166 	switch (ctx->curr) {
11167 	case QUEUE_DESTROY_ID:
11168 		flow_id = out->args.destroy.rule
11169 				+ out->args.destroy.rule_n++;
11170 		if ((uint8_t *)flow_id > (uint8_t *)out + size)
11171 			return -1;
11172 		ctx->objdata = 0;
11173 		ctx->object = flow_id;
11174 		ctx->objmask = NULL;
11175 		return len;
11176 	case QUEUE_DESTROY_POSTPONE:
11177 		return len;
11178 	default:
11179 		return -1;
11180 	}
11181 }
11182 
11183 /** Parse tokens for push queue command. */
11184 static int
11185 parse_push(struct context *ctx, const struct token *token,
11186 	   const char *str, unsigned int len,
11187 	   void *buf, unsigned int size)
11188 {
11189 	struct buffer *out = buf;
11190 
11191 	/* Token name must match. */
11192 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11193 		return -1;
11194 	/* Nothing else to do if there is no buffer. */
11195 	if (!out)
11196 		return len;
11197 	if (!out->command) {
11198 		if (ctx->curr != PUSH)
11199 			return -1;
11200 		if (sizeof(*out) > size)
11201 			return -1;
11202 		out->command = ctx->curr;
11203 		ctx->objdata = 0;
11204 		ctx->object = out;
11205 		ctx->objmask = NULL;
11206 		out->args.vc.data = (uint8_t *)out + size;
11207 	}
11208 	return len;
11209 }
11210 
11211 /** Parse tokens for pull command. */
11212 static int
11213 parse_pull(struct context *ctx, const struct token *token,
11214 	   const char *str, unsigned int len,
11215 	   void *buf, unsigned int size)
11216 {
11217 	struct buffer *out = buf;
11218 
11219 	/* Token name must match. */
11220 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11221 		return -1;
11222 	/* Nothing else to do if there is no buffer. */
11223 	if (!out)
11224 		return len;
11225 	if (!out->command) {
11226 		if (ctx->curr != PULL)
11227 			return -1;
11228 		if (sizeof(*out) > size)
11229 			return -1;
11230 		out->command = ctx->curr;
11231 		ctx->objdata = 0;
11232 		ctx->object = out;
11233 		ctx->objmask = NULL;
11234 		out->args.vc.data = (uint8_t *)out + size;
11235 	}
11236 	return len;
11237 }
11238 
11239 /** Parse tokens for hash calculation commands. */
11240 static int
11241 parse_hash(struct context *ctx, const struct token *token,
11242 	 const char *str, unsigned int len,
11243 	 void *buf, unsigned int size)
11244 {
11245 	struct buffer *out = buf;
11246 
11247 	/* Token name must match. */
11248 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11249 		return -1;
11250 	/* Nothing else to do if there is no buffer. */
11251 	if (!out)
11252 		return len;
11253 	if (!out->command) {
11254 		if (ctx->curr != HASH)
11255 			return -1;
11256 		if (sizeof(*out) > size)
11257 			return -1;
11258 		out->command = ctx->curr;
11259 		ctx->objdata = 0;
11260 		ctx->object = out;
11261 		ctx->objmask = NULL;
11262 		out->args.vc.data = (uint8_t *)out + size;
11263 		return len;
11264 	}
11265 	switch (ctx->curr) {
11266 	case HASH_CALC_TABLE:
11267 	case HASH_CALC_PATTERN_INDEX:
11268 		return len;
11269 	case ITEM_PATTERN:
11270 		out->args.vc.pattern =
11271 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11272 					       sizeof(double));
11273 		ctx->object = out->args.vc.pattern;
11274 		ctx->objmask = NULL;
11275 		return len;
11276 	case HASH_CALC_ENCAP:
11277 		out->args.vc.encap_hash = 1;
11278 		return len;
11279 	case ENCAP_HASH_FIELD_SRC_PORT:
11280 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_SRC_PORT;
11281 		return len;
11282 	case ENCAP_HASH_FIELD_GRE_FLOW_ID:
11283 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_NVGRE_FLOW_ID;
11284 		return len;
11285 	default:
11286 		return -1;
11287 	}
11288 }
11289 
11290 static int
11291 parse_group(struct context *ctx, const struct token *token,
11292 	    const char *str, unsigned int len,
11293 	    void *buf, unsigned int size)
11294 {
11295 	struct buffer *out = buf;
11296 
11297 	/* Token name must match. */
11298 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11299 		return -1;
11300 	/* Nothing else to do if there is no buffer. */
11301 	if (!out)
11302 		return len;
11303 	if (!out->command) {
11304 		if (ctx->curr != FLOW_GROUP)
11305 			return -1;
11306 		if (sizeof(*out) > size)
11307 			return -1;
11308 		out->command = ctx->curr;
11309 		ctx->objdata = 0;
11310 		ctx->object = out;
11311 		ctx->objmask = NULL;
11312 		out->args.vc.data = (uint8_t *)out + size;
11313 		return len;
11314 	}
11315 	switch (ctx->curr) {
11316 	case GROUP_INGRESS:
11317 		out->args.vc.attr.ingress = 1;
11318 		return len;
11319 	case GROUP_EGRESS:
11320 		out->args.vc.attr.egress = 1;
11321 		return len;
11322 	case GROUP_TRANSFER:
11323 		out->args.vc.attr.transfer = 1;
11324 		return len;
11325 	case GROUP_SET_MISS_ACTIONS:
11326 		out->command = ctx->curr;
11327 		ctx->objdata = 0;
11328 		ctx->object = out;
11329 		ctx->objmask = NULL;
11330 		out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11331 							       sizeof(double));
11332 		return len;
11333 	default:
11334 		return -1;
11335 	}
11336 }
11337 
11338 static int
11339 parse_flex(struct context *ctx, const struct token *token,
11340 	     const char *str, unsigned int len,
11341 	     void *buf, unsigned int size)
11342 {
11343 	struct buffer *out = buf;
11344 
11345 	/* Token name must match. */
11346 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11347 		return -1;
11348 	/* Nothing else to do if there is no buffer. */
11349 	if (!out)
11350 		return len;
11351 	if (out->command == ZERO) {
11352 		if (ctx->curr != FLEX)
11353 			return -1;
11354 		if (sizeof(*out) > size)
11355 			return -1;
11356 		out->command = ctx->curr;
11357 		ctx->objdata = 0;
11358 		ctx->object = out;
11359 		ctx->objmask = NULL;
11360 	} else {
11361 		switch (ctx->curr) {
11362 		default:
11363 			break;
11364 		case FLEX_ITEM_INIT:
11365 		case FLEX_ITEM_CREATE:
11366 		case FLEX_ITEM_DESTROY:
11367 			out->command = ctx->curr;
11368 			break;
11369 		}
11370 	}
11371 
11372 	return len;
11373 }
11374 
11375 static int
11376 parse_tunnel(struct context *ctx, const struct token *token,
11377 	     const char *str, unsigned int len,
11378 	     void *buf, unsigned int size)
11379 {
11380 	struct buffer *out = buf;
11381 
11382 	/* Token name must match. */
11383 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11384 		return -1;
11385 	/* Nothing else to do if there is no buffer. */
11386 	if (!out)
11387 		return len;
11388 	if (!out->command) {
11389 		if (ctx->curr != TUNNEL)
11390 			return -1;
11391 		if (sizeof(*out) > size)
11392 			return -1;
11393 		out->command = ctx->curr;
11394 		ctx->objdata = 0;
11395 		ctx->object = out;
11396 		ctx->objmask = NULL;
11397 	} else {
11398 		switch (ctx->curr) {
11399 		default:
11400 			break;
11401 		case TUNNEL_CREATE:
11402 		case TUNNEL_DESTROY:
11403 		case TUNNEL_LIST:
11404 			out->command = ctx->curr;
11405 			break;
11406 		case TUNNEL_CREATE_TYPE:
11407 		case TUNNEL_DESTROY_ID:
11408 			ctx->object = &out->args.vc.tunnel_ops;
11409 			break;
11410 		}
11411 	}
11412 
11413 	return len;
11414 }
11415 
11416 /**
11417  * Parse signed/unsigned integers 8 to 64-bit long.
11418  *
11419  * Last argument (ctx->args) is retrieved to determine integer type and
11420  * storage location.
11421  */
11422 static int
11423 parse_int(struct context *ctx, const struct token *token,
11424 	  const char *str, unsigned int len,
11425 	  void *buf, unsigned int size)
11426 {
11427 	const struct arg *arg = pop_args(ctx);
11428 	uintmax_t u;
11429 	char *end;
11430 
11431 	(void)token;
11432 	/* Argument is expected. */
11433 	if (!arg)
11434 		return -1;
11435 	errno = 0;
11436 	u = arg->sign ?
11437 		(uintmax_t)strtoimax(str, &end, 0) :
11438 		strtoumax(str, &end, 0);
11439 	if (errno || (size_t)(end - str) != len)
11440 		goto error;
11441 	if (arg->bounded &&
11442 	    ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
11443 			    (intmax_t)u > (intmax_t)arg->max)) ||
11444 	     (!arg->sign && (u < arg->min || u > arg->max))))
11445 		goto error;
11446 	if (!ctx->object)
11447 		return len;
11448 	if (arg->mask) {
11449 		if (!arg_entry_bf_fill(ctx->object, u, arg) ||
11450 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
11451 			goto error;
11452 		return len;
11453 	}
11454 	buf = (uint8_t *)ctx->object + arg->offset;
11455 	size = arg->size;
11456 	if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
11457 		return -1;
11458 objmask:
11459 	switch (size) {
11460 	case sizeof(uint8_t):
11461 		*(uint8_t *)buf = u;
11462 		break;
11463 	case sizeof(uint16_t):
11464 		*(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
11465 		break;
11466 	case sizeof(uint8_t [3]):
11467 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
11468 		if (!arg->hton) {
11469 			((uint8_t *)buf)[0] = u;
11470 			((uint8_t *)buf)[1] = u >> 8;
11471 			((uint8_t *)buf)[2] = u >> 16;
11472 			break;
11473 		}
11474 #endif
11475 		((uint8_t *)buf)[0] = u >> 16;
11476 		((uint8_t *)buf)[1] = u >> 8;
11477 		((uint8_t *)buf)[2] = u;
11478 		break;
11479 	case sizeof(uint32_t):
11480 		*(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
11481 		break;
11482 	case sizeof(uint64_t):
11483 		*(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
11484 		break;
11485 	default:
11486 		goto error;
11487 	}
11488 	if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
11489 		u = -1;
11490 		buf = (uint8_t *)ctx->objmask + arg->offset;
11491 		goto objmask;
11492 	}
11493 	return len;
11494 error:
11495 	push_args(ctx, arg);
11496 	return -1;
11497 }
11498 
11499 /**
11500  * Parse a string.
11501  *
11502  * Three arguments (ctx->args) are retrieved from the stack to store data,
11503  * its actual length and address (in that order).
11504  */
11505 static int
11506 parse_string(struct context *ctx, const struct token *token,
11507 	     const char *str, unsigned int len,
11508 	     void *buf, unsigned int size)
11509 {
11510 	const struct arg *arg_data = pop_args(ctx);
11511 	const struct arg *arg_len = pop_args(ctx);
11512 	const struct arg *arg_addr = pop_args(ctx);
11513 	char tmp[16]; /* Ought to be enough. */
11514 	int ret;
11515 
11516 	/* Arguments are expected. */
11517 	if (!arg_data)
11518 		return -1;
11519 	if (!arg_len) {
11520 		push_args(ctx, arg_data);
11521 		return -1;
11522 	}
11523 	if (!arg_addr) {
11524 		push_args(ctx, arg_len);
11525 		push_args(ctx, arg_data);
11526 		return -1;
11527 	}
11528 	size = arg_data->size;
11529 	/* Bit-mask fill is not supported. */
11530 	if (arg_data->mask || size < len)
11531 		goto error;
11532 	if (!ctx->object)
11533 		return len;
11534 	/* Let parse_int() fill length information first. */
11535 	ret = snprintf(tmp, sizeof(tmp), "%u", len);
11536 	if (ret < 0)
11537 		goto error;
11538 	push_args(ctx, arg_len);
11539 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11540 	if (ret < 0) {
11541 		pop_args(ctx);
11542 		goto error;
11543 	}
11544 	buf = (uint8_t *)ctx->object + arg_data->offset;
11545 	/* Output buffer is not necessarily NUL-terminated. */
11546 	memcpy(buf, str, len);
11547 	memset((uint8_t *)buf + len, 0x00, size - len);
11548 	if (ctx->objmask)
11549 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11550 	/* Save address if requested. */
11551 	if (arg_addr->size) {
11552 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11553 		       (void *[]){
11554 			(uint8_t *)ctx->object + arg_data->offset
11555 		       },
11556 		       arg_addr->size);
11557 		if (ctx->objmask)
11558 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11559 			       (void *[]){
11560 				(uint8_t *)ctx->objmask + arg_data->offset
11561 			       },
11562 			       arg_addr->size);
11563 	}
11564 	return len;
11565 error:
11566 	push_args(ctx, arg_addr);
11567 	push_args(ctx, arg_len);
11568 	push_args(ctx, arg_data);
11569 	return -1;
11570 }
11571 
11572 static int
11573 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
11574 {
11575 	const uint8_t *head = dst;
11576 	uint32_t left;
11577 
11578 	if (*size == 0)
11579 		return -1;
11580 
11581 	left = *size;
11582 
11583 	/* Convert chars to bytes */
11584 	while (left) {
11585 		char tmp[3], *end = tmp;
11586 		uint32_t read_lim = left & 1 ? 1 : 2;
11587 
11588 		snprintf(tmp, read_lim + 1, "%s", src);
11589 		*dst = strtoul(tmp, &end, 16);
11590 		if (*end) {
11591 			*dst = 0;
11592 			*size = (uint32_t)(dst - head);
11593 			return -1;
11594 		}
11595 		left -= read_lim;
11596 		src += read_lim;
11597 		dst++;
11598 	}
11599 	*dst = 0;
11600 	*size = (uint32_t)(dst - head);
11601 	return 0;
11602 }
11603 
11604 static int
11605 parse_hex(struct context *ctx, const struct token *token,
11606 		const char *str, unsigned int len,
11607 		void *buf, unsigned int size)
11608 {
11609 	const struct arg *arg_data = pop_args(ctx);
11610 	const struct arg *arg_len = pop_args(ctx);
11611 	const struct arg *arg_addr = pop_args(ctx);
11612 	char tmp[16]; /* Ought to be enough. */
11613 	int ret;
11614 	unsigned int hexlen = len;
11615 	unsigned int length = 256;
11616 	uint8_t hex_tmp[length];
11617 
11618 	/* Arguments are expected. */
11619 	if (!arg_data)
11620 		return -1;
11621 	if (!arg_len) {
11622 		push_args(ctx, arg_data);
11623 		return -1;
11624 	}
11625 	if (!arg_addr) {
11626 		push_args(ctx, arg_len);
11627 		push_args(ctx, arg_data);
11628 		return -1;
11629 	}
11630 	size = arg_data->size;
11631 	/* Bit-mask fill is not supported. */
11632 	if (arg_data->mask)
11633 		goto error;
11634 	if (!ctx->object)
11635 		return len;
11636 
11637 	/* translate bytes string to array. */
11638 	if (str[0] == '0' && ((str[1] == 'x') ||
11639 			(str[1] == 'X'))) {
11640 		str += 2;
11641 		hexlen -= 2;
11642 	}
11643 	if (hexlen > length)
11644 		goto error;
11645 	ret = parse_hex_string(str, hex_tmp, &hexlen);
11646 	if (ret < 0)
11647 		goto error;
11648 	/* Check the converted binary fits into data buffer. */
11649 	if (hexlen > size)
11650 		goto error;
11651 	/* Let parse_int() fill length information first. */
11652 	ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
11653 	if (ret < 0)
11654 		goto error;
11655 	/* Save length if requested. */
11656 	if (arg_len->size) {
11657 		push_args(ctx, arg_len);
11658 		ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11659 		if (ret < 0) {
11660 			pop_args(ctx);
11661 			goto error;
11662 		}
11663 	}
11664 	buf = (uint8_t *)ctx->object + arg_data->offset;
11665 	/* Output buffer is not necessarily NUL-terminated. */
11666 	memcpy(buf, hex_tmp, hexlen);
11667 	memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
11668 	if (ctx->objmask)
11669 		memset((uint8_t *)ctx->objmask + arg_data->offset,
11670 					0xff, hexlen);
11671 	/* Save address if requested. */
11672 	if (arg_addr->size) {
11673 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11674 		       (void *[]){
11675 			(uint8_t *)ctx->object + arg_data->offset
11676 		       },
11677 		       arg_addr->size);
11678 		if (ctx->objmask)
11679 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11680 			       (void *[]){
11681 				(uint8_t *)ctx->objmask + arg_data->offset
11682 			       },
11683 			       arg_addr->size);
11684 	}
11685 	return len;
11686 error:
11687 	push_args(ctx, arg_addr);
11688 	push_args(ctx, arg_len);
11689 	push_args(ctx, arg_data);
11690 	return -1;
11691 
11692 }
11693 
11694 /**
11695  * Parse a zero-ended string.
11696  */
11697 static int
11698 parse_string0(struct context *ctx, const struct token *token __rte_unused,
11699 	     const char *str, unsigned int len,
11700 	     void *buf, unsigned int size)
11701 {
11702 	const struct arg *arg_data = pop_args(ctx);
11703 
11704 	/* Arguments are expected. */
11705 	if (!arg_data)
11706 		return -1;
11707 	size = arg_data->size;
11708 	/* Bit-mask fill is not supported. */
11709 	if (arg_data->mask || size < len + 1)
11710 		goto error;
11711 	if (!ctx->object)
11712 		return len;
11713 	buf = (uint8_t *)ctx->object + arg_data->offset;
11714 	strncpy(buf, str, len);
11715 	if (ctx->objmask)
11716 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11717 	return len;
11718 error:
11719 	push_args(ctx, arg_data);
11720 	return -1;
11721 }
11722 
11723 /**
11724  * Parse a MAC address.
11725  *
11726  * Last argument (ctx->args) is retrieved to determine storage size and
11727  * location.
11728  */
11729 static int
11730 parse_mac_addr(struct context *ctx, const struct token *token,
11731 	       const char *str, unsigned int len,
11732 	       void *buf, unsigned int size)
11733 {
11734 	const struct arg *arg = pop_args(ctx);
11735 	struct rte_ether_addr tmp;
11736 	int ret;
11737 
11738 	(void)token;
11739 	/* Argument is expected. */
11740 	if (!arg)
11741 		return -1;
11742 	size = arg->size;
11743 	/* Bit-mask fill is not supported. */
11744 	if (arg->mask || size != sizeof(tmp))
11745 		goto error;
11746 	/* Only network endian is supported. */
11747 	if (!arg->hton)
11748 		goto error;
11749 	ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
11750 	if (ret < 0 || (unsigned int)ret != len)
11751 		goto error;
11752 	if (!ctx->object)
11753 		return len;
11754 	buf = (uint8_t *)ctx->object + arg->offset;
11755 	memcpy(buf, &tmp, size);
11756 	if (ctx->objmask)
11757 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11758 	return len;
11759 error:
11760 	push_args(ctx, arg);
11761 	return -1;
11762 }
11763 
11764 /**
11765  * Parse an IPv4 address.
11766  *
11767  * Last argument (ctx->args) is retrieved to determine storage size and
11768  * location.
11769  */
11770 static int
11771 parse_ipv4_addr(struct context *ctx, const struct token *token,
11772 		const char *str, unsigned int len,
11773 		void *buf, unsigned int size)
11774 {
11775 	const struct arg *arg = pop_args(ctx);
11776 	char str2[len + 1];
11777 	struct in_addr tmp;
11778 	int ret;
11779 
11780 	/* Argument is expected. */
11781 	if (!arg)
11782 		return -1;
11783 	size = arg->size;
11784 	/* Bit-mask fill is not supported. */
11785 	if (arg->mask || size != sizeof(tmp))
11786 		goto error;
11787 	/* Only network endian is supported. */
11788 	if (!arg->hton)
11789 		goto error;
11790 	memcpy(str2, str, len);
11791 	str2[len] = '\0';
11792 	ret = inet_pton(AF_INET, str2, &tmp);
11793 	if (ret != 1) {
11794 		/* Attempt integer parsing. */
11795 		push_args(ctx, arg);
11796 		return parse_int(ctx, token, str, len, buf, size);
11797 	}
11798 	if (!ctx->object)
11799 		return len;
11800 	buf = (uint8_t *)ctx->object + arg->offset;
11801 	memcpy(buf, &tmp, size);
11802 	if (ctx->objmask)
11803 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11804 	return len;
11805 error:
11806 	push_args(ctx, arg);
11807 	return -1;
11808 }
11809 
11810 /**
11811  * Parse an IPv6 address.
11812  *
11813  * Last argument (ctx->args) is retrieved to determine storage size and
11814  * location.
11815  */
11816 static int
11817 parse_ipv6_addr(struct context *ctx, const struct token *token,
11818 		const char *str, unsigned int len,
11819 		void *buf, unsigned int size)
11820 {
11821 	const struct arg *arg = pop_args(ctx);
11822 	char str2[len + 1];
11823 	struct in6_addr tmp;
11824 	int ret;
11825 
11826 	(void)token;
11827 	/* Argument is expected. */
11828 	if (!arg)
11829 		return -1;
11830 	size = arg->size;
11831 	/* Bit-mask fill is not supported. */
11832 	if (arg->mask || size != sizeof(tmp))
11833 		goto error;
11834 	/* Only network endian is supported. */
11835 	if (!arg->hton)
11836 		goto error;
11837 	memcpy(str2, str, len);
11838 	str2[len] = '\0';
11839 	ret = inet_pton(AF_INET6, str2, &tmp);
11840 	if (ret != 1)
11841 		goto error;
11842 	if (!ctx->object)
11843 		return len;
11844 	buf = (uint8_t *)ctx->object + arg->offset;
11845 	memcpy(buf, &tmp, size);
11846 	if (ctx->objmask)
11847 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11848 	return len;
11849 error:
11850 	push_args(ctx, arg);
11851 	return -1;
11852 }
11853 
11854 /** Boolean values (even indices stand for false). */
11855 static const char *const boolean_name[] = {
11856 	"0", "1",
11857 	"false", "true",
11858 	"no", "yes",
11859 	"N", "Y",
11860 	"off", "on",
11861 	NULL,
11862 };
11863 
11864 /**
11865  * Parse a boolean value.
11866  *
11867  * Last argument (ctx->args) is retrieved to determine storage size and
11868  * location.
11869  */
11870 static int
11871 parse_boolean(struct context *ctx, const struct token *token,
11872 	      const char *str, unsigned int len,
11873 	      void *buf, unsigned int size)
11874 {
11875 	const struct arg *arg = pop_args(ctx);
11876 	unsigned int i;
11877 	int ret;
11878 
11879 	/* Argument is expected. */
11880 	if (!arg)
11881 		return -1;
11882 	for (i = 0; boolean_name[i]; ++i)
11883 		if (!strcmp_partial(boolean_name[i], str, len))
11884 			break;
11885 	/* Process token as integer. */
11886 	if (boolean_name[i])
11887 		str = i & 1 ? "1" : "0";
11888 	push_args(ctx, arg);
11889 	ret = parse_int(ctx, token, str, strlen(str), buf, size);
11890 	return ret > 0 ? (int)len : ret;
11891 }
11892 
11893 /** Parse port and update context. */
11894 static int
11895 parse_port(struct context *ctx, const struct token *token,
11896 	   const char *str, unsigned int len,
11897 	   void *buf, unsigned int size)
11898 {
11899 	struct buffer *out = &(struct buffer){ .port = 0 };
11900 	int ret;
11901 
11902 	if (buf)
11903 		out = buf;
11904 	else {
11905 		ctx->objdata = 0;
11906 		ctx->object = out;
11907 		ctx->objmask = NULL;
11908 		size = sizeof(*out);
11909 	}
11910 	ret = parse_int(ctx, token, str, len, out, size);
11911 	if (ret >= 0)
11912 		ctx->port = out->port;
11913 	if (!buf)
11914 		ctx->object = NULL;
11915 	return ret;
11916 }
11917 
11918 /** Parse tokens for shared indirect actions. */
11919 static int
11920 parse_ia_port(struct context *ctx, const struct token *token,
11921 	      const char *str, unsigned int len,
11922 	      void *buf, unsigned int size)
11923 {
11924 	struct rte_flow_action *action = ctx->object;
11925 	uint32_t id;
11926 	int ret;
11927 
11928 	(void)buf;
11929 	(void)size;
11930 	ctx->objdata = 0;
11931 	ctx->object = &id;
11932 	ctx->objmask = NULL;
11933 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11934 	ctx->object = action;
11935 	if (ret != (int)len)
11936 		return ret;
11937 	/* set indirect action */
11938 	if (action)
11939 		action->conf = (void *)(uintptr_t)id;
11940 	return ret;
11941 }
11942 
11943 static int
11944 parse_ia_id2ptr(struct context *ctx, const struct token *token,
11945 		const char *str, unsigned int len,
11946 		void *buf, unsigned int size)
11947 {
11948 	struct rte_flow_action *action = ctx->object;
11949 	uint32_t id;
11950 	int ret;
11951 
11952 	(void)buf;
11953 	(void)size;
11954 	ctx->objdata = 0;
11955 	ctx->object = &id;
11956 	ctx->objmask = NULL;
11957 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11958 	ctx->object = action;
11959 	if (ret != (int)len)
11960 		return ret;
11961 	/* set indirect action */
11962 	if (action) {
11963 		portid_t port_id = ctx->port;
11964 		if (ctx->prev == INDIRECT_ACTION_PORT)
11965 			port_id = (portid_t)(uintptr_t)action->conf;
11966 		action->conf = port_action_handle_get_by_id(port_id, id);
11967 		ret = (action->conf) ? ret : -1;
11968 	}
11969 	return ret;
11970 }
11971 
11972 static int
11973 parse_indlst_id2ptr(struct context *ctx, const struct token *token,
11974 		    const char *str, unsigned int len,
11975 		    __rte_unused void *buf, __rte_unused unsigned int size)
11976 {
11977 	struct rte_flow_action *action = ctx->object;
11978 	struct rte_flow_action_indirect_list *action_conf;
11979 	const struct indlst_conf *indlst_conf;
11980 	uint32_t id;
11981 	int ret;
11982 
11983 	ctx->objdata = 0;
11984 	ctx->object = &id;
11985 	ctx->objmask = NULL;
11986 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11987 	ctx->object = action;
11988 	if (ret != (int)len)
11989 		return ret;
11990 
11991 	/* set handle and conf */
11992 	if (action) {
11993 		action_conf = (void *)(uintptr_t)action->conf;
11994 		action_conf->conf = NULL;
11995 		switch (ctx->curr) {
11996 		case INDIRECT_LIST_ACTION_ID2PTR_HANDLE:
11997 		action_conf->handle = (typeof(action_conf->handle))
11998 					port_action_handle_get_by_id(ctx->port, id);
11999 			if (!action_conf->handle) {
12000 				printf("no indirect list handle for id %u\n", id);
12001 				return -1;
12002 			}
12003 			break;
12004 		case INDIRECT_LIST_ACTION_ID2PTR_CONF:
12005 			indlst_conf = indirect_action_list_conf_get(id);
12006 			if (!indlst_conf)
12007 				return -1;
12008 			action_conf->conf = (const void **)indlst_conf->conf;
12009 			break;
12010 		default:
12011 			break;
12012 		}
12013 	}
12014 	return ret;
12015 }
12016 
12017 static int
12018 parse_meter_profile_id2ptr(struct context *ctx, const struct token *token,
12019 		const char *str, unsigned int len,
12020 		void *buf, unsigned int size)
12021 {
12022 	struct rte_flow_action *action = ctx->object;
12023 	struct rte_flow_action_meter_mark *meter;
12024 	struct rte_flow_meter_profile *profile = NULL;
12025 	uint32_t id = 0;
12026 	int ret;
12027 
12028 	(void)buf;
12029 	(void)size;
12030 	ctx->objdata = 0;
12031 	ctx->object = &id;
12032 	ctx->objmask = NULL;
12033 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12034 	ctx->object = action;
12035 	if (ret != (int)len)
12036 		return ret;
12037 	/* set meter profile */
12038 	if (action) {
12039 		meter = (struct rte_flow_action_meter_mark *)
12040 			(uintptr_t)(action->conf);
12041 		profile = port_meter_profile_get_by_id(ctx->port, id);
12042 		meter->profile = profile;
12043 		ret = (profile) ? ret : -1;
12044 	}
12045 	return ret;
12046 }
12047 
12048 static int
12049 parse_meter_policy_id2ptr(struct context *ctx, const struct token *token,
12050 		const char *str, unsigned int len,
12051 		void *buf, unsigned int size)
12052 {
12053 	struct rte_flow_action *action = ctx->object;
12054 	struct rte_flow_action_meter_mark *meter;
12055 	struct rte_flow_meter_policy *policy = NULL;
12056 	uint32_t id = 0;
12057 	int ret;
12058 
12059 	(void)buf;
12060 	(void)size;
12061 	ctx->objdata = 0;
12062 	ctx->object = &id;
12063 	ctx->objmask = NULL;
12064 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12065 	ctx->object = action;
12066 	if (ret != (int)len)
12067 		return ret;
12068 	/* set meter policy */
12069 	if (action) {
12070 		meter = (struct rte_flow_action_meter_mark *)
12071 			(uintptr_t)(action->conf);
12072 		policy = port_meter_policy_get_by_id(ctx->port, id);
12073 		meter->policy = policy;
12074 		ret = (policy) ? ret : -1;
12075 	}
12076 	return ret;
12077 }
12078 
12079 /** Parse set command, initialize output buffer for subsequent tokens. */
12080 static int
12081 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
12082 			  const char *str, unsigned int len,
12083 			  void *buf, unsigned int size)
12084 {
12085 	struct buffer *out = buf;
12086 
12087 	/* Token name must match. */
12088 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12089 		return -1;
12090 	/* Nothing else to do if there is no buffer. */
12091 	if (!out)
12092 		return len;
12093 	/* Make sure buffer is large enough. */
12094 	if (size < sizeof(*out))
12095 		return -1;
12096 	ctx->objdata = 0;
12097 	ctx->objmask = NULL;
12098 	ctx->object = out;
12099 	if (!out->command)
12100 		return -1;
12101 	out->command = ctx->curr;
12102 	/* For encap/decap we need is pattern */
12103 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12104 						       sizeof(double));
12105 	return len;
12106 }
12107 
12108 /** Parse set command, initialize output buffer for subsequent tokens. */
12109 static int
12110 parse_set_sample_action(struct context *ctx, const struct token *token,
12111 			  const char *str, unsigned int len,
12112 			  void *buf, unsigned int size)
12113 {
12114 	struct buffer *out = buf;
12115 
12116 	/* Token name must match. */
12117 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12118 		return -1;
12119 	/* Nothing else to do if there is no buffer. */
12120 	if (!out)
12121 		return len;
12122 	/* Make sure buffer is large enough. */
12123 	if (size < sizeof(*out))
12124 		return -1;
12125 	ctx->objdata = 0;
12126 	ctx->objmask = NULL;
12127 	ctx->object = out;
12128 	if (!out->command)
12129 		return -1;
12130 	out->command = ctx->curr;
12131 	/* For sampler we need is actions */
12132 	out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12133 						       sizeof(double));
12134 	return len;
12135 }
12136 
12137 /** Parse set command, initialize output buffer for subsequent tokens. */
12138 static int
12139 parse_set_ipv6_ext_action(struct context *ctx, const struct token *token,
12140 			  const char *str, unsigned int len,
12141 			  void *buf, unsigned int size)
12142 {
12143 	struct buffer *out = buf;
12144 
12145 	/* Token name must match. */
12146 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12147 		return -1;
12148 	/* Nothing else to do if there is no buffer. */
12149 	if (!out)
12150 		return len;
12151 	/* Make sure buffer is large enough. */
12152 	if (size < sizeof(*out))
12153 		return -1;
12154 	ctx->objdata = 0;
12155 	ctx->objmask = NULL;
12156 	ctx->object = out;
12157 	if (!out->command)
12158 		return -1;
12159 	out->command = ctx->curr;
12160 	/* For ipv6_ext_push/remove we need is pattern */
12161 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12162 						       sizeof(double));
12163 	return len;
12164 }
12165 
12166 /**
12167  * Parse set raw_encap/raw_decap command,
12168  * initialize output buffer for subsequent tokens.
12169  */
12170 static int
12171 parse_set_init(struct context *ctx, const struct token *token,
12172 	       const char *str, unsigned int len,
12173 	       void *buf, unsigned int size)
12174 {
12175 	struct buffer *out = buf;
12176 
12177 	/* Token name must match. */
12178 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12179 		return -1;
12180 	/* Nothing else to do if there is no buffer. */
12181 	if (!out)
12182 		return len;
12183 	/* Make sure buffer is large enough. */
12184 	if (size < sizeof(*out))
12185 		return -1;
12186 	/* Initialize buffer. */
12187 	memset(out, 0x00, sizeof(*out));
12188 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
12189 	ctx->objdata = 0;
12190 	ctx->object = out;
12191 	ctx->objmask = NULL;
12192 	if (!out->command) {
12193 		if (ctx->curr != SET)
12194 			return -1;
12195 		if (sizeof(*out) > size)
12196 			return -1;
12197 		out->command = ctx->curr;
12198 		out->args.vc.data = (uint8_t *)out + size;
12199 		ctx->object  = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12200 						       sizeof(double));
12201 	}
12202 	return len;
12203 }
12204 
12205 /*
12206  * Replace testpmd handles in a flex flow item with real values.
12207  */
12208 static int
12209 parse_flex_handle(struct context *ctx, const struct token *token,
12210 		  const char *str, unsigned int len,
12211 		  void *buf, unsigned int size)
12212 {
12213 	struct rte_flow_item_flex *spec, *mask;
12214 	const struct rte_flow_item_flex *src_spec, *src_mask;
12215 	const struct arg *arg = pop_args(ctx);
12216 	uint32_t offset;
12217 	uint16_t handle;
12218 	int ret;
12219 
12220 	if (!arg) {
12221 		printf("Bad environment\n");
12222 		return -1;
12223 	}
12224 	offset = arg->offset;
12225 	push_args(ctx, arg);
12226 	ret = parse_int(ctx, token, str, len, buf, size);
12227 	if (ret <= 0 || !ctx->object)
12228 		return ret;
12229 	if (ctx->port >= RTE_MAX_ETHPORTS) {
12230 		printf("Bad port\n");
12231 		return -1;
12232 	}
12233 	if (offset == offsetof(struct rte_flow_item_flex, handle)) {
12234 		const struct flex_item *fp;
12235 		spec = ctx->object;
12236 		handle = (uint16_t)(uintptr_t)spec->handle;
12237 		if (handle >= FLEX_MAX_PARSERS_NUM) {
12238 			printf("Bad flex item handle\n");
12239 			return -1;
12240 		}
12241 		fp = flex_items[ctx->port][handle];
12242 		if (!fp) {
12243 			printf("Bad flex item handle\n");
12244 			return -1;
12245 		}
12246 		spec->handle = fp->flex_handle;
12247 		mask = spec + 2; /* spec, last, mask */
12248 		mask->handle = fp->flex_handle;
12249 	} else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
12250 		handle = (uint16_t)(uintptr_t)
12251 			((struct rte_flow_item_flex *)ctx->object)->pattern;
12252 		if (handle >= FLEX_MAX_PATTERNS_NUM) {
12253 			printf("Bad pattern handle\n");
12254 			return -1;
12255 		}
12256 		src_spec = &flex_patterns[handle].spec;
12257 		src_mask = &flex_patterns[handle].mask;
12258 		spec = ctx->object;
12259 		mask = spec + 2; /* spec, last, mask */
12260 		/* fill flow rule spec and mask parameters */
12261 		spec->length = src_spec->length;
12262 		spec->pattern = src_spec->pattern;
12263 		mask->length = src_mask->length;
12264 		mask->pattern = src_mask->pattern;
12265 	} else {
12266 		printf("Bad arguments - unknown flex item offset\n");
12267 		return -1;
12268 	}
12269 	return ret;
12270 }
12271 
12272 /** Parse Meter color name */
12273 static int
12274 parse_meter_color(struct context *ctx, const struct token *token,
12275 		  const char *str, unsigned int len, void *buf,
12276 		  unsigned int size)
12277 {
12278 	struct rte_flow_item_meter_color *meter_color;
12279 	unsigned int i;
12280 
12281 	(void)token;
12282 	(void)buf;
12283 	(void)size;
12284 	for (i = 0; meter_colors[i]; ++i)
12285 		if (!strcmp_partial(meter_colors[i], str, len))
12286 			break;
12287 	if (!meter_colors[i])
12288 		return -1;
12289 	if (!ctx->object)
12290 		return len;
12291 	meter_color = ctx->object;
12292 	meter_color->color = (enum rte_color)i;
12293 	return len;
12294 }
12295 
12296 /** Parse Insertion Table Type name */
12297 static int
12298 parse_insertion_table_type(struct context *ctx, const struct token *token,
12299 			   const char *str, unsigned int len, void *buf,
12300 			   unsigned int size)
12301 {
12302 	const struct arg *arg = pop_args(ctx);
12303 	unsigned int i;
12304 	char tmp[2];
12305 	int ret;
12306 
12307 	(void)size;
12308 	/* Argument is expected. */
12309 	if (!arg)
12310 		return -1;
12311 	for (i = 0; table_insertion_types[i]; ++i)
12312 		if (!strcmp_partial(table_insertion_types[i], str, len))
12313 			break;
12314 	if (!table_insertion_types[i])
12315 		return -1;
12316 	push_args(ctx, arg);
12317 	snprintf(tmp, sizeof(tmp), "%u", i);
12318 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12319 	return ret > 0 ? (int)len : ret;
12320 }
12321 
12322 /** Parse Hash Calculation Table Type name */
12323 static int
12324 parse_hash_table_type(struct context *ctx, const struct token *token,
12325 		      const char *str, unsigned int len, void *buf,
12326 		      unsigned int size)
12327 {
12328 	const struct arg *arg = pop_args(ctx);
12329 	unsigned int i;
12330 	char tmp[2];
12331 	int ret;
12332 
12333 	(void)size;
12334 	/* Argument is expected. */
12335 	if (!arg)
12336 		return -1;
12337 	for (i = 0; table_hash_funcs[i]; ++i)
12338 		if (!strcmp_partial(table_hash_funcs[i], str, len))
12339 			break;
12340 	if (!table_hash_funcs[i])
12341 		return -1;
12342 	push_args(ctx, arg);
12343 	snprintf(tmp, sizeof(tmp), "%u", i);
12344 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12345 	return ret > 0 ? (int)len : ret;
12346 }
12347 
12348 static int
12349 parse_name_to_index(struct context *ctx, const struct token *token,
12350 		    const char *str, unsigned int len, void *buf,
12351 		    unsigned int size,
12352 		    const char *const names[], size_t names_size, uint32_t *dst)
12353 {
12354 	int ret;
12355 	uint32_t i;
12356 
12357 	RTE_SET_USED(token);
12358 	RTE_SET_USED(buf);
12359 	RTE_SET_USED(size);
12360 	if (!ctx->object)
12361 		return len;
12362 	for (i = 0; i < names_size; i++) {
12363 		if (!names[i])
12364 			continue;
12365 		ret = strcmp_partial(names[i], str,
12366 				     RTE_MIN(len, strlen(names[i])));
12367 		if (!ret) {
12368 			*dst = i;
12369 			return len;
12370 		}
12371 	}
12372 	return -1;
12373 }
12374 
12375 static const char *const quota_mode_names[] = {
12376 	NULL,
12377 	[RTE_FLOW_QUOTA_MODE_PACKET] = "packet",
12378 	[RTE_FLOW_QUOTA_MODE_L2] = "l2",
12379 	[RTE_FLOW_QUOTA_MODE_L3] = "l3"
12380 };
12381 
12382 static const char *const quota_state_names[] = {
12383 	[RTE_FLOW_QUOTA_STATE_PASS] = "pass",
12384 	[RTE_FLOW_QUOTA_STATE_BLOCK] = "block"
12385 };
12386 
12387 static const char *const quota_update_names[] = {
12388 	[RTE_FLOW_UPDATE_QUOTA_SET] = "set",
12389 	[RTE_FLOW_UPDATE_QUOTA_ADD] = "add"
12390 };
12391 
12392 static const char *const query_update_mode_names[] = {
12393 	[RTE_FLOW_QU_QUERY_FIRST] = "query_first",
12394 	[RTE_FLOW_QU_UPDATE_FIRST] = "update_first"
12395 };
12396 
12397 static int
12398 parse_quota_state_name(struct context *ctx, const struct token *token,
12399 		       const char *str, unsigned int len, void *buf,
12400 		       unsigned int size)
12401 {
12402 	struct rte_flow_item_quota *quota = ctx->object;
12403 
12404 	return parse_name_to_index(ctx, token, str, len, buf, size,
12405 				   quota_state_names,
12406 				   RTE_DIM(quota_state_names),
12407 				   (uint32_t *)&quota->state);
12408 }
12409 
12410 static int
12411 parse_quota_mode_name(struct context *ctx, const struct token *token,
12412 		      const char *str, unsigned int len, void *buf,
12413 		      unsigned int size)
12414 {
12415 	struct rte_flow_action_quota *quota = ctx->object;
12416 
12417 	return parse_name_to_index(ctx, token, str, len, buf, size,
12418 				   quota_mode_names,
12419 				   RTE_DIM(quota_mode_names),
12420 				   (uint32_t *)&quota->mode);
12421 }
12422 
12423 static int
12424 parse_quota_update_name(struct context *ctx, const struct token *token,
12425 			const char *str, unsigned int len, void *buf,
12426 			unsigned int size)
12427 {
12428 	struct rte_flow_update_quota *update = ctx->object;
12429 
12430 	return parse_name_to_index(ctx, token, str, len, buf, size,
12431 				   quota_update_names,
12432 				   RTE_DIM(quota_update_names),
12433 				   (uint32_t *)&update->op);
12434 }
12435 
12436 static int
12437 parse_qu_mode_name(struct context *ctx, const struct token *token,
12438 		   const char *str, unsigned int len, void *buf,
12439 		   unsigned int size)
12440 {
12441 	struct buffer *out = ctx->object;
12442 
12443 	return parse_name_to_index(ctx, token, str, len, buf, size,
12444 				   query_update_mode_names,
12445 				   RTE_DIM(query_update_mode_names),
12446 				   (uint32_t *)&out->args.ia.qu_mode);
12447 }
12448 
12449 /** No completion. */
12450 static int
12451 comp_none(struct context *ctx, const struct token *token,
12452 	  unsigned int ent, char *buf, unsigned int size)
12453 {
12454 	(void)ctx;
12455 	(void)token;
12456 	(void)ent;
12457 	(void)buf;
12458 	(void)size;
12459 	return 0;
12460 }
12461 
12462 /** Complete boolean values. */
12463 static int
12464 comp_boolean(struct context *ctx, const struct token *token,
12465 	     unsigned int ent, char *buf, unsigned int size)
12466 {
12467 	unsigned int i;
12468 
12469 	(void)ctx;
12470 	(void)token;
12471 	for (i = 0; boolean_name[i]; ++i)
12472 		if (buf && i == ent)
12473 			return strlcpy(buf, boolean_name[i], size);
12474 	if (buf)
12475 		return -1;
12476 	return i;
12477 }
12478 
12479 /** Complete action names. */
12480 static int
12481 comp_action(struct context *ctx, const struct token *token,
12482 	    unsigned int ent, char *buf, unsigned int size)
12483 {
12484 	unsigned int i;
12485 
12486 	(void)ctx;
12487 	(void)token;
12488 	for (i = 0; next_action[i]; ++i)
12489 		if (buf && i == ent)
12490 			return strlcpy(buf, token_list[next_action[i]].name,
12491 				       size);
12492 	if (buf)
12493 		return -1;
12494 	return i;
12495 }
12496 
12497 /** Complete available ports. */
12498 static int
12499 comp_port(struct context *ctx, const struct token *token,
12500 	  unsigned int ent, char *buf, unsigned int size)
12501 {
12502 	unsigned int i = 0;
12503 	portid_t p;
12504 
12505 	(void)ctx;
12506 	(void)token;
12507 	RTE_ETH_FOREACH_DEV(p) {
12508 		if (buf && i == ent)
12509 			return snprintf(buf, size, "%u", p);
12510 		++i;
12511 	}
12512 	if (buf)
12513 		return -1;
12514 	return i;
12515 }
12516 
12517 /** Complete available rule IDs. */
12518 static int
12519 comp_rule_id(struct context *ctx, const struct token *token,
12520 	     unsigned int ent, char *buf, unsigned int size)
12521 {
12522 	unsigned int i = 0;
12523 	struct rte_port *port;
12524 	struct port_flow *pf;
12525 
12526 	(void)token;
12527 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12528 	    ctx->port == (portid_t)RTE_PORT_ALL)
12529 		return -1;
12530 	port = &ports[ctx->port];
12531 	for (pf = port->flow_list; pf != NULL; pf = pf->next) {
12532 		if (buf && i == ent)
12533 			return snprintf(buf, size, "%"PRIu64, pf->id);
12534 		++i;
12535 	}
12536 	if (buf)
12537 		return -1;
12538 	return i;
12539 }
12540 
12541 /** Complete operation for compare match item. */
12542 static int
12543 comp_set_compare_op(struct context *ctx, const struct token *token,
12544 		    unsigned int ent, char *buf, unsigned int size)
12545 {
12546 	RTE_SET_USED(ctx);
12547 	RTE_SET_USED(token);
12548 	if (!buf)
12549 		return RTE_DIM(compare_ops);
12550 	if (ent < RTE_DIM(compare_ops) - 1)
12551 		return strlcpy(buf, compare_ops[ent], size);
12552 	return -1;
12553 }
12554 
12555 /** Complete field id for compare match item. */
12556 static int
12557 comp_set_compare_field_id(struct context *ctx, const struct token *token,
12558 			  unsigned int ent, char *buf, unsigned int size)
12559 {
12560 	const char *name;
12561 
12562 	RTE_SET_USED(token);
12563 	if (!buf)
12564 		return RTE_DIM(flow_field_ids);
12565 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12566 		return -1;
12567 	name = flow_field_ids[ent];
12568 	if (ctx->curr == ITEM_COMPARE_FIELD_B_TYPE ||
12569 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12570 		return strlcpy(buf, name, size);
12571 	return -1;
12572 }
12573 
12574 /** Complete type field for RSS action. */
12575 static int
12576 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
12577 			unsigned int ent, char *buf, unsigned int size)
12578 {
12579 	unsigned int i;
12580 
12581 	(void)ctx;
12582 	(void)token;
12583 	for (i = 0; rss_type_table[i].str; ++i)
12584 		;
12585 	if (!buf)
12586 		return i + 1;
12587 	if (ent < i)
12588 		return strlcpy(buf, rss_type_table[ent].str, size);
12589 	if (ent == i)
12590 		return snprintf(buf, size, "end");
12591 	return -1;
12592 }
12593 
12594 /** Complete queue field for RSS action. */
12595 static int
12596 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
12597 			 unsigned int ent, char *buf, unsigned int size)
12598 {
12599 	(void)ctx;
12600 	(void)token;
12601 	if (!buf)
12602 		return nb_rxq + 1;
12603 	if (ent < nb_rxq)
12604 		return snprintf(buf, size, "%u", ent);
12605 	if (ent == nb_rxq)
12606 		return snprintf(buf, size, "end");
12607 	return -1;
12608 }
12609 
12610 /** Complete index number for set raw_encap/raw_decap commands. */
12611 static int
12612 comp_set_raw_index(struct context *ctx, const struct token *token,
12613 		   unsigned int ent, char *buf, unsigned int size)
12614 {
12615 	uint16_t idx = 0;
12616 	uint16_t nb = 0;
12617 
12618 	RTE_SET_USED(ctx);
12619 	RTE_SET_USED(token);
12620 	for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
12621 		if (buf && idx == ent)
12622 			return snprintf(buf, size, "%u", idx);
12623 		++nb;
12624 	}
12625 	return nb;
12626 }
12627 
12628 /** Complete index number for set raw_ipv6_ext_push/ipv6_ext_remove commands. */
12629 static int
12630 comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
12631 			unsigned int ent, char *buf, unsigned int size)
12632 {
12633 	uint16_t idx = 0;
12634 	uint16_t nb = 0;
12635 
12636 	RTE_SET_USED(ctx);
12637 	RTE_SET_USED(token);
12638 	for (idx = 0; idx < IPV6_EXT_PUSH_CONFS_MAX_NUM; ++idx) {
12639 		if (buf && idx == ent)
12640 			return snprintf(buf, size, "%u", idx);
12641 		++nb;
12642 	}
12643 	return nb;
12644 }
12645 
12646 /** Complete index number for set raw_encap/raw_decap commands. */
12647 static int
12648 comp_set_sample_index(struct context *ctx, const struct token *token,
12649 		   unsigned int ent, char *buf, unsigned int size)
12650 {
12651 	uint16_t idx = 0;
12652 	uint16_t nb = 0;
12653 
12654 	RTE_SET_USED(ctx);
12655 	RTE_SET_USED(token);
12656 	for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
12657 		if (buf && idx == ent)
12658 			return snprintf(buf, size, "%u", idx);
12659 		++nb;
12660 	}
12661 	return nb;
12662 }
12663 
12664 /** Complete operation for modify_field command. */
12665 static int
12666 comp_set_modify_field_op(struct context *ctx, const struct token *token,
12667 		   unsigned int ent, char *buf, unsigned int size)
12668 {
12669 	RTE_SET_USED(ctx);
12670 	RTE_SET_USED(token);
12671 	if (!buf)
12672 		return RTE_DIM(modify_field_ops);
12673 	if (ent < RTE_DIM(modify_field_ops) - 1)
12674 		return strlcpy(buf, modify_field_ops[ent], size);
12675 	return -1;
12676 }
12677 
12678 /** Complete field id for modify_field command. */
12679 static int
12680 comp_set_modify_field_id(struct context *ctx, const struct token *token,
12681 		   unsigned int ent, char *buf, unsigned int size)
12682 {
12683 	const char *name;
12684 
12685 	RTE_SET_USED(token);
12686 	if (!buf)
12687 		return RTE_DIM(flow_field_ids);
12688 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12689 		return -1;
12690 	name = flow_field_ids[ent];
12691 	if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
12692 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12693 		return strlcpy(buf, name, size);
12694 	return -1;
12695 }
12696 
12697 /** Complete available pattern template IDs. */
12698 static int
12699 comp_pattern_template_id(struct context *ctx, const struct token *token,
12700 			 unsigned int ent, char *buf, unsigned int size)
12701 {
12702 	unsigned int i = 0;
12703 	struct rte_port *port;
12704 	struct port_template *pt;
12705 
12706 	(void)token;
12707 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12708 	    ctx->port == (portid_t)RTE_PORT_ALL)
12709 		return -1;
12710 	port = &ports[ctx->port];
12711 	for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) {
12712 		if (buf && i == ent)
12713 			return snprintf(buf, size, "%u", pt->id);
12714 		++i;
12715 	}
12716 	if (buf)
12717 		return -1;
12718 	return i;
12719 }
12720 
12721 /** Complete available actions template IDs. */
12722 static int
12723 comp_actions_template_id(struct context *ctx, const struct token *token,
12724 			 unsigned int ent, char *buf, unsigned int size)
12725 {
12726 	unsigned int i = 0;
12727 	struct rte_port *port;
12728 	struct port_template *pt;
12729 
12730 	(void)token;
12731 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12732 	    ctx->port == (portid_t)RTE_PORT_ALL)
12733 		return -1;
12734 	port = &ports[ctx->port];
12735 	for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) {
12736 		if (buf && i == ent)
12737 			return snprintf(buf, size, "%u", pt->id);
12738 		++i;
12739 	}
12740 	if (buf)
12741 		return -1;
12742 	return i;
12743 }
12744 
12745 /** Complete available table IDs. */
12746 static int
12747 comp_table_id(struct context *ctx, const struct token *token,
12748 	      unsigned int ent, char *buf, unsigned int size)
12749 {
12750 	unsigned int i = 0;
12751 	struct rte_port *port;
12752 	struct port_table *pt;
12753 
12754 	(void)token;
12755 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12756 	    ctx->port == (portid_t)RTE_PORT_ALL)
12757 		return -1;
12758 	port = &ports[ctx->port];
12759 	for (pt = port->table_list; pt != NULL; pt = pt->next) {
12760 		if (buf && i == ent)
12761 			return snprintf(buf, size, "%u", pt->id);
12762 		++i;
12763 	}
12764 	if (buf)
12765 		return -1;
12766 	return i;
12767 }
12768 
12769 /** Complete available queue IDs. */
12770 static int
12771 comp_queue_id(struct context *ctx, const struct token *token,
12772 	      unsigned int ent, char *buf, unsigned int size)
12773 {
12774 	unsigned int i = 0;
12775 	struct rte_port *port;
12776 
12777 	(void)token;
12778 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12779 	    ctx->port == (portid_t)RTE_PORT_ALL)
12780 		return -1;
12781 	port = &ports[ctx->port];
12782 	for (i = 0; i < port->queue_nb; i++) {
12783 		if (buf && i == ent)
12784 			return snprintf(buf, size, "%u", i);
12785 	}
12786 	if (buf)
12787 		return -1;
12788 	return i;
12789 }
12790 
12791 static int
12792 comp_names_to_index(struct context *ctx, const struct token *token,
12793 		    unsigned int ent, char *buf, unsigned int size,
12794 		    const char *const names[], size_t names_size)
12795 {
12796 	RTE_SET_USED(ctx);
12797 	RTE_SET_USED(token);
12798 	if (!buf)
12799 		return names_size;
12800 	if (names[ent] && ent < names_size)
12801 		return rte_strscpy(buf, names[ent], size);
12802 	return -1;
12803 
12804 }
12805 
12806 /** Complete available Meter colors. */
12807 static int
12808 comp_meter_color(struct context *ctx, const struct token *token,
12809 		 unsigned int ent, char *buf, unsigned int size)
12810 {
12811 	RTE_SET_USED(ctx);
12812 	RTE_SET_USED(token);
12813 	if (!buf)
12814 		return RTE_DIM(meter_colors);
12815 	if (ent < RTE_DIM(meter_colors) - 1)
12816 		return strlcpy(buf, meter_colors[ent], size);
12817 	return -1;
12818 }
12819 
12820 /** Complete available Insertion Table types. */
12821 static int
12822 comp_insertion_table_type(struct context *ctx, const struct token *token,
12823 			  unsigned int ent, char *buf, unsigned int size)
12824 {
12825 	RTE_SET_USED(ctx);
12826 	RTE_SET_USED(token);
12827 	if (!buf)
12828 		return RTE_DIM(table_insertion_types);
12829 	if (ent < RTE_DIM(table_insertion_types) - 1)
12830 		return rte_strscpy(buf, table_insertion_types[ent], size);
12831 	return -1;
12832 }
12833 
12834 /** Complete available Hash Calculation Table types. */
12835 static int
12836 comp_hash_table_type(struct context *ctx, const struct token *token,
12837 		     unsigned int ent, char *buf, unsigned int size)
12838 {
12839 	RTE_SET_USED(ctx);
12840 	RTE_SET_USED(token);
12841 	if (!buf)
12842 		return RTE_DIM(table_hash_funcs);
12843 	if (ent < RTE_DIM(table_hash_funcs) - 1)
12844 		return rte_strscpy(buf, table_hash_funcs[ent], size);
12845 	return -1;
12846 }
12847 
12848 static int
12849 comp_quota_state_name(struct context *ctx, const struct token *token,
12850 		      unsigned int ent, char *buf, unsigned int size)
12851 {
12852 	return comp_names_to_index(ctx, token, ent, buf, size,
12853 				   quota_state_names,
12854 				   RTE_DIM(quota_state_names));
12855 }
12856 
12857 static int
12858 comp_quota_mode_name(struct context *ctx, const struct token *token,
12859 		     unsigned int ent, char *buf, unsigned int size)
12860 {
12861 	return comp_names_to_index(ctx, token, ent, buf, size,
12862 				   quota_mode_names,
12863 				   RTE_DIM(quota_mode_names));
12864 }
12865 
12866 static int
12867 comp_quota_update_name(struct context *ctx, const struct token *token,
12868 		       unsigned int ent, char *buf, unsigned int size)
12869 {
12870 	return comp_names_to_index(ctx, token, ent, buf, size,
12871 				   quota_update_names,
12872 				   RTE_DIM(quota_update_names));
12873 }
12874 
12875 static int
12876 comp_qu_mode_name(struct context *ctx, const struct token *token,
12877 		  unsigned int ent, char *buf, unsigned int size)
12878 {
12879 	return comp_names_to_index(ctx, token, ent, buf, size,
12880 				   query_update_mode_names,
12881 				   RTE_DIM(query_update_mode_names));
12882 }
12883 
12884 /** Internal context. */
12885 static struct context cmd_flow_context;
12886 
12887 /** Global parser instance (cmdline API). */
12888 cmdline_parse_inst_t cmd_flow;
12889 cmdline_parse_inst_t cmd_set_raw;
12890 
12891 /** Initialize context. */
12892 static void
12893 cmd_flow_context_init(struct context *ctx)
12894 {
12895 	/* A full memset() is not necessary. */
12896 	ctx->curr = ZERO;
12897 	ctx->prev = ZERO;
12898 	ctx->next_num = 0;
12899 	ctx->args_num = 0;
12900 	ctx->eol = 0;
12901 	ctx->last = 0;
12902 	ctx->port = 0;
12903 	ctx->objdata = 0;
12904 	ctx->object = NULL;
12905 	ctx->objmask = NULL;
12906 }
12907 
12908 /** Parse a token (cmdline API). */
12909 static int
12910 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
12911 	       unsigned int size)
12912 {
12913 	struct context *ctx = &cmd_flow_context;
12914 	const struct token *token;
12915 	const enum index *list;
12916 	int len;
12917 	int i;
12918 
12919 	(void)hdr;
12920 	token = &token_list[ctx->curr];
12921 	/* Check argument length. */
12922 	ctx->eol = 0;
12923 	ctx->last = 1;
12924 	for (len = 0; src[len]; ++len)
12925 		if (src[len] == '#' || isspace(src[len]))
12926 			break;
12927 	if (!len)
12928 		return -1;
12929 	/* Last argument and EOL detection. */
12930 	for (i = len; src[i]; ++i)
12931 		if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
12932 			break;
12933 		else if (!isspace(src[i])) {
12934 			ctx->last = 0;
12935 			break;
12936 		}
12937 	for (; src[i]; ++i)
12938 		if (src[i] == '\r' || src[i] == '\n') {
12939 			ctx->eol = 1;
12940 			break;
12941 		}
12942 	/* Initialize context if necessary. */
12943 	if (!ctx->next_num) {
12944 		if (!token->next)
12945 			return 0;
12946 		ctx->next[ctx->next_num++] = token->next[0];
12947 	}
12948 	/* Process argument through candidates. */
12949 	ctx->prev = ctx->curr;
12950 	list = ctx->next[ctx->next_num - 1];
12951 	for (i = 0; list[i]; ++i) {
12952 		const struct token *next = &token_list[list[i]];
12953 		int tmp;
12954 
12955 		ctx->curr = list[i];
12956 		if (next->call)
12957 			tmp = next->call(ctx, next, src, len, result, size);
12958 		else
12959 			tmp = parse_default(ctx, next, src, len, result, size);
12960 		if (tmp == -1 || tmp != len)
12961 			continue;
12962 		token = next;
12963 		break;
12964 	}
12965 	if (!list[i])
12966 		return -1;
12967 	--ctx->next_num;
12968 	/* Push subsequent tokens if any. */
12969 	if (token->next)
12970 		for (i = 0; token->next[i]; ++i) {
12971 			if (ctx->next_num == RTE_DIM(ctx->next))
12972 				return -1;
12973 			ctx->next[ctx->next_num++] = token->next[i];
12974 		}
12975 	/* Push arguments if any. */
12976 	if (token->args)
12977 		for (i = 0; token->args[i]; ++i) {
12978 			if (ctx->args_num == RTE_DIM(ctx->args))
12979 				return -1;
12980 			ctx->args[ctx->args_num++] = token->args[i];
12981 		}
12982 	return len;
12983 }
12984 
12985 int
12986 flow_parse(const char *src, void *result, unsigned int size,
12987 	   struct rte_flow_attr **attr,
12988 	   struct rte_flow_item **pattern, struct rte_flow_action **actions)
12989 {
12990 	int ret;
12991 	struct context saved_flow_ctx = cmd_flow_context;
12992 
12993 	cmd_flow_context_init(&cmd_flow_context);
12994 	do {
12995 		ret = cmd_flow_parse(NULL, src, result, size);
12996 		if (ret > 0) {
12997 			src += ret;
12998 			while (isspace(*src))
12999 				src++;
13000 		}
13001 	} while (ret > 0 && strlen(src));
13002 	cmd_flow_context = saved_flow_ctx;
13003 	*attr = &((struct buffer *)result)->args.vc.attr;
13004 	*pattern = ((struct buffer *)result)->args.vc.pattern;
13005 	*actions = ((struct buffer *)result)->args.vc.actions;
13006 	return (ret >= 0 && !strlen(src)) ? 0 : -1;
13007 }
13008 
13009 /** Return number of completion entries (cmdline API). */
13010 static int
13011 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
13012 {
13013 	struct context *ctx = &cmd_flow_context;
13014 	const struct token *token = &token_list[ctx->curr];
13015 	const enum index *list;
13016 	int i;
13017 
13018 	(void)hdr;
13019 	/* Count number of tokens in current list. */
13020 	if (ctx->next_num)
13021 		list = ctx->next[ctx->next_num - 1];
13022 	else
13023 		list = token->next[0];
13024 	for (i = 0; list[i]; ++i)
13025 		;
13026 	if (!i)
13027 		return 0;
13028 	/*
13029 	 * If there is a single token, use its completion callback, otherwise
13030 	 * return the number of entries.
13031 	 */
13032 	token = &token_list[list[0]];
13033 	if (i == 1 && token->comp) {
13034 		/* Save index for cmd_flow_get_help(). */
13035 		ctx->prev = list[0];
13036 		return token->comp(ctx, token, 0, NULL, 0);
13037 	}
13038 	return i;
13039 }
13040 
13041 /** Return a completion entry (cmdline API). */
13042 static int
13043 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
13044 			  char *dst, unsigned int size)
13045 {
13046 	struct context *ctx = &cmd_flow_context;
13047 	const struct token *token = &token_list[ctx->curr];
13048 	const enum index *list;
13049 	int i;
13050 
13051 	(void)hdr;
13052 	/* Count number of tokens in current list. */
13053 	if (ctx->next_num)
13054 		list = ctx->next[ctx->next_num - 1];
13055 	else
13056 		list = token->next[0];
13057 	for (i = 0; list[i]; ++i)
13058 		;
13059 	if (!i)
13060 		return -1;
13061 	/* If there is a single token, use its completion callback. */
13062 	token = &token_list[list[0]];
13063 	if (i == 1 && token->comp) {
13064 		/* Save index for cmd_flow_get_help(). */
13065 		ctx->prev = list[0];
13066 		return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
13067 	}
13068 	/* Otherwise make sure the index is valid and use defaults. */
13069 	if (index >= i)
13070 		return -1;
13071 	token = &token_list[list[index]];
13072 	strlcpy(dst, token->name, size);
13073 	/* Save index for cmd_flow_get_help(). */
13074 	ctx->prev = list[index];
13075 	return 0;
13076 }
13077 
13078 /** Populate help strings for current token (cmdline API). */
13079 static int
13080 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
13081 {
13082 	struct context *ctx = &cmd_flow_context;
13083 	const struct token *token = &token_list[ctx->prev];
13084 
13085 	(void)hdr;
13086 	if (!size)
13087 		return -1;
13088 	/* Set token type and update global help with details. */
13089 	strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
13090 	if (token->help)
13091 		cmd_flow.help_str = token->help;
13092 	else
13093 		cmd_flow.help_str = token->name;
13094 	return 0;
13095 }
13096 
13097 /** Token definition template (cmdline API). */
13098 static struct cmdline_token_hdr cmd_flow_token_hdr = {
13099 	.ops = &(struct cmdline_token_ops){
13100 		.parse = cmd_flow_parse,
13101 		.complete_get_nb = cmd_flow_complete_get_nb,
13102 		.complete_get_elt = cmd_flow_complete_get_elt,
13103 		.get_help = cmd_flow_get_help,
13104 	},
13105 	.offset = 0,
13106 };
13107 
13108 /** Populate the next dynamic token. */
13109 static void
13110 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
13111 	     cmdline_parse_token_hdr_t **hdr_inst)
13112 {
13113 	struct context *ctx = &cmd_flow_context;
13114 
13115 	/* Always reinitialize context before requesting the first token. */
13116 	if (!(hdr_inst - cmd_flow.tokens))
13117 		cmd_flow_context_init(ctx);
13118 	/* Return NULL when no more tokens are expected. */
13119 	if (!ctx->next_num && ctx->curr) {
13120 		*hdr = NULL;
13121 		return;
13122 	}
13123 	/* Determine if command should end here. */
13124 	if (ctx->eol && ctx->last && ctx->next_num) {
13125 		const enum index *list = ctx->next[ctx->next_num - 1];
13126 		int i;
13127 
13128 		for (i = 0; list[i]; ++i) {
13129 			if (list[i] != END)
13130 				continue;
13131 			*hdr = NULL;
13132 			return;
13133 		}
13134 	}
13135 	*hdr = &cmd_flow_token_hdr;
13136 }
13137 
13138 static SLIST_HEAD(, indlst_conf) indlst_conf_head =
13139 	SLIST_HEAD_INITIALIZER();
13140 
13141 static void
13142 indirect_action_flow_conf_create(const struct buffer *in)
13143 {
13144 	int len, ret;
13145 	uint32_t i;
13146 	struct indlst_conf *indlst_conf = NULL;
13147 	size_t base = RTE_ALIGN(sizeof(*indlst_conf), 8);
13148 	struct rte_flow_action *src = in->args.vc.actions;
13149 
13150 	if (!in->args.vc.actions_n)
13151 		goto end;
13152 	len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, src, NULL);
13153 	if (len <= 0)
13154 		goto end;
13155 	len = RTE_ALIGN(len, 16);
13156 
13157 	indlst_conf = calloc(1, base + len +
13158 			     in->args.vc.actions_n * sizeof(uintptr_t));
13159 	if (!indlst_conf)
13160 		goto end;
13161 	indlst_conf->id = in->args.vc.attr.group;
13162 	indlst_conf->conf_num = in->args.vc.actions_n - 1;
13163 	indlst_conf->actions = RTE_PTR_ADD(indlst_conf, base);
13164 	ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, indlst_conf->actions,
13165 			    len, src, NULL);
13166 	if (ret <= 0) {
13167 		free(indlst_conf);
13168 		indlst_conf = NULL;
13169 		goto end;
13170 	}
13171 	indlst_conf->conf = RTE_PTR_ADD(indlst_conf, base + len);
13172 	for (i = 0; i < indlst_conf->conf_num; i++)
13173 		indlst_conf->conf[i] = indlst_conf->actions[i].conf;
13174 	SLIST_INSERT_HEAD(&indlst_conf_head, indlst_conf, next);
13175 end:
13176 	if (indlst_conf)
13177 		printf("created indirect action list configuration %u\n",
13178 		       in->args.vc.attr.group);
13179 	else
13180 		printf("cannot create indirect action list configuration %u\n",
13181 		       in->args.vc.attr.group);
13182 }
13183 
13184 static const struct indlst_conf *
13185 indirect_action_list_conf_get(uint32_t conf_id)
13186 {
13187 	const struct indlst_conf *conf;
13188 
13189 	SLIST_FOREACH(conf, &indlst_conf_head, next) {
13190 		if (conf->id == conf_id)
13191 			return conf;
13192 	}
13193 	return NULL;
13194 }
13195 
13196 /** Dispatch parsed buffer to function calls. */
13197 static void
13198 cmd_flow_parsed(const struct buffer *in)
13199 {
13200 	switch (in->command) {
13201 	case INFO:
13202 		port_flow_get_info(in->port);
13203 		break;
13204 	case CONFIGURE:
13205 		port_flow_configure(in->port,
13206 				    &in->args.configure.port_attr,
13207 				    in->args.configure.nb_queue,
13208 				    &in->args.configure.queue_attr);
13209 		break;
13210 	case PATTERN_TEMPLATE_CREATE:
13211 		port_flow_pattern_template_create(in->port,
13212 				in->args.vc.pat_templ_id,
13213 				&((const struct rte_flow_pattern_template_attr) {
13214 					.relaxed_matching = in->args.vc.attr.reserved,
13215 					.ingress = in->args.vc.attr.ingress,
13216 					.egress = in->args.vc.attr.egress,
13217 					.transfer = in->args.vc.attr.transfer,
13218 				}),
13219 				in->args.vc.pattern);
13220 		break;
13221 	case PATTERN_TEMPLATE_DESTROY:
13222 		port_flow_pattern_template_destroy(in->port,
13223 				in->args.templ_destroy.template_id_n,
13224 				in->args.templ_destroy.template_id);
13225 		break;
13226 	case ACTIONS_TEMPLATE_CREATE:
13227 		port_flow_actions_template_create(in->port,
13228 				in->args.vc.act_templ_id,
13229 				&((const struct rte_flow_actions_template_attr) {
13230 					.ingress = in->args.vc.attr.ingress,
13231 					.egress = in->args.vc.attr.egress,
13232 					.transfer = in->args.vc.attr.transfer,
13233 				}),
13234 				in->args.vc.actions,
13235 				in->args.vc.masks);
13236 		break;
13237 	case ACTIONS_TEMPLATE_DESTROY:
13238 		port_flow_actions_template_destroy(in->port,
13239 				in->args.templ_destroy.template_id_n,
13240 				in->args.templ_destroy.template_id);
13241 		break;
13242 	case TABLE_CREATE:
13243 		port_flow_template_table_create(in->port, in->args.table.id,
13244 			&in->args.table.attr, in->args.table.pat_templ_id_n,
13245 			in->args.table.pat_templ_id, in->args.table.act_templ_id_n,
13246 			in->args.table.act_templ_id);
13247 		break;
13248 	case TABLE_DESTROY:
13249 		port_flow_template_table_destroy(in->port,
13250 					in->args.table_destroy.table_id_n,
13251 					in->args.table_destroy.table_id);
13252 		break;
13253 	case TABLE_RESIZE_COMPLETE:
13254 		port_flow_template_table_resize_complete
13255 			(in->port, in->args.table_destroy.table_id[0]);
13256 		break;
13257 	case GROUP_SET_MISS_ACTIONS:
13258 		port_queue_group_set_miss_actions(in->port, &in->args.vc.attr,
13259 						  in->args.vc.actions);
13260 		break;
13261 	case TABLE_RESIZE:
13262 		port_flow_template_table_resize(in->port, in->args.table.id,
13263 						in->args.table.attr.nb_flows);
13264 		break;
13265 	case QUEUE_CREATE:
13266 		port_queue_flow_create(in->port, in->queue, in->postpone,
13267 			in->args.vc.table_id, in->args.vc.rule_id,
13268 			in->args.vc.pat_templ_id, in->args.vc.act_templ_id,
13269 			in->args.vc.pattern, in->args.vc.actions);
13270 		break;
13271 	case QUEUE_DESTROY:
13272 		port_queue_flow_destroy(in->port, in->queue, in->postpone,
13273 					in->args.destroy.rule_n,
13274 					in->args.destroy.rule);
13275 		break;
13276 	case QUEUE_FLOW_UPDATE_RESIZED:
13277 		port_queue_flow_update_resized(in->port, in->queue,
13278 					       in->postpone,
13279 					       in->args.destroy.rule[0]);
13280 		break;
13281 	case QUEUE_UPDATE:
13282 		port_queue_flow_update(in->port, in->queue, in->postpone,
13283 				in->args.vc.rule_id, in->args.vc.act_templ_id,
13284 				in->args.vc.actions);
13285 		break;
13286 	case PUSH:
13287 		port_queue_flow_push(in->port, in->queue);
13288 		break;
13289 	case PULL:
13290 		port_queue_flow_pull(in->port, in->queue);
13291 		break;
13292 	case HASH:
13293 		if (!in->args.vc.encap_hash)
13294 			port_flow_hash_calc(in->port, in->args.vc.table_id,
13295 					    in->args.vc.pat_templ_id,
13296 					    in->args.vc.pattern);
13297 		else
13298 			port_flow_hash_calc_encap(in->port, in->args.vc.field,
13299 						  in->args.vc.pattern);
13300 		break;
13301 	case QUEUE_AGED:
13302 		port_queue_flow_aged(in->port, in->queue,
13303 				     in->args.aged.destroy);
13304 		break;
13305 	case QUEUE_INDIRECT_ACTION_CREATE:
13306 	case QUEUE_INDIRECT_ACTION_LIST_CREATE:
13307 		port_queue_action_handle_create(
13308 				in->port, in->queue, in->postpone,
13309 				in->args.vc.attr.group,
13310 				in->command == QUEUE_INDIRECT_ACTION_LIST_CREATE,
13311 				&((const struct rte_flow_indir_action_conf) {
13312 					.ingress = in->args.vc.attr.ingress,
13313 					.egress = in->args.vc.attr.egress,
13314 					.transfer = in->args.vc.attr.transfer,
13315 				}),
13316 				in->args.vc.actions);
13317 		break;
13318 	case QUEUE_INDIRECT_ACTION_DESTROY:
13319 		port_queue_action_handle_destroy(in->port,
13320 					   in->queue, in->postpone,
13321 					   in->args.ia_destroy.action_id_n,
13322 					   in->args.ia_destroy.action_id);
13323 		break;
13324 	case QUEUE_INDIRECT_ACTION_UPDATE:
13325 		port_queue_action_handle_update(in->port,
13326 						in->queue, in->postpone,
13327 						in->args.vc.attr.group,
13328 						in->args.vc.actions);
13329 		break;
13330 	case QUEUE_INDIRECT_ACTION_QUERY:
13331 		port_queue_action_handle_query(in->port,
13332 					       in->queue, in->postpone,
13333 					       in->args.ia.action_id);
13334 		break;
13335 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
13336 		port_queue_action_handle_query_update(in->port, in->queue,
13337 						      in->postpone,
13338 						      in->args.ia.action_id,
13339 						      in->args.ia.qu_mode,
13340 						      in->args.vc.actions);
13341 		break;
13342 	case INDIRECT_ACTION_CREATE:
13343 	case INDIRECT_ACTION_LIST_CREATE:
13344 		port_action_handle_create(
13345 				in->port, in->args.vc.attr.group,
13346 				in->command == INDIRECT_ACTION_LIST_CREATE,
13347 				&((const struct rte_flow_indir_action_conf) {
13348 					.ingress = in->args.vc.attr.ingress,
13349 					.egress = in->args.vc.attr.egress,
13350 					.transfer = in->args.vc.attr.transfer,
13351 				}),
13352 				in->args.vc.actions);
13353 		break;
13354 	case INDIRECT_ACTION_FLOW_CONF_CREATE:
13355 		indirect_action_flow_conf_create(in);
13356 		break;
13357 	case INDIRECT_ACTION_DESTROY:
13358 		port_action_handle_destroy(in->port,
13359 					   in->args.ia_destroy.action_id_n,
13360 					   in->args.ia_destroy.action_id);
13361 		break;
13362 	case INDIRECT_ACTION_UPDATE:
13363 		port_action_handle_update(in->port, in->args.vc.attr.group,
13364 					  in->args.vc.actions);
13365 		break;
13366 	case INDIRECT_ACTION_QUERY:
13367 		port_action_handle_query(in->port, in->args.ia.action_id);
13368 		break;
13369 	case INDIRECT_ACTION_QUERY_UPDATE:
13370 		port_action_handle_query_update(in->port,
13371 						in->args.ia.action_id,
13372 						in->args.ia.qu_mode,
13373 						in->args.vc.actions);
13374 		break;
13375 	case VALIDATE:
13376 		port_flow_validate(in->port, &in->args.vc.attr,
13377 				   in->args.vc.pattern, in->args.vc.actions,
13378 				   &in->args.vc.tunnel_ops);
13379 		break;
13380 	case CREATE:
13381 		port_flow_create(in->port, &in->args.vc.attr,
13382 				 in->args.vc.pattern, in->args.vc.actions,
13383 				 &in->args.vc.tunnel_ops, in->args.vc.user_id);
13384 		break;
13385 	case DESTROY:
13386 		port_flow_destroy(in->port, in->args.destroy.rule_n,
13387 				  in->args.destroy.rule,
13388 				  in->args.destroy.is_user_id);
13389 		break;
13390 	case UPDATE:
13391 		port_flow_update(in->port, in->args.vc.rule_id,
13392 				 in->args.vc.actions, in->args.vc.user_id);
13393 		break;
13394 	case FLUSH:
13395 		port_flow_flush(in->port);
13396 		break;
13397 	case DUMP_ONE:
13398 	case DUMP_ALL:
13399 		port_flow_dump(in->port, in->args.dump.mode,
13400 				in->args.dump.rule, in->args.dump.file,
13401 				in->args.dump.is_user_id);
13402 		break;
13403 	case QUERY:
13404 		port_flow_query(in->port, in->args.query.rule,
13405 				&in->args.query.action,
13406 				in->args.query.is_user_id);
13407 		break;
13408 	case LIST:
13409 		port_flow_list(in->port, in->args.list.group_n,
13410 			       in->args.list.group);
13411 		break;
13412 	case ISOLATE:
13413 		port_flow_isolate(in->port, in->args.isolate.set);
13414 		break;
13415 	case AGED:
13416 		port_flow_aged(in->port, in->args.aged.destroy);
13417 		break;
13418 	case TUNNEL_CREATE:
13419 		port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
13420 		break;
13421 	case TUNNEL_DESTROY:
13422 		port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
13423 		break;
13424 	case TUNNEL_LIST:
13425 		port_flow_tunnel_list(in->port);
13426 		break;
13427 	case ACTION_POL_G:
13428 		port_meter_policy_add(in->port, in->args.policy.policy_id,
13429 					in->args.vc.actions);
13430 		break;
13431 	case FLEX_ITEM_CREATE:
13432 		flex_item_create(in->port, in->args.flex.token,
13433 				 in->args.flex.filename);
13434 		break;
13435 	case FLEX_ITEM_DESTROY:
13436 		flex_item_destroy(in->port, in->args.flex.token);
13437 		break;
13438 	default:
13439 		break;
13440 	}
13441 	fflush(stdout);
13442 }
13443 
13444 /** Token generator and output processing callback (cmdline API). */
13445 static void
13446 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
13447 {
13448 	if (cl == NULL)
13449 		cmd_flow_tok(arg0, arg2);
13450 	else
13451 		cmd_flow_parsed(arg0);
13452 }
13453 
13454 /** Global parser instance (cmdline API). */
13455 cmdline_parse_inst_t cmd_flow = {
13456 	.f = cmd_flow_cb,
13457 	.data = NULL, /**< Unused. */
13458 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
13459 	.tokens = {
13460 		NULL,
13461 	}, /**< Tokens are returned by cmd_flow_tok(). */
13462 };
13463 
13464 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
13465 
13466 static void
13467 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
13468 {
13469 	struct rte_ipv4_hdr *ipv4;
13470 	struct rte_ether_hdr *eth;
13471 	struct rte_ipv6_hdr *ipv6;
13472 	struct rte_vxlan_hdr *vxlan;
13473 	struct rte_vxlan_gpe_hdr *gpe;
13474 	struct rte_flow_item_nvgre *nvgre;
13475 	uint32_t ipv6_vtc_flow;
13476 
13477 	switch (item->type) {
13478 	case RTE_FLOW_ITEM_TYPE_ETH:
13479 		eth = (struct rte_ether_hdr *)buf;
13480 		if (next_proto)
13481 			eth->ether_type = rte_cpu_to_be_16(next_proto);
13482 		break;
13483 	case RTE_FLOW_ITEM_TYPE_IPV4:
13484 		ipv4 = (struct rte_ipv4_hdr *)buf;
13485 		if (!ipv4->version_ihl)
13486 			ipv4->version_ihl = RTE_IPV4_VHL_DEF;
13487 		if (next_proto && ipv4->next_proto_id == 0)
13488 			ipv4->next_proto_id = (uint8_t)next_proto;
13489 		break;
13490 	case RTE_FLOW_ITEM_TYPE_IPV6:
13491 		ipv6 = (struct rte_ipv6_hdr *)buf;
13492 		if (next_proto && ipv6->proto == 0)
13493 			ipv6->proto = (uint8_t)next_proto;
13494 		ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
13495 		ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
13496 		ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
13497 		ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
13498 		break;
13499 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13500 		vxlan = (struct rte_vxlan_hdr *)buf;
13501 		vxlan->vx_flags = 0x08;
13502 		break;
13503 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13504 		gpe = (struct rte_vxlan_gpe_hdr *)buf;
13505 		gpe->vx_flags = 0x0C;
13506 		break;
13507 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13508 		nvgre = (struct rte_flow_item_nvgre *)buf;
13509 		nvgre->protocol = rte_cpu_to_be_16(0x6558);
13510 		nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
13511 		break;
13512 	default:
13513 		break;
13514 	}
13515 }
13516 
13517 /** Helper of get item's default mask. */
13518 static const void *
13519 flow_item_default_mask(const struct rte_flow_item *item)
13520 {
13521 	const void *mask = NULL;
13522 	static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
13523 	static struct rte_flow_item_ipv6_routing_ext ipv6_routing_ext_default_mask = {
13524 		.hdr = {
13525 			.next_hdr = 0xff,
13526 			.type = 0xff,
13527 			.segments_left = 0xff,
13528 		},
13529 	};
13530 
13531 	switch (item->type) {
13532 	case RTE_FLOW_ITEM_TYPE_ANY:
13533 		mask = &rte_flow_item_any_mask;
13534 		break;
13535 	case RTE_FLOW_ITEM_TYPE_PORT_ID:
13536 		mask = &rte_flow_item_port_id_mask;
13537 		break;
13538 	case RTE_FLOW_ITEM_TYPE_RAW:
13539 		mask = &rte_flow_item_raw_mask;
13540 		break;
13541 	case RTE_FLOW_ITEM_TYPE_ETH:
13542 		mask = &rte_flow_item_eth_mask;
13543 		break;
13544 	case RTE_FLOW_ITEM_TYPE_VLAN:
13545 		mask = &rte_flow_item_vlan_mask;
13546 		break;
13547 	case RTE_FLOW_ITEM_TYPE_IPV4:
13548 		mask = &rte_flow_item_ipv4_mask;
13549 		break;
13550 	case RTE_FLOW_ITEM_TYPE_IPV6:
13551 		mask = &rte_flow_item_ipv6_mask;
13552 		break;
13553 	case RTE_FLOW_ITEM_TYPE_ICMP:
13554 		mask = &rte_flow_item_icmp_mask;
13555 		break;
13556 	case RTE_FLOW_ITEM_TYPE_UDP:
13557 		mask = &rte_flow_item_udp_mask;
13558 		break;
13559 	case RTE_FLOW_ITEM_TYPE_TCP:
13560 		mask = &rte_flow_item_tcp_mask;
13561 		break;
13562 	case RTE_FLOW_ITEM_TYPE_SCTP:
13563 		mask = &rte_flow_item_sctp_mask;
13564 		break;
13565 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13566 		mask = &rte_flow_item_vxlan_mask;
13567 		break;
13568 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13569 		mask = &rte_flow_item_vxlan_gpe_mask;
13570 		break;
13571 	case RTE_FLOW_ITEM_TYPE_E_TAG:
13572 		mask = &rte_flow_item_e_tag_mask;
13573 		break;
13574 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13575 		mask = &rte_flow_item_nvgre_mask;
13576 		break;
13577 	case RTE_FLOW_ITEM_TYPE_MPLS:
13578 		mask = &rte_flow_item_mpls_mask;
13579 		break;
13580 	case RTE_FLOW_ITEM_TYPE_GRE:
13581 		mask = &rte_flow_item_gre_mask;
13582 		break;
13583 	case RTE_FLOW_ITEM_TYPE_GRE_KEY:
13584 		mask = &gre_key_default_mask;
13585 		break;
13586 	case RTE_FLOW_ITEM_TYPE_META:
13587 		mask = &rte_flow_item_meta_mask;
13588 		break;
13589 	case RTE_FLOW_ITEM_TYPE_RANDOM:
13590 		mask = &rte_flow_item_random_mask;
13591 		break;
13592 	case RTE_FLOW_ITEM_TYPE_FUZZY:
13593 		mask = &rte_flow_item_fuzzy_mask;
13594 		break;
13595 	case RTE_FLOW_ITEM_TYPE_GTP:
13596 		mask = &rte_flow_item_gtp_mask;
13597 		break;
13598 	case RTE_FLOW_ITEM_TYPE_GTP_PSC:
13599 		mask = &rte_flow_item_gtp_psc_mask;
13600 		break;
13601 	case RTE_FLOW_ITEM_TYPE_GENEVE:
13602 		mask = &rte_flow_item_geneve_mask;
13603 		break;
13604 	case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
13605 		mask = &rte_flow_item_geneve_opt_mask;
13606 		break;
13607 	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
13608 		mask = &rte_flow_item_pppoe_proto_id_mask;
13609 		break;
13610 	case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
13611 		mask = &rte_flow_item_l2tpv3oip_mask;
13612 		break;
13613 	case RTE_FLOW_ITEM_TYPE_ESP:
13614 		mask = &rte_flow_item_esp_mask;
13615 		break;
13616 	case RTE_FLOW_ITEM_TYPE_AH:
13617 		mask = &rte_flow_item_ah_mask;
13618 		break;
13619 	case RTE_FLOW_ITEM_TYPE_PFCP:
13620 		mask = &rte_flow_item_pfcp_mask;
13621 		break;
13622 	case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
13623 	case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
13624 		mask = &rte_flow_item_ethdev_mask;
13625 		break;
13626 	case RTE_FLOW_ITEM_TYPE_L2TPV2:
13627 		mask = &rte_flow_item_l2tpv2_mask;
13628 		break;
13629 	case RTE_FLOW_ITEM_TYPE_PPP:
13630 		mask = &rte_flow_item_ppp_mask;
13631 		break;
13632 	case RTE_FLOW_ITEM_TYPE_METER_COLOR:
13633 		mask = &rte_flow_item_meter_color_mask;
13634 		break;
13635 	case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13636 		mask = &ipv6_routing_ext_default_mask;
13637 		break;
13638 	case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
13639 		mask = &rte_flow_item_aggr_affinity_mask;
13640 		break;
13641 	case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
13642 		mask = &rte_flow_item_tx_queue_mask;
13643 		break;
13644 	case RTE_FLOW_ITEM_TYPE_IB_BTH:
13645 		mask = &rte_flow_item_ib_bth_mask;
13646 		break;
13647 	case RTE_FLOW_ITEM_TYPE_PTYPE:
13648 		mask = &rte_flow_item_ptype_mask;
13649 		break;
13650 	default:
13651 		break;
13652 	}
13653 	return mask;
13654 }
13655 
13656 /** Dispatch parsed buffer to function calls. */
13657 static void
13658 cmd_set_ipv6_ext_parsed(const struct buffer *in)
13659 {
13660 	uint32_t n = in->args.vc.pattern_n;
13661 	int i = 0;
13662 	struct rte_flow_item *item = NULL;
13663 	size_t size = 0;
13664 	uint8_t *data = NULL;
13665 	uint8_t *type = NULL;
13666 	size_t *total_size = NULL;
13667 	uint16_t idx = in->port; /* We borrow port field as index */
13668 	struct rte_flow_item_ipv6_routing_ext *ext;
13669 	const struct rte_flow_item_ipv6_ext *ipv6_ext;
13670 
13671 	RTE_ASSERT(in->command == SET_IPV6_EXT_PUSH ||
13672 		   in->command == SET_IPV6_EXT_REMOVE);
13673 
13674 	if (in->command == SET_IPV6_EXT_REMOVE) {
13675 		if (n != 1 || in->args.vc.pattern->type !=
13676 		    RTE_FLOW_ITEM_TYPE_IPV6_EXT) {
13677 			fprintf(stderr, "Error - Not supported item\n");
13678 			return;
13679 		}
13680 		type = (uint8_t *)&ipv6_ext_remove_confs[idx].type;
13681 		item = in->args.vc.pattern;
13682 		ipv6_ext = item->spec;
13683 		*type = ipv6_ext->next_hdr;
13684 		return;
13685 	}
13686 
13687 	total_size = &ipv6_ext_push_confs[idx].size;
13688 	data = (uint8_t *)&ipv6_ext_push_confs[idx].data;
13689 	type = (uint8_t *)&ipv6_ext_push_confs[idx].type;
13690 
13691 	*total_size = 0;
13692 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13693 	for (i = n - 1 ; i >= 0; --i) {
13694 		item = in->args.vc.pattern + i;
13695 		switch (item->type) {
13696 		case RTE_FLOW_ITEM_TYPE_IPV6_EXT:
13697 			ipv6_ext = item->spec;
13698 			*type = ipv6_ext->next_hdr;
13699 			break;
13700 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13701 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13702 			if (!ext->hdr.hdr_len) {
13703 				size = sizeof(struct rte_ipv6_routing_ext) +
13704 				(ext->hdr.segments_left << 4);
13705 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
13706 				/* Indicate no TLV once SRH. */
13707 				if (ext->hdr.type == 4)
13708 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
13709 			} else {
13710 				size = sizeof(struct rte_ipv6_routing_ext) +
13711 				(ext->hdr.hdr_len << 3);
13712 			}
13713 			*total_size += size;
13714 			memcpy(data, ext, size);
13715 			break;
13716 		default:
13717 			fprintf(stderr, "Error - Not supported item\n");
13718 			goto error;
13719 		}
13720 	}
13721 	RTE_ASSERT((*total_size) <= ACTION_IPV6_EXT_PUSH_MAX_DATA);
13722 	return;
13723 error:
13724 	*total_size = 0;
13725 	memset(data, 0x00, ACTION_IPV6_EXT_PUSH_MAX_DATA);
13726 }
13727 
13728 /** Dispatch parsed buffer to function calls. */
13729 static void
13730 cmd_set_raw_parsed_sample(const struct buffer *in)
13731 {
13732 	uint32_t n = in->args.vc.actions_n;
13733 	uint32_t i = 0;
13734 	struct rte_flow_action *action = NULL;
13735 	struct rte_flow_action *data = NULL;
13736 	const struct rte_flow_action_rss *rss = NULL;
13737 	size_t size = 0;
13738 	uint16_t idx = in->port; /* We borrow port field as index */
13739 	uint32_t max_size = sizeof(struct rte_flow_action) *
13740 						ACTION_SAMPLE_ACTIONS_NUM;
13741 
13742 	RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
13743 	data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
13744 	memset(data, 0x00, max_size);
13745 	for (; i <= n - 1; i++) {
13746 		action = in->args.vc.actions + i;
13747 		if (action->type == RTE_FLOW_ACTION_TYPE_END)
13748 			break;
13749 		switch (action->type) {
13750 		case RTE_FLOW_ACTION_TYPE_MARK:
13751 			size = sizeof(struct rte_flow_action_mark);
13752 			rte_memcpy(&sample_mark[idx],
13753 				(const void *)action->conf, size);
13754 			action->conf = &sample_mark[idx];
13755 			break;
13756 		case RTE_FLOW_ACTION_TYPE_COUNT:
13757 			size = sizeof(struct rte_flow_action_count);
13758 			rte_memcpy(&sample_count[idx],
13759 				(const void *)action->conf, size);
13760 			action->conf = &sample_count[idx];
13761 			break;
13762 		case RTE_FLOW_ACTION_TYPE_QUEUE:
13763 			size = sizeof(struct rte_flow_action_queue);
13764 			rte_memcpy(&sample_queue[idx],
13765 				(const void *)action->conf, size);
13766 			action->conf = &sample_queue[idx];
13767 			break;
13768 		case RTE_FLOW_ACTION_TYPE_RSS:
13769 			size = sizeof(struct rte_flow_action_rss);
13770 			rss = action->conf;
13771 			rte_memcpy(&sample_rss_data[idx].conf,
13772 				   (const void *)rss, size);
13773 			if (rss->key_len && rss->key) {
13774 				sample_rss_data[idx].conf.key =
13775 						sample_rss_data[idx].key;
13776 				rte_memcpy((void *)((uintptr_t)
13777 					   sample_rss_data[idx].conf.key),
13778 					   (const void *)rss->key,
13779 					   sizeof(uint8_t) * rss->key_len);
13780 			}
13781 			if (rss->queue_num && rss->queue) {
13782 				sample_rss_data[idx].conf.queue =
13783 						sample_rss_data[idx].queue;
13784 				rte_memcpy((void *)((uintptr_t)
13785 					   sample_rss_data[idx].conf.queue),
13786 					   (const void *)rss->queue,
13787 					   sizeof(uint16_t) * rss->queue_num);
13788 			}
13789 			action->conf = &sample_rss_data[idx].conf;
13790 			break;
13791 		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
13792 			size = sizeof(struct rte_flow_action_raw_encap);
13793 			rte_memcpy(&sample_encap[idx],
13794 				(const void *)action->conf, size);
13795 			action->conf = &sample_encap[idx];
13796 			break;
13797 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
13798 			size = sizeof(struct rte_flow_action_port_id);
13799 			rte_memcpy(&sample_port_id[idx],
13800 				(const void *)action->conf, size);
13801 			action->conf = &sample_port_id[idx];
13802 			break;
13803 		case RTE_FLOW_ACTION_TYPE_PF:
13804 			break;
13805 		case RTE_FLOW_ACTION_TYPE_VF:
13806 			size = sizeof(struct rte_flow_action_vf);
13807 			rte_memcpy(&sample_vf[idx],
13808 					(const void *)action->conf, size);
13809 			action->conf = &sample_vf[idx];
13810 			break;
13811 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
13812 			size = sizeof(struct rte_flow_action_vxlan_encap);
13813 			parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
13814 			action->conf = &sample_vxlan_encap[idx].conf;
13815 			break;
13816 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
13817 			size = sizeof(struct rte_flow_action_nvgre_encap);
13818 			parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
13819 			action->conf = &sample_nvgre_encap[idx];
13820 			break;
13821 		case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
13822 			size = sizeof(struct rte_flow_action_ethdev);
13823 			rte_memcpy(&sample_port_representor[idx],
13824 					(const void *)action->conf, size);
13825 			action->conf = &sample_port_representor[idx];
13826 			break;
13827 		case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
13828 			size = sizeof(struct rte_flow_action_ethdev);
13829 			rte_memcpy(&sample_represented_port[idx],
13830 					(const void *)action->conf, size);
13831 			action->conf = &sample_represented_port[idx];
13832 			break;
13833 		default:
13834 			fprintf(stderr, "Error - Not supported action\n");
13835 			return;
13836 		}
13837 		rte_memcpy(data, action, sizeof(struct rte_flow_action));
13838 		data++;
13839 	}
13840 }
13841 
13842 /** Dispatch parsed buffer to function calls. */
13843 static void
13844 cmd_set_raw_parsed(const struct buffer *in)
13845 {
13846 	uint32_t n = in->args.vc.pattern_n;
13847 	int i = 0;
13848 	struct rte_flow_item *item = NULL;
13849 	size_t size = 0;
13850 	uint8_t *data = NULL;
13851 	uint8_t *data_tail = NULL;
13852 	size_t *total_size = NULL;
13853 	uint16_t upper_layer = 0;
13854 	uint16_t proto = 0;
13855 	uint16_t idx = in->port; /* We borrow port field as index */
13856 	int gtp_psc = -1; /* GTP PSC option index. */
13857 	const void *src_spec;
13858 
13859 	if (in->command == SET_SAMPLE_ACTIONS)
13860 		return cmd_set_raw_parsed_sample(in);
13861 	else if (in->command == SET_IPV6_EXT_PUSH ||
13862 		 in->command == SET_IPV6_EXT_REMOVE)
13863 		return cmd_set_ipv6_ext_parsed(in);
13864 	RTE_ASSERT(in->command == SET_RAW_ENCAP ||
13865 		   in->command == SET_RAW_DECAP);
13866 	if (in->command == SET_RAW_ENCAP) {
13867 		total_size = &raw_encap_confs[idx].size;
13868 		data = (uint8_t *)&raw_encap_confs[idx].data;
13869 	} else {
13870 		total_size = &raw_decap_confs[idx].size;
13871 		data = (uint8_t *)&raw_decap_confs[idx].data;
13872 	}
13873 	*total_size = 0;
13874 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13875 	/* process hdr from upper layer to low layer (L3/L4 -> L2). */
13876 	data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
13877 	for (i = n - 1 ; i >= 0; --i) {
13878 		const struct rte_flow_item_gtp *gtp;
13879 		const struct rte_flow_item_geneve_opt *opt;
13880 		struct rte_flow_item_ipv6_routing_ext *ext;
13881 
13882 		item = in->args.vc.pattern + i;
13883 		if (item->spec == NULL)
13884 			item->spec = flow_item_default_mask(item);
13885 		src_spec = item->spec;
13886 		switch (item->type) {
13887 		case RTE_FLOW_ITEM_TYPE_ETH:
13888 			size = sizeof(struct rte_ether_hdr);
13889 			break;
13890 		case RTE_FLOW_ITEM_TYPE_VLAN:
13891 			size = sizeof(struct rte_vlan_hdr);
13892 			proto = RTE_ETHER_TYPE_VLAN;
13893 			break;
13894 		case RTE_FLOW_ITEM_TYPE_IPV4:
13895 			size = sizeof(struct rte_ipv4_hdr);
13896 			proto = RTE_ETHER_TYPE_IPV4;
13897 			break;
13898 		case RTE_FLOW_ITEM_TYPE_IPV6:
13899 			size = sizeof(struct rte_ipv6_hdr);
13900 			proto = RTE_ETHER_TYPE_IPV6;
13901 			break;
13902 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13903 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13904 			if (!ext->hdr.hdr_len) {
13905 				size = sizeof(struct rte_ipv6_routing_ext) +
13906 					(ext->hdr.segments_left << 4);
13907 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
13908 				/* SRv6 without TLV. */
13909 				if (ext->hdr.type == RTE_IPV6_SRCRT_TYPE_4)
13910 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
13911 			} else {
13912 				size = sizeof(struct rte_ipv6_routing_ext) +
13913 					(ext->hdr.hdr_len << 3);
13914 			}
13915 			proto = IPPROTO_ROUTING;
13916 			break;
13917 		case RTE_FLOW_ITEM_TYPE_UDP:
13918 			size = sizeof(struct rte_udp_hdr);
13919 			proto = 0x11;
13920 			break;
13921 		case RTE_FLOW_ITEM_TYPE_TCP:
13922 			size = sizeof(struct rte_tcp_hdr);
13923 			proto = 0x06;
13924 			break;
13925 		case RTE_FLOW_ITEM_TYPE_VXLAN:
13926 			size = sizeof(struct rte_vxlan_hdr);
13927 			break;
13928 		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13929 			size = sizeof(struct rte_vxlan_gpe_hdr);
13930 			break;
13931 		case RTE_FLOW_ITEM_TYPE_GRE:
13932 			size = sizeof(struct rte_gre_hdr);
13933 			proto = 0x2F;
13934 			break;
13935 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
13936 			size = sizeof(rte_be32_t);
13937 			proto = 0x0;
13938 			break;
13939 		case RTE_FLOW_ITEM_TYPE_MPLS:
13940 			size = sizeof(struct rte_mpls_hdr);
13941 			proto = 0x0;
13942 			break;
13943 		case RTE_FLOW_ITEM_TYPE_NVGRE:
13944 			size = sizeof(struct rte_flow_item_nvgre);
13945 			proto = 0x2F;
13946 			break;
13947 		case RTE_FLOW_ITEM_TYPE_GENEVE:
13948 			size = sizeof(struct rte_geneve_hdr);
13949 			break;
13950 		case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
13951 			opt = (const struct rte_flow_item_geneve_opt *)
13952 								item->spec;
13953 			size = offsetof(struct rte_flow_item_geneve_opt,
13954 					option_len) + sizeof(uint8_t);
13955 			if (opt->option_len && opt->data) {
13956 				*total_size += opt->option_len *
13957 					       sizeof(uint32_t);
13958 				rte_memcpy(data_tail - (*total_size),
13959 					   opt->data,
13960 					   opt->option_len * sizeof(uint32_t));
13961 			}
13962 			break;
13963 		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
13964 			size = sizeof(rte_be32_t);
13965 			proto = 0x73;
13966 			break;
13967 		case RTE_FLOW_ITEM_TYPE_ESP:
13968 			size = sizeof(struct rte_esp_hdr);
13969 			proto = 0x32;
13970 			break;
13971 		case RTE_FLOW_ITEM_TYPE_AH:
13972 			size = sizeof(struct rte_flow_item_ah);
13973 			proto = 0x33;
13974 			break;
13975 		case RTE_FLOW_ITEM_TYPE_GTP:
13976 			if (gtp_psc < 0) {
13977 				size = sizeof(struct rte_gtp_hdr);
13978 				break;
13979 			}
13980 			if (gtp_psc != i + 1) {
13981 				fprintf(stderr,
13982 					"Error - GTP PSC does not follow GTP\n");
13983 				goto error;
13984 			}
13985 			gtp = item->spec;
13986 			if (gtp->hdr.s == 1 || gtp->hdr.pn == 1) {
13987 				/* Only E flag should be set. */
13988 				fprintf(stderr,
13989 					"Error - GTP unsupported flags\n");
13990 				goto error;
13991 			} else {
13992 				struct rte_gtp_hdr_ext_word ext_word = {
13993 					.next_ext = 0x85
13994 				};
13995 
13996 				/* We have to add GTP header extra word. */
13997 				*total_size += sizeof(ext_word);
13998 				rte_memcpy(data_tail - (*total_size),
13999 					   &ext_word, sizeof(ext_word));
14000 			}
14001 			size = sizeof(struct rte_gtp_hdr);
14002 			break;
14003 		case RTE_FLOW_ITEM_TYPE_GTP_PSC:
14004 			if (gtp_psc >= 0) {
14005 				fprintf(stderr,
14006 					"Error - Multiple GTP PSC items\n");
14007 				goto error;
14008 			} else {
14009 				const struct rte_flow_item_gtp_psc
14010 					*opt = item->spec;
14011 				struct rte_gtp_psc_generic_hdr *hdr;
14012 				size_t hdr_size = RTE_ALIGN(sizeof(*hdr),
14013 							 sizeof(int32_t));
14014 
14015 				*total_size += hdr_size;
14016 				hdr = (typeof(hdr))(data_tail - (*total_size));
14017 				memset(hdr, 0, hdr_size);
14018 				*hdr = opt->hdr;
14019 				hdr->ext_hdr_len = 1;
14020 				gtp_psc = i;
14021 				size = 0;
14022 			}
14023 			break;
14024 		case RTE_FLOW_ITEM_TYPE_PFCP:
14025 			size = sizeof(struct rte_flow_item_pfcp);
14026 			break;
14027 		case RTE_FLOW_ITEM_TYPE_FLEX:
14028 			if (item->spec != NULL) {
14029 				size = ((const struct rte_flow_item_flex *)item->spec)->length;
14030 				src_spec = ((const struct rte_flow_item_flex *)item->spec)->pattern;
14031 			} else {
14032 				size = 0;
14033 				src_spec = NULL;
14034 			}
14035 			break;
14036 		case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
14037 			size = 0;
14038 			if (item->spec) {
14039 				const struct rte_flow_item_gre_opt
14040 					*opt = item->spec;
14041 				if (opt->checksum_rsvd.checksum) {
14042 					*total_size +=
14043 						sizeof(opt->checksum_rsvd);
14044 					rte_memcpy(data_tail - (*total_size),
14045 						   &opt->checksum_rsvd,
14046 						   sizeof(opt->checksum_rsvd));
14047 				}
14048 				if (opt->key.key) {
14049 					*total_size += sizeof(opt->key.key);
14050 					rte_memcpy(data_tail - (*total_size),
14051 						   &opt->key.key,
14052 						   sizeof(opt->key.key));
14053 				}
14054 				if (opt->sequence.sequence) {
14055 					*total_size += sizeof(opt->sequence.sequence);
14056 					rte_memcpy(data_tail - (*total_size),
14057 						   &opt->sequence.sequence,
14058 						   sizeof(opt->sequence.sequence));
14059 				}
14060 			}
14061 			proto = 0x2F;
14062 			break;
14063 		default:
14064 			fprintf(stderr, "Error - Not supported item\n");
14065 			goto error;
14066 		}
14067 		if (size) {
14068 			*total_size += size;
14069 			rte_memcpy(data_tail - (*total_size), src_spec, size);
14070 			/* update some fields which cannot be set by cmdline */
14071 			update_fields((data_tail - (*total_size)), item,
14072 				      upper_layer);
14073 			upper_layer = proto;
14074 		}
14075 	}
14076 	if (verbose_level & 0x1)
14077 		printf("total data size is %zu\n", (*total_size));
14078 	RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
14079 	memmove(data, (data_tail - (*total_size)), *total_size);
14080 	return;
14081 
14082 error:
14083 	*total_size = 0;
14084 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
14085 }
14086 
14087 /** Populate help strings for current token (cmdline API). */
14088 static int
14089 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
14090 		     unsigned int size)
14091 {
14092 	struct context *ctx = &cmd_flow_context;
14093 	const struct token *token = &token_list[ctx->prev];
14094 
14095 	(void)hdr;
14096 	if (!size)
14097 		return -1;
14098 	/* Set token type and update global help with details. */
14099 	snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
14100 	if (token->help)
14101 		cmd_set_raw.help_str = token->help;
14102 	else
14103 		cmd_set_raw.help_str = token->name;
14104 	return 0;
14105 }
14106 
14107 /** Token definition template (cmdline API). */
14108 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
14109 	.ops = &(struct cmdline_token_ops){
14110 		.parse = cmd_flow_parse,
14111 		.complete_get_nb = cmd_flow_complete_get_nb,
14112 		.complete_get_elt = cmd_flow_complete_get_elt,
14113 		.get_help = cmd_set_raw_get_help,
14114 	},
14115 	.offset = 0,
14116 };
14117 
14118 /** Populate the next dynamic token. */
14119 static void
14120 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
14121 	     cmdline_parse_token_hdr_t **hdr_inst)
14122 {
14123 	struct context *ctx = &cmd_flow_context;
14124 
14125 	/* Always reinitialize context before requesting the first token. */
14126 	if (!(hdr_inst - cmd_set_raw.tokens)) {
14127 		cmd_flow_context_init(ctx);
14128 		ctx->curr = START_SET;
14129 	}
14130 	/* Return NULL when no more tokens are expected. */
14131 	if (!ctx->next_num && (ctx->curr != START_SET)) {
14132 		*hdr = NULL;
14133 		return;
14134 	}
14135 	/* Determine if command should end here. */
14136 	if (ctx->eol && ctx->last && ctx->next_num) {
14137 		const enum index *list = ctx->next[ctx->next_num - 1];
14138 		int i;
14139 
14140 		for (i = 0; list[i]; ++i) {
14141 			if (list[i] != END)
14142 				continue;
14143 			*hdr = NULL;
14144 			return;
14145 		}
14146 	}
14147 	*hdr = &cmd_set_raw_token_hdr;
14148 }
14149 
14150 /** Token generator and output processing callback (cmdline API). */
14151 static void
14152 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
14153 {
14154 	if (cl == NULL)
14155 		cmd_set_raw_tok(arg0, arg2);
14156 	else
14157 		cmd_set_raw_parsed(arg0);
14158 }
14159 
14160 /** Global parser instance (cmdline API). */
14161 cmdline_parse_inst_t cmd_set_raw = {
14162 	.f = cmd_set_raw_cb,
14163 	.data = NULL, /**< Unused. */
14164 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
14165 	.tokens = {
14166 		NULL,
14167 	}, /**< Tokens are returned by cmd_flow_tok(). */
14168 };
14169 
14170 /* *** display raw_encap/raw_decap buf */
14171 struct cmd_show_set_raw_result {
14172 	cmdline_fixed_string_t cmd_show;
14173 	cmdline_fixed_string_t cmd_what;
14174 	cmdline_fixed_string_t cmd_all;
14175 	uint16_t cmd_index;
14176 };
14177 
14178 static void
14179 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
14180 {
14181 	struct cmd_show_set_raw_result *res = parsed_result;
14182 	uint16_t index = res->cmd_index;
14183 	uint8_t all = 0;
14184 	uint8_t *raw_data = NULL;
14185 	size_t raw_size = 0;
14186 	char title[16] = {0};
14187 
14188 	RTE_SET_USED(cl);
14189 	RTE_SET_USED(data);
14190 	if (!strcmp(res->cmd_all, "all")) {
14191 		all = 1;
14192 		index = 0;
14193 	} else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
14194 		fprintf(stderr, "index should be 0-%u\n",
14195 			RAW_ENCAP_CONFS_MAX_NUM - 1);
14196 		return;
14197 	}
14198 	do {
14199 		if (!strcmp(res->cmd_what, "raw_encap")) {
14200 			raw_data = (uint8_t *)&raw_encap_confs[index].data;
14201 			raw_size = raw_encap_confs[index].size;
14202 			snprintf(title, 16, "\nindex: %u", index);
14203 			rte_hexdump(stdout, title, raw_data, raw_size);
14204 		} else {
14205 			raw_data = (uint8_t *)&raw_decap_confs[index].data;
14206 			raw_size = raw_decap_confs[index].size;
14207 			snprintf(title, 16, "\nindex: %u", index);
14208 			rte_hexdump(stdout, title, raw_data, raw_size);
14209 		}
14210 	} while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
14211 }
14212 
14213 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
14214 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14215 			cmd_show, "show");
14216 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
14217 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14218 			cmd_what, "raw_encap#raw_decap");
14219 static cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
14220 	TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
14221 			cmd_index, RTE_UINT16);
14222 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
14223 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14224 			cmd_all, "all");
14225 cmdline_parse_inst_t cmd_show_set_raw = {
14226 	.f = cmd_show_set_raw_parsed,
14227 	.data = NULL,
14228 	.help_str = "show <raw_encap|raw_decap> <index>",
14229 	.tokens = {
14230 		(void *)&cmd_show_set_raw_cmd_show,
14231 		(void *)&cmd_show_set_raw_cmd_what,
14232 		(void *)&cmd_show_set_raw_cmd_index,
14233 		NULL,
14234 	},
14235 };
14236 cmdline_parse_inst_t cmd_show_set_raw_all = {
14237 	.f = cmd_show_set_raw_parsed,
14238 	.data = NULL,
14239 	.help_str = "show <raw_encap|raw_decap> all",
14240 	.tokens = {
14241 		(void *)&cmd_show_set_raw_cmd_show,
14242 		(void *)&cmd_show_set_raw_cmd_what,
14243 		(void *)&cmd_show_set_raw_cmd_all,
14244 		NULL,
14245 	},
14246 };
14247