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