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