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