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