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