xref: /dpdk/app/test-pmd/cmdline_flow.c (revision 389fca7577cc89dd64b9ef37b6a6f64e6e1f68d2)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2016 6WIND S.A.
3  * Copyright 2016 Mellanox Technologies, Ltd
4  */
5 
6 #include <stddef.h>
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <inttypes.h>
11 #include <errno.h>
12 #include <ctype.h>
13 #include <string.h>
14 
15 #include <rte_string_fns.h>
16 #include <rte_common.h>
17 #include <rte_ethdev.h>
18 #include <rte_byteorder.h>
19 #include <cmdline_parse.h>
20 #include <cmdline_parse_etheraddr.h>
21 #include <cmdline_parse_string.h>
22 #include <cmdline_parse_num.h>
23 #include <rte_flow.h>
24 #include <rte_hexdump.h>
25 #include <rte_vxlan.h>
26 #include <rte_gre.h>
27 #include <rte_mpls.h>
28 #include <rte_gtp.h>
29 #include <rte_geneve.h>
30 
31 #include "testpmd.h"
32 
33 /** Parser token indices. */
34 enum index {
35 	/* Special tokens. */
36 	ZERO = 0,
37 	END,
38 	START_SET,
39 	END_SET,
40 
41 	/* Common tokens. */
42 	COMMON_INTEGER,
43 	COMMON_UNSIGNED,
44 	COMMON_PREFIX,
45 	COMMON_BOOLEAN,
46 	COMMON_STRING,
47 	COMMON_HEX,
48 	COMMON_FILE_PATH,
49 	COMMON_MAC_ADDR,
50 	COMMON_IPV4_ADDR,
51 	COMMON_IPV6_ADDR,
52 	COMMON_RULE_ID,
53 	COMMON_PORT_ID,
54 	COMMON_GROUP_ID,
55 	COMMON_PRIORITY_LEVEL,
56 	COMMON_INDIRECT_ACTION_ID,
57 	COMMON_PROFILE_ID,
58 	COMMON_POLICY_ID,
59 	COMMON_FLEX_HANDLE,
60 	COMMON_FLEX_TOKEN,
61 	COMMON_PATTERN_TEMPLATE_ID,
62 	COMMON_ACTIONS_TEMPLATE_ID,
63 	COMMON_TABLE_ID,
64 	COMMON_QUEUE_ID,
65 
66 	/* TOP-level command. */
67 	ADD,
68 
69 	/* Top-level command. */
70 	SET,
71 	/* Sub-leve commands. */
72 	SET_RAW_ENCAP,
73 	SET_RAW_DECAP,
74 	SET_RAW_INDEX,
75 	SET_SAMPLE_ACTIONS,
76 	SET_SAMPLE_INDEX,
77 	SET_IPV6_EXT_REMOVE,
78 	SET_IPV6_EXT_PUSH,
79 	SET_IPV6_EXT_INDEX,
80 
81 	/* Top-level command. */
82 	FLOW,
83 	/* Sub-level commands. */
84 	INFO,
85 	CONFIGURE,
86 	PATTERN_TEMPLATE,
87 	ACTIONS_TEMPLATE,
88 	TABLE,
89 	FLOW_GROUP,
90 	INDIRECT_ACTION,
91 	VALIDATE,
92 	CREATE,
93 	DESTROY,
94 	UPDATE,
95 	FLUSH,
96 	DUMP,
97 	QUERY,
98 	LIST,
99 	AGED,
100 	ISOLATE,
101 	TUNNEL,
102 	FLEX,
103 	QUEUE,
104 	PUSH,
105 	PULL,
106 	HASH,
107 
108 	/* Flex arguments */
109 	FLEX_ITEM_INIT,
110 	FLEX_ITEM_CREATE,
111 	FLEX_ITEM_DESTROY,
112 
113 	/* Pattern template arguments. */
114 	PATTERN_TEMPLATE_CREATE,
115 	PATTERN_TEMPLATE_DESTROY,
116 	PATTERN_TEMPLATE_CREATE_ID,
117 	PATTERN_TEMPLATE_DESTROY_ID,
118 	PATTERN_TEMPLATE_RELAXED_MATCHING,
119 	PATTERN_TEMPLATE_INGRESS,
120 	PATTERN_TEMPLATE_EGRESS,
121 	PATTERN_TEMPLATE_TRANSFER,
122 	PATTERN_TEMPLATE_SPEC,
123 
124 	/* Actions template arguments. */
125 	ACTIONS_TEMPLATE_CREATE,
126 	ACTIONS_TEMPLATE_DESTROY,
127 	ACTIONS_TEMPLATE_CREATE_ID,
128 	ACTIONS_TEMPLATE_DESTROY_ID,
129 	ACTIONS_TEMPLATE_INGRESS,
130 	ACTIONS_TEMPLATE_EGRESS,
131 	ACTIONS_TEMPLATE_TRANSFER,
132 	ACTIONS_TEMPLATE_SPEC,
133 	ACTIONS_TEMPLATE_MASK,
134 
135 	/* Queue arguments. */
136 	QUEUE_CREATE,
137 	QUEUE_DESTROY,
138 	QUEUE_FLOW_UPDATE_RESIZED,
139 	QUEUE_UPDATE,
140 	QUEUE_AGED,
141 	QUEUE_INDIRECT_ACTION,
142 
143 	/* Queue create arguments. */
144 	QUEUE_CREATE_POSTPONE,
145 	QUEUE_TEMPLATE_TABLE,
146 	QUEUE_PATTERN_TEMPLATE,
147 	QUEUE_ACTIONS_TEMPLATE,
148 	QUEUE_RULE_ID,
149 
150 	/* Queue destroy arguments. */
151 	QUEUE_DESTROY_ID,
152 	QUEUE_DESTROY_POSTPONE,
153 
154 	/* Queue update arguments. */
155 	QUEUE_UPDATE_ID,
156 
157 	/* Queue indirect action arguments */
158 	QUEUE_INDIRECT_ACTION_CREATE,
159 	QUEUE_INDIRECT_ACTION_LIST_CREATE,
160 	QUEUE_INDIRECT_ACTION_UPDATE,
161 	QUEUE_INDIRECT_ACTION_DESTROY,
162 	QUEUE_INDIRECT_ACTION_QUERY,
163 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
164 
165 	/* Queue indirect action create arguments */
166 	QUEUE_INDIRECT_ACTION_CREATE_ID,
167 	QUEUE_INDIRECT_ACTION_INGRESS,
168 	QUEUE_INDIRECT_ACTION_EGRESS,
169 	QUEUE_INDIRECT_ACTION_TRANSFER,
170 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
171 	QUEUE_INDIRECT_ACTION_SPEC,
172 	QUEUE_INDIRECT_ACTION_LIST,
173 
174 	/* Queue indirect action update arguments */
175 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
176 
177 	/* Queue indirect action destroy arguments */
178 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
179 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
180 
181 	/* Queue indirect action query arguments */
182 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
183 
184 	/* Queue indirect action query_update arguments */
185 	QUEUE_INDIRECT_ACTION_QU_MODE,
186 
187 	/* Push arguments. */
188 	PUSH_QUEUE,
189 
190 	/* Pull arguments. */
191 	PULL_QUEUE,
192 
193 	/* Table arguments. */
194 	TABLE_CREATE,
195 	TABLE_DESTROY,
196 	TABLE_RESIZE,
197 	TABLE_RESIZE_COMPLETE,
198 	TABLE_CREATE_ID,
199 	TABLE_DESTROY_ID,
200 	TABLE_RESIZE_ID,
201 	TABLE_RESIZE_RULES_NUMBER,
202 	TABLE_INSERTION_TYPE,
203 	TABLE_INSERTION_TYPE_NAME,
204 	TABLE_HASH_FUNC,
205 	TABLE_HASH_FUNC_NAME,
206 	TABLE_GROUP,
207 	TABLE_PRIORITY,
208 	TABLE_INGRESS,
209 	TABLE_EGRESS,
210 	TABLE_TRANSFER,
211 	TABLE_TRANSFER_WIRE_ORIG,
212 	TABLE_TRANSFER_VPORT_ORIG,
213 	TABLE_RESIZABLE,
214 	TABLE_RULES_NUMBER,
215 	TABLE_PATTERN_TEMPLATE,
216 	TABLE_ACTIONS_TEMPLATE,
217 
218 	/* Group arguments */
219 	GROUP_ID,
220 	GROUP_INGRESS,
221 	GROUP_EGRESS,
222 	GROUP_TRANSFER,
223 	GROUP_SET_MISS_ACTIONS,
224 
225 	/* Hash calculation arguments. */
226 	HASH_CALC_TABLE,
227 	HASH_CALC_PATTERN_INDEX,
228 	HASH_CALC_PATTERN,
229 	HASH_CALC_ENCAP,
230 	HASH_CALC_DEST,
231 	ENCAP_HASH_FIELD_SRC_PORT,
232 	ENCAP_HASH_FIELD_GRE_FLOW_ID,
233 
234 	/* Tunnel arguments. */
235 	TUNNEL_CREATE,
236 	TUNNEL_CREATE_TYPE,
237 	TUNNEL_LIST,
238 	TUNNEL_DESTROY,
239 	TUNNEL_DESTROY_ID,
240 
241 	/* Destroy arguments. */
242 	DESTROY_RULE,
243 	DESTROY_IS_USER_ID,
244 
245 	/* Query arguments. */
246 	QUERY_ACTION,
247 	QUERY_IS_USER_ID,
248 
249 	/* List arguments. */
250 	LIST_GROUP,
251 
252 	/* Destroy aged flow arguments. */
253 	AGED_DESTROY,
254 
255 	/* Validate/create arguments. */
256 	VC_GROUP,
257 	VC_PRIORITY,
258 	VC_INGRESS,
259 	VC_EGRESS,
260 	VC_TRANSFER,
261 	VC_TUNNEL_SET,
262 	VC_TUNNEL_MATCH,
263 	VC_USER_ID,
264 	VC_IS_USER_ID,
265 
266 	/* Dump arguments */
267 	DUMP_ALL,
268 	DUMP_ONE,
269 	DUMP_IS_USER_ID,
270 
271 	/* Configure arguments */
272 	CONFIG_QUEUES_NUMBER,
273 	CONFIG_QUEUES_SIZE,
274 	CONFIG_COUNTERS_NUMBER,
275 	CONFIG_AGING_OBJECTS_NUMBER,
276 	CONFIG_METERS_NUMBER,
277 	CONFIG_CONN_TRACK_NUMBER,
278 	CONFIG_QUOTAS_NUMBER,
279 	CONFIG_FLAGS,
280 	CONFIG_HOST_PORT,
281 
282 	/* Indirect action arguments */
283 	INDIRECT_ACTION_CREATE,
284 	INDIRECT_ACTION_LIST_CREATE,
285 	INDIRECT_ACTION_FLOW_CONF_CREATE,
286 	INDIRECT_ACTION_UPDATE,
287 	INDIRECT_ACTION_DESTROY,
288 	INDIRECT_ACTION_QUERY,
289 	INDIRECT_ACTION_QUERY_UPDATE,
290 
291 	/* Indirect action create arguments */
292 	INDIRECT_ACTION_CREATE_ID,
293 	INDIRECT_ACTION_INGRESS,
294 	INDIRECT_ACTION_EGRESS,
295 	INDIRECT_ACTION_TRANSFER,
296 	INDIRECT_ACTION_SPEC,
297 	INDIRECT_ACTION_LIST,
298 	INDIRECT_ACTION_FLOW_CONF,
299 
300 	/* Indirect action destroy arguments */
301 	INDIRECT_ACTION_DESTROY_ID,
302 
303 	/* Indirect action query-and-update arguments */
304 	INDIRECT_ACTION_QU_MODE,
305 	INDIRECT_ACTION_QU_MODE_NAME,
306 
307 	/* Validate/create pattern. */
308 	ITEM_PATTERN,
309 	ITEM_PARAM_IS,
310 	ITEM_PARAM_SPEC,
311 	ITEM_PARAM_LAST,
312 	ITEM_PARAM_MASK,
313 	ITEM_PARAM_PREFIX,
314 	ITEM_NEXT,
315 	ITEM_END,
316 	ITEM_VOID,
317 	ITEM_INVERT,
318 	ITEM_ANY,
319 	ITEM_ANY_NUM,
320 	ITEM_PORT_ID,
321 	ITEM_PORT_ID_ID,
322 	ITEM_MARK,
323 	ITEM_MARK_ID,
324 	ITEM_RAW,
325 	ITEM_RAW_RELATIVE,
326 	ITEM_RAW_SEARCH,
327 	ITEM_RAW_OFFSET,
328 	ITEM_RAW_LIMIT,
329 	ITEM_RAW_PATTERN,
330 	ITEM_RAW_PATTERN_HEX,
331 	ITEM_ETH,
332 	ITEM_ETH_DST,
333 	ITEM_ETH_SRC,
334 	ITEM_ETH_TYPE,
335 	ITEM_ETH_HAS_VLAN,
336 	ITEM_VLAN,
337 	ITEM_VLAN_TCI,
338 	ITEM_VLAN_PCP,
339 	ITEM_VLAN_DEI,
340 	ITEM_VLAN_VID,
341 	ITEM_VLAN_INNER_TYPE,
342 	ITEM_VLAN_HAS_MORE_VLAN,
343 	ITEM_IPV4,
344 	ITEM_IPV4_VER_IHL,
345 	ITEM_IPV4_TOS,
346 	ITEM_IPV4_LENGTH,
347 	ITEM_IPV4_ID,
348 	ITEM_IPV4_FRAGMENT_OFFSET,
349 	ITEM_IPV4_TTL,
350 	ITEM_IPV4_PROTO,
351 	ITEM_IPV4_SRC,
352 	ITEM_IPV4_DST,
353 	ITEM_IPV6,
354 	ITEM_IPV6_TC,
355 	ITEM_IPV6_FLOW,
356 	ITEM_IPV6_LEN,
357 	ITEM_IPV6_PROTO,
358 	ITEM_IPV6_HOP,
359 	ITEM_IPV6_SRC,
360 	ITEM_IPV6_DST,
361 	ITEM_IPV6_HAS_FRAG_EXT,
362 	ITEM_IPV6_ROUTING_EXT,
363 	ITEM_IPV6_ROUTING_EXT_TYPE,
364 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
365 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
366 	ITEM_ICMP,
367 	ITEM_ICMP_TYPE,
368 	ITEM_ICMP_CODE,
369 	ITEM_ICMP_IDENT,
370 	ITEM_ICMP_SEQ,
371 	ITEM_UDP,
372 	ITEM_UDP_SRC,
373 	ITEM_UDP_DST,
374 	ITEM_TCP,
375 	ITEM_TCP_SRC,
376 	ITEM_TCP_DST,
377 	ITEM_TCP_FLAGS,
378 	ITEM_SCTP,
379 	ITEM_SCTP_SRC,
380 	ITEM_SCTP_DST,
381 	ITEM_SCTP_TAG,
382 	ITEM_SCTP_CKSUM,
383 	ITEM_VXLAN,
384 	ITEM_VXLAN_VNI,
385 	ITEM_VXLAN_FLAG_G,
386 	ITEM_VXLAN_FLAG_VER,
387 	ITEM_VXLAN_FLAG_I,
388 	ITEM_VXLAN_FLAG_P,
389 	ITEM_VXLAN_FLAG_B,
390 	ITEM_VXLAN_FLAG_O,
391 	ITEM_VXLAN_FLAG_D,
392 	ITEM_VXLAN_FLAG_A,
393 	ITEM_VXLAN_GBP_ID,
394 	/* Used for "struct rte_vxlan_hdr", GPE Next protocol */
395 	ITEM_VXLAN_GPE_PROTO,
396 	ITEM_VXLAN_FIRST_RSVD,
397 	ITEM_VXLAN_SECND_RSVD,
398 	ITEM_VXLAN_THIRD_RSVD,
399 	ITEM_VXLAN_LAST_RSVD,
400 	ITEM_E_TAG,
401 	ITEM_E_TAG_GRP_ECID_B,
402 	ITEM_NVGRE,
403 	ITEM_NVGRE_TNI,
404 	ITEM_MPLS,
405 	ITEM_MPLS_LABEL,
406 	ITEM_MPLS_TC,
407 	ITEM_MPLS_S,
408 	ITEM_MPLS_TTL,
409 	ITEM_GRE,
410 	ITEM_GRE_PROTO,
411 	ITEM_GRE_C_RSVD0_VER,
412 	ITEM_GRE_C_BIT,
413 	ITEM_GRE_K_BIT,
414 	ITEM_GRE_S_BIT,
415 	ITEM_FUZZY,
416 	ITEM_FUZZY_THRESH,
417 	ITEM_GTP,
418 	ITEM_GTP_FLAGS,
419 	ITEM_GTP_MSG_TYPE,
420 	ITEM_GTP_TEID,
421 	ITEM_GTPC,
422 	ITEM_GTPU,
423 	ITEM_GENEVE,
424 	ITEM_GENEVE_VNI,
425 	ITEM_GENEVE_PROTO,
426 	ITEM_GENEVE_OPTLEN,
427 	ITEM_VXLAN_GPE,
428 	ITEM_VXLAN_GPE_VNI,
429 	/* Used for "struct rte_vxlan_gpe_hdr", deprecated, prefer ITEM_VXLAN_GPE_PROTO */
430 	ITEM_VXLAN_GPE_PROTO_IN_DEPRECATED_VXLAN_GPE_HDR,
431 	ITEM_VXLAN_GPE_FLAGS,
432 	ITEM_VXLAN_GPE_RSVD0,
433 	ITEM_VXLAN_GPE_RSVD1,
434 	ITEM_ARP_ETH_IPV4,
435 	ITEM_ARP_ETH_IPV4_SHA,
436 	ITEM_ARP_ETH_IPV4_SPA,
437 	ITEM_ARP_ETH_IPV4_THA,
438 	ITEM_ARP_ETH_IPV4_TPA,
439 	ITEM_IPV6_EXT,
440 	ITEM_IPV6_EXT_NEXT_HDR,
441 	ITEM_IPV6_FRAG_EXT,
442 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
443 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
444 	ITEM_IPV6_FRAG_EXT_ID,
445 	ITEM_ICMP6,
446 	ITEM_ICMP6_TYPE,
447 	ITEM_ICMP6_CODE,
448 	ITEM_ICMP6_ECHO_REQUEST,
449 	ITEM_ICMP6_ECHO_REQUEST_ID,
450 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
451 	ITEM_ICMP6_ECHO_REPLY,
452 	ITEM_ICMP6_ECHO_REPLY_ID,
453 	ITEM_ICMP6_ECHO_REPLY_SEQ,
454 	ITEM_ICMP6_ND_NS,
455 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
456 	ITEM_ICMP6_ND_NA,
457 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
458 	ITEM_ICMP6_ND_OPT,
459 	ITEM_ICMP6_ND_OPT_TYPE,
460 	ITEM_ICMP6_ND_OPT_SLA_ETH,
461 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
462 	ITEM_ICMP6_ND_OPT_TLA_ETH,
463 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
464 	ITEM_META,
465 	ITEM_META_DATA,
466 	ITEM_RANDOM,
467 	ITEM_RANDOM_VALUE,
468 	ITEM_GRE_KEY,
469 	ITEM_GRE_KEY_VALUE,
470 	ITEM_GRE_OPTION,
471 	ITEM_GRE_OPTION_CHECKSUM,
472 	ITEM_GRE_OPTION_KEY,
473 	ITEM_GRE_OPTION_SEQUENCE,
474 	ITEM_GTP_PSC,
475 	ITEM_GTP_PSC_QFI,
476 	ITEM_GTP_PSC_PDU_T,
477 	ITEM_PPPOES,
478 	ITEM_PPPOED,
479 	ITEM_PPPOE_SEID,
480 	ITEM_PPPOE_PROTO_ID,
481 	ITEM_HIGIG2,
482 	ITEM_HIGIG2_CLASSIFICATION,
483 	ITEM_HIGIG2_VID,
484 	ITEM_TAG,
485 	ITEM_TAG_DATA,
486 	ITEM_TAG_INDEX,
487 	ITEM_L2TPV3OIP,
488 	ITEM_L2TPV3OIP_SESSION_ID,
489 	ITEM_ESP,
490 	ITEM_ESP_SPI,
491 	ITEM_AH,
492 	ITEM_AH_SPI,
493 	ITEM_PFCP,
494 	ITEM_PFCP_S_FIELD,
495 	ITEM_PFCP_SEID,
496 	ITEM_ECPRI,
497 	ITEM_ECPRI_COMMON,
498 	ITEM_ECPRI_COMMON_TYPE,
499 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
500 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
501 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
502 	ITEM_ECPRI_MSG_IQ_DATA_PCID,
503 	ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
504 	ITEM_ECPRI_MSG_DLY_MSR_MSRID,
505 	ITEM_GENEVE_OPT,
506 	ITEM_GENEVE_OPT_CLASS,
507 	ITEM_GENEVE_OPT_TYPE,
508 	ITEM_GENEVE_OPT_LENGTH,
509 	ITEM_GENEVE_OPT_DATA,
510 	ITEM_INTEGRITY,
511 	ITEM_INTEGRITY_LEVEL,
512 	ITEM_INTEGRITY_VALUE,
513 	ITEM_CONNTRACK,
514 	ITEM_POL_PORT,
515 	ITEM_POL_METER,
516 	ITEM_POL_POLICY,
517 	ITEM_PORT_REPRESENTOR,
518 	ITEM_PORT_REPRESENTOR_PORT_ID,
519 	ITEM_REPRESENTED_PORT,
520 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
521 	ITEM_FLEX,
522 	ITEM_FLEX_ITEM_HANDLE,
523 	ITEM_FLEX_PATTERN_HANDLE,
524 	ITEM_L2TPV2,
525 	ITEM_L2TPV2_TYPE,
526 	ITEM_L2TPV2_TYPE_DATA,
527 	ITEM_L2TPV2_TYPE_DATA_L,
528 	ITEM_L2TPV2_TYPE_DATA_S,
529 	ITEM_L2TPV2_TYPE_DATA_O,
530 	ITEM_L2TPV2_TYPE_DATA_L_S,
531 	ITEM_L2TPV2_TYPE_CTRL,
532 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
533 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
534 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
535 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
536 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
537 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
538 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
539 	ITEM_L2TPV2_MSG_DATA_S_NS,
540 	ITEM_L2TPV2_MSG_DATA_S_NR,
541 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
542 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
543 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
544 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
545 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
546 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
547 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
548 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
549 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
550 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
551 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
552 	ITEM_L2TPV2_MSG_CTRL_NS,
553 	ITEM_L2TPV2_MSG_CTRL_NR,
554 	ITEM_PPP,
555 	ITEM_PPP_ADDR,
556 	ITEM_PPP_CTRL,
557 	ITEM_PPP_PROTO_ID,
558 	ITEM_METER,
559 	ITEM_METER_COLOR,
560 	ITEM_METER_COLOR_NAME,
561 	ITEM_QUOTA,
562 	ITEM_QUOTA_STATE,
563 	ITEM_QUOTA_STATE_NAME,
564 	ITEM_AGGR_AFFINITY,
565 	ITEM_AGGR_AFFINITY_VALUE,
566 	ITEM_TX_QUEUE,
567 	ITEM_TX_QUEUE_VALUE,
568 	ITEM_IB_BTH,
569 	ITEM_IB_BTH_OPCODE,
570 	ITEM_IB_BTH_PKEY,
571 	ITEM_IB_BTH_DST_QPN,
572 	ITEM_IB_BTH_PSN,
573 	ITEM_IPV6_PUSH_REMOVE_EXT,
574 	ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
575 	ITEM_PTYPE,
576 	ITEM_PTYPE_VALUE,
577 	ITEM_NSH,
578 	ITEM_COMPARE,
579 	ITEM_COMPARE_OP,
580 	ITEM_COMPARE_OP_VALUE,
581 	ITEM_COMPARE_FIELD_A_TYPE,
582 	ITEM_COMPARE_FIELD_A_TYPE_VALUE,
583 	ITEM_COMPARE_FIELD_A_LEVEL,
584 	ITEM_COMPARE_FIELD_A_LEVEL_VALUE,
585 	ITEM_COMPARE_FIELD_A_TAG_INDEX,
586 	ITEM_COMPARE_FIELD_A_TYPE_ID,
587 	ITEM_COMPARE_FIELD_A_CLASS_ID,
588 	ITEM_COMPARE_FIELD_A_OFFSET,
589 	ITEM_COMPARE_FIELD_B_TYPE,
590 	ITEM_COMPARE_FIELD_B_TYPE_VALUE,
591 	ITEM_COMPARE_FIELD_B_LEVEL,
592 	ITEM_COMPARE_FIELD_B_LEVEL_VALUE,
593 	ITEM_COMPARE_FIELD_B_TAG_INDEX,
594 	ITEM_COMPARE_FIELD_B_TYPE_ID,
595 	ITEM_COMPARE_FIELD_B_CLASS_ID,
596 	ITEM_COMPARE_FIELD_B_OFFSET,
597 	ITEM_COMPARE_FIELD_B_VALUE,
598 	ITEM_COMPARE_FIELD_B_POINTER,
599 	ITEM_COMPARE_FIELD_WIDTH,
600 
601 	/* Validate/create actions. */
602 	ACTIONS,
603 	ACTION_NEXT,
604 	ACTION_END,
605 	ACTION_VOID,
606 	ACTION_PASSTHRU,
607 	ACTION_SKIP_CMAN,
608 	ACTION_JUMP,
609 	ACTION_JUMP_GROUP,
610 	ACTION_MARK,
611 	ACTION_MARK_ID,
612 	ACTION_FLAG,
613 	ACTION_QUEUE,
614 	ACTION_QUEUE_INDEX,
615 	ACTION_DROP,
616 	ACTION_COUNT,
617 	ACTION_COUNT_ID,
618 	ACTION_RSS,
619 	ACTION_RSS_FUNC,
620 	ACTION_RSS_LEVEL,
621 	ACTION_RSS_FUNC_DEFAULT,
622 	ACTION_RSS_FUNC_TOEPLITZ,
623 	ACTION_RSS_FUNC_SIMPLE_XOR,
624 	ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
625 	ACTION_RSS_TYPES,
626 	ACTION_RSS_TYPE,
627 	ACTION_RSS_KEY,
628 	ACTION_RSS_KEY_LEN,
629 	ACTION_RSS_QUEUES,
630 	ACTION_RSS_QUEUE,
631 	ACTION_PF,
632 	ACTION_VF,
633 	ACTION_VF_ORIGINAL,
634 	ACTION_VF_ID,
635 	ACTION_PORT_ID,
636 	ACTION_PORT_ID_ORIGINAL,
637 	ACTION_PORT_ID_ID,
638 	ACTION_METER,
639 	ACTION_METER_COLOR,
640 	ACTION_METER_COLOR_TYPE,
641 	ACTION_METER_COLOR_GREEN,
642 	ACTION_METER_COLOR_YELLOW,
643 	ACTION_METER_COLOR_RED,
644 	ACTION_METER_ID,
645 	ACTION_METER_MARK,
646 	ACTION_METER_PROFILE,
647 	ACTION_METER_PROFILE_ID2PTR,
648 	ACTION_METER_POLICY,
649 	ACTION_METER_POLICY_ID2PTR,
650 	ACTION_METER_COLOR_MODE,
651 	ACTION_METER_STATE,
652 	ACTION_OF_DEC_NW_TTL,
653 	ACTION_OF_POP_VLAN,
654 	ACTION_OF_PUSH_VLAN,
655 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
656 	ACTION_OF_SET_VLAN_VID,
657 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
658 	ACTION_OF_SET_VLAN_PCP,
659 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
660 	ACTION_OF_POP_MPLS,
661 	ACTION_OF_POP_MPLS_ETHERTYPE,
662 	ACTION_OF_PUSH_MPLS,
663 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
664 	ACTION_VXLAN_ENCAP,
665 	ACTION_VXLAN_DECAP,
666 	ACTION_NVGRE_ENCAP,
667 	ACTION_NVGRE_DECAP,
668 	ACTION_L2_ENCAP,
669 	ACTION_L2_DECAP,
670 	ACTION_MPLSOGRE_ENCAP,
671 	ACTION_MPLSOGRE_DECAP,
672 	ACTION_MPLSOUDP_ENCAP,
673 	ACTION_MPLSOUDP_DECAP,
674 	ACTION_SET_IPV4_SRC,
675 	ACTION_SET_IPV4_SRC_IPV4_SRC,
676 	ACTION_SET_IPV4_DST,
677 	ACTION_SET_IPV4_DST_IPV4_DST,
678 	ACTION_SET_IPV6_SRC,
679 	ACTION_SET_IPV6_SRC_IPV6_SRC,
680 	ACTION_SET_IPV6_DST,
681 	ACTION_SET_IPV6_DST_IPV6_DST,
682 	ACTION_SET_TP_SRC,
683 	ACTION_SET_TP_SRC_TP_SRC,
684 	ACTION_SET_TP_DST,
685 	ACTION_SET_TP_DST_TP_DST,
686 	ACTION_MAC_SWAP,
687 	ACTION_DEC_TTL,
688 	ACTION_SET_TTL,
689 	ACTION_SET_TTL_TTL,
690 	ACTION_SET_MAC_SRC,
691 	ACTION_SET_MAC_SRC_MAC_SRC,
692 	ACTION_SET_MAC_DST,
693 	ACTION_SET_MAC_DST_MAC_DST,
694 	ACTION_INC_TCP_SEQ,
695 	ACTION_INC_TCP_SEQ_VALUE,
696 	ACTION_DEC_TCP_SEQ,
697 	ACTION_DEC_TCP_SEQ_VALUE,
698 	ACTION_INC_TCP_ACK,
699 	ACTION_INC_TCP_ACK_VALUE,
700 	ACTION_DEC_TCP_ACK,
701 	ACTION_DEC_TCP_ACK_VALUE,
702 	ACTION_RAW_ENCAP,
703 	ACTION_RAW_DECAP,
704 	ACTION_RAW_ENCAP_SIZE,
705 	ACTION_RAW_ENCAP_INDEX,
706 	ACTION_RAW_ENCAP_INDEX_VALUE,
707 	ACTION_RAW_DECAP_INDEX,
708 	ACTION_RAW_DECAP_INDEX_VALUE,
709 	ACTION_SET_TAG,
710 	ACTION_SET_TAG_DATA,
711 	ACTION_SET_TAG_INDEX,
712 	ACTION_SET_TAG_MASK,
713 	ACTION_SET_META,
714 	ACTION_SET_META_DATA,
715 	ACTION_SET_META_MASK,
716 	ACTION_SET_IPV4_DSCP,
717 	ACTION_SET_IPV4_DSCP_VALUE,
718 	ACTION_SET_IPV6_DSCP,
719 	ACTION_SET_IPV6_DSCP_VALUE,
720 	ACTION_AGE,
721 	ACTION_AGE_TIMEOUT,
722 	ACTION_AGE_UPDATE,
723 	ACTION_AGE_UPDATE_TIMEOUT,
724 	ACTION_AGE_UPDATE_TOUCH,
725 	ACTION_SAMPLE,
726 	ACTION_SAMPLE_RATIO,
727 	ACTION_SAMPLE_INDEX,
728 	ACTION_SAMPLE_INDEX_VALUE,
729 	ACTION_INDIRECT,
730 	ACTION_INDIRECT_LIST,
731 	ACTION_INDIRECT_LIST_HANDLE,
732 	ACTION_INDIRECT_LIST_CONF,
733 	INDIRECT_LIST_ACTION_ID2PTR_HANDLE,
734 	INDIRECT_LIST_ACTION_ID2PTR_CONF,
735 	ACTION_SHARED_INDIRECT,
736 	INDIRECT_ACTION_PORT,
737 	INDIRECT_ACTION_ID2PTR,
738 	ACTION_MODIFY_FIELD,
739 	ACTION_MODIFY_FIELD_OP,
740 	ACTION_MODIFY_FIELD_OP_VALUE,
741 	ACTION_MODIFY_FIELD_DST_TYPE,
742 	ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
743 	ACTION_MODIFY_FIELD_DST_LEVEL,
744 	ACTION_MODIFY_FIELD_DST_LEVEL_VALUE,
745 	ACTION_MODIFY_FIELD_DST_TAG_INDEX,
746 	ACTION_MODIFY_FIELD_DST_TYPE_ID,
747 	ACTION_MODIFY_FIELD_DST_CLASS_ID,
748 	ACTION_MODIFY_FIELD_DST_OFFSET,
749 	ACTION_MODIFY_FIELD_SRC_TYPE,
750 	ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
751 	ACTION_MODIFY_FIELD_SRC_LEVEL,
752 	ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE,
753 	ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
754 	ACTION_MODIFY_FIELD_SRC_TYPE_ID,
755 	ACTION_MODIFY_FIELD_SRC_CLASS_ID,
756 	ACTION_MODIFY_FIELD_SRC_OFFSET,
757 	ACTION_MODIFY_FIELD_SRC_VALUE,
758 	ACTION_MODIFY_FIELD_SRC_POINTER,
759 	ACTION_MODIFY_FIELD_WIDTH,
760 	ACTION_CONNTRACK,
761 	ACTION_CONNTRACK_UPDATE,
762 	ACTION_CONNTRACK_UPDATE_DIR,
763 	ACTION_CONNTRACK_UPDATE_CTX,
764 	ACTION_POL_G,
765 	ACTION_POL_Y,
766 	ACTION_POL_R,
767 	ACTION_PORT_REPRESENTOR,
768 	ACTION_PORT_REPRESENTOR_PORT_ID,
769 	ACTION_REPRESENTED_PORT,
770 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
771 	ACTION_SEND_TO_KERNEL,
772 	ACTION_QUOTA_CREATE,
773 	ACTION_QUOTA_CREATE_LIMIT,
774 	ACTION_QUOTA_CREATE_MODE,
775 	ACTION_QUOTA_CREATE_MODE_NAME,
776 	ACTION_QUOTA_QU,
777 	ACTION_QUOTA_QU_LIMIT,
778 	ACTION_QUOTA_QU_UPDATE_OP,
779 	ACTION_QUOTA_QU_UPDATE_OP_NAME,
780 	ACTION_IPV6_EXT_REMOVE,
781 	ACTION_IPV6_EXT_REMOVE_INDEX,
782 	ACTION_IPV6_EXT_REMOVE_INDEX_VALUE,
783 	ACTION_IPV6_EXT_PUSH,
784 	ACTION_IPV6_EXT_PUSH_INDEX,
785 	ACTION_IPV6_EXT_PUSH_INDEX_VALUE,
786 	ACTION_NAT64,
787 	ACTION_NAT64_MODE,
788 };
789 
790 /** Maximum size for pattern in struct rte_flow_item_raw. */
791 #define ITEM_RAW_PATTERN_SIZE 512
792 
793 /** Maximum size for GENEVE option data pattern in bytes. */
794 #define ITEM_GENEVE_OPT_DATA_SIZE 124
795 
796 /** Storage size for struct rte_flow_item_raw including pattern. */
797 #define ITEM_RAW_SIZE \
798 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
799 
800 static const char *const compare_ops[] = {
801 	"eq", "ne", "lt", "le", "gt", "ge", NULL
802 };
803 
804 /** Maximum size for external pattern in struct rte_flow_field_data. */
805 #define FLOW_FIELD_PATTERN_SIZE 32
806 
807 /** Storage size for struct rte_flow_action_modify_field including pattern. */
808 #define ACTION_MODIFY_SIZE \
809 	(sizeof(struct rte_flow_action_modify_field) + \
810 	FLOW_FIELD_PATTERN_SIZE)
811 
812 /** Maximum number of queue indices in struct rte_flow_action_rss. */
813 #define ACTION_RSS_QUEUE_NUM 128
814 
815 /** Storage for struct rte_flow_action_rss including external data. */
816 struct action_rss_data {
817 	struct rte_flow_action_rss conf;
818 	uint8_t key[RSS_HASH_KEY_LENGTH];
819 	uint16_t queue[ACTION_RSS_QUEUE_NUM];
820 };
821 
822 /** Maximum data size in struct rte_flow_action_raw_encap. */
823 #define ACTION_RAW_ENCAP_MAX_DATA 512
824 #define RAW_ENCAP_CONFS_MAX_NUM 8
825 
826 /** Storage for struct rte_flow_action_raw_encap. */
827 struct raw_encap_conf {
828 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
829 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
830 	size_t size;
831 };
832 
833 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
834 
835 /** Storage for struct rte_flow_action_raw_encap including external data. */
836 struct action_raw_encap_data {
837 	struct rte_flow_action_raw_encap conf;
838 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
839 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
840 	uint16_t idx;
841 };
842 
843 /** Storage for struct rte_flow_action_raw_decap. */
844 struct raw_decap_conf {
845 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
846 	size_t size;
847 };
848 
849 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
850 
851 /** Storage for struct rte_flow_action_raw_decap including external data. */
852 struct action_raw_decap_data {
853 	struct rte_flow_action_raw_decap conf;
854 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
855 	uint16_t idx;
856 };
857 
858 /** Maximum data size in struct rte_flow_action_ipv6_ext_push. */
859 #define ACTION_IPV6_EXT_PUSH_MAX_DATA 512
860 #define IPV6_EXT_PUSH_CONFS_MAX_NUM 8
861 
862 /** Storage for struct rte_flow_action_ipv6_ext_push. */
863 struct ipv6_ext_push_conf {
864 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
865 	size_t size;
866 	uint8_t type;
867 };
868 
869 struct ipv6_ext_push_conf ipv6_ext_push_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
870 
871 /** Storage for struct rte_flow_action_ipv6_ext_push including external data. */
872 struct action_ipv6_ext_push_data {
873 	struct rte_flow_action_ipv6_ext_push conf;
874 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
875 	uint8_t type;
876 	uint16_t idx;
877 };
878 
879 /** Storage for struct rte_flow_action_ipv6_ext_remove. */
880 struct ipv6_ext_remove_conf {
881 	struct rte_flow_action_ipv6_ext_remove conf;
882 	uint8_t type;
883 };
884 
885 struct ipv6_ext_remove_conf ipv6_ext_remove_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
886 
887 /** Storage for struct rte_flow_action_ipv6_ext_remove including external data. */
888 struct action_ipv6_ext_remove_data {
889 	struct rte_flow_action_ipv6_ext_remove conf;
890 	uint8_t type;
891 	uint16_t idx;
892 };
893 
894 struct vxlan_encap_conf vxlan_encap_conf = {
895 	.select_ipv4 = 1,
896 	.select_vlan = 0,
897 	.select_tos_ttl = 0,
898 	.vni = "\x00\x00\x00",
899 	.udp_src = 0,
900 	.udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
901 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
902 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
903 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
904 		"\x00\x00\x00\x00\x00\x00\x00\x01",
905 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
906 		"\x00\x00\x00\x00\x00\x00\x11\x11",
907 	.vlan_tci = 0,
908 	.ip_tos = 0,
909 	.ip_ttl = 255,
910 	.eth_src = "\x00\x00\x00\x00\x00\x00",
911 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
912 };
913 
914 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
915 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
916 
917 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
918 struct action_vxlan_encap_data {
919 	struct rte_flow_action_vxlan_encap conf;
920 	struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
921 	struct rte_flow_item_eth item_eth;
922 	struct rte_flow_item_vlan item_vlan;
923 	union {
924 		struct rte_flow_item_ipv4 item_ipv4;
925 		struct rte_flow_item_ipv6 item_ipv6;
926 	};
927 	struct rte_flow_item_udp item_udp;
928 	struct rte_flow_item_vxlan item_vxlan;
929 };
930 
931 struct nvgre_encap_conf nvgre_encap_conf = {
932 	.select_ipv4 = 1,
933 	.select_vlan = 0,
934 	.tni = "\x00\x00\x00",
935 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
936 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
937 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
938 		"\x00\x00\x00\x00\x00\x00\x00\x01",
939 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
940 		"\x00\x00\x00\x00\x00\x00\x11\x11",
941 	.vlan_tci = 0,
942 	.eth_src = "\x00\x00\x00\x00\x00\x00",
943 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
944 };
945 
946 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
947 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
948 
949 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
950 struct action_nvgre_encap_data {
951 	struct rte_flow_action_nvgre_encap conf;
952 	struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
953 	struct rte_flow_item_eth item_eth;
954 	struct rte_flow_item_vlan item_vlan;
955 	union {
956 		struct rte_flow_item_ipv4 item_ipv4;
957 		struct rte_flow_item_ipv6 item_ipv6;
958 	};
959 	struct rte_flow_item_nvgre item_nvgre;
960 };
961 
962 struct l2_encap_conf l2_encap_conf;
963 
964 struct l2_decap_conf l2_decap_conf;
965 
966 struct mplsogre_encap_conf mplsogre_encap_conf;
967 
968 struct mplsogre_decap_conf mplsogre_decap_conf;
969 
970 struct mplsoudp_encap_conf mplsoudp_encap_conf;
971 
972 struct mplsoudp_decap_conf mplsoudp_decap_conf;
973 
974 struct rte_flow_action_conntrack conntrack_context;
975 
976 #define ACTION_SAMPLE_ACTIONS_NUM 10
977 #define RAW_SAMPLE_CONFS_MAX_NUM 8
978 /** Storage for struct rte_flow_action_sample including external data. */
979 struct action_sample_data {
980 	struct rte_flow_action_sample conf;
981 	uint32_t idx;
982 };
983 /** Storage for struct rte_flow_action_sample. */
984 struct raw_sample_conf {
985 	struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
986 };
987 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
988 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
989 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
990 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
991 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
992 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
993 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
994 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
995 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
996 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
997 struct rte_flow_action_ethdev sample_port_representor[RAW_SAMPLE_CONFS_MAX_NUM];
998 struct rte_flow_action_ethdev sample_represented_port[RAW_SAMPLE_CONFS_MAX_NUM];
999 
1000 static const char *const modify_field_ops[] = {
1001 	"set", "add", "sub", NULL
1002 };
1003 
1004 static const char *const flow_field_ids[] = {
1005 	"start", "mac_dst", "mac_src",
1006 	"vlan_type", "vlan_id", "mac_type",
1007 	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
1008 	"ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
1009 	"tcp_port_src", "tcp_port_dst",
1010 	"tcp_seq_num", "tcp_ack_num", "tcp_flags",
1011 	"udp_port_src", "udp_port_dst",
1012 	"vxlan_vni", "geneve_vni", "gtp_teid",
1013 	"tag", "mark", "meta", "pointer", "value",
1014 	"ipv4_ecn", "ipv6_ecn", "gtp_psc_qfi", "meter_color",
1015 	"ipv6_proto",
1016 	"flex_item",
1017 	"hash_result",
1018 	"geneve_opt_type", "geneve_opt_class", "geneve_opt_data", "mpls",
1019 	"tcp_data_off", "ipv4_ihl", "ipv4_total_len", "ipv6_payload_len",
1020 	"ipv4_proto",
1021 	"ipv6_flow_label", "ipv6_traffic_class",
1022 	"esp_spi", "esp_seq_num", "esp_proto",
1023 	"random",
1024 	"vxlan_last_rsvd",
1025 	NULL
1026 };
1027 
1028 static const char *const meter_colors[] = {
1029 	"green", "yellow", "red", "all", NULL
1030 };
1031 
1032 static const char *const table_insertion_types[] = {
1033 	"pattern", "index", NULL
1034 };
1035 
1036 static const char *const table_hash_funcs[] = {
1037 	"default", "linear", "crc32", "crc16", NULL
1038 };
1039 
1040 #define RAW_IPSEC_CONFS_MAX_NUM 8
1041 
1042 /** Maximum number of subsequent tokens and arguments on the stack. */
1043 #define CTX_STACK_SIZE 16
1044 
1045 /** Parser context. */
1046 struct context {
1047 	/** Stack of subsequent token lists to process. */
1048 	const enum index *next[CTX_STACK_SIZE];
1049 	/** Arguments for stacked tokens. */
1050 	const void *args[CTX_STACK_SIZE];
1051 	enum index curr; /**< Current token index. */
1052 	enum index prev; /**< Index of the last token seen. */
1053 	int next_num; /**< Number of entries in next[]. */
1054 	int args_num; /**< Number of entries in args[]. */
1055 	uint32_t eol:1; /**< EOL has been detected. */
1056 	uint32_t last:1; /**< No more arguments. */
1057 	portid_t port; /**< Current port ID (for completions). */
1058 	uint32_t objdata; /**< Object-specific data. */
1059 	void *object; /**< Address of current object for relative offsets. */
1060 	void *objmask; /**< Object a full mask must be written to. */
1061 };
1062 
1063 /** Token argument. */
1064 struct arg {
1065 	uint32_t hton:1; /**< Use network byte ordering. */
1066 	uint32_t sign:1; /**< Value is signed. */
1067 	uint32_t bounded:1; /**< Value is bounded. */
1068 	uintmax_t min; /**< Minimum value if bounded. */
1069 	uintmax_t max; /**< Maximum value if bounded. */
1070 	uint32_t offset; /**< Relative offset from ctx->object. */
1071 	uint32_t size; /**< Field size. */
1072 	const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
1073 };
1074 
1075 /** Parser token definition. */
1076 struct token {
1077 	/** Type displayed during completion (defaults to "TOKEN"). */
1078 	const char *type;
1079 	/** Help displayed during completion (defaults to token name). */
1080 	const char *help;
1081 	/** Private data used by parser functions. */
1082 	const void *priv;
1083 	/**
1084 	 * Lists of subsequent tokens to push on the stack. Each call to the
1085 	 * parser consumes the last entry of that stack.
1086 	 */
1087 	const enum index *const *next;
1088 	/** Arguments stack for subsequent tokens that need them. */
1089 	const struct arg *const *args;
1090 	/**
1091 	 * Token-processing callback, returns -1 in case of error, the
1092 	 * length of the matched string otherwise. If NULL, attempts to
1093 	 * match the token name.
1094 	 *
1095 	 * If buf is not NULL, the result should be stored in it according
1096 	 * to context. An error is returned if not large enough.
1097 	 */
1098 	int (*call)(struct context *ctx, const struct token *token,
1099 		    const char *str, unsigned int len,
1100 		    void *buf, unsigned int size);
1101 	/**
1102 	 * Callback that provides possible values for this token, used for
1103 	 * completion. Returns -1 in case of error, the number of possible
1104 	 * values otherwise. If NULL, the token name is used.
1105 	 *
1106 	 * If buf is not NULL, entry index ent is written to buf and the
1107 	 * full length of the entry is returned (same behavior as
1108 	 * snprintf()).
1109 	 */
1110 	int (*comp)(struct context *ctx, const struct token *token,
1111 		    unsigned int ent, char *buf, unsigned int size);
1112 	/** Mandatory token name, no default value. */
1113 	const char *name;
1114 };
1115 
1116 /** Static initializer for the next field. */
1117 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
1118 
1119 /** Static initializer for a NEXT() entry. */
1120 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
1121 
1122 /** Static initializer for the args field. */
1123 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
1124 
1125 /** Static initializer for ARGS() to target a field. */
1126 #define ARGS_ENTRY(s, f) \
1127 	(&(const struct arg){ \
1128 		.offset = offsetof(s, f), \
1129 		.size = sizeof(((s *)0)->f), \
1130 	})
1131 
1132 /** Static initializer for ARGS() to target a bit-field. */
1133 #define ARGS_ENTRY_BF(s, f, b) \
1134 	(&(const struct arg){ \
1135 		.size = sizeof(s), \
1136 		.mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
1137 	})
1138 
1139 /** Static initializer for ARGS() to target a field with limits. */
1140 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
1141 	(&(const struct arg){ \
1142 		.bounded = 1, \
1143 		.min = (i), \
1144 		.max = (a), \
1145 		.offset = offsetof(s, f), \
1146 		.size = sizeof(((s *)0)->f), \
1147 	})
1148 
1149 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
1150 #define ARGS_ENTRY_MASK(s, f, m) \
1151 	(&(const struct arg){ \
1152 		.offset = offsetof(s, f), \
1153 		.size = sizeof(((s *)0)->f), \
1154 		.mask = (const void *)(m), \
1155 	})
1156 
1157 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
1158 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
1159 	(&(const struct arg){ \
1160 		.hton = 1, \
1161 		.offset = offsetof(s, f), \
1162 		.size = sizeof(((s *)0)->f), \
1163 		.mask = (const void *)(m), \
1164 	})
1165 
1166 /** Static initializer for ARGS() to target a pointer. */
1167 #define ARGS_ENTRY_PTR(s, f) \
1168 	(&(const struct arg){ \
1169 		.size = sizeof(*((s *)0)->f), \
1170 	})
1171 
1172 /** Static initializer for ARGS() with arbitrary offset and size. */
1173 #define ARGS_ENTRY_ARB(o, s) \
1174 	(&(const struct arg){ \
1175 		.offset = (o), \
1176 		.size = (s), \
1177 	})
1178 
1179 /** Same as ARGS_ENTRY_ARB() with bounded values. */
1180 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
1181 	(&(const struct arg){ \
1182 		.bounded = 1, \
1183 		.min = (i), \
1184 		.max = (a), \
1185 		.offset = (o), \
1186 		.size = (s), \
1187 	})
1188 
1189 /** Same as ARGS_ENTRY() using network byte ordering. */
1190 #define ARGS_ENTRY_HTON(s, f) \
1191 	(&(const struct arg){ \
1192 		.hton = 1, \
1193 		.offset = offsetof(s, f), \
1194 		.size = sizeof(((s *)0)->f), \
1195 	})
1196 
1197 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
1198 #define ARG_ENTRY_HTON(s) \
1199 	(&(const struct arg){ \
1200 		.hton = 1, \
1201 		.offset = 0, \
1202 		.size = sizeof(s), \
1203 	})
1204 
1205 /** Parser output buffer layout expected by cmd_flow_parsed(). */
1206 struct buffer {
1207 	enum index command; /**< Flow command. */
1208 	portid_t port; /**< Affected port ID. */
1209 	queueid_t queue; /** Async queue ID. */
1210 	bool postpone; /** Postpone async operation */
1211 	union {
1212 		struct {
1213 			struct rte_flow_port_attr port_attr;
1214 			uint32_t nb_queue;
1215 			struct rte_flow_queue_attr queue_attr;
1216 		} configure; /**< Configuration arguments. */
1217 		struct {
1218 			uint32_t *template_id;
1219 			uint32_t template_id_n;
1220 		} templ_destroy; /**< Template destroy arguments. */
1221 		struct {
1222 			uint32_t id;
1223 			struct rte_flow_template_table_attr attr;
1224 			uint32_t *pat_templ_id;
1225 			uint32_t pat_templ_id_n;
1226 			uint32_t *act_templ_id;
1227 			uint32_t act_templ_id_n;
1228 		} table; /**< Table arguments. */
1229 		struct {
1230 			uint32_t *table_id;
1231 			uint32_t table_id_n;
1232 		} table_destroy; /**< Template destroy arguments. */
1233 		struct {
1234 			uint32_t *action_id;
1235 			uint32_t action_id_n;
1236 		} ia_destroy; /**< Indirect action destroy arguments. */
1237 		struct {
1238 			uint32_t action_id;
1239 			enum rte_flow_query_update_mode qu_mode;
1240 		} ia; /* Indirect action query arguments */
1241 		struct {
1242 			uint32_t table_id;
1243 			uint32_t pat_templ_id;
1244 			uint32_t rule_id;
1245 			uint32_t act_templ_id;
1246 			struct rte_flow_attr attr;
1247 			struct tunnel_ops tunnel_ops;
1248 			uintptr_t user_id;
1249 			struct rte_flow_item *pattern;
1250 			struct rte_flow_action *actions;
1251 			struct rte_flow_action *masks;
1252 			uint32_t pattern_n;
1253 			uint32_t actions_n;
1254 			uint8_t *data;
1255 			enum rte_flow_encap_hash_field field;
1256 			uint8_t encap_hash;
1257 		} vc; /**< Validate/create arguments. */
1258 		struct {
1259 			uint64_t *rule;
1260 			uint64_t rule_n;
1261 			bool is_user_id;
1262 		} destroy; /**< Destroy arguments. */
1263 		struct {
1264 			char file[128];
1265 			bool mode;
1266 			uint64_t rule;
1267 			bool is_user_id;
1268 		} dump; /**< Dump arguments. */
1269 		struct {
1270 			uint64_t rule;
1271 			struct rte_flow_action action;
1272 			bool is_user_id;
1273 		} query; /**< Query arguments. */
1274 		struct {
1275 			uint32_t *group;
1276 			uint32_t group_n;
1277 		} list; /**< List arguments. */
1278 		struct {
1279 			int set;
1280 		} isolate; /**< Isolated mode arguments. */
1281 		struct {
1282 			int destroy;
1283 		} aged; /**< Aged arguments. */
1284 		struct {
1285 			uint32_t policy_id;
1286 		} policy;/**< Policy arguments. */
1287 		struct {
1288 			uint16_t token;
1289 			uintptr_t uintptr;
1290 			char filename[128];
1291 		} flex; /**< Flex arguments*/
1292 	} args; /**< Command arguments. */
1293 };
1294 
1295 /** Private data for pattern items. */
1296 struct parse_item_priv {
1297 	enum rte_flow_item_type type; /**< Item type. */
1298 	uint32_t size; /**< Size of item specification structure. */
1299 };
1300 
1301 #define PRIV_ITEM(t, s) \
1302 	(&(const struct parse_item_priv){ \
1303 		.type = RTE_FLOW_ITEM_TYPE_ ## t, \
1304 		.size = s, \
1305 	})
1306 
1307 /** Private data for actions. */
1308 struct parse_action_priv {
1309 	enum rte_flow_action_type type; /**< Action type. */
1310 	uint32_t size; /**< Size of action configuration structure. */
1311 };
1312 
1313 #define PRIV_ACTION(t, s) \
1314 	(&(const struct parse_action_priv){ \
1315 		.type = RTE_FLOW_ACTION_TYPE_ ## t, \
1316 		.size = s, \
1317 	})
1318 
1319 static const enum index next_flex_item[] = {
1320 	FLEX_ITEM_INIT,
1321 	FLEX_ITEM_CREATE,
1322 	FLEX_ITEM_DESTROY,
1323 	ZERO,
1324 };
1325 
1326 static const enum index next_config_attr[] = {
1327 	CONFIG_QUEUES_NUMBER,
1328 	CONFIG_QUEUES_SIZE,
1329 	CONFIG_COUNTERS_NUMBER,
1330 	CONFIG_AGING_OBJECTS_NUMBER,
1331 	CONFIG_METERS_NUMBER,
1332 	CONFIG_CONN_TRACK_NUMBER,
1333 	CONFIG_QUOTAS_NUMBER,
1334 	CONFIG_FLAGS,
1335 	CONFIG_HOST_PORT,
1336 	END,
1337 	ZERO,
1338 };
1339 
1340 static const enum index next_pt_subcmd[] = {
1341 	PATTERN_TEMPLATE_CREATE,
1342 	PATTERN_TEMPLATE_DESTROY,
1343 	ZERO,
1344 };
1345 
1346 static const enum index next_pt_attr[] = {
1347 	PATTERN_TEMPLATE_CREATE_ID,
1348 	PATTERN_TEMPLATE_RELAXED_MATCHING,
1349 	PATTERN_TEMPLATE_INGRESS,
1350 	PATTERN_TEMPLATE_EGRESS,
1351 	PATTERN_TEMPLATE_TRANSFER,
1352 	PATTERN_TEMPLATE_SPEC,
1353 	ZERO,
1354 };
1355 
1356 static const enum index next_pt_destroy_attr[] = {
1357 	PATTERN_TEMPLATE_DESTROY_ID,
1358 	END,
1359 	ZERO,
1360 };
1361 
1362 static const enum index next_at_subcmd[] = {
1363 	ACTIONS_TEMPLATE_CREATE,
1364 	ACTIONS_TEMPLATE_DESTROY,
1365 	ZERO,
1366 };
1367 
1368 static const enum index next_at_attr[] = {
1369 	ACTIONS_TEMPLATE_CREATE_ID,
1370 	ACTIONS_TEMPLATE_INGRESS,
1371 	ACTIONS_TEMPLATE_EGRESS,
1372 	ACTIONS_TEMPLATE_TRANSFER,
1373 	ACTIONS_TEMPLATE_SPEC,
1374 	ZERO,
1375 };
1376 
1377 static const enum index next_at_destroy_attr[] = {
1378 	ACTIONS_TEMPLATE_DESTROY_ID,
1379 	END,
1380 	ZERO,
1381 };
1382 
1383 static const enum index next_group_attr[] = {
1384 	GROUP_INGRESS,
1385 	GROUP_EGRESS,
1386 	GROUP_TRANSFER,
1387 	GROUP_SET_MISS_ACTIONS,
1388 	ZERO,
1389 };
1390 
1391 static const enum index next_table_subcmd[] = {
1392 	TABLE_CREATE,
1393 	TABLE_DESTROY,
1394 	TABLE_RESIZE,
1395 	TABLE_RESIZE_COMPLETE,
1396 	ZERO,
1397 };
1398 
1399 static const enum index next_table_attr[] = {
1400 	TABLE_CREATE_ID,
1401 	TABLE_GROUP,
1402 	TABLE_INSERTION_TYPE,
1403 	TABLE_HASH_FUNC,
1404 	TABLE_PRIORITY,
1405 	TABLE_INGRESS,
1406 	TABLE_EGRESS,
1407 	TABLE_TRANSFER,
1408 	TABLE_TRANSFER_WIRE_ORIG,
1409 	TABLE_TRANSFER_VPORT_ORIG,
1410 	TABLE_RESIZABLE,
1411 	TABLE_RULES_NUMBER,
1412 	TABLE_PATTERN_TEMPLATE,
1413 	TABLE_ACTIONS_TEMPLATE,
1414 	END,
1415 	ZERO,
1416 };
1417 
1418 static const enum index next_table_destroy_attr[] = {
1419 	TABLE_DESTROY_ID,
1420 	END,
1421 	ZERO,
1422 };
1423 
1424 static const enum index next_queue_subcmd[] = {
1425 	QUEUE_CREATE,
1426 	QUEUE_DESTROY,
1427 	QUEUE_FLOW_UPDATE_RESIZED,
1428 	QUEUE_UPDATE,
1429 	QUEUE_AGED,
1430 	QUEUE_INDIRECT_ACTION,
1431 	ZERO,
1432 };
1433 
1434 static const enum index next_queue_destroy_attr[] = {
1435 	QUEUE_DESTROY_ID,
1436 	END,
1437 	ZERO,
1438 };
1439 
1440 static const enum index next_qia_subcmd[] = {
1441 	QUEUE_INDIRECT_ACTION_CREATE,
1442 	QUEUE_INDIRECT_ACTION_UPDATE,
1443 	QUEUE_INDIRECT_ACTION_DESTROY,
1444 	QUEUE_INDIRECT_ACTION_QUERY,
1445 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
1446 	ZERO,
1447 };
1448 
1449 static const enum index next_qia_create_attr[] = {
1450 	QUEUE_INDIRECT_ACTION_CREATE_ID,
1451 	QUEUE_INDIRECT_ACTION_INGRESS,
1452 	QUEUE_INDIRECT_ACTION_EGRESS,
1453 	QUEUE_INDIRECT_ACTION_TRANSFER,
1454 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
1455 	QUEUE_INDIRECT_ACTION_SPEC,
1456 	QUEUE_INDIRECT_ACTION_LIST,
1457 	ZERO,
1458 };
1459 
1460 static const enum index next_qia_update_attr[] = {
1461 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1462 	QUEUE_INDIRECT_ACTION_SPEC,
1463 	ZERO,
1464 };
1465 
1466 static const enum index next_qia_destroy_attr[] = {
1467 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
1468 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
1469 	END,
1470 	ZERO,
1471 };
1472 
1473 static const enum index next_qia_query_attr[] = {
1474 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
1475 	END,
1476 	ZERO,
1477 };
1478 
1479 static const enum index next_ia_create_attr[] = {
1480 	INDIRECT_ACTION_CREATE_ID,
1481 	INDIRECT_ACTION_INGRESS,
1482 	INDIRECT_ACTION_EGRESS,
1483 	INDIRECT_ACTION_TRANSFER,
1484 	INDIRECT_ACTION_SPEC,
1485 	INDIRECT_ACTION_LIST,
1486 	INDIRECT_ACTION_FLOW_CONF,
1487 	ZERO,
1488 };
1489 
1490 static const enum index next_ia[] = {
1491 	INDIRECT_ACTION_ID2PTR,
1492 	ACTION_NEXT,
1493 	ZERO
1494 };
1495 
1496 static const enum index next_ial[] = {
1497 	ACTION_INDIRECT_LIST_HANDLE,
1498 	ACTION_INDIRECT_LIST_CONF,
1499 	ACTION_NEXT,
1500 	ZERO
1501 };
1502 
1503 static const enum index next_qia_qu_attr[] = {
1504 	QUEUE_INDIRECT_ACTION_QU_MODE,
1505 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1506 	INDIRECT_ACTION_SPEC,
1507 	ZERO
1508 };
1509 
1510 static const enum index next_ia_qu_attr[] = {
1511 	INDIRECT_ACTION_QU_MODE,
1512 	INDIRECT_ACTION_SPEC,
1513 	ZERO
1514 };
1515 
1516 static const enum index next_dump_subcmd[] = {
1517 	DUMP_ALL,
1518 	DUMP_ONE,
1519 	DUMP_IS_USER_ID,
1520 	ZERO,
1521 };
1522 
1523 static const enum index next_ia_subcmd[] = {
1524 	INDIRECT_ACTION_CREATE,
1525 	INDIRECT_ACTION_UPDATE,
1526 	INDIRECT_ACTION_DESTROY,
1527 	INDIRECT_ACTION_QUERY,
1528 	INDIRECT_ACTION_QUERY_UPDATE,
1529 	ZERO,
1530 };
1531 
1532 static const enum index next_vc_attr[] = {
1533 	VC_GROUP,
1534 	VC_PRIORITY,
1535 	VC_INGRESS,
1536 	VC_EGRESS,
1537 	VC_TRANSFER,
1538 	VC_TUNNEL_SET,
1539 	VC_TUNNEL_MATCH,
1540 	VC_USER_ID,
1541 	ITEM_PATTERN,
1542 	ZERO,
1543 };
1544 
1545 static const enum index next_destroy_attr[] = {
1546 	DESTROY_RULE,
1547 	DESTROY_IS_USER_ID,
1548 	END,
1549 	ZERO,
1550 };
1551 
1552 static const enum index next_dump_attr[] = {
1553 	COMMON_FILE_PATH,
1554 	END,
1555 	ZERO,
1556 };
1557 
1558 static const enum index next_query_attr[] = {
1559 	QUERY_IS_USER_ID,
1560 	END,
1561 	ZERO,
1562 };
1563 
1564 static const enum index next_list_attr[] = {
1565 	LIST_GROUP,
1566 	END,
1567 	ZERO,
1568 };
1569 
1570 static const enum index next_aged_attr[] = {
1571 	AGED_DESTROY,
1572 	END,
1573 	ZERO,
1574 };
1575 
1576 static const enum index next_ia_destroy_attr[] = {
1577 	INDIRECT_ACTION_DESTROY_ID,
1578 	END,
1579 	ZERO,
1580 };
1581 
1582 static const enum index next_async_insert_subcmd[] = {
1583 	QUEUE_PATTERN_TEMPLATE,
1584 	QUEUE_RULE_ID,
1585 	ZERO,
1586 };
1587 
1588 static const enum index item_param[] = {
1589 	ITEM_PARAM_IS,
1590 	ITEM_PARAM_SPEC,
1591 	ITEM_PARAM_LAST,
1592 	ITEM_PARAM_MASK,
1593 	ITEM_PARAM_PREFIX,
1594 	ZERO,
1595 };
1596 
1597 static const enum index next_item[] = {
1598 	ITEM_END,
1599 	ITEM_VOID,
1600 	ITEM_INVERT,
1601 	ITEM_ANY,
1602 	ITEM_PORT_ID,
1603 	ITEM_MARK,
1604 	ITEM_RAW,
1605 	ITEM_ETH,
1606 	ITEM_VLAN,
1607 	ITEM_IPV4,
1608 	ITEM_IPV6,
1609 	ITEM_ICMP,
1610 	ITEM_UDP,
1611 	ITEM_TCP,
1612 	ITEM_SCTP,
1613 	ITEM_VXLAN,
1614 	ITEM_E_TAG,
1615 	ITEM_NVGRE,
1616 	ITEM_MPLS,
1617 	ITEM_GRE,
1618 	ITEM_FUZZY,
1619 	ITEM_GTP,
1620 	ITEM_GTPC,
1621 	ITEM_GTPU,
1622 	ITEM_GENEVE,
1623 	ITEM_VXLAN_GPE,
1624 	ITEM_ARP_ETH_IPV4,
1625 	ITEM_IPV6_EXT,
1626 	ITEM_IPV6_FRAG_EXT,
1627 	ITEM_IPV6_ROUTING_EXT,
1628 	ITEM_ICMP6,
1629 	ITEM_ICMP6_ECHO_REQUEST,
1630 	ITEM_ICMP6_ECHO_REPLY,
1631 	ITEM_ICMP6_ND_NS,
1632 	ITEM_ICMP6_ND_NA,
1633 	ITEM_ICMP6_ND_OPT,
1634 	ITEM_ICMP6_ND_OPT_SLA_ETH,
1635 	ITEM_ICMP6_ND_OPT_TLA_ETH,
1636 	ITEM_META,
1637 	ITEM_RANDOM,
1638 	ITEM_GRE_KEY,
1639 	ITEM_GRE_OPTION,
1640 	ITEM_GTP_PSC,
1641 	ITEM_PPPOES,
1642 	ITEM_PPPOED,
1643 	ITEM_PPPOE_PROTO_ID,
1644 	ITEM_HIGIG2,
1645 	ITEM_TAG,
1646 	ITEM_L2TPV3OIP,
1647 	ITEM_ESP,
1648 	ITEM_AH,
1649 	ITEM_PFCP,
1650 	ITEM_ECPRI,
1651 	ITEM_GENEVE_OPT,
1652 	ITEM_INTEGRITY,
1653 	ITEM_CONNTRACK,
1654 	ITEM_PORT_REPRESENTOR,
1655 	ITEM_REPRESENTED_PORT,
1656 	ITEM_FLEX,
1657 	ITEM_L2TPV2,
1658 	ITEM_PPP,
1659 	ITEM_METER,
1660 	ITEM_QUOTA,
1661 	ITEM_AGGR_AFFINITY,
1662 	ITEM_TX_QUEUE,
1663 	ITEM_IB_BTH,
1664 	ITEM_PTYPE,
1665 	ITEM_NSH,
1666 	ITEM_COMPARE,
1667 	END_SET,
1668 	ZERO,
1669 };
1670 
1671 static const enum index item_fuzzy[] = {
1672 	ITEM_FUZZY_THRESH,
1673 	ITEM_NEXT,
1674 	ZERO,
1675 };
1676 
1677 static const enum index item_any[] = {
1678 	ITEM_ANY_NUM,
1679 	ITEM_NEXT,
1680 	ZERO,
1681 };
1682 
1683 static const enum index item_port_id[] = {
1684 	ITEM_PORT_ID_ID,
1685 	ITEM_NEXT,
1686 	ZERO,
1687 };
1688 
1689 static const enum index item_mark[] = {
1690 	ITEM_MARK_ID,
1691 	ITEM_NEXT,
1692 	ZERO,
1693 };
1694 
1695 static const enum index item_raw[] = {
1696 	ITEM_RAW_RELATIVE,
1697 	ITEM_RAW_SEARCH,
1698 	ITEM_RAW_OFFSET,
1699 	ITEM_RAW_LIMIT,
1700 	ITEM_RAW_PATTERN,
1701 	ITEM_RAW_PATTERN_HEX,
1702 	ITEM_NEXT,
1703 	ZERO,
1704 };
1705 
1706 static const enum index item_eth[] = {
1707 	ITEM_ETH_DST,
1708 	ITEM_ETH_SRC,
1709 	ITEM_ETH_TYPE,
1710 	ITEM_ETH_HAS_VLAN,
1711 	ITEM_NEXT,
1712 	ZERO,
1713 };
1714 
1715 static const enum index item_vlan[] = {
1716 	ITEM_VLAN_TCI,
1717 	ITEM_VLAN_PCP,
1718 	ITEM_VLAN_DEI,
1719 	ITEM_VLAN_VID,
1720 	ITEM_VLAN_INNER_TYPE,
1721 	ITEM_VLAN_HAS_MORE_VLAN,
1722 	ITEM_NEXT,
1723 	ZERO,
1724 };
1725 
1726 static const enum index item_ipv4[] = {
1727 	ITEM_IPV4_VER_IHL,
1728 	ITEM_IPV4_TOS,
1729 	ITEM_IPV4_LENGTH,
1730 	ITEM_IPV4_ID,
1731 	ITEM_IPV4_FRAGMENT_OFFSET,
1732 	ITEM_IPV4_TTL,
1733 	ITEM_IPV4_PROTO,
1734 	ITEM_IPV4_SRC,
1735 	ITEM_IPV4_DST,
1736 	ITEM_NEXT,
1737 	ZERO,
1738 };
1739 
1740 static const enum index item_ipv6[] = {
1741 	ITEM_IPV6_TC,
1742 	ITEM_IPV6_FLOW,
1743 	ITEM_IPV6_LEN,
1744 	ITEM_IPV6_PROTO,
1745 	ITEM_IPV6_HOP,
1746 	ITEM_IPV6_SRC,
1747 	ITEM_IPV6_DST,
1748 	ITEM_IPV6_HAS_FRAG_EXT,
1749 	ITEM_IPV6_ROUTING_EXT,
1750 	ITEM_NEXT,
1751 	ZERO,
1752 };
1753 
1754 static const enum index item_ipv6_routing_ext[] = {
1755 	ITEM_IPV6_ROUTING_EXT_TYPE,
1756 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
1757 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
1758 	ITEM_NEXT,
1759 	ZERO,
1760 };
1761 
1762 static const enum index item_icmp[] = {
1763 	ITEM_ICMP_TYPE,
1764 	ITEM_ICMP_CODE,
1765 	ITEM_ICMP_IDENT,
1766 	ITEM_ICMP_SEQ,
1767 	ITEM_NEXT,
1768 	ZERO,
1769 };
1770 
1771 static const enum index item_udp[] = {
1772 	ITEM_UDP_SRC,
1773 	ITEM_UDP_DST,
1774 	ITEM_NEXT,
1775 	ZERO,
1776 };
1777 
1778 static const enum index item_tcp[] = {
1779 	ITEM_TCP_SRC,
1780 	ITEM_TCP_DST,
1781 	ITEM_TCP_FLAGS,
1782 	ITEM_NEXT,
1783 	ZERO,
1784 };
1785 
1786 static const enum index item_sctp[] = {
1787 	ITEM_SCTP_SRC,
1788 	ITEM_SCTP_DST,
1789 	ITEM_SCTP_TAG,
1790 	ITEM_SCTP_CKSUM,
1791 	ITEM_NEXT,
1792 	ZERO,
1793 };
1794 
1795 static const enum index item_vxlan[] = {
1796 	ITEM_VXLAN_VNI,
1797 	ITEM_VXLAN_FLAG_G,
1798 	ITEM_VXLAN_FLAG_VER,
1799 	ITEM_VXLAN_FLAG_I,
1800 	ITEM_VXLAN_FLAG_P,
1801 	ITEM_VXLAN_FLAG_B,
1802 	ITEM_VXLAN_FLAG_O,
1803 	ITEM_VXLAN_FLAG_D,
1804 	ITEM_VXLAN_FLAG_A,
1805 	ITEM_VXLAN_GBP_ID,
1806 	ITEM_VXLAN_GPE_PROTO,
1807 	ITEM_VXLAN_FIRST_RSVD,
1808 	ITEM_VXLAN_SECND_RSVD,
1809 	ITEM_VXLAN_THIRD_RSVD,
1810 	ITEM_VXLAN_LAST_RSVD,
1811 	ITEM_NEXT,
1812 	ZERO,
1813 };
1814 
1815 static const enum index item_e_tag[] = {
1816 	ITEM_E_TAG_GRP_ECID_B,
1817 	ITEM_NEXT,
1818 	ZERO,
1819 };
1820 
1821 static const enum index item_nvgre[] = {
1822 	ITEM_NVGRE_TNI,
1823 	ITEM_NEXT,
1824 	ZERO,
1825 };
1826 
1827 static const enum index item_mpls[] = {
1828 	ITEM_MPLS_LABEL,
1829 	ITEM_MPLS_TC,
1830 	ITEM_MPLS_S,
1831 	ITEM_MPLS_TTL,
1832 	ITEM_NEXT,
1833 	ZERO,
1834 };
1835 
1836 static const enum index item_gre[] = {
1837 	ITEM_GRE_PROTO,
1838 	ITEM_GRE_C_RSVD0_VER,
1839 	ITEM_GRE_C_BIT,
1840 	ITEM_GRE_K_BIT,
1841 	ITEM_GRE_S_BIT,
1842 	ITEM_NEXT,
1843 	ZERO,
1844 };
1845 
1846 static const enum index item_gre_key[] = {
1847 	ITEM_GRE_KEY_VALUE,
1848 	ITEM_NEXT,
1849 	ZERO,
1850 };
1851 
1852 static const enum index item_gre_option[] = {
1853 	ITEM_GRE_OPTION_CHECKSUM,
1854 	ITEM_GRE_OPTION_KEY,
1855 	ITEM_GRE_OPTION_SEQUENCE,
1856 	ITEM_NEXT,
1857 	ZERO,
1858 };
1859 
1860 static const enum index item_gtp[] = {
1861 	ITEM_GTP_FLAGS,
1862 	ITEM_GTP_MSG_TYPE,
1863 	ITEM_GTP_TEID,
1864 	ITEM_NEXT,
1865 	ZERO,
1866 };
1867 
1868 static const enum index item_geneve[] = {
1869 	ITEM_GENEVE_VNI,
1870 	ITEM_GENEVE_PROTO,
1871 	ITEM_GENEVE_OPTLEN,
1872 	ITEM_NEXT,
1873 	ZERO,
1874 };
1875 
1876 static const enum index item_vxlan_gpe[] = {
1877 	ITEM_VXLAN_GPE_VNI,
1878 	ITEM_VXLAN_GPE_PROTO_IN_DEPRECATED_VXLAN_GPE_HDR,
1879 	ITEM_VXLAN_GPE_FLAGS,
1880 	ITEM_VXLAN_GPE_RSVD0,
1881 	ITEM_VXLAN_GPE_RSVD1,
1882 	ITEM_NEXT,
1883 	ZERO,
1884 };
1885 
1886 static const enum index item_arp_eth_ipv4[] = {
1887 	ITEM_ARP_ETH_IPV4_SHA,
1888 	ITEM_ARP_ETH_IPV4_SPA,
1889 	ITEM_ARP_ETH_IPV4_THA,
1890 	ITEM_ARP_ETH_IPV4_TPA,
1891 	ITEM_NEXT,
1892 	ZERO,
1893 };
1894 
1895 static const enum index item_ipv6_ext[] = {
1896 	ITEM_IPV6_EXT_NEXT_HDR,
1897 	ITEM_NEXT,
1898 	ZERO,
1899 };
1900 
1901 static const enum index item_ipv6_frag_ext[] = {
1902 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1903 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1904 	ITEM_IPV6_FRAG_EXT_ID,
1905 	ITEM_NEXT,
1906 	ZERO,
1907 };
1908 
1909 static const enum index item_icmp6[] = {
1910 	ITEM_ICMP6_TYPE,
1911 	ITEM_ICMP6_CODE,
1912 	ITEM_NEXT,
1913 	ZERO,
1914 };
1915 
1916 static const enum index item_icmp6_echo_request[] = {
1917 	ITEM_ICMP6_ECHO_REQUEST_ID,
1918 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
1919 	ITEM_NEXT,
1920 	ZERO,
1921 };
1922 
1923 static const enum index item_icmp6_echo_reply[] = {
1924 	ITEM_ICMP6_ECHO_REPLY_ID,
1925 	ITEM_ICMP6_ECHO_REPLY_SEQ,
1926 	ITEM_NEXT,
1927 	ZERO,
1928 };
1929 
1930 static const enum index item_icmp6_nd_ns[] = {
1931 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
1932 	ITEM_NEXT,
1933 	ZERO,
1934 };
1935 
1936 static const enum index item_icmp6_nd_na[] = {
1937 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
1938 	ITEM_NEXT,
1939 	ZERO,
1940 };
1941 
1942 static const enum index item_icmp6_nd_opt[] = {
1943 	ITEM_ICMP6_ND_OPT_TYPE,
1944 	ITEM_NEXT,
1945 	ZERO,
1946 };
1947 
1948 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1949 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1950 	ITEM_NEXT,
1951 	ZERO,
1952 };
1953 
1954 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1955 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1956 	ITEM_NEXT,
1957 	ZERO,
1958 };
1959 
1960 static const enum index item_meta[] = {
1961 	ITEM_META_DATA,
1962 	ITEM_NEXT,
1963 	ZERO,
1964 };
1965 
1966 static const enum index item_random[] = {
1967 	ITEM_RANDOM_VALUE,
1968 	ITEM_NEXT,
1969 	ZERO,
1970 };
1971 
1972 static const enum index item_gtp_psc[] = {
1973 	ITEM_GTP_PSC_QFI,
1974 	ITEM_GTP_PSC_PDU_T,
1975 	ITEM_NEXT,
1976 	ZERO,
1977 };
1978 
1979 static const enum index item_pppoed[] = {
1980 	ITEM_PPPOE_SEID,
1981 	ITEM_NEXT,
1982 	ZERO,
1983 };
1984 
1985 static const enum index item_pppoes[] = {
1986 	ITEM_PPPOE_SEID,
1987 	ITEM_NEXT,
1988 	ZERO,
1989 };
1990 
1991 static const enum index item_pppoe_proto_id[] = {
1992 	ITEM_NEXT,
1993 	ZERO,
1994 };
1995 
1996 static const enum index item_higig2[] = {
1997 	ITEM_HIGIG2_CLASSIFICATION,
1998 	ITEM_HIGIG2_VID,
1999 	ITEM_NEXT,
2000 	ZERO,
2001 };
2002 
2003 static const enum index item_esp[] = {
2004 	ITEM_ESP_SPI,
2005 	ITEM_NEXT,
2006 	ZERO,
2007 };
2008 
2009 static const enum index item_ah[] = {
2010 	ITEM_AH_SPI,
2011 	ITEM_NEXT,
2012 	ZERO,
2013 };
2014 
2015 static const enum index item_pfcp[] = {
2016 	ITEM_PFCP_S_FIELD,
2017 	ITEM_PFCP_SEID,
2018 	ITEM_NEXT,
2019 	ZERO,
2020 };
2021 
2022 static const enum index next_set_raw[] = {
2023 	SET_RAW_INDEX,
2024 	ITEM_ETH,
2025 	ZERO,
2026 };
2027 
2028 static const enum index item_tag[] = {
2029 	ITEM_TAG_DATA,
2030 	ITEM_TAG_INDEX,
2031 	ITEM_NEXT,
2032 	ZERO,
2033 };
2034 
2035 static const enum index item_l2tpv3oip[] = {
2036 	ITEM_L2TPV3OIP_SESSION_ID,
2037 	ITEM_NEXT,
2038 	ZERO,
2039 };
2040 
2041 static const enum index item_ecpri[] = {
2042 	ITEM_ECPRI_COMMON,
2043 	ITEM_NEXT,
2044 	ZERO,
2045 };
2046 
2047 static const enum index item_ecpri_common[] = {
2048 	ITEM_ECPRI_COMMON_TYPE,
2049 	ZERO,
2050 };
2051 
2052 static const enum index item_ecpri_common_type[] = {
2053 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
2054 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
2055 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
2056 	ZERO,
2057 };
2058 
2059 static const enum index item_geneve_opt[] = {
2060 	ITEM_GENEVE_OPT_CLASS,
2061 	ITEM_GENEVE_OPT_TYPE,
2062 	ITEM_GENEVE_OPT_LENGTH,
2063 	ITEM_GENEVE_OPT_DATA,
2064 	ITEM_NEXT,
2065 	ZERO,
2066 };
2067 
2068 static const enum index item_integrity[] = {
2069 	ITEM_INTEGRITY_LEVEL,
2070 	ITEM_INTEGRITY_VALUE,
2071 	ZERO,
2072 };
2073 
2074 static const enum index item_integrity_lv[] = {
2075 	ITEM_INTEGRITY_LEVEL,
2076 	ITEM_INTEGRITY_VALUE,
2077 	ITEM_NEXT,
2078 	ZERO,
2079 };
2080 
2081 static const enum index item_port_representor[] = {
2082 	ITEM_PORT_REPRESENTOR_PORT_ID,
2083 	ITEM_NEXT,
2084 	ZERO,
2085 };
2086 
2087 static const enum index item_represented_port[] = {
2088 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
2089 	ITEM_NEXT,
2090 	ZERO,
2091 };
2092 
2093 static const enum index item_flex[] = {
2094 	ITEM_FLEX_PATTERN_HANDLE,
2095 	ITEM_FLEX_ITEM_HANDLE,
2096 	ITEM_NEXT,
2097 	ZERO,
2098 };
2099 
2100 static const enum index item_l2tpv2[] = {
2101 	ITEM_L2TPV2_TYPE,
2102 	ITEM_NEXT,
2103 	ZERO,
2104 };
2105 
2106 static const enum index item_l2tpv2_type[] = {
2107 	ITEM_L2TPV2_TYPE_DATA,
2108 	ITEM_L2TPV2_TYPE_DATA_L,
2109 	ITEM_L2TPV2_TYPE_DATA_S,
2110 	ITEM_L2TPV2_TYPE_DATA_O,
2111 	ITEM_L2TPV2_TYPE_DATA_L_S,
2112 	ITEM_L2TPV2_TYPE_CTRL,
2113 	ZERO,
2114 };
2115 
2116 static const enum index item_l2tpv2_type_data[] = {
2117 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
2118 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
2119 	ITEM_NEXT,
2120 	ZERO,
2121 };
2122 
2123 static const enum index item_l2tpv2_type_data_l[] = {
2124 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
2125 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
2126 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
2127 	ITEM_NEXT,
2128 	ZERO,
2129 };
2130 
2131 static const enum index item_l2tpv2_type_data_s[] = {
2132 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
2133 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
2134 	ITEM_L2TPV2_MSG_DATA_S_NS,
2135 	ITEM_L2TPV2_MSG_DATA_S_NR,
2136 	ITEM_NEXT,
2137 	ZERO,
2138 };
2139 
2140 static const enum index item_l2tpv2_type_data_o[] = {
2141 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
2142 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
2143 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
2144 	ITEM_NEXT,
2145 	ZERO,
2146 };
2147 
2148 static const enum index item_l2tpv2_type_data_l_s[] = {
2149 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
2150 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
2151 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
2152 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
2153 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
2154 	ITEM_NEXT,
2155 	ZERO,
2156 };
2157 
2158 static const enum index item_l2tpv2_type_ctrl[] = {
2159 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
2160 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
2161 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
2162 	ITEM_L2TPV2_MSG_CTRL_NS,
2163 	ITEM_L2TPV2_MSG_CTRL_NR,
2164 	ITEM_NEXT,
2165 	ZERO,
2166 };
2167 
2168 static const enum index item_ppp[] = {
2169 	ITEM_PPP_ADDR,
2170 	ITEM_PPP_CTRL,
2171 	ITEM_PPP_PROTO_ID,
2172 	ITEM_NEXT,
2173 	ZERO,
2174 };
2175 
2176 static const enum index item_meter[] = {
2177 	ITEM_METER_COLOR,
2178 	ITEM_NEXT,
2179 	ZERO,
2180 };
2181 
2182 static const enum index item_quota[] = {
2183 	ITEM_QUOTA_STATE,
2184 	ITEM_NEXT,
2185 	ZERO,
2186 };
2187 
2188 static const enum index item_aggr_affinity[] = {
2189 	ITEM_AGGR_AFFINITY_VALUE,
2190 	ITEM_NEXT,
2191 	ZERO,
2192 };
2193 
2194 static const enum index item_tx_queue[] = {
2195 	ITEM_TX_QUEUE_VALUE,
2196 	ITEM_NEXT,
2197 	ZERO,
2198 };
2199 
2200 static const enum index item_ib_bth[] = {
2201 	ITEM_IB_BTH_OPCODE,
2202 	ITEM_IB_BTH_PKEY,
2203 	ITEM_IB_BTH_DST_QPN,
2204 	ITEM_IB_BTH_PSN,
2205 	ITEM_NEXT,
2206 	ZERO,
2207 };
2208 
2209 static const enum index item_ptype[] = {
2210 	ITEM_PTYPE_VALUE,
2211 	ITEM_NEXT,
2212 	ZERO,
2213 };
2214 
2215 static const enum index item_nsh[] = {
2216 	ITEM_NEXT,
2217 	ZERO,
2218 };
2219 
2220 static const enum index item_compare_field[] = {
2221 	ITEM_COMPARE_OP,
2222 	ITEM_COMPARE_FIELD_A_TYPE,
2223 	ITEM_COMPARE_FIELD_B_TYPE,
2224 	ITEM_NEXT,
2225 	ZERO,
2226 };
2227 
2228 static const enum index compare_field_a[] = {
2229 	ITEM_COMPARE_FIELD_A_TYPE,
2230 	ITEM_COMPARE_FIELD_A_LEVEL,
2231 	ITEM_COMPARE_FIELD_A_TAG_INDEX,
2232 	ITEM_COMPARE_FIELD_A_TYPE_ID,
2233 	ITEM_COMPARE_FIELD_A_CLASS_ID,
2234 	ITEM_COMPARE_FIELD_A_OFFSET,
2235 	ITEM_COMPARE_FIELD_B_TYPE,
2236 	ZERO,
2237 };
2238 
2239 static const enum index compare_field_b[] = {
2240 	ITEM_COMPARE_FIELD_B_TYPE,
2241 	ITEM_COMPARE_FIELD_B_LEVEL,
2242 	ITEM_COMPARE_FIELD_B_TAG_INDEX,
2243 	ITEM_COMPARE_FIELD_B_TYPE_ID,
2244 	ITEM_COMPARE_FIELD_B_CLASS_ID,
2245 	ITEM_COMPARE_FIELD_B_OFFSET,
2246 	ITEM_COMPARE_FIELD_B_VALUE,
2247 	ITEM_COMPARE_FIELD_B_POINTER,
2248 	ITEM_COMPARE_FIELD_WIDTH,
2249 	ZERO,
2250 };
2251 
2252 static const enum index next_action[] = {
2253 	ACTION_END,
2254 	ACTION_VOID,
2255 	ACTION_PASSTHRU,
2256 	ACTION_SKIP_CMAN,
2257 	ACTION_JUMP,
2258 	ACTION_MARK,
2259 	ACTION_FLAG,
2260 	ACTION_QUEUE,
2261 	ACTION_DROP,
2262 	ACTION_COUNT,
2263 	ACTION_RSS,
2264 	ACTION_PF,
2265 	ACTION_VF,
2266 	ACTION_PORT_ID,
2267 	ACTION_METER,
2268 	ACTION_METER_COLOR,
2269 	ACTION_METER_MARK,
2270 	ACTION_OF_DEC_NW_TTL,
2271 	ACTION_OF_POP_VLAN,
2272 	ACTION_OF_PUSH_VLAN,
2273 	ACTION_OF_SET_VLAN_VID,
2274 	ACTION_OF_SET_VLAN_PCP,
2275 	ACTION_OF_POP_MPLS,
2276 	ACTION_OF_PUSH_MPLS,
2277 	ACTION_VXLAN_ENCAP,
2278 	ACTION_VXLAN_DECAP,
2279 	ACTION_NVGRE_ENCAP,
2280 	ACTION_NVGRE_DECAP,
2281 	ACTION_L2_ENCAP,
2282 	ACTION_L2_DECAP,
2283 	ACTION_MPLSOGRE_ENCAP,
2284 	ACTION_MPLSOGRE_DECAP,
2285 	ACTION_MPLSOUDP_ENCAP,
2286 	ACTION_MPLSOUDP_DECAP,
2287 	ACTION_SET_IPV4_SRC,
2288 	ACTION_SET_IPV4_DST,
2289 	ACTION_SET_IPV6_SRC,
2290 	ACTION_SET_IPV6_DST,
2291 	ACTION_SET_TP_SRC,
2292 	ACTION_SET_TP_DST,
2293 	ACTION_MAC_SWAP,
2294 	ACTION_DEC_TTL,
2295 	ACTION_SET_TTL,
2296 	ACTION_SET_MAC_SRC,
2297 	ACTION_SET_MAC_DST,
2298 	ACTION_INC_TCP_SEQ,
2299 	ACTION_DEC_TCP_SEQ,
2300 	ACTION_INC_TCP_ACK,
2301 	ACTION_DEC_TCP_ACK,
2302 	ACTION_RAW_ENCAP,
2303 	ACTION_RAW_DECAP,
2304 	ACTION_SET_TAG,
2305 	ACTION_SET_META,
2306 	ACTION_SET_IPV4_DSCP,
2307 	ACTION_SET_IPV6_DSCP,
2308 	ACTION_AGE,
2309 	ACTION_AGE_UPDATE,
2310 	ACTION_SAMPLE,
2311 	ACTION_INDIRECT,
2312 	ACTION_INDIRECT_LIST,
2313 	ACTION_SHARED_INDIRECT,
2314 	ACTION_MODIFY_FIELD,
2315 	ACTION_CONNTRACK,
2316 	ACTION_CONNTRACK_UPDATE,
2317 	ACTION_PORT_REPRESENTOR,
2318 	ACTION_REPRESENTED_PORT,
2319 	ACTION_SEND_TO_KERNEL,
2320 	ACTION_QUOTA_CREATE,
2321 	ACTION_QUOTA_QU,
2322 	ACTION_IPV6_EXT_REMOVE,
2323 	ACTION_IPV6_EXT_PUSH,
2324 	ACTION_NAT64,
2325 	ZERO,
2326 };
2327 
2328 static const enum index action_quota_create[] = {
2329 	ACTION_QUOTA_CREATE_LIMIT,
2330 	ACTION_QUOTA_CREATE_MODE,
2331 	ACTION_NEXT,
2332 	ZERO
2333 };
2334 
2335 static const enum index action_quota_update[] = {
2336 	ACTION_QUOTA_QU_LIMIT,
2337 	ACTION_QUOTA_QU_UPDATE_OP,
2338 	ACTION_NEXT,
2339 	ZERO
2340 };
2341 
2342 static const enum index action_mark[] = {
2343 	ACTION_MARK_ID,
2344 	ACTION_NEXT,
2345 	ZERO,
2346 };
2347 
2348 static const enum index action_queue[] = {
2349 	ACTION_QUEUE_INDEX,
2350 	ACTION_NEXT,
2351 	ZERO,
2352 };
2353 
2354 static const enum index action_count[] = {
2355 	ACTION_COUNT_ID,
2356 	ACTION_NEXT,
2357 	ZERO,
2358 };
2359 
2360 static const enum index action_rss[] = {
2361 	ACTION_RSS_FUNC,
2362 	ACTION_RSS_LEVEL,
2363 	ACTION_RSS_TYPES,
2364 	ACTION_RSS_KEY,
2365 	ACTION_RSS_KEY_LEN,
2366 	ACTION_RSS_QUEUES,
2367 	ACTION_NEXT,
2368 	ZERO,
2369 };
2370 
2371 static const enum index action_vf[] = {
2372 	ACTION_VF_ORIGINAL,
2373 	ACTION_VF_ID,
2374 	ACTION_NEXT,
2375 	ZERO,
2376 };
2377 
2378 static const enum index action_port_id[] = {
2379 	ACTION_PORT_ID_ORIGINAL,
2380 	ACTION_PORT_ID_ID,
2381 	ACTION_NEXT,
2382 	ZERO,
2383 };
2384 
2385 static const enum index action_meter[] = {
2386 	ACTION_METER_ID,
2387 	ACTION_NEXT,
2388 	ZERO,
2389 };
2390 
2391 static const enum index action_meter_color[] = {
2392 	ACTION_METER_COLOR_TYPE,
2393 	ACTION_NEXT,
2394 	ZERO,
2395 };
2396 
2397 static const enum index action_meter_mark[] = {
2398 	ACTION_METER_PROFILE,
2399 	ACTION_METER_POLICY,
2400 	ACTION_METER_COLOR_MODE,
2401 	ACTION_METER_STATE,
2402 	ACTION_NEXT,
2403 	ZERO,
2404 };
2405 
2406 static const enum index action_of_push_vlan[] = {
2407 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
2408 	ACTION_NEXT,
2409 	ZERO,
2410 };
2411 
2412 static const enum index action_of_set_vlan_vid[] = {
2413 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
2414 	ACTION_NEXT,
2415 	ZERO,
2416 };
2417 
2418 static const enum index action_of_set_vlan_pcp[] = {
2419 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
2420 	ACTION_NEXT,
2421 	ZERO,
2422 };
2423 
2424 static const enum index action_of_pop_mpls[] = {
2425 	ACTION_OF_POP_MPLS_ETHERTYPE,
2426 	ACTION_NEXT,
2427 	ZERO,
2428 };
2429 
2430 static const enum index action_of_push_mpls[] = {
2431 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
2432 	ACTION_NEXT,
2433 	ZERO,
2434 };
2435 
2436 static const enum index action_set_ipv4_src[] = {
2437 	ACTION_SET_IPV4_SRC_IPV4_SRC,
2438 	ACTION_NEXT,
2439 	ZERO,
2440 };
2441 
2442 static const enum index action_set_mac_src[] = {
2443 	ACTION_SET_MAC_SRC_MAC_SRC,
2444 	ACTION_NEXT,
2445 	ZERO,
2446 };
2447 
2448 static const enum index action_set_ipv4_dst[] = {
2449 	ACTION_SET_IPV4_DST_IPV4_DST,
2450 	ACTION_NEXT,
2451 	ZERO,
2452 };
2453 
2454 static const enum index action_set_ipv6_src[] = {
2455 	ACTION_SET_IPV6_SRC_IPV6_SRC,
2456 	ACTION_NEXT,
2457 	ZERO,
2458 };
2459 
2460 static const enum index action_set_ipv6_dst[] = {
2461 	ACTION_SET_IPV6_DST_IPV6_DST,
2462 	ACTION_NEXT,
2463 	ZERO,
2464 };
2465 
2466 static const enum index action_set_tp_src[] = {
2467 	ACTION_SET_TP_SRC_TP_SRC,
2468 	ACTION_NEXT,
2469 	ZERO,
2470 };
2471 
2472 static const enum index action_set_tp_dst[] = {
2473 	ACTION_SET_TP_DST_TP_DST,
2474 	ACTION_NEXT,
2475 	ZERO,
2476 };
2477 
2478 static const enum index action_set_ttl[] = {
2479 	ACTION_SET_TTL_TTL,
2480 	ACTION_NEXT,
2481 	ZERO,
2482 };
2483 
2484 static const enum index action_jump[] = {
2485 	ACTION_JUMP_GROUP,
2486 	ACTION_NEXT,
2487 	ZERO,
2488 };
2489 
2490 static const enum index action_set_mac_dst[] = {
2491 	ACTION_SET_MAC_DST_MAC_DST,
2492 	ACTION_NEXT,
2493 	ZERO,
2494 };
2495 
2496 static const enum index action_inc_tcp_seq[] = {
2497 	ACTION_INC_TCP_SEQ_VALUE,
2498 	ACTION_NEXT,
2499 	ZERO,
2500 };
2501 
2502 static const enum index action_dec_tcp_seq[] = {
2503 	ACTION_DEC_TCP_SEQ_VALUE,
2504 	ACTION_NEXT,
2505 	ZERO,
2506 };
2507 
2508 static const enum index action_inc_tcp_ack[] = {
2509 	ACTION_INC_TCP_ACK_VALUE,
2510 	ACTION_NEXT,
2511 	ZERO,
2512 };
2513 
2514 static const enum index action_dec_tcp_ack[] = {
2515 	ACTION_DEC_TCP_ACK_VALUE,
2516 	ACTION_NEXT,
2517 	ZERO,
2518 };
2519 
2520 static const enum index action_raw_encap[] = {
2521 	ACTION_RAW_ENCAP_SIZE,
2522 	ACTION_RAW_ENCAP_INDEX,
2523 	ACTION_NEXT,
2524 	ZERO,
2525 };
2526 
2527 static const enum index action_raw_decap[] = {
2528 	ACTION_RAW_DECAP_INDEX,
2529 	ACTION_NEXT,
2530 	ZERO,
2531 };
2532 
2533 static const enum index action_ipv6_ext_remove[] = {
2534 	ACTION_IPV6_EXT_REMOVE_INDEX,
2535 	ACTION_NEXT,
2536 	ZERO,
2537 };
2538 
2539 static const enum index action_ipv6_ext_push[] = {
2540 	ACTION_IPV6_EXT_PUSH_INDEX,
2541 	ACTION_NEXT,
2542 	ZERO,
2543 };
2544 
2545 static const enum index action_set_tag[] = {
2546 	ACTION_SET_TAG_DATA,
2547 	ACTION_SET_TAG_INDEX,
2548 	ACTION_SET_TAG_MASK,
2549 	ACTION_NEXT,
2550 	ZERO,
2551 };
2552 
2553 static const enum index action_set_meta[] = {
2554 	ACTION_SET_META_DATA,
2555 	ACTION_SET_META_MASK,
2556 	ACTION_NEXT,
2557 	ZERO,
2558 };
2559 
2560 static const enum index action_set_ipv4_dscp[] = {
2561 	ACTION_SET_IPV4_DSCP_VALUE,
2562 	ACTION_NEXT,
2563 	ZERO,
2564 };
2565 
2566 static const enum index action_set_ipv6_dscp[] = {
2567 	ACTION_SET_IPV6_DSCP_VALUE,
2568 	ACTION_NEXT,
2569 	ZERO,
2570 };
2571 
2572 static const enum index action_age[] = {
2573 	ACTION_AGE,
2574 	ACTION_AGE_TIMEOUT,
2575 	ACTION_NEXT,
2576 	ZERO,
2577 };
2578 
2579 static const enum index action_age_update[] = {
2580 	ACTION_AGE_UPDATE,
2581 	ACTION_AGE_UPDATE_TIMEOUT,
2582 	ACTION_AGE_UPDATE_TOUCH,
2583 	ACTION_NEXT,
2584 	ZERO,
2585 };
2586 
2587 static const enum index action_sample[] = {
2588 	ACTION_SAMPLE,
2589 	ACTION_SAMPLE_RATIO,
2590 	ACTION_SAMPLE_INDEX,
2591 	ACTION_NEXT,
2592 	ZERO,
2593 };
2594 
2595 static const enum index next_action_sample[] = {
2596 	ACTION_QUEUE,
2597 	ACTION_RSS,
2598 	ACTION_MARK,
2599 	ACTION_COUNT,
2600 	ACTION_PORT_ID,
2601 	ACTION_RAW_ENCAP,
2602 	ACTION_VXLAN_ENCAP,
2603 	ACTION_NVGRE_ENCAP,
2604 	ACTION_REPRESENTED_PORT,
2605 	ACTION_PORT_REPRESENTOR,
2606 	ACTION_NEXT,
2607 	ZERO,
2608 };
2609 
2610 static const enum index item_ipv6_push_ext[] = {
2611 	ITEM_IPV6_PUSH_REMOVE_EXT,
2612 	ZERO,
2613 };
2614 
2615 static const enum index item_ipv6_push_ext_type[] = {
2616 	ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
2617 	ZERO,
2618 };
2619 
2620 static const enum index item_ipv6_push_ext_header[] = {
2621 	ITEM_IPV6_ROUTING_EXT,
2622 	ITEM_NEXT,
2623 	ZERO,
2624 };
2625 
2626 static const enum index action_modify_field_dst[] = {
2627 	ACTION_MODIFY_FIELD_DST_LEVEL,
2628 	ACTION_MODIFY_FIELD_DST_TAG_INDEX,
2629 	ACTION_MODIFY_FIELD_DST_TYPE_ID,
2630 	ACTION_MODIFY_FIELD_DST_CLASS_ID,
2631 	ACTION_MODIFY_FIELD_DST_OFFSET,
2632 	ACTION_MODIFY_FIELD_SRC_TYPE,
2633 	ZERO,
2634 };
2635 
2636 static const enum index action_modify_field_src[] = {
2637 	ACTION_MODIFY_FIELD_SRC_LEVEL,
2638 	ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
2639 	ACTION_MODIFY_FIELD_SRC_TYPE_ID,
2640 	ACTION_MODIFY_FIELD_SRC_CLASS_ID,
2641 	ACTION_MODIFY_FIELD_SRC_OFFSET,
2642 	ACTION_MODIFY_FIELD_SRC_VALUE,
2643 	ACTION_MODIFY_FIELD_SRC_POINTER,
2644 	ACTION_MODIFY_FIELD_WIDTH,
2645 	ZERO,
2646 };
2647 
2648 static const enum index action_update_conntrack[] = {
2649 	ACTION_CONNTRACK_UPDATE_DIR,
2650 	ACTION_CONNTRACK_UPDATE_CTX,
2651 	ACTION_NEXT,
2652 	ZERO,
2653 };
2654 
2655 static const enum index action_port_representor[] = {
2656 	ACTION_PORT_REPRESENTOR_PORT_ID,
2657 	ACTION_NEXT,
2658 	ZERO,
2659 };
2660 
2661 static const enum index action_represented_port[] = {
2662 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
2663 	ACTION_NEXT,
2664 	ZERO,
2665 };
2666 
2667 static const enum index action_nat64[] = {
2668 	ACTION_NAT64_MODE,
2669 	ACTION_NEXT,
2670 	ZERO,
2671 };
2672 
2673 static const enum index next_hash_subcmd[] = {
2674 	HASH_CALC_TABLE,
2675 	HASH_CALC_ENCAP,
2676 	ZERO,
2677 };
2678 
2679 static const enum index next_hash_encap_dest_subcmd[] = {
2680 	ENCAP_HASH_FIELD_SRC_PORT,
2681 	ENCAP_HASH_FIELD_GRE_FLOW_ID,
2682 	ZERO,
2683 };
2684 
2685 static int parse_set_raw_encap_decap(struct context *, const struct token *,
2686 				     const char *, unsigned int,
2687 				     void *, unsigned int);
2688 static int parse_set_sample_action(struct context *, const struct token *,
2689 				   const char *, unsigned int,
2690 				   void *, unsigned int);
2691 static int parse_set_ipv6_ext_action(struct context *, const struct token *,
2692 				     const char *, unsigned int,
2693 				     void *, unsigned int);
2694 static int parse_set_init(struct context *, const struct token *,
2695 			  const char *, unsigned int,
2696 			  void *, unsigned int);
2697 static int
2698 parse_flex_handle(struct context *, const struct token *,
2699 		  const char *, unsigned int, void *, unsigned int);
2700 static int parse_init(struct context *, const struct token *,
2701 		      const char *, unsigned int,
2702 		      void *, unsigned int);
2703 static int parse_vc(struct context *, const struct token *,
2704 		    const char *, unsigned int,
2705 		    void *, unsigned int);
2706 static int parse_vc_spec(struct context *, const struct token *,
2707 			 const char *, unsigned int, void *, unsigned int);
2708 static int parse_vc_conf(struct context *, const struct token *,
2709 			 const char *, unsigned int, void *, unsigned int);
2710 static int parse_vc_conf_timeout(struct context *, const struct token *,
2711 				 const char *, unsigned int, void *,
2712 				 unsigned int);
2713 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
2714 				    const char *, unsigned int,
2715 				    void *, unsigned int);
2716 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *,
2717 				    const char *, unsigned int,
2718 				    void *, unsigned int);
2719 static int parse_vc_action_meter_color_type(struct context *,
2720 					const struct token *,
2721 					const char *, unsigned int, void *,
2722 					unsigned int);
2723 static int parse_vc_action_rss(struct context *, const struct token *,
2724 			       const char *, unsigned int, void *,
2725 			       unsigned int);
2726 static int parse_vc_action_rss_func(struct context *, const struct token *,
2727 				    const char *, unsigned int, void *,
2728 				    unsigned int);
2729 static int parse_vc_action_rss_type(struct context *, const struct token *,
2730 				    const char *, unsigned int, void *,
2731 				    unsigned int);
2732 static int parse_vc_action_rss_queue(struct context *, const struct token *,
2733 				     const char *, unsigned int, void *,
2734 				     unsigned int);
2735 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
2736 				       const char *, unsigned int, void *,
2737 				       unsigned int);
2738 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
2739 				       const char *, unsigned int, void *,
2740 				       unsigned int);
2741 static int parse_vc_action_l2_encap(struct context *, const struct token *,
2742 				    const char *, unsigned int, void *,
2743 				    unsigned int);
2744 static int parse_vc_action_l2_decap(struct context *, const struct token *,
2745 				    const char *, unsigned int, void *,
2746 				    unsigned int);
2747 static int parse_vc_action_mplsogre_encap(struct context *,
2748 					  const struct token *, const char *,
2749 					  unsigned int, void *, unsigned int);
2750 static int parse_vc_action_mplsogre_decap(struct context *,
2751 					  const struct token *, const char *,
2752 					  unsigned int, void *, unsigned int);
2753 static int parse_vc_action_mplsoudp_encap(struct context *,
2754 					  const struct token *, const char *,
2755 					  unsigned int, void *, unsigned int);
2756 static int parse_vc_action_mplsoudp_decap(struct context *,
2757 					  const struct token *, const char *,
2758 					  unsigned int, void *, unsigned int);
2759 static int parse_vc_action_raw_encap(struct context *,
2760 				     const struct token *, const char *,
2761 				     unsigned int, void *, unsigned int);
2762 static int parse_vc_action_raw_decap(struct context *,
2763 				     const struct token *, const char *,
2764 				     unsigned int, void *, unsigned int);
2765 static int parse_vc_action_raw_encap_index(struct context *,
2766 					   const struct token *, const char *,
2767 					   unsigned int, void *, unsigned int);
2768 static int parse_vc_action_raw_decap_index(struct context *,
2769 					   const struct token *, const char *,
2770 					   unsigned int, void *, unsigned int);
2771 static int parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
2772 					   const char *str, unsigned int len, void *buf,
2773 					   unsigned int size);
2774 static int parse_vc_action_ipv6_ext_remove_index(struct context *ctx,
2775 						 const struct token *token,
2776 						 const char *str, unsigned int len,
2777 						 void *buf,
2778 						 unsigned int size);
2779 static int parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
2780 					 const char *str, unsigned int len, void *buf,
2781 					 unsigned int size);
2782 static int parse_vc_action_ipv6_ext_push_index(struct context *ctx,
2783 					       const struct token *token,
2784 					       const char *str, unsigned int len,
2785 					       void *buf,
2786 					       unsigned int size);
2787 static int parse_vc_action_set_meta(struct context *ctx,
2788 				    const struct token *token, const char *str,
2789 				    unsigned int len, void *buf,
2790 					unsigned int size);
2791 static int parse_vc_action_sample(struct context *ctx,
2792 				    const struct token *token, const char *str,
2793 				    unsigned int len, void *buf,
2794 				    unsigned int size);
2795 static int
2796 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
2797 				const char *str, unsigned int len, void *buf,
2798 				unsigned int size);
2799 static int
2800 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
2801 				const char *str, unsigned int len, void *buf,
2802 				unsigned int size);
2803 static int
2804 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
2805 				const char *str, unsigned int len, void *buf,
2806 				unsigned int size);
2807 static int
2808 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
2809 				const char *str, unsigned int len, void *buf,
2810 				unsigned int size);
2811 static int
2812 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
2813 			 const char *str, unsigned int len, void *buf,
2814 			 unsigned int size);
2815 static int parse_destroy(struct context *, const struct token *,
2816 			 const char *, unsigned int,
2817 			 void *, unsigned int);
2818 static int parse_flush(struct context *, const struct token *,
2819 		       const char *, unsigned int,
2820 		       void *, unsigned int);
2821 static int parse_dump(struct context *, const struct token *,
2822 		      const char *, unsigned int,
2823 		      void *, unsigned int);
2824 static int parse_query(struct context *, const struct token *,
2825 		       const char *, unsigned int,
2826 		       void *, unsigned int);
2827 static int parse_action(struct context *, const struct token *,
2828 			const char *, unsigned int,
2829 			void *, unsigned int);
2830 static int parse_list(struct context *, const struct token *,
2831 		      const char *, unsigned int,
2832 		      void *, unsigned int);
2833 static int parse_aged(struct context *, const struct token *,
2834 		      const char *, unsigned int,
2835 		      void *, unsigned int);
2836 static int parse_isolate(struct context *, const struct token *,
2837 			 const char *, unsigned int,
2838 			 void *, unsigned int);
2839 static int parse_configure(struct context *, const struct token *,
2840 			   const char *, unsigned int,
2841 			   void *, unsigned int);
2842 static int parse_template(struct context *, const struct token *,
2843 			  const char *, unsigned int,
2844 			  void *, unsigned int);
2845 static int parse_template_destroy(struct context *, const struct token *,
2846 				  const char *, unsigned int,
2847 				  void *, unsigned int);
2848 static int parse_table(struct context *, const struct token *,
2849 		       const char *, unsigned int, void *, unsigned int);
2850 static int parse_table_destroy(struct context *, const struct token *,
2851 			       const char *, unsigned int,
2852 			       void *, unsigned int);
2853 static int parse_qo(struct context *, const struct token *,
2854 		    const char *, unsigned int,
2855 		    void *, unsigned int);
2856 static int parse_qo_destroy(struct context *, const struct token *,
2857 			    const char *, unsigned int,
2858 			    void *, unsigned int);
2859 static int parse_qia(struct context *, const struct token *,
2860 		     const char *, unsigned int,
2861 		     void *, unsigned int);
2862 static int parse_qia_destroy(struct context *, const struct token *,
2863 			     const char *, unsigned int,
2864 			     void *, unsigned int);
2865 static int parse_push(struct context *, const struct token *,
2866 		      const char *, unsigned int,
2867 		      void *, unsigned int);
2868 static int parse_pull(struct context *, const struct token *,
2869 		      const char *, unsigned int,
2870 		      void *, unsigned int);
2871 static int parse_group(struct context *, const struct token *,
2872 		       const char *, unsigned int,
2873 		       void *, unsigned int);
2874 static int parse_hash(struct context *, const struct token *,
2875 		      const char *, unsigned int,
2876 		      void *, unsigned int);
2877 static int parse_tunnel(struct context *, const struct token *,
2878 			const char *, unsigned int,
2879 			void *, unsigned int);
2880 static int parse_flex(struct context *, const struct token *,
2881 		      const char *, unsigned int, void *, unsigned int);
2882 static int parse_int(struct context *, const struct token *,
2883 		     const char *, unsigned int,
2884 		     void *, unsigned int);
2885 static int parse_prefix(struct context *, const struct token *,
2886 			const char *, unsigned int,
2887 			void *, unsigned int);
2888 static int parse_boolean(struct context *, const struct token *,
2889 			 const char *, unsigned int,
2890 			 void *, unsigned int);
2891 static int parse_string(struct context *, const struct token *,
2892 			const char *, unsigned int,
2893 			void *, unsigned int);
2894 static int parse_hex(struct context *ctx, const struct token *token,
2895 			const char *str, unsigned int len,
2896 			void *buf, unsigned int size);
2897 static int parse_string0(struct context *, const struct token *,
2898 			const char *, unsigned int,
2899 			void *, unsigned int);
2900 static int parse_mac_addr(struct context *, const struct token *,
2901 			  const char *, unsigned int,
2902 			  void *, unsigned int);
2903 static int parse_ipv4_addr(struct context *, const struct token *,
2904 			   const char *, unsigned int,
2905 			   void *, unsigned int);
2906 static int parse_ipv6_addr(struct context *, const struct token *,
2907 			   const char *, unsigned int,
2908 			   void *, unsigned int);
2909 static int parse_port(struct context *, const struct token *,
2910 		      const char *, unsigned int,
2911 		      void *, unsigned int);
2912 static int parse_ia(struct context *, const struct token *,
2913 		    const char *, unsigned int,
2914 		    void *, unsigned int);
2915 static int parse_ia_destroy(struct context *ctx, const struct token *token,
2916 			    const char *str, unsigned int len,
2917 			    void *buf, unsigned int size);
2918 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
2919 			   const char *str, unsigned int len, void *buf,
2920 			   unsigned int size);
2921 
2922 static int parse_indlst_id2ptr(struct context *ctx, const struct token *token,
2923 			       const char *str, unsigned int len, void *buf,
2924 			       unsigned int size);
2925 static int parse_ia_port(struct context *ctx, const struct token *token,
2926 			 const char *str, unsigned int len, void *buf,
2927 			 unsigned int size);
2928 static int parse_mp(struct context *, const struct token *,
2929 		    const char *, unsigned int,
2930 		    void *, unsigned int);
2931 static int parse_meter_profile_id2ptr(struct context *ctx,
2932 				      const struct token *token,
2933 				      const char *str, unsigned int len,
2934 				      void *buf, unsigned int size);
2935 static int parse_meter_policy_id2ptr(struct context *ctx,
2936 				     const struct token *token,
2937 				     const char *str, unsigned int len,
2938 				     void *buf, unsigned int size);
2939 static int parse_meter_color(struct context *ctx, const struct token *token,
2940 			     const char *str, unsigned int len, void *buf,
2941 			     unsigned int size);
2942 static int parse_insertion_table_type(struct context *ctx, const struct token *token,
2943 				      const char *str, unsigned int len, void *buf,
2944 				      unsigned int size);
2945 static int parse_hash_table_type(struct context *ctx, const struct token *token,
2946 				 const char *str, unsigned int len, void *buf,
2947 				 unsigned int size);
2948 static int
2949 parse_quota_state_name(struct context *ctx, const struct token *token,
2950 		       const char *str, unsigned int len, void *buf,
2951 		       unsigned int size);
2952 static int
2953 parse_quota_mode_name(struct context *ctx, const struct token *token,
2954 		      const char *str, unsigned int len, void *buf,
2955 		      unsigned int size);
2956 static int
2957 parse_quota_update_name(struct context *ctx, const struct token *token,
2958 			const char *str, unsigned int len, void *buf,
2959 			unsigned int size);
2960 static int
2961 parse_qu_mode_name(struct context *ctx, const struct token *token,
2962 		   const char *str, unsigned int len, void *buf,
2963 		   unsigned int size);
2964 static int comp_none(struct context *, const struct token *,
2965 		     unsigned int, char *, unsigned int);
2966 static int comp_boolean(struct context *, const struct token *,
2967 			unsigned int, char *, unsigned int);
2968 static int comp_action(struct context *, const struct token *,
2969 		       unsigned int, char *, unsigned int);
2970 static int comp_port(struct context *, const struct token *,
2971 		     unsigned int, char *, unsigned int);
2972 static int comp_rule_id(struct context *, const struct token *,
2973 			unsigned int, char *, unsigned int);
2974 static int comp_vc_action_rss_type(struct context *, const struct token *,
2975 				   unsigned int, char *, unsigned int);
2976 static int comp_vc_action_rss_queue(struct context *, const struct token *,
2977 				    unsigned int, char *, unsigned int);
2978 static int comp_set_raw_index(struct context *, const struct token *,
2979 			      unsigned int, char *, unsigned int);
2980 static int comp_set_sample_index(struct context *, const struct token *,
2981 			      unsigned int, char *, unsigned int);
2982 static int comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
2983 				   unsigned int ent, char *buf, unsigned int size);
2984 static int comp_set_modify_field_op(struct context *, const struct token *,
2985 			      unsigned int, char *, unsigned int);
2986 static int comp_set_modify_field_id(struct context *, const struct token *,
2987 			      unsigned int, char *, unsigned int);
2988 static int comp_pattern_template_id(struct context *, const struct token *,
2989 				    unsigned int, char *, unsigned int);
2990 static int comp_actions_template_id(struct context *, const struct token *,
2991 				    unsigned int, char *, unsigned int);
2992 static int comp_table_id(struct context *, const struct token *,
2993 			 unsigned int, char *, unsigned int);
2994 static int comp_queue_id(struct context *, const struct token *,
2995 			 unsigned int, char *, unsigned int);
2996 static int comp_meter_color(struct context *, const struct token *,
2997 			    unsigned int, char *, unsigned int);
2998 static int comp_insertion_table_type(struct context *, const struct token *,
2999 				     unsigned int, char *, unsigned int);
3000 static int comp_hash_table_type(struct context *, const struct token *,
3001 				unsigned int, char *, unsigned int);
3002 static int
3003 comp_quota_state_name(struct context *ctx, const struct token *token,
3004 		      unsigned int ent, char *buf, unsigned int size);
3005 static int
3006 comp_quota_mode_name(struct context *ctx, const struct token *token,
3007 		     unsigned int ent, char *buf, unsigned int size);
3008 static int
3009 comp_quota_update_name(struct context *ctx, const struct token *token,
3010 		       unsigned int ent, char *buf, unsigned int size);
3011 static int
3012 comp_qu_mode_name(struct context *ctx, const struct token *token,
3013 		  unsigned int ent, char *buf, unsigned int size);
3014 static int
3015 comp_set_compare_field_id(struct context *ctx, const struct token *token,
3016 			  unsigned int ent, char *buf, unsigned int size);
3017 static int
3018 comp_set_compare_op(struct context *ctx, const struct token *token,
3019 		    unsigned int ent, char *buf, unsigned int size);
3020 static int
3021 parse_vc_compare_op(struct context *ctx, const struct token *token,
3022 			 const char *str, unsigned int len, void *buf,
3023 			 unsigned int size);
3024 static int
3025 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
3026 			  const char *str, unsigned int len, void *buf,
3027 			  unsigned int size);
3028 static int
3029 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
3030 			     const char *str, unsigned int len, void *buf,
3031 			     unsigned int size);
3032 
3033 struct indlst_conf {
3034 	uint32_t id;
3035 	uint32_t conf_num;
3036 	struct rte_flow_action *actions;
3037 	const void **conf;
3038 	SLIST_ENTRY(indlst_conf) next;
3039 };
3040 
3041 static const struct indlst_conf *indirect_action_list_conf_get(uint32_t conf_id);
3042 
3043 /** Token definitions. */
3044 static const struct token token_list[] = {
3045 	/* Special tokens. */
3046 	[ZERO] = {
3047 		.name = "ZERO",
3048 		.help = "null entry, abused as the entry point",
3049 		.next = NEXT(NEXT_ENTRY(FLOW, ADD)),
3050 	},
3051 	[END] = {
3052 		.name = "",
3053 		.type = "RETURN",
3054 		.help = "command may end here",
3055 	},
3056 	[START_SET] = {
3057 		.name = "START_SET",
3058 		.help = "null entry, abused as the entry point for set",
3059 		.next = NEXT(NEXT_ENTRY(SET)),
3060 	},
3061 	[END_SET] = {
3062 		.name = "end_set",
3063 		.type = "RETURN",
3064 		.help = "set command may end here",
3065 	},
3066 	/* Common tokens. */
3067 	[COMMON_INTEGER] = {
3068 		.name = "{int}",
3069 		.type = "INTEGER",
3070 		.help = "integer value",
3071 		.call = parse_int,
3072 		.comp = comp_none,
3073 	},
3074 	[COMMON_UNSIGNED] = {
3075 		.name = "{unsigned}",
3076 		.type = "UNSIGNED",
3077 		.help = "unsigned integer value",
3078 		.call = parse_int,
3079 		.comp = comp_none,
3080 	},
3081 	[COMMON_PREFIX] = {
3082 		.name = "{prefix}",
3083 		.type = "PREFIX",
3084 		.help = "prefix length for bit-mask",
3085 		.call = parse_prefix,
3086 		.comp = comp_none,
3087 	},
3088 	[COMMON_BOOLEAN] = {
3089 		.name = "{boolean}",
3090 		.type = "BOOLEAN",
3091 		.help = "any boolean value",
3092 		.call = parse_boolean,
3093 		.comp = comp_boolean,
3094 	},
3095 	[COMMON_STRING] = {
3096 		.name = "{string}",
3097 		.type = "STRING",
3098 		.help = "fixed string",
3099 		.call = parse_string,
3100 		.comp = comp_none,
3101 	},
3102 	[COMMON_HEX] = {
3103 		.name = "{hex}",
3104 		.type = "HEX",
3105 		.help = "fixed string",
3106 		.call = parse_hex,
3107 	},
3108 	[COMMON_FILE_PATH] = {
3109 		.name = "{file path}",
3110 		.type = "STRING",
3111 		.help = "file path",
3112 		.call = parse_string0,
3113 		.comp = comp_none,
3114 	},
3115 	[COMMON_MAC_ADDR] = {
3116 		.name = "{MAC address}",
3117 		.type = "MAC-48",
3118 		.help = "standard MAC address notation",
3119 		.call = parse_mac_addr,
3120 		.comp = comp_none,
3121 	},
3122 	[COMMON_IPV4_ADDR] = {
3123 		.name = "{IPv4 address}",
3124 		.type = "IPV4 ADDRESS",
3125 		.help = "standard IPv4 address notation",
3126 		.call = parse_ipv4_addr,
3127 		.comp = comp_none,
3128 	},
3129 	[COMMON_IPV6_ADDR] = {
3130 		.name = "{IPv6 address}",
3131 		.type = "IPV6 ADDRESS",
3132 		.help = "standard IPv6 address notation",
3133 		.call = parse_ipv6_addr,
3134 		.comp = comp_none,
3135 	},
3136 	[COMMON_RULE_ID] = {
3137 		.name = "{rule id}",
3138 		.type = "RULE ID",
3139 		.help = "rule identifier",
3140 		.call = parse_int,
3141 		.comp = comp_rule_id,
3142 	},
3143 	[COMMON_PORT_ID] = {
3144 		.name = "{port_id}",
3145 		.type = "PORT ID",
3146 		.help = "port identifier",
3147 		.call = parse_port,
3148 		.comp = comp_port,
3149 	},
3150 	[COMMON_GROUP_ID] = {
3151 		.name = "{group_id}",
3152 		.type = "GROUP ID",
3153 		.help = "group identifier",
3154 		.call = parse_int,
3155 		.comp = comp_none,
3156 	},
3157 	[COMMON_PRIORITY_LEVEL] = {
3158 		.name = "{level}",
3159 		.type = "PRIORITY",
3160 		.help = "priority level",
3161 		.call = parse_int,
3162 		.comp = comp_none,
3163 	},
3164 	[COMMON_INDIRECT_ACTION_ID] = {
3165 		.name = "{indirect_action_id}",
3166 		.type = "INDIRECT_ACTION_ID",
3167 		.help = "indirect action id",
3168 		.call = parse_int,
3169 		.comp = comp_none,
3170 	},
3171 	[COMMON_PROFILE_ID] = {
3172 		.name = "{profile_id}",
3173 		.type = "PROFILE_ID",
3174 		.help = "profile id",
3175 		.call = parse_int,
3176 		.comp = comp_none,
3177 	},
3178 	[COMMON_POLICY_ID] = {
3179 		.name = "{policy_id}",
3180 		.type = "POLICY_ID",
3181 		.help = "policy id",
3182 		.call = parse_int,
3183 		.comp = comp_none,
3184 	},
3185 	[COMMON_FLEX_TOKEN] = {
3186 		.name = "{flex token}",
3187 		.type = "flex token",
3188 		.help = "flex token",
3189 		.call = parse_int,
3190 		.comp = comp_none,
3191 	},
3192 	[COMMON_FLEX_HANDLE] = {
3193 		.name = "{flex handle}",
3194 		.type = "FLEX HANDLE",
3195 		.help = "fill flex item data",
3196 		.call = parse_flex_handle,
3197 		.comp = comp_none,
3198 	},
3199 	[COMMON_PATTERN_TEMPLATE_ID] = {
3200 		.name = "{pattern_template_id}",
3201 		.type = "PATTERN_TEMPLATE_ID",
3202 		.help = "pattern template id",
3203 		.call = parse_int,
3204 		.comp = comp_pattern_template_id,
3205 	},
3206 	[COMMON_ACTIONS_TEMPLATE_ID] = {
3207 		.name = "{actions_template_id}",
3208 		.type = "ACTIONS_TEMPLATE_ID",
3209 		.help = "actions template id",
3210 		.call = parse_int,
3211 		.comp = comp_actions_template_id,
3212 	},
3213 	[COMMON_TABLE_ID] = {
3214 		.name = "{table_id}",
3215 		.type = "TABLE_ID",
3216 		.help = "table id",
3217 		.call = parse_int,
3218 		.comp = comp_table_id,
3219 	},
3220 	[COMMON_QUEUE_ID] = {
3221 		.name = "{queue_id}",
3222 		.type = "QUEUE_ID",
3223 		.help = "queue id",
3224 		.call = parse_int,
3225 		.comp = comp_queue_id,
3226 	},
3227 	/* Top-level command. */
3228 	[FLOW] = {
3229 		.name = "flow",
3230 		.type = "{command} {port_id} [{arg} [...]]",
3231 		.help = "manage ingress/egress flow rules",
3232 		.next = NEXT(NEXT_ENTRY
3233 			     (INFO,
3234 			      CONFIGURE,
3235 			      PATTERN_TEMPLATE,
3236 			      ACTIONS_TEMPLATE,
3237 			      TABLE,
3238 			      FLOW_GROUP,
3239 			      INDIRECT_ACTION,
3240 			      VALIDATE,
3241 			      CREATE,
3242 			      DESTROY,
3243 			      UPDATE,
3244 			      FLUSH,
3245 			      DUMP,
3246 			      LIST,
3247 			      AGED,
3248 			      QUERY,
3249 			      ISOLATE,
3250 			      TUNNEL,
3251 			      FLEX,
3252 			      QUEUE,
3253 			      PUSH,
3254 			      PULL,
3255 			      HASH)),
3256 		.call = parse_init,
3257 	},
3258 	/* Top-level command. */
3259 	[INFO] = {
3260 		.name = "info",
3261 		.help = "get information about flow engine",
3262 		.next = NEXT(NEXT_ENTRY(END),
3263 			     NEXT_ENTRY(COMMON_PORT_ID)),
3264 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3265 		.call = parse_configure,
3266 	},
3267 	/* Top-level command. */
3268 	[CONFIGURE] = {
3269 		.name = "configure",
3270 		.help = "configure flow engine",
3271 		.next = NEXT(next_config_attr,
3272 			     NEXT_ENTRY(COMMON_PORT_ID)),
3273 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3274 		.call = parse_configure,
3275 	},
3276 	/* Configure arguments. */
3277 	[CONFIG_QUEUES_NUMBER] = {
3278 		.name = "queues_number",
3279 		.help = "number of queues",
3280 		.next = NEXT(next_config_attr,
3281 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3282 		.args = ARGS(ARGS_ENTRY(struct buffer,
3283 					args.configure.nb_queue)),
3284 	},
3285 	[CONFIG_QUEUES_SIZE] = {
3286 		.name = "queues_size",
3287 		.help = "number of elements in queues",
3288 		.next = NEXT(next_config_attr,
3289 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3290 		.args = ARGS(ARGS_ENTRY(struct buffer,
3291 					args.configure.queue_attr.size)),
3292 	},
3293 	[CONFIG_COUNTERS_NUMBER] = {
3294 		.name = "counters_number",
3295 		.help = "number of counters",
3296 		.next = NEXT(next_config_attr,
3297 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3298 		.args = ARGS(ARGS_ENTRY(struct buffer,
3299 					args.configure.port_attr.nb_counters)),
3300 	},
3301 	[CONFIG_AGING_OBJECTS_NUMBER] = {
3302 		.name = "aging_counters_number",
3303 		.help = "number of aging objects",
3304 		.next = NEXT(next_config_attr,
3305 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3306 		.args = ARGS(ARGS_ENTRY(struct buffer,
3307 					args.configure.port_attr.nb_aging_objects)),
3308 	},
3309 	[CONFIG_QUOTAS_NUMBER] = {
3310 		.name = "quotas_number",
3311 		.help = "number of quotas",
3312 		.next = NEXT(next_config_attr,
3313 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3314 		.args = ARGS(ARGS_ENTRY(struct buffer,
3315 				     args.configure.port_attr.nb_quotas)),
3316 	},
3317 	[CONFIG_METERS_NUMBER] = {
3318 		.name = "meters_number",
3319 		.help = "number of meters",
3320 		.next = NEXT(next_config_attr,
3321 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3322 		.args = ARGS(ARGS_ENTRY(struct buffer,
3323 					args.configure.port_attr.nb_meters)),
3324 	},
3325 	[CONFIG_CONN_TRACK_NUMBER] = {
3326 		.name = "conn_tracks_number",
3327 		.help = "number of connection trackings",
3328 		.next = NEXT(next_config_attr,
3329 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3330 		.args = ARGS(ARGS_ENTRY(struct buffer,
3331 					args.configure.port_attr.nb_conn_tracks)),
3332 	},
3333 	[CONFIG_FLAGS] = {
3334 		.name = "flags",
3335 		.help = "configuration flags",
3336 		.next = NEXT(next_config_attr,
3337 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3338 		.args = ARGS(ARGS_ENTRY(struct buffer,
3339 					args.configure.port_attr.flags)),
3340 	},
3341 	[CONFIG_HOST_PORT] = {
3342 		.name = "host_port",
3343 		.help = "host port for shared objects",
3344 		.next = NEXT(next_config_attr,
3345 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3346 		.args = ARGS(ARGS_ENTRY(struct buffer,
3347 					args.configure.port_attr.host_port_id)),
3348 	},
3349 	/* Top-level command. */
3350 	[PATTERN_TEMPLATE] = {
3351 		.name = "pattern_template",
3352 		.type = "{command} {port_id} [{arg} [...]]",
3353 		.help = "manage pattern templates",
3354 		.next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3355 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3356 		.call = parse_template,
3357 	},
3358 	/* Sub-level commands. */
3359 	[PATTERN_TEMPLATE_CREATE] = {
3360 		.name = "create",
3361 		.help = "create pattern template",
3362 		.next = NEXT(next_pt_attr),
3363 		.call = parse_template,
3364 	},
3365 	[PATTERN_TEMPLATE_DESTROY] = {
3366 		.name = "destroy",
3367 		.help = "destroy pattern template",
3368 		.next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)),
3369 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3370 		.call = parse_template_destroy,
3371 	},
3372 	/* Pattern template arguments. */
3373 	[PATTERN_TEMPLATE_CREATE_ID] = {
3374 		.name = "pattern_template_id",
3375 		.help = "specify a pattern template id to create",
3376 		.next = NEXT(next_pt_attr,
3377 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3378 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)),
3379 	},
3380 	[PATTERN_TEMPLATE_DESTROY_ID] = {
3381 		.name = "pattern_template",
3382 		.help = "specify a pattern template id to destroy",
3383 		.next = NEXT(next_pt_destroy_attr,
3384 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3385 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3386 					    args.templ_destroy.template_id)),
3387 		.call = parse_template_destroy,
3388 	},
3389 	[PATTERN_TEMPLATE_RELAXED_MATCHING] = {
3390 		.name = "relaxed",
3391 		.help = "is matching relaxed",
3392 		.next = NEXT(next_pt_attr,
3393 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3394 		.args = ARGS(ARGS_ENTRY_BF(struct buffer,
3395 			     args.vc.attr.reserved, 1)),
3396 	},
3397 	[PATTERN_TEMPLATE_INGRESS] = {
3398 		.name = "ingress",
3399 		.help = "attribute pattern to ingress",
3400 		.next = NEXT(next_pt_attr),
3401 		.call = parse_template,
3402 	},
3403 	[PATTERN_TEMPLATE_EGRESS] = {
3404 		.name = "egress",
3405 		.help = "attribute pattern to egress",
3406 		.next = NEXT(next_pt_attr),
3407 		.call = parse_template,
3408 	},
3409 	[PATTERN_TEMPLATE_TRANSFER] = {
3410 		.name = "transfer",
3411 		.help = "attribute pattern to transfer",
3412 		.next = NEXT(next_pt_attr),
3413 		.call = parse_template,
3414 	},
3415 	[PATTERN_TEMPLATE_SPEC] = {
3416 		.name = "template",
3417 		.help = "specify item to create pattern template",
3418 		.next = NEXT(next_item),
3419 	},
3420 	/* Top-level command. */
3421 	[ACTIONS_TEMPLATE] = {
3422 		.name = "actions_template",
3423 		.type = "{command} {port_id} [{arg} [...]]",
3424 		.help = "manage actions templates",
3425 		.next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3426 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3427 		.call = parse_template,
3428 	},
3429 	/* Sub-level commands. */
3430 	[ACTIONS_TEMPLATE_CREATE] = {
3431 		.name = "create",
3432 		.help = "create actions template",
3433 		.next = NEXT(next_at_attr),
3434 		.call = parse_template,
3435 	},
3436 	[ACTIONS_TEMPLATE_DESTROY] = {
3437 		.name = "destroy",
3438 		.help = "destroy actions template",
3439 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)),
3440 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3441 		.call = parse_template_destroy,
3442 	},
3443 	/* Actions template arguments. */
3444 	[ACTIONS_TEMPLATE_CREATE_ID] = {
3445 		.name = "actions_template_id",
3446 		.help = "specify an actions template id to create",
3447 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK),
3448 			     NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC),
3449 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3450 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)),
3451 	},
3452 	[ACTIONS_TEMPLATE_DESTROY_ID] = {
3453 		.name = "actions_template",
3454 		.help = "specify an actions template id to destroy",
3455 		.next = NEXT(next_at_destroy_attr,
3456 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3457 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3458 					    args.templ_destroy.template_id)),
3459 		.call = parse_template_destroy,
3460 	},
3461 	[ACTIONS_TEMPLATE_INGRESS] = {
3462 		.name = "ingress",
3463 		.help = "attribute actions to ingress",
3464 		.next = NEXT(next_at_attr),
3465 		.call = parse_template,
3466 	},
3467 	[ACTIONS_TEMPLATE_EGRESS] = {
3468 		.name = "egress",
3469 		.help = "attribute actions to egress",
3470 		.next = NEXT(next_at_attr),
3471 		.call = parse_template,
3472 	},
3473 	[ACTIONS_TEMPLATE_TRANSFER] = {
3474 		.name = "transfer",
3475 		.help = "attribute actions to transfer",
3476 		.next = NEXT(next_at_attr),
3477 		.call = parse_template,
3478 	},
3479 	[ACTIONS_TEMPLATE_SPEC] = {
3480 		.name = "template",
3481 		.help = "specify action to create actions template",
3482 		.next = NEXT(next_action),
3483 		.call = parse_template,
3484 	},
3485 	[ACTIONS_TEMPLATE_MASK] = {
3486 		.name = "mask",
3487 		.help = "specify action mask to create actions template",
3488 		.next = NEXT(next_action),
3489 		.call = parse_template,
3490 	},
3491 	/* Top-level command. */
3492 	[TABLE] = {
3493 		.name = "template_table",
3494 		.type = "{command} {port_id} [{arg} [...]]",
3495 		.help = "manage template tables",
3496 		.next = NEXT(next_table_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3497 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3498 		.call = parse_table,
3499 	},
3500 	/* Sub-level commands. */
3501 	[TABLE_CREATE] = {
3502 		.name = "create",
3503 		.help = "create template table",
3504 		.next = NEXT(next_table_attr),
3505 		.call = parse_table,
3506 	},
3507 	[TABLE_DESTROY] = {
3508 		.name = "destroy",
3509 		.help = "destroy template table",
3510 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3511 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3512 		.call = parse_table_destroy,
3513 	},
3514 	[TABLE_RESIZE] = {
3515 		.name = "resize",
3516 		.help = "resize template table",
3517 		.next = NEXT(NEXT_ENTRY(TABLE_RESIZE_ID)),
3518 		.call = parse_table
3519 	},
3520 	[TABLE_RESIZE_COMPLETE] = {
3521 		.name = "resize_complete",
3522 		.help = "complete table resize",
3523 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3524 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3525 		.call = parse_table_destroy,
3526 	},
3527 	/* Table  arguments. */
3528 	[TABLE_CREATE_ID] = {
3529 		.name = "table_id",
3530 		.help = "specify table id to create",
3531 		.next = NEXT(next_table_attr,
3532 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3533 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3534 	},
3535 	[TABLE_DESTROY_ID] = {
3536 		.name = "table",
3537 		.help = "table id",
3538 		.next = NEXT(next_table_destroy_attr,
3539 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3540 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3541 					    args.table_destroy.table_id)),
3542 		.call = parse_table_destroy,
3543 	},
3544 	[TABLE_RESIZE_ID] = {
3545 		.name = "table_resize_id",
3546 		.help = "table resize id",
3547 		.next = NEXT(NEXT_ENTRY(TABLE_RESIZE_RULES_NUMBER),
3548 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3549 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3550 		.call = parse_table
3551 	},
3552 	[TABLE_RESIZE_RULES_NUMBER] = {
3553 		.name = "table_resize_rules_num",
3554 		.help = "table resize rules number",
3555 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_UNSIGNED)),
3556 		.args = ARGS(ARGS_ENTRY(struct buffer,
3557 					args.table.attr.nb_flows)),
3558 		.call = parse_table
3559 	},
3560 	[TABLE_INSERTION_TYPE] = {
3561 		.name = "insertion_type",
3562 		.help = "specify insertion type",
3563 		.next = NEXT(next_table_attr,
3564 			     NEXT_ENTRY(TABLE_INSERTION_TYPE_NAME)),
3565 		.args = ARGS(ARGS_ENTRY(struct buffer,
3566 					args.table.attr.insertion_type)),
3567 	},
3568 	[TABLE_INSERTION_TYPE_NAME] = {
3569 		.name = "insertion_type_name",
3570 		.help = "insertion type name",
3571 		.call = parse_insertion_table_type,
3572 		.comp = comp_insertion_table_type,
3573 	},
3574 	[TABLE_HASH_FUNC] = {
3575 		.name = "hash_func",
3576 		.help = "specify hash calculation function",
3577 		.next = NEXT(next_table_attr,
3578 			     NEXT_ENTRY(TABLE_HASH_FUNC_NAME)),
3579 		.args = ARGS(ARGS_ENTRY(struct buffer,
3580 					args.table.attr.hash_func)),
3581 	},
3582 	[TABLE_HASH_FUNC_NAME] = {
3583 		.name = "hash_func_name",
3584 		.help = "hash calculation function name",
3585 		.call = parse_hash_table_type,
3586 		.comp = comp_hash_table_type,
3587 	},
3588 	[TABLE_GROUP] = {
3589 		.name = "group",
3590 		.help = "specify a group",
3591 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3592 		.args = ARGS(ARGS_ENTRY(struct buffer,
3593 					args.table.attr.flow_attr.group)),
3594 	},
3595 	[TABLE_PRIORITY] = {
3596 		.name = "priority",
3597 		.help = "specify a priority level",
3598 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
3599 		.args = ARGS(ARGS_ENTRY(struct buffer,
3600 					args.table.attr.flow_attr.priority)),
3601 	},
3602 	[TABLE_EGRESS] = {
3603 		.name = "egress",
3604 		.help = "affect rule to egress",
3605 		.next = NEXT(next_table_attr),
3606 		.call = parse_table,
3607 	},
3608 	[TABLE_INGRESS] = {
3609 		.name = "ingress",
3610 		.help = "affect rule to ingress",
3611 		.next = NEXT(next_table_attr),
3612 		.call = parse_table,
3613 	},
3614 	[TABLE_TRANSFER] = {
3615 		.name = "transfer",
3616 		.help = "affect rule to transfer",
3617 		.next = NEXT(next_table_attr),
3618 		.call = parse_table,
3619 	},
3620 	[TABLE_TRANSFER_WIRE_ORIG] = {
3621 		.name = "wire_orig",
3622 		.help = "affect rule direction to transfer",
3623 		.next = NEXT(next_table_attr),
3624 		.call = parse_table,
3625 	},
3626 	[TABLE_TRANSFER_VPORT_ORIG] = {
3627 		.name = "vport_orig",
3628 		.help = "affect rule direction to transfer",
3629 		.next = NEXT(next_table_attr),
3630 		.call = parse_table,
3631 	},
3632 	[TABLE_RESIZABLE] = {
3633 		.name = "resizable",
3634 		.help = "set resizable attribute",
3635 		.next = NEXT(next_table_attr),
3636 		.call = parse_table,
3637 	},
3638 	[TABLE_RULES_NUMBER] = {
3639 		.name = "rules_number",
3640 		.help = "number of rules in table",
3641 		.next = NEXT(next_table_attr,
3642 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3643 		.args = ARGS(ARGS_ENTRY(struct buffer,
3644 					args.table.attr.nb_flows)),
3645 		.call = parse_table,
3646 	},
3647 	[TABLE_PATTERN_TEMPLATE] = {
3648 		.name = "pattern_template",
3649 		.help = "specify pattern template id",
3650 		.next = NEXT(next_table_attr,
3651 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3652 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3653 					    args.table.pat_templ_id)),
3654 		.call = parse_table,
3655 	},
3656 	[TABLE_ACTIONS_TEMPLATE] = {
3657 		.name = "actions_template",
3658 		.help = "specify actions template id",
3659 		.next = NEXT(next_table_attr,
3660 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3661 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3662 					    args.table.act_templ_id)),
3663 		.call = parse_table,
3664 	},
3665 	/* Top-level command. */
3666 	[FLOW_GROUP] = {
3667 		.name = "group",
3668 		.help = "manage flow groups",
3669 		.next = NEXT(NEXT_ENTRY(GROUP_ID), NEXT_ENTRY(COMMON_PORT_ID)),
3670 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3671 		.call = parse_group,
3672 	},
3673 	/* Sub-level commands. */
3674 	[GROUP_SET_MISS_ACTIONS] = {
3675 		.name = "set_miss_actions",
3676 		.help = "set group miss actions",
3677 		.next = NEXT(next_action),
3678 		.call = parse_group,
3679 	},
3680 	/* Group arguments */
3681 	[GROUP_ID]	= {
3682 		.name = "group_id",
3683 		.help = "group id",
3684 		.next = NEXT(next_group_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3685 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3686 	},
3687 	[GROUP_INGRESS] = {
3688 		.name = "ingress",
3689 		.help = "group ingress attr",
3690 		.next = NEXT(next_group_attr),
3691 		.call = parse_group,
3692 	},
3693 	[GROUP_EGRESS] = {
3694 		.name = "egress",
3695 		.help = "group egress attr",
3696 		.next = NEXT(next_group_attr),
3697 		.call = parse_group,
3698 	},
3699 	[GROUP_TRANSFER] = {
3700 		.name = "transfer",
3701 		.help = "group transfer attr",
3702 		.next = NEXT(next_group_attr),
3703 		.call = parse_group,
3704 	},
3705 	/* Top-level command. */
3706 	[QUEUE] = {
3707 		.name = "queue",
3708 		.help = "queue a flow rule operation",
3709 		.next = NEXT(next_queue_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3710 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3711 		.call = parse_qo,
3712 	},
3713 	/* Sub-level commands. */
3714 	[QUEUE_CREATE] = {
3715 		.name = "create",
3716 		.help = "create a flow rule",
3717 		.next = NEXT(NEXT_ENTRY(QUEUE_TEMPLATE_TABLE),
3718 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3719 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3720 		.call = parse_qo,
3721 	},
3722 	[QUEUE_DESTROY] = {
3723 		.name = "destroy",
3724 		.help = "destroy a flow rule",
3725 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_POSTPONE),
3726 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3727 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3728 		.call = parse_qo_destroy,
3729 	},
3730 	[QUEUE_FLOW_UPDATE_RESIZED] = {
3731 		.name = "update_resized",
3732 		.help = "update a flow after table resize",
3733 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3734 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3735 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3736 		.call = parse_qo_destroy,
3737 	},
3738 	[QUEUE_UPDATE] = {
3739 		.name = "update",
3740 		.help = "update a flow rule",
3741 		.next = NEXT(NEXT_ENTRY(QUEUE_UPDATE_ID),
3742 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3743 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3744 		.call = parse_qo,
3745 	},
3746 	[QUEUE_AGED] = {
3747 		.name = "aged",
3748 		.help = "list and destroy aged flows",
3749 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_QUEUE_ID)),
3750 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3751 		.call = parse_aged,
3752 	},
3753 	[QUEUE_INDIRECT_ACTION] = {
3754 		.name = "indirect_action",
3755 		.help = "queue indirect actions",
3756 		.next = NEXT(next_qia_subcmd, NEXT_ENTRY(COMMON_QUEUE_ID)),
3757 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3758 		.call = parse_qia,
3759 	},
3760 	/* Queue  arguments. */
3761 	[QUEUE_TEMPLATE_TABLE] = {
3762 		.name = "template_table",
3763 		.help = "specify table id",
3764 		.next = NEXT(next_async_insert_subcmd,
3765 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3766 		.args = ARGS(ARGS_ENTRY(struct buffer,
3767 					args.vc.table_id)),
3768 		.call = parse_qo,
3769 	},
3770 	[QUEUE_PATTERN_TEMPLATE] = {
3771 		.name = "pattern_template",
3772 		.help = "specify pattern template index",
3773 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3774 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3775 		.args = ARGS(ARGS_ENTRY(struct buffer,
3776 					args.vc.pat_templ_id)),
3777 		.call = parse_qo,
3778 	},
3779 	[QUEUE_ACTIONS_TEMPLATE] = {
3780 		.name = "actions_template",
3781 		.help = "specify actions template index",
3782 		.next = NEXT(NEXT_ENTRY(QUEUE_CREATE_POSTPONE),
3783 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3784 		.args = ARGS(ARGS_ENTRY(struct buffer,
3785 					args.vc.act_templ_id)),
3786 		.call = parse_qo,
3787 	},
3788 	[QUEUE_RULE_ID] = {
3789 		.name = "rule_index",
3790 		.help = "specify flow rule index",
3791 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3792 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3793 		.args = ARGS(ARGS_ENTRY(struct buffer,
3794 					args.vc.rule_id)),
3795 		.call = parse_qo,
3796 	},
3797 	[QUEUE_CREATE_POSTPONE] = {
3798 		.name = "postpone",
3799 		.help = "postpone create operation",
3800 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
3801 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3802 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3803 		.call = parse_qo,
3804 	},
3805 	[QUEUE_DESTROY_POSTPONE] = {
3806 		.name = "postpone",
3807 		.help = "postpone destroy operation",
3808 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3809 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3810 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3811 		.call = parse_qo_destroy,
3812 	},
3813 	[QUEUE_DESTROY_ID] = {
3814 		.name = "rule",
3815 		.help = "specify rule id to destroy",
3816 		.next = NEXT(next_queue_destroy_attr,
3817 			NEXT_ENTRY(COMMON_UNSIGNED)),
3818 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3819 					    args.destroy.rule)),
3820 		.call = parse_qo_destroy,
3821 	},
3822 	[QUEUE_UPDATE_ID] = {
3823 		.name = "rule",
3824 		.help = "specify rule id to update",
3825 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3826 			NEXT_ENTRY(COMMON_UNSIGNED)),
3827 		.args = ARGS(ARGS_ENTRY(struct buffer,
3828 				     args.vc.rule_id)),
3829 		.call = parse_qo,
3830 	},
3831 	/* Queue indirect action arguments */
3832 	[QUEUE_INDIRECT_ACTION_CREATE] = {
3833 		.name = "create",
3834 		.help = "create indirect action",
3835 		.next = NEXT(next_qia_create_attr),
3836 		.call = parse_qia,
3837 	},
3838 	[QUEUE_INDIRECT_ACTION_UPDATE] = {
3839 		.name = "update",
3840 		.help = "update indirect action",
3841 		.next = NEXT(next_qia_update_attr,
3842 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3843 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3844 		.call = parse_qia,
3845 	},
3846 	[QUEUE_INDIRECT_ACTION_DESTROY] = {
3847 		.name = "destroy",
3848 		.help = "destroy indirect action",
3849 		.next = NEXT(next_qia_destroy_attr),
3850 		.call = parse_qia_destroy,
3851 	},
3852 	[QUEUE_INDIRECT_ACTION_QUERY] = {
3853 		.name = "query",
3854 		.help = "query indirect action",
3855 		.next = NEXT(next_qia_query_attr,
3856 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3857 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3858 		.call = parse_qia,
3859 	},
3860 	/* Indirect action destroy arguments. */
3861 	[QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE] = {
3862 		.name = "postpone",
3863 		.help = "postpone destroy operation",
3864 		.next = NEXT(next_qia_destroy_attr,
3865 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3866 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3867 	},
3868 	[QUEUE_INDIRECT_ACTION_DESTROY_ID] = {
3869 		.name = "action_id",
3870 		.help = "specify a indirect action id to destroy",
3871 		.next = NEXT(next_qia_destroy_attr,
3872 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3873 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3874 					    args.ia_destroy.action_id)),
3875 		.call = parse_qia_destroy,
3876 	},
3877 	[QUEUE_INDIRECT_ACTION_QUERY_UPDATE] = {
3878 		.name = "query_update",
3879 		.help = "indirect query [and|or] update action",
3880 		.next = NEXT(next_qia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3881 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3882 		.call = parse_qia
3883 	},
3884 	[QUEUE_INDIRECT_ACTION_QU_MODE] = {
3885 		.name = "mode",
3886 		.help = "indirect query [and|or] update action",
3887 		.next = NEXT(next_qia_qu_attr,
3888 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
3889 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
3890 		.call = parse_qia
3891 	},
3892 	/* Indirect action update arguments. */
3893 	[QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE] = {
3894 		.name = "postpone",
3895 		.help = "postpone update operation",
3896 		.next = NEXT(next_qia_update_attr,
3897 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3898 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3899 	},
3900 	/* Indirect action update arguments. */
3901 	[QUEUE_INDIRECT_ACTION_QUERY_POSTPONE] = {
3902 		.name = "postpone",
3903 		.help = "postpone query operation",
3904 		.next = NEXT(next_qia_query_attr,
3905 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3906 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3907 	},
3908 	/* Indirect action create arguments. */
3909 	[QUEUE_INDIRECT_ACTION_CREATE_ID] = {
3910 		.name = "action_id",
3911 		.help = "specify a indirect action id to create",
3912 		.next = NEXT(next_qia_create_attr,
3913 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3914 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3915 	},
3916 	[QUEUE_INDIRECT_ACTION_INGRESS] = {
3917 		.name = "ingress",
3918 		.help = "affect rule to ingress",
3919 		.next = NEXT(next_qia_create_attr),
3920 		.call = parse_qia,
3921 	},
3922 	[QUEUE_INDIRECT_ACTION_EGRESS] = {
3923 		.name = "egress",
3924 		.help = "affect rule to egress",
3925 		.next = NEXT(next_qia_create_attr),
3926 		.call = parse_qia,
3927 	},
3928 	[QUEUE_INDIRECT_ACTION_TRANSFER] = {
3929 		.name = "transfer",
3930 		.help = "affect rule to transfer",
3931 		.next = NEXT(next_qia_create_attr),
3932 		.call = parse_qia,
3933 	},
3934 	[QUEUE_INDIRECT_ACTION_CREATE_POSTPONE] = {
3935 		.name = "postpone",
3936 		.help = "postpone create operation",
3937 		.next = NEXT(next_qia_create_attr,
3938 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3939 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3940 	},
3941 	[QUEUE_INDIRECT_ACTION_SPEC] = {
3942 		.name = "action",
3943 		.help = "specify action to create indirect handle",
3944 		.next = NEXT(next_action),
3945 	},
3946 	[QUEUE_INDIRECT_ACTION_LIST] = {
3947 		.name = "list",
3948 		.help = "specify actions for indirect handle list",
3949 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
3950 		.call = parse_qia,
3951 	},
3952 	/* Top-level command. */
3953 	[PUSH] = {
3954 		.name = "push",
3955 		.help = "push enqueued operations",
3956 		.next = NEXT(NEXT_ENTRY(PUSH_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3957 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3958 		.call = parse_push,
3959 	},
3960 	/* Sub-level commands. */
3961 	[PUSH_QUEUE] = {
3962 		.name = "queue",
3963 		.help = "specify queue id",
3964 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3965 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3966 	},
3967 	/* Top-level command. */
3968 	[PULL] = {
3969 		.name = "pull",
3970 		.help = "pull flow operations results",
3971 		.next = NEXT(NEXT_ENTRY(PULL_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3972 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3973 		.call = parse_pull,
3974 	},
3975 	/* Sub-level commands. */
3976 	[PULL_QUEUE] = {
3977 		.name = "queue",
3978 		.help = "specify queue id",
3979 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3980 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3981 	},
3982 	/* Top-level command. */
3983 	[HASH] = {
3984 		.name = "hash",
3985 		.help = "calculate hash for a given pattern in a given template table",
3986 		.next = NEXT(next_hash_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3987 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3988 		.call = parse_hash,
3989 	},
3990 	/* Sub-level commands. */
3991 	[HASH_CALC_TABLE] = {
3992 		.name = "template_table",
3993 		.help = "specify table id",
3994 		.next = NEXT(NEXT_ENTRY(HASH_CALC_PATTERN_INDEX),
3995 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3996 		.args = ARGS(ARGS_ENTRY(struct buffer,
3997 					args.vc.table_id)),
3998 		.call = parse_hash,
3999 	},
4000 	[HASH_CALC_ENCAP] = {
4001 		.name = "encap",
4002 		.help = "calculates encap hash",
4003 		.next = NEXT(next_hash_encap_dest_subcmd),
4004 		.call = parse_hash,
4005 	},
4006 	[HASH_CALC_PATTERN_INDEX] = {
4007 		.name = "pattern_template",
4008 		.help = "specify pattern template id",
4009 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
4010 			     NEXT_ENTRY(COMMON_UNSIGNED)),
4011 		.args = ARGS(ARGS_ENTRY(struct buffer,
4012 					args.vc.pat_templ_id)),
4013 		.call = parse_hash,
4014 	},
4015 	[ENCAP_HASH_FIELD_SRC_PORT] = {
4016 		.name = "hash_field_sport",
4017 		.help = "the encap hash field is src port",
4018 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
4019 		.call = parse_hash,
4020 	},
4021 	[ENCAP_HASH_FIELD_GRE_FLOW_ID] = {
4022 		.name = "hash_field_flow_id",
4023 		.help = "the encap hash field is NVGRE flow id",
4024 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
4025 		.call = parse_hash,
4026 	},
4027 	/* Top-level command. */
4028 	[INDIRECT_ACTION] = {
4029 		.name = "indirect_action",
4030 		.type = "{command} {port_id} [{arg} [...]]",
4031 		.help = "manage indirect actions",
4032 		.next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
4033 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4034 		.call = parse_ia,
4035 	},
4036 	/* Sub-level commands. */
4037 	[INDIRECT_ACTION_CREATE] = {
4038 		.name = "create",
4039 		.help = "create indirect action",
4040 		.next = NEXT(next_ia_create_attr),
4041 		.call = parse_ia,
4042 	},
4043 	[INDIRECT_ACTION_UPDATE] = {
4044 		.name = "update",
4045 		.help = "update indirect action",
4046 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
4047 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4048 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
4049 		.call = parse_ia,
4050 	},
4051 	[INDIRECT_ACTION_DESTROY] = {
4052 		.name = "destroy",
4053 		.help = "destroy indirect action",
4054 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
4055 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4056 		.call = parse_ia_destroy,
4057 	},
4058 	[INDIRECT_ACTION_QUERY] = {
4059 		.name = "query",
4060 		.help = "query indirect action",
4061 		.next = NEXT(NEXT_ENTRY(END),
4062 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4063 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
4064 		.call = parse_ia,
4065 	},
4066 	[INDIRECT_ACTION_QUERY_UPDATE] = {
4067 		.name = "query_update",
4068 		.help = "query [and|or] update",
4069 		.next = NEXT(next_ia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4070 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
4071 		.call = parse_ia
4072 	},
4073 	[INDIRECT_ACTION_QU_MODE] = {
4074 		.name = "mode",
4075 		.help = "query_update mode",
4076 		.next = NEXT(next_ia_qu_attr,
4077 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
4078 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
4079 		.call = parse_ia,
4080 	},
4081 	[INDIRECT_ACTION_QU_MODE_NAME] = {
4082 		.name = "mode_name",
4083 		.help = "query-update mode name",
4084 		.call = parse_qu_mode_name,
4085 		.comp = comp_qu_mode_name,
4086 	},
4087 	[VALIDATE] = {
4088 		.name = "validate",
4089 		.help = "check whether a flow rule can be created",
4090 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4091 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4092 		.call = parse_vc,
4093 	},
4094 	[CREATE] = {
4095 		.name = "create",
4096 		.help = "create a flow rule",
4097 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4098 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4099 		.call = parse_vc,
4100 	},
4101 	[DESTROY] = {
4102 		.name = "destroy",
4103 		.help = "destroy specific flow rules",
4104 		.next = NEXT(next_destroy_attr,
4105 			     NEXT_ENTRY(COMMON_PORT_ID)),
4106 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4107 		.call = parse_destroy,
4108 	},
4109 	[UPDATE] = {
4110 		.name = "update",
4111 		.help = "update a flow rule with new actions",
4112 		.next = NEXT(NEXT_ENTRY(VC_IS_USER_ID, END),
4113 			     NEXT_ENTRY(ACTIONS),
4114 			     NEXT_ENTRY(COMMON_RULE_ID),
4115 			     NEXT_ENTRY(COMMON_PORT_ID)),
4116 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.rule_id),
4117 			     ARGS_ENTRY(struct buffer, port)),
4118 		.call = parse_vc,
4119 	},
4120 	[FLUSH] = {
4121 		.name = "flush",
4122 		.help = "destroy all flow rules",
4123 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4124 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4125 		.call = parse_flush,
4126 	},
4127 	[DUMP] = {
4128 		.name = "dump",
4129 		.help = "dump single/all flow rules to file",
4130 		.next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
4131 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4132 		.call = parse_dump,
4133 	},
4134 	[QUERY] = {
4135 		.name = "query",
4136 		.help = "query an existing flow rule",
4137 		.next = NEXT(next_query_attr, NEXT_ENTRY(QUERY_ACTION),
4138 			     NEXT_ENTRY(COMMON_RULE_ID),
4139 			     NEXT_ENTRY(COMMON_PORT_ID)),
4140 		.args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
4141 			     ARGS_ENTRY(struct buffer, args.query.rule),
4142 			     ARGS_ENTRY(struct buffer, port)),
4143 		.call = parse_query,
4144 	},
4145 	[LIST] = {
4146 		.name = "list",
4147 		.help = "list existing flow rules",
4148 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4149 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4150 		.call = parse_list,
4151 	},
4152 	[AGED] = {
4153 		.name = "aged",
4154 		.help = "list and destroy aged flows",
4155 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4156 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4157 		.call = parse_aged,
4158 	},
4159 	[ISOLATE] = {
4160 		.name = "isolate",
4161 		.help = "restrict ingress traffic to the defined flow rules",
4162 		.next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
4163 			     NEXT_ENTRY(COMMON_PORT_ID)),
4164 		.args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
4165 			     ARGS_ENTRY(struct buffer, port)),
4166 		.call = parse_isolate,
4167 	},
4168 	[FLEX] = {
4169 		.name = "flex_item",
4170 		.help = "flex item API",
4171 		.next = NEXT(next_flex_item),
4172 		.call = parse_flex,
4173 	},
4174 	[FLEX_ITEM_INIT] = {
4175 		.name = "init",
4176 		.help = "flex item init",
4177 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
4178 			     ARGS_ENTRY(struct buffer, port)),
4179 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
4180 			     NEXT_ENTRY(COMMON_PORT_ID)),
4181 		.call = parse_flex
4182 	},
4183 	[FLEX_ITEM_CREATE] = {
4184 		.name = "create",
4185 		.help = "flex item create",
4186 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename),
4187 			     ARGS_ENTRY(struct buffer, args.flex.token),
4188 			     ARGS_ENTRY(struct buffer, port)),
4189 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH),
4190 			     NEXT_ENTRY(COMMON_FLEX_TOKEN),
4191 			     NEXT_ENTRY(COMMON_PORT_ID)),
4192 		.call = parse_flex
4193 	},
4194 	[FLEX_ITEM_DESTROY] = {
4195 		.name = "destroy",
4196 		.help = "flex item destroy",
4197 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
4198 			     ARGS_ENTRY(struct buffer, port)),
4199 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
4200 			     NEXT_ENTRY(COMMON_PORT_ID)),
4201 		.call = parse_flex
4202 	},
4203 	[TUNNEL] = {
4204 		.name = "tunnel",
4205 		.help = "new tunnel API",
4206 		.next = NEXT(NEXT_ENTRY
4207 			     (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
4208 		.call = parse_tunnel,
4209 	},
4210 	/* Tunnel arguments. */
4211 	[TUNNEL_CREATE] = {
4212 		.name = "create",
4213 		.help = "create new tunnel object",
4214 		.next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
4215 			     NEXT_ENTRY(COMMON_PORT_ID)),
4216 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4217 		.call = parse_tunnel,
4218 	},
4219 	[TUNNEL_CREATE_TYPE] = {
4220 		.name = "type",
4221 		.help = "create new tunnel",
4222 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
4223 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
4224 		.call = parse_tunnel,
4225 	},
4226 	[TUNNEL_DESTROY] = {
4227 		.name = "destroy",
4228 		.help = "destroy tunnel",
4229 		.next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
4230 			     NEXT_ENTRY(COMMON_PORT_ID)),
4231 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4232 		.call = parse_tunnel,
4233 	},
4234 	[TUNNEL_DESTROY_ID] = {
4235 		.name = "id",
4236 		.help = "tunnel identifier to destroy",
4237 		.next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
4238 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4239 		.call = parse_tunnel,
4240 	},
4241 	[TUNNEL_LIST] = {
4242 		.name = "list",
4243 		.help = "list existing tunnels",
4244 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4245 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4246 		.call = parse_tunnel,
4247 	},
4248 	/* Destroy arguments. */
4249 	[DESTROY_RULE] = {
4250 		.name = "rule",
4251 		.help = "specify a rule identifier",
4252 		.next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4253 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
4254 		.call = parse_destroy,
4255 	},
4256 	[DESTROY_IS_USER_ID] = {
4257 		.name = "user_id",
4258 		.help = "rule identifier is user-id",
4259 		.next = NEXT(next_destroy_attr),
4260 		.call = parse_destroy,
4261 	},
4262 	/* Dump arguments. */
4263 	[DUMP_ALL] = {
4264 		.name = "all",
4265 		.help = "dump all",
4266 		.next = NEXT(next_dump_attr),
4267 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
4268 		.call = parse_dump,
4269 	},
4270 	[DUMP_ONE] = {
4271 		.name = "rule",
4272 		.help = "dump one rule",
4273 		.next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4274 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
4275 				ARGS_ENTRY(struct buffer, args.dump.rule)),
4276 		.call = parse_dump,
4277 	},
4278 	[DUMP_IS_USER_ID] = {
4279 		.name = "user_id",
4280 		.help = "rule identifier is user-id",
4281 		.next = NEXT(next_dump_subcmd),
4282 		.call = parse_dump,
4283 	},
4284 	/* Query arguments. */
4285 	[QUERY_ACTION] = {
4286 		.name = "{action}",
4287 		.type = "ACTION",
4288 		.help = "action to query, must be part of the rule",
4289 		.call = parse_action,
4290 		.comp = comp_action,
4291 	},
4292 	[QUERY_IS_USER_ID] = {
4293 		.name = "user_id",
4294 		.help = "rule identifier is user-id",
4295 		.next = NEXT(next_query_attr),
4296 		.call = parse_query,
4297 	},
4298 	/* List arguments. */
4299 	[LIST_GROUP] = {
4300 		.name = "group",
4301 		.help = "specify a group",
4302 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4303 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
4304 		.call = parse_list,
4305 	},
4306 	[AGED_DESTROY] = {
4307 		.name = "destroy",
4308 		.help = "specify aged flows need be destroyed",
4309 		.call = parse_aged,
4310 		.comp = comp_none,
4311 	},
4312 	/* Validate/create attributes. */
4313 	[VC_GROUP] = {
4314 		.name = "group",
4315 		.help = "specify a group",
4316 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4317 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
4318 		.call = parse_vc,
4319 	},
4320 	[VC_PRIORITY] = {
4321 		.name = "priority",
4322 		.help = "specify a priority level",
4323 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
4324 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
4325 		.call = parse_vc,
4326 	},
4327 	[VC_INGRESS] = {
4328 		.name = "ingress",
4329 		.help = "affect rule to ingress",
4330 		.next = NEXT(next_vc_attr),
4331 		.call = parse_vc,
4332 	},
4333 	[VC_EGRESS] = {
4334 		.name = "egress",
4335 		.help = "affect rule to egress",
4336 		.next = NEXT(next_vc_attr),
4337 		.call = parse_vc,
4338 	},
4339 	[VC_TRANSFER] = {
4340 		.name = "transfer",
4341 		.help = "apply rule directly to endpoints found in pattern",
4342 		.next = NEXT(next_vc_attr),
4343 		.call = parse_vc,
4344 	},
4345 	[VC_TUNNEL_SET] = {
4346 		.name = "tunnel_set",
4347 		.help = "tunnel steer rule",
4348 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4349 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4350 		.call = parse_vc,
4351 	},
4352 	[VC_TUNNEL_MATCH] = {
4353 		.name = "tunnel_match",
4354 		.help = "tunnel match rule",
4355 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4356 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4357 		.call = parse_vc,
4358 	},
4359 	[VC_USER_ID] = {
4360 		.name = "user_id",
4361 		.help = "specify a user id to create",
4362 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4363 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.user_id)),
4364 		.call = parse_vc,
4365 	},
4366 	[VC_IS_USER_ID] = {
4367 		.name = "user_id",
4368 		.help = "rule identifier is user-id",
4369 		.call = parse_vc,
4370 	},
4371 	/* Validate/create pattern. */
4372 	[ITEM_PATTERN] = {
4373 		.name = "pattern",
4374 		.help = "submit a list of pattern items",
4375 		.next = NEXT(next_item),
4376 		.call = parse_vc,
4377 	},
4378 	[ITEM_PARAM_IS] = {
4379 		.name = "is",
4380 		.help = "match value perfectly (with full bit-mask)",
4381 		.call = parse_vc_spec,
4382 	},
4383 	[ITEM_PARAM_SPEC] = {
4384 		.name = "spec",
4385 		.help = "match value according to configured bit-mask",
4386 		.call = parse_vc_spec,
4387 	},
4388 	[ITEM_PARAM_LAST] = {
4389 		.name = "last",
4390 		.help = "specify upper bound to establish a range",
4391 		.call = parse_vc_spec,
4392 	},
4393 	[ITEM_PARAM_MASK] = {
4394 		.name = "mask",
4395 		.help = "specify bit-mask with relevant bits set to one",
4396 		.call = parse_vc_spec,
4397 	},
4398 	[ITEM_PARAM_PREFIX] = {
4399 		.name = "prefix",
4400 		.help = "generate bit-mask from a prefix length",
4401 		.call = parse_vc_spec,
4402 	},
4403 	[ITEM_NEXT] = {
4404 		.name = "/",
4405 		.help = "specify next pattern item",
4406 		.next = NEXT(next_item),
4407 	},
4408 	[ITEM_END] = {
4409 		.name = "end",
4410 		.help = "end list of pattern items",
4411 		.priv = PRIV_ITEM(END, 0),
4412 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
4413 		.call = parse_vc,
4414 	},
4415 	[ITEM_VOID] = {
4416 		.name = "void",
4417 		.help = "no-op pattern item",
4418 		.priv = PRIV_ITEM(VOID, 0),
4419 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4420 		.call = parse_vc,
4421 	},
4422 	[ITEM_INVERT] = {
4423 		.name = "invert",
4424 		.help = "perform actions when pattern does not match",
4425 		.priv = PRIV_ITEM(INVERT, 0),
4426 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4427 		.call = parse_vc,
4428 	},
4429 	[ITEM_ANY] = {
4430 		.name = "any",
4431 		.help = "match any protocol for the current layer",
4432 		.priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
4433 		.next = NEXT(item_any),
4434 		.call = parse_vc,
4435 	},
4436 	[ITEM_ANY_NUM] = {
4437 		.name = "num",
4438 		.help = "number of layers covered",
4439 		.next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4440 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
4441 	},
4442 	[ITEM_PORT_ID] = {
4443 		.name = "port_id",
4444 		.help = "match traffic from/to a given DPDK port ID",
4445 		.priv = PRIV_ITEM(PORT_ID,
4446 				  sizeof(struct rte_flow_item_port_id)),
4447 		.next = NEXT(item_port_id),
4448 		.call = parse_vc,
4449 	},
4450 	[ITEM_PORT_ID_ID] = {
4451 		.name = "id",
4452 		.help = "DPDK port ID",
4453 		.next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
4454 			     item_param),
4455 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
4456 	},
4457 	[ITEM_MARK] = {
4458 		.name = "mark",
4459 		.help = "match traffic against value set in previously matched rule",
4460 		.priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
4461 		.next = NEXT(item_mark),
4462 		.call = parse_vc,
4463 	},
4464 	[ITEM_MARK_ID] = {
4465 		.name = "id",
4466 		.help = "Integer value to match against",
4467 		.next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
4468 			     item_param),
4469 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
4470 	},
4471 	[ITEM_RAW] = {
4472 		.name = "raw",
4473 		.help = "match an arbitrary byte string",
4474 		.priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
4475 		.next = NEXT(item_raw),
4476 		.call = parse_vc,
4477 	},
4478 	[ITEM_RAW_RELATIVE] = {
4479 		.name = "relative",
4480 		.help = "look for pattern after the previous item",
4481 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4482 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4483 					   relative, 1)),
4484 	},
4485 	[ITEM_RAW_SEARCH] = {
4486 		.name = "search",
4487 		.help = "search pattern from offset (see also limit)",
4488 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4489 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4490 					   search, 1)),
4491 	},
4492 	[ITEM_RAW_OFFSET] = {
4493 		.name = "offset",
4494 		.help = "absolute or relative offset for pattern",
4495 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
4496 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
4497 	},
4498 	[ITEM_RAW_LIMIT] = {
4499 		.name = "limit",
4500 		.help = "search area limit for start of pattern",
4501 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4502 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
4503 	},
4504 	[ITEM_RAW_PATTERN] = {
4505 		.name = "pattern",
4506 		.help = "byte string to look for",
4507 		.next = NEXT(item_raw,
4508 			     NEXT_ENTRY(COMMON_STRING),
4509 			     NEXT_ENTRY(ITEM_PARAM_IS,
4510 					ITEM_PARAM_SPEC,
4511 					ITEM_PARAM_MASK)),
4512 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4513 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4514 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4515 					    ITEM_RAW_PATTERN_SIZE)),
4516 	},
4517 	[ITEM_RAW_PATTERN_HEX] = {
4518 		.name = "pattern_hex",
4519 		.help = "hex string to look for",
4520 		.next = NEXT(item_raw,
4521 			     NEXT_ENTRY(COMMON_HEX),
4522 			     NEXT_ENTRY(ITEM_PARAM_IS,
4523 					ITEM_PARAM_SPEC,
4524 					ITEM_PARAM_MASK)),
4525 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4526 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4527 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4528 					    ITEM_RAW_PATTERN_SIZE)),
4529 	},
4530 	[ITEM_ETH] = {
4531 		.name = "eth",
4532 		.help = "match Ethernet header",
4533 		.priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
4534 		.next = NEXT(item_eth),
4535 		.call = parse_vc,
4536 	},
4537 	[ITEM_ETH_DST] = {
4538 		.name = "dst",
4539 		.help = "destination MAC",
4540 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4541 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.dst_addr)),
4542 	},
4543 	[ITEM_ETH_SRC] = {
4544 		.name = "src",
4545 		.help = "source MAC",
4546 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4547 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.src_addr)),
4548 	},
4549 	[ITEM_ETH_TYPE] = {
4550 		.name = "type",
4551 		.help = "EtherType",
4552 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4553 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.ether_type)),
4554 	},
4555 	[ITEM_ETH_HAS_VLAN] = {
4556 		.name = "has_vlan",
4557 		.help = "packet header contains VLAN",
4558 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4559 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
4560 					   has_vlan, 1)),
4561 	},
4562 	[ITEM_VLAN] = {
4563 		.name = "vlan",
4564 		.help = "match 802.1Q/ad VLAN tag",
4565 		.priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
4566 		.next = NEXT(item_vlan),
4567 		.call = parse_vc,
4568 	},
4569 	[ITEM_VLAN_TCI] = {
4570 		.name = "tci",
4571 		.help = "tag control information",
4572 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4573 			     item_param),
4574 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, hdr.vlan_tci)),
4575 	},
4576 	[ITEM_VLAN_PCP] = {
4577 		.name = "pcp",
4578 		.help = "priority code point",
4579 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4580 			     item_param),
4581 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4582 						  hdr.vlan_tci, "\xe0\x00")),
4583 	},
4584 	[ITEM_VLAN_DEI] = {
4585 		.name = "dei",
4586 		.help = "drop eligible indicator",
4587 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4588 			     item_param),
4589 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4590 						  hdr.vlan_tci, "\x10\x00")),
4591 	},
4592 	[ITEM_VLAN_VID] = {
4593 		.name = "vid",
4594 		.help = "VLAN identifier",
4595 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4596 			     item_param),
4597 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4598 						  hdr.vlan_tci, "\x0f\xff")),
4599 	},
4600 	[ITEM_VLAN_INNER_TYPE] = {
4601 		.name = "inner_type",
4602 		.help = "inner EtherType",
4603 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4604 			     item_param),
4605 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
4606 					     hdr.eth_proto)),
4607 	},
4608 	[ITEM_VLAN_HAS_MORE_VLAN] = {
4609 		.name = "has_more_vlan",
4610 		.help = "packet header contains another VLAN",
4611 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4612 			     item_param),
4613 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
4614 					   has_more_vlan, 1)),
4615 	},
4616 	[ITEM_IPV4] = {
4617 		.name = "ipv4",
4618 		.help = "match IPv4 header",
4619 		.priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
4620 		.next = NEXT(item_ipv4),
4621 		.call = parse_vc,
4622 	},
4623 	[ITEM_IPV4_VER_IHL] = {
4624 		.name = "version_ihl",
4625 		.help = "match header length",
4626 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4627 			     item_param),
4628 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
4629 				     hdr.version_ihl)),
4630 	},
4631 	[ITEM_IPV4_TOS] = {
4632 		.name = "tos",
4633 		.help = "type of service",
4634 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4635 			     item_param),
4636 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4637 					     hdr.type_of_service)),
4638 	},
4639 	[ITEM_IPV4_LENGTH] = {
4640 		.name = "length",
4641 		.help = "total length",
4642 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4643 			     item_param),
4644 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4645 					     hdr.total_length)),
4646 	},
4647 	[ITEM_IPV4_ID] = {
4648 		.name = "packet_id",
4649 		.help = "fragment packet id",
4650 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4651 			     item_param),
4652 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4653 					     hdr.packet_id)),
4654 	},
4655 	[ITEM_IPV4_FRAGMENT_OFFSET] = {
4656 		.name = "fragment_offset",
4657 		.help = "fragmentation flags and fragment offset",
4658 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4659 			     item_param),
4660 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4661 					     hdr.fragment_offset)),
4662 	},
4663 	[ITEM_IPV4_TTL] = {
4664 		.name = "ttl",
4665 		.help = "time to live",
4666 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4667 			     item_param),
4668 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4669 					     hdr.time_to_live)),
4670 	},
4671 	[ITEM_IPV4_PROTO] = {
4672 		.name = "proto",
4673 		.help = "next protocol ID",
4674 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4675 			     item_param),
4676 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4677 					     hdr.next_proto_id)),
4678 	},
4679 	[ITEM_IPV4_SRC] = {
4680 		.name = "src",
4681 		.help = "source address",
4682 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4683 			     item_param),
4684 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4685 					     hdr.src_addr)),
4686 	},
4687 	[ITEM_IPV4_DST] = {
4688 		.name = "dst",
4689 		.help = "destination address",
4690 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4691 			     item_param),
4692 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4693 					     hdr.dst_addr)),
4694 	},
4695 	[ITEM_IPV6] = {
4696 		.name = "ipv6",
4697 		.help = "match IPv6 header",
4698 		.priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
4699 		.next = NEXT(item_ipv6),
4700 		.call = parse_vc,
4701 	},
4702 	[ITEM_IPV6_TC] = {
4703 		.name = "tc",
4704 		.help = "traffic class",
4705 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4706 			     item_param),
4707 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4708 						  hdr.vtc_flow,
4709 						  "\x0f\xf0\x00\x00")),
4710 	},
4711 	[ITEM_IPV6_FLOW] = {
4712 		.name = "flow",
4713 		.help = "flow label",
4714 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4715 			     item_param),
4716 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4717 						  hdr.vtc_flow,
4718 						  "\x00\x0f\xff\xff")),
4719 	},
4720 	[ITEM_IPV6_LEN] = {
4721 		.name = "length",
4722 		.help = "payload length",
4723 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4724 			     item_param),
4725 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4726 					     hdr.payload_len)),
4727 	},
4728 	[ITEM_IPV6_PROTO] = {
4729 		.name = "proto",
4730 		.help = "protocol (next header)",
4731 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4732 			     item_param),
4733 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4734 					     hdr.proto)),
4735 	},
4736 	[ITEM_IPV6_HOP] = {
4737 		.name = "hop",
4738 		.help = "hop limit",
4739 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4740 			     item_param),
4741 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4742 					     hdr.hop_limits)),
4743 	},
4744 	[ITEM_IPV6_SRC] = {
4745 		.name = "src",
4746 		.help = "source address",
4747 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4748 			     item_param),
4749 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4750 					     hdr.src_addr)),
4751 	},
4752 	[ITEM_IPV6_DST] = {
4753 		.name = "dst",
4754 		.help = "destination address",
4755 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4756 			     item_param),
4757 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4758 					     hdr.dst_addr)),
4759 	},
4760 	[ITEM_IPV6_HAS_FRAG_EXT] = {
4761 		.name = "has_frag_ext",
4762 		.help = "fragment packet attribute",
4763 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4764 			     item_param),
4765 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
4766 					   has_frag_ext, 1)),
4767 	},
4768 	[ITEM_IPV6_ROUTING_EXT] = {
4769 		.name = "ipv6_routing_ext",
4770 		.help = "match IPv6 routing extension header",
4771 		.priv = PRIV_ITEM(IPV6_ROUTING_EXT,
4772 				  sizeof(struct rte_flow_item_ipv6_routing_ext)),
4773 		.next = NEXT(item_ipv6_routing_ext),
4774 		.call = parse_vc,
4775 	},
4776 	[ITEM_IPV6_ROUTING_EXT_TYPE] = {
4777 		.name = "ext_type",
4778 		.help = "match IPv6 routing extension header type",
4779 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4780 			     item_param),
4781 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4782 					     hdr.type)),
4783 	},
4784 	[ITEM_IPV6_ROUTING_EXT_NEXT_HDR] = {
4785 		.name = "ext_next_hdr",
4786 		.help = "match IPv6 routing extension header next header type",
4787 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4788 			     item_param),
4789 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4790 					     hdr.next_hdr)),
4791 	},
4792 	[ITEM_IPV6_ROUTING_EXT_SEG_LEFT] = {
4793 		.name = "ext_seg_left",
4794 		.help = "match IPv6 routing extension header segment left",
4795 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4796 			     item_param),
4797 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4798 					     hdr.segments_left)),
4799 	},
4800 	[ITEM_ICMP] = {
4801 		.name = "icmp",
4802 		.help = "match ICMP header",
4803 		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
4804 		.next = NEXT(item_icmp),
4805 		.call = parse_vc,
4806 	},
4807 	[ITEM_ICMP_TYPE] = {
4808 		.name = "type",
4809 		.help = "ICMP packet type",
4810 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4811 			     item_param),
4812 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4813 					     hdr.icmp_type)),
4814 	},
4815 	[ITEM_ICMP_CODE] = {
4816 		.name = "code",
4817 		.help = "ICMP packet code",
4818 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4819 			     item_param),
4820 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4821 					     hdr.icmp_code)),
4822 	},
4823 	[ITEM_ICMP_IDENT] = {
4824 		.name = "ident",
4825 		.help = "ICMP packet identifier",
4826 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4827 			     item_param),
4828 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4829 					     hdr.icmp_ident)),
4830 	},
4831 	[ITEM_ICMP_SEQ] = {
4832 		.name = "seq",
4833 		.help = "ICMP packet sequence number",
4834 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4835 			     item_param),
4836 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4837 					     hdr.icmp_seq_nb)),
4838 	},
4839 	[ITEM_UDP] = {
4840 		.name = "udp",
4841 		.help = "match UDP header",
4842 		.priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
4843 		.next = NEXT(item_udp),
4844 		.call = parse_vc,
4845 	},
4846 	[ITEM_UDP_SRC] = {
4847 		.name = "src",
4848 		.help = "UDP source port",
4849 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
4850 			     item_param),
4851 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4852 					     hdr.src_port)),
4853 	},
4854 	[ITEM_UDP_DST] = {
4855 		.name = "dst",
4856 		.help = "UDP destination port",
4857 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4858 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4859 					     hdr.dst_port)),
4860 	},
4861 	[ITEM_TCP] = {
4862 		.name = "tcp",
4863 		.help = "match TCP header",
4864 		.priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
4865 		.next = NEXT(item_tcp),
4866 		.call = parse_vc,
4867 	},
4868 	[ITEM_TCP_SRC] = {
4869 		.name = "src",
4870 		.help = "TCP source port",
4871 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4872 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4873 					     hdr.src_port)),
4874 	},
4875 	[ITEM_TCP_DST] = {
4876 		.name = "dst",
4877 		.help = "TCP destination port",
4878 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4879 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4880 					     hdr.dst_port)),
4881 	},
4882 	[ITEM_TCP_FLAGS] = {
4883 		.name = "flags",
4884 		.help = "TCP flags",
4885 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4886 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4887 					     hdr.tcp_flags)),
4888 	},
4889 	[ITEM_SCTP] = {
4890 		.name = "sctp",
4891 		.help = "match SCTP header",
4892 		.priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
4893 		.next = NEXT(item_sctp),
4894 		.call = parse_vc,
4895 	},
4896 	[ITEM_SCTP_SRC] = {
4897 		.name = "src",
4898 		.help = "SCTP source port",
4899 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4900 			     item_param),
4901 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4902 					     hdr.src_port)),
4903 	},
4904 	[ITEM_SCTP_DST] = {
4905 		.name = "dst",
4906 		.help = "SCTP destination port",
4907 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4908 			     item_param),
4909 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4910 					     hdr.dst_port)),
4911 	},
4912 	[ITEM_SCTP_TAG] = {
4913 		.name = "tag",
4914 		.help = "validation tag",
4915 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4916 			     item_param),
4917 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4918 					     hdr.tag)),
4919 	},
4920 	[ITEM_SCTP_CKSUM] = {
4921 		.name = "cksum",
4922 		.help = "checksum",
4923 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4924 			     item_param),
4925 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4926 					     hdr.cksum)),
4927 	},
4928 	[ITEM_VXLAN] = {
4929 		.name = "vxlan",
4930 		.help = "match VXLAN header",
4931 		.priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
4932 		.next = NEXT(item_vxlan),
4933 		.call = parse_vc,
4934 	},
4935 	[ITEM_VXLAN_VNI] = {
4936 		.name = "vni",
4937 		.help = "VXLAN identifier",
4938 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4939 			     item_param),
4940 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, hdr.vni)),
4941 	},
4942 	[ITEM_VXLAN_FLAG_G] = {
4943 		.name = "flag_g",
4944 		.help = "VXLAN GBP bit",
4945 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4946 			     item_param),
4947 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4948 					   hdr.flag_g, 1)),
4949 	},
4950 	[ITEM_VXLAN_FLAG_VER] = {
4951 		.name = "flag_ver",
4952 		.help = "VXLAN GPE version",
4953 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4954 			     item_param),
4955 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4956 					   hdr.flag_ver, 2)),
4957 	},
4958 	[ITEM_VXLAN_FLAG_I] = {
4959 		.name = "flag_i",
4960 		.help = "VXLAN Instance bit",
4961 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4962 			     item_param),
4963 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4964 					   hdr.flag_i, 1)),
4965 	},
4966 	[ITEM_VXLAN_FLAG_P] = {
4967 		.name = "flag_p",
4968 		.help = "VXLAN GPE Next Protocol bit",
4969 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4970 			     item_param),
4971 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4972 					   hdr.flag_p, 1)),
4973 	},
4974 	[ITEM_VXLAN_FLAG_B] = {
4975 		.name = "flag_b",
4976 		.help = "VXLAN GPE Ingress-Replicated BUM",
4977 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4978 			     item_param),
4979 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4980 					   hdr.flag_b, 1)),
4981 	},
4982 	[ITEM_VXLAN_FLAG_O] = {
4983 		.name = "flag_o",
4984 		.help = "VXLAN GPE OAM Packet bit",
4985 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4986 			     item_param),
4987 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4988 					   hdr.flag_o, 1)),
4989 	},
4990 	[ITEM_VXLAN_FLAG_D] = {
4991 		.name = "flag_d",
4992 		.help = "VXLAN GBP Don't Learn bit",
4993 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4994 			     item_param),
4995 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4996 					   hdr.flag_d, 1)),
4997 	},
4998 	[ITEM_VXLAN_FLAG_A] = {
4999 		.name = "flag_a",
5000 		.help = "VXLAN GBP Applied bit",
5001 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5002 			     item_param),
5003 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
5004 					   hdr.flag_a, 1)),
5005 	},
5006 	[ITEM_VXLAN_GBP_ID] = {
5007 		.name = "group_policy_id",
5008 		.help = "VXLAN GBP ID",
5009 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5010 			     item_param),
5011 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5012 					     hdr.policy_id)),
5013 	},
5014 	[ITEM_VXLAN_GPE_PROTO] = {
5015 		.name = "protocol",
5016 		.help = "VXLAN GPE next protocol",
5017 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5018 			     item_param),
5019 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5020 					     hdr.proto)),
5021 	},
5022 	[ITEM_VXLAN_FIRST_RSVD] = {
5023 		.name = "first_rsvd",
5024 		.help = "VXLAN rsvd0 first byte",
5025 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5026 			     item_param),
5027 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5028 					     hdr.rsvd0[0])),
5029 	},
5030 	[ITEM_VXLAN_SECND_RSVD] = {
5031 		.name = "second_rsvd",
5032 		.help = "VXLAN rsvd0 second byte",
5033 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5034 			     item_param),
5035 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5036 					     hdr.rsvd0[1])),
5037 	},
5038 	[ITEM_VXLAN_THIRD_RSVD] = {
5039 		.name = "third_rsvd",
5040 		.help = "VXLAN rsvd0 third byte",
5041 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5042 			     item_param),
5043 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5044 					     hdr.rsvd0[2])),
5045 	},
5046 	[ITEM_VXLAN_LAST_RSVD] = {
5047 		.name = "last_rsvd",
5048 		.help = "VXLAN last reserved byte",
5049 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5050 			     item_param),
5051 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5052 					     hdr.last_rsvd)),
5053 	},
5054 	[ITEM_E_TAG] = {
5055 		.name = "e_tag",
5056 		.help = "match E-Tag header",
5057 		.priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
5058 		.next = NEXT(item_e_tag),
5059 		.call = parse_vc,
5060 	},
5061 	[ITEM_E_TAG_GRP_ECID_B] = {
5062 		.name = "grp_ecid_b",
5063 		.help = "GRP and E-CID base",
5064 		.next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
5065 			     item_param),
5066 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
5067 						  rsvd_grp_ecid_b,
5068 						  "\x3f\xff")),
5069 	},
5070 	[ITEM_NVGRE] = {
5071 		.name = "nvgre",
5072 		.help = "match NVGRE header",
5073 		.priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
5074 		.next = NEXT(item_nvgre),
5075 		.call = parse_vc,
5076 	},
5077 	[ITEM_NVGRE_TNI] = {
5078 		.name = "tni",
5079 		.help = "virtual subnet ID",
5080 		.next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
5081 			     item_param),
5082 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
5083 	},
5084 	[ITEM_MPLS] = {
5085 		.name = "mpls",
5086 		.help = "match MPLS header",
5087 		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
5088 		.next = NEXT(item_mpls),
5089 		.call = parse_vc,
5090 	},
5091 	[ITEM_MPLS_LABEL] = {
5092 		.name = "label",
5093 		.help = "MPLS label",
5094 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
5095 			     item_param),
5096 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
5097 						  label_tc_s,
5098 						  "\xff\xff\xf0")),
5099 	},
5100 	[ITEM_MPLS_TC] = {
5101 		.name = "tc",
5102 		.help = "MPLS Traffic Class",
5103 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
5104 			     item_param),
5105 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
5106 						  label_tc_s,
5107 						  "\x00\x00\x0e")),
5108 	},
5109 	[ITEM_MPLS_S] = {
5110 		.name = "s",
5111 		.help = "MPLS Bottom-of-Stack",
5112 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
5113 			     item_param),
5114 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
5115 						  label_tc_s,
5116 						  "\x00\x00\x01")),
5117 	},
5118 	[ITEM_MPLS_TTL] = {
5119 		.name = "ttl",
5120 		.help = "MPLS Time-to-Live",
5121 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
5122 			     item_param),
5123 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_mpls, ttl)),
5124 	},
5125 	[ITEM_GRE] = {
5126 		.name = "gre",
5127 		.help = "match GRE header",
5128 		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
5129 		.next = NEXT(item_gre),
5130 		.call = parse_vc,
5131 	},
5132 	[ITEM_GRE_PROTO] = {
5133 		.name = "protocol",
5134 		.help = "GRE protocol type",
5135 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
5136 			     item_param),
5137 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
5138 					     protocol)),
5139 	},
5140 	[ITEM_GRE_C_RSVD0_VER] = {
5141 		.name = "c_rsvd0_ver",
5142 		.help =
5143 			"checksum (1b), undefined (1b), key bit (1b),"
5144 			" sequence number (1b), reserved 0 (9b),"
5145 			" version (3b)",
5146 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
5147 			     item_param),
5148 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
5149 					     c_rsvd0_ver)),
5150 	},
5151 	[ITEM_GRE_C_BIT] = {
5152 		.name = "c_bit",
5153 		.help = "checksum bit (C)",
5154 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
5155 			     item_param),
5156 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5157 						  c_rsvd0_ver,
5158 						  "\x80\x00\x00\x00")),
5159 	},
5160 	[ITEM_GRE_S_BIT] = {
5161 		.name = "s_bit",
5162 		.help = "sequence number bit (S)",
5163 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
5164 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5165 						  c_rsvd0_ver,
5166 						  "\x10\x00\x00\x00")),
5167 	},
5168 	[ITEM_GRE_K_BIT] = {
5169 		.name = "k_bit",
5170 		.help = "key bit (K)",
5171 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
5172 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5173 						  c_rsvd0_ver,
5174 						  "\x20\x00\x00\x00")),
5175 	},
5176 	[ITEM_FUZZY] = {
5177 		.name = "fuzzy",
5178 		.help = "fuzzy pattern match, expect faster than default",
5179 		.priv = PRIV_ITEM(FUZZY,
5180 				sizeof(struct rte_flow_item_fuzzy)),
5181 		.next = NEXT(item_fuzzy),
5182 		.call = parse_vc,
5183 	},
5184 	[ITEM_FUZZY_THRESH] = {
5185 		.name = "thresh",
5186 		.help = "match accuracy threshold",
5187 		.next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
5188 			     item_param),
5189 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
5190 					thresh)),
5191 	},
5192 	[ITEM_GTP] = {
5193 		.name = "gtp",
5194 		.help = "match GTP header",
5195 		.priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
5196 		.next = NEXT(item_gtp),
5197 		.call = parse_vc,
5198 	},
5199 	[ITEM_GTP_FLAGS] = {
5200 		.name = "v_pt_rsv_flags",
5201 		.help = "GTP flags",
5202 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5203 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
5204 					hdr.gtp_hdr_info)),
5205 	},
5206 	[ITEM_GTP_MSG_TYPE] = {
5207 		.name = "msg_type",
5208 		.help = "GTP message type",
5209 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5210 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, hdr.msg_type)),
5211 	},
5212 	[ITEM_GTP_TEID] = {
5213 		.name = "teid",
5214 		.help = "tunnel endpoint identifier",
5215 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5216 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, hdr.teid)),
5217 	},
5218 	[ITEM_GTPC] = {
5219 		.name = "gtpc",
5220 		.help = "match GTP header",
5221 		.priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
5222 		.next = NEXT(item_gtp),
5223 		.call = parse_vc,
5224 	},
5225 	[ITEM_GTPU] = {
5226 		.name = "gtpu",
5227 		.help = "match GTP header",
5228 		.priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
5229 		.next = NEXT(item_gtp),
5230 		.call = parse_vc,
5231 	},
5232 	[ITEM_GENEVE] = {
5233 		.name = "geneve",
5234 		.help = "match GENEVE header",
5235 		.priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
5236 		.next = NEXT(item_geneve),
5237 		.call = parse_vc,
5238 	},
5239 	[ITEM_GENEVE_VNI] = {
5240 		.name = "vni",
5241 		.help = "virtual network identifier",
5242 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5243 			     item_param),
5244 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
5245 	},
5246 	[ITEM_GENEVE_PROTO] = {
5247 		.name = "protocol",
5248 		.help = "GENEVE protocol type",
5249 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5250 			     item_param),
5251 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
5252 					     protocol)),
5253 	},
5254 	[ITEM_GENEVE_OPTLEN] = {
5255 		.name = "optlen",
5256 		.help = "GENEVE options length in dwords",
5257 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5258 			     item_param),
5259 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
5260 						  ver_opt_len_o_c_rsvd0,
5261 						  "\x3f\x00")),
5262 	},
5263 	[ITEM_VXLAN_GPE] = {
5264 		.name = "vxlan-gpe",
5265 		.help = "match VXLAN-GPE header",
5266 		.priv = PRIV_ITEM(VXLAN_GPE,
5267 				  sizeof(struct rte_flow_item_vxlan_gpe)),
5268 		.next = NEXT(item_vxlan_gpe),
5269 		.call = parse_vc,
5270 	},
5271 	[ITEM_VXLAN_GPE_VNI] = {
5272 		.name = "vni",
5273 		.help = "VXLAN-GPE identifier",
5274 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5275 			     item_param),
5276 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5277 					     hdr.vni)),
5278 	},
5279 	[ITEM_VXLAN_GPE_PROTO_IN_DEPRECATED_VXLAN_GPE_HDR] = {
5280 		.name = "protocol",
5281 		.help = "VXLAN-GPE next protocol",
5282 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5283 			     item_param),
5284 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5285 					     protocol)),
5286 	},
5287 	[ITEM_VXLAN_GPE_FLAGS] = {
5288 		.name = "flags",
5289 		.help = "VXLAN-GPE flags",
5290 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5291 			     item_param),
5292 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5293 					     flags)),
5294 	},
5295 	[ITEM_VXLAN_GPE_RSVD0] = {
5296 		.name = "rsvd0",
5297 		.help = "VXLAN-GPE rsvd0",
5298 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5299 			     item_param),
5300 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5301 					     rsvd0)),
5302 	},
5303 	[ITEM_VXLAN_GPE_RSVD1] = {
5304 		.name = "rsvd1",
5305 		.help = "VXLAN-GPE rsvd1",
5306 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5307 			     item_param),
5308 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5309 					     rsvd1)),
5310 	},
5311 	[ITEM_ARP_ETH_IPV4] = {
5312 		.name = "arp_eth_ipv4",
5313 		.help = "match ARP header for Ethernet/IPv4",
5314 		.priv = PRIV_ITEM(ARP_ETH_IPV4,
5315 				  sizeof(struct rte_flow_item_arp_eth_ipv4)),
5316 		.next = NEXT(item_arp_eth_ipv4),
5317 		.call = parse_vc,
5318 	},
5319 	[ITEM_ARP_ETH_IPV4_SHA] = {
5320 		.name = "sha",
5321 		.help = "sender hardware address",
5322 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5323 			     item_param),
5324 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5325 					     hdr.arp_data.arp_sha)),
5326 	},
5327 	[ITEM_ARP_ETH_IPV4_SPA] = {
5328 		.name = "spa",
5329 		.help = "sender IPv4 address",
5330 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5331 			     item_param),
5332 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5333 					     hdr.arp_data.arp_sip)),
5334 	},
5335 	[ITEM_ARP_ETH_IPV4_THA] = {
5336 		.name = "tha",
5337 		.help = "target hardware address",
5338 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5339 			     item_param),
5340 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5341 					     hdr.arp_data.arp_tha)),
5342 	},
5343 	[ITEM_ARP_ETH_IPV4_TPA] = {
5344 		.name = "tpa",
5345 		.help = "target IPv4 address",
5346 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5347 			     item_param),
5348 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5349 					     hdr.arp_data.arp_tip)),
5350 	},
5351 	[ITEM_IPV6_EXT] = {
5352 		.name = "ipv6_ext",
5353 		.help = "match presence of any IPv6 extension header",
5354 		.priv = PRIV_ITEM(IPV6_EXT,
5355 				  sizeof(struct rte_flow_item_ipv6_ext)),
5356 		.next = NEXT(item_ipv6_ext),
5357 		.call = parse_vc,
5358 	},
5359 	[ITEM_IPV6_EXT_NEXT_HDR] = {
5360 		.name = "next_hdr",
5361 		.help = "next header",
5362 		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5363 			     item_param),
5364 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
5365 					     next_hdr)),
5366 	},
5367 	[ITEM_IPV6_FRAG_EXT] = {
5368 		.name = "ipv6_frag_ext",
5369 		.help = "match presence of IPv6 fragment extension header",
5370 		.priv = PRIV_ITEM(IPV6_FRAG_EXT,
5371 				sizeof(struct rte_flow_item_ipv6_frag_ext)),
5372 		.next = NEXT(item_ipv6_frag_ext),
5373 		.call = parse_vc,
5374 	},
5375 	[ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
5376 		.name = "next_hdr",
5377 		.help = "next header",
5378 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5379 			     item_param),
5380 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
5381 					hdr.next_header)),
5382 	},
5383 	[ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
5384 		.name = "frag_data",
5385 		.help = "fragment flags and offset",
5386 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5387 			     item_param),
5388 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5389 					     hdr.frag_data)),
5390 	},
5391 	[ITEM_IPV6_FRAG_EXT_ID] = {
5392 		.name = "packet_id",
5393 		.help = "fragment packet id",
5394 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5395 			     item_param),
5396 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5397 					     hdr.id)),
5398 	},
5399 	[ITEM_ICMP6] = {
5400 		.name = "icmp6",
5401 		.help = "match any ICMPv6 header",
5402 		.priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
5403 		.next = NEXT(item_icmp6),
5404 		.call = parse_vc,
5405 	},
5406 	[ITEM_ICMP6_TYPE] = {
5407 		.name = "type",
5408 		.help = "ICMPv6 type",
5409 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5410 			     item_param),
5411 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5412 					     type)),
5413 	},
5414 	[ITEM_ICMP6_CODE] = {
5415 		.name = "code",
5416 		.help = "ICMPv6 code",
5417 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5418 			     item_param),
5419 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5420 					     code)),
5421 	},
5422 	[ITEM_ICMP6_ECHO_REQUEST] = {
5423 		.name = "icmp6_echo_request",
5424 		.help = "match ICMPv6 echo request",
5425 		.priv = PRIV_ITEM(ICMP6_ECHO_REQUEST,
5426 				  sizeof(struct rte_flow_item_icmp6_echo)),
5427 		.next = NEXT(item_icmp6_echo_request),
5428 		.call = parse_vc,
5429 	},
5430 	[ITEM_ICMP6_ECHO_REQUEST_ID] = {
5431 		.name = "ident",
5432 		.help = "ICMPv6 echo request identifier",
5433 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5434 			     item_param),
5435 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5436 					     hdr.identifier)),
5437 	},
5438 	[ITEM_ICMP6_ECHO_REQUEST_SEQ] = {
5439 		.name = "seq",
5440 		.help = "ICMPv6 echo request sequence",
5441 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5442 			     item_param),
5443 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5444 					     hdr.sequence)),
5445 	},
5446 	[ITEM_ICMP6_ECHO_REPLY] = {
5447 		.name = "icmp6_echo_reply",
5448 		.help = "match ICMPv6 echo reply",
5449 		.priv = PRIV_ITEM(ICMP6_ECHO_REPLY,
5450 				  sizeof(struct rte_flow_item_icmp6_echo)),
5451 		.next = NEXT(item_icmp6_echo_reply),
5452 		.call = parse_vc,
5453 	},
5454 	[ITEM_ICMP6_ECHO_REPLY_ID] = {
5455 		.name = "ident",
5456 		.help = "ICMPv6 echo reply identifier",
5457 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5458 			     item_param),
5459 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5460 					     hdr.identifier)),
5461 	},
5462 	[ITEM_ICMP6_ECHO_REPLY_SEQ] = {
5463 		.name = "seq",
5464 		.help = "ICMPv6 echo reply sequence",
5465 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5466 			     item_param),
5467 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5468 					     hdr.sequence)),
5469 	},
5470 	[ITEM_ICMP6_ND_NS] = {
5471 		.name = "icmp6_nd_ns",
5472 		.help = "match ICMPv6 neighbor discovery solicitation",
5473 		.priv = PRIV_ITEM(ICMP6_ND_NS,
5474 				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
5475 		.next = NEXT(item_icmp6_nd_ns),
5476 		.call = parse_vc,
5477 	},
5478 	[ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
5479 		.name = "target_addr",
5480 		.help = "target address",
5481 		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
5482 			     item_param),
5483 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
5484 					     target_addr)),
5485 	},
5486 	[ITEM_ICMP6_ND_NA] = {
5487 		.name = "icmp6_nd_na",
5488 		.help = "match ICMPv6 neighbor discovery advertisement",
5489 		.priv = PRIV_ITEM(ICMP6_ND_NA,
5490 				  sizeof(struct rte_flow_item_icmp6_nd_na)),
5491 		.next = NEXT(item_icmp6_nd_na),
5492 		.call = parse_vc,
5493 	},
5494 	[ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
5495 		.name = "target_addr",
5496 		.help = "target address",
5497 		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
5498 			     item_param),
5499 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
5500 					     target_addr)),
5501 	},
5502 	[ITEM_ICMP6_ND_OPT] = {
5503 		.name = "icmp6_nd_opt",
5504 		.help = "match presence of any ICMPv6 neighbor discovery"
5505 			" option",
5506 		.priv = PRIV_ITEM(ICMP6_ND_OPT,
5507 				  sizeof(struct rte_flow_item_icmp6_nd_opt)),
5508 		.next = NEXT(item_icmp6_nd_opt),
5509 		.call = parse_vc,
5510 	},
5511 	[ITEM_ICMP6_ND_OPT_TYPE] = {
5512 		.name = "type",
5513 		.help = "ND option type",
5514 		.next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5515 			     item_param),
5516 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
5517 					     type)),
5518 	},
5519 	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
5520 		.name = "icmp6_nd_opt_sla_eth",
5521 		.help = "match ICMPv6 neighbor discovery source Ethernet"
5522 			" link-layer address option",
5523 		.priv = PRIV_ITEM
5524 			(ICMP6_ND_OPT_SLA_ETH,
5525 			 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
5526 		.next = NEXT(item_icmp6_nd_opt_sla_eth),
5527 		.call = parse_vc,
5528 	},
5529 	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
5530 		.name = "sla",
5531 		.help = "source Ethernet LLA",
5532 		.next = NEXT(item_icmp6_nd_opt_sla_eth,
5533 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5534 		.args = ARGS(ARGS_ENTRY_HTON
5535 			     (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
5536 	},
5537 	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
5538 		.name = "icmp6_nd_opt_tla_eth",
5539 		.help = "match ICMPv6 neighbor discovery target Ethernet"
5540 			" link-layer address option",
5541 		.priv = PRIV_ITEM
5542 			(ICMP6_ND_OPT_TLA_ETH,
5543 			 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
5544 		.next = NEXT(item_icmp6_nd_opt_tla_eth),
5545 		.call = parse_vc,
5546 	},
5547 	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
5548 		.name = "tla",
5549 		.help = "target Ethernet LLA",
5550 		.next = NEXT(item_icmp6_nd_opt_tla_eth,
5551 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5552 		.args = ARGS(ARGS_ENTRY_HTON
5553 			     (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
5554 	},
5555 	[ITEM_META] = {
5556 		.name = "meta",
5557 		.help = "match metadata header",
5558 		.priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
5559 		.next = NEXT(item_meta),
5560 		.call = parse_vc,
5561 	},
5562 	[ITEM_META_DATA] = {
5563 		.name = "data",
5564 		.help = "metadata value",
5565 		.next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
5566 			     item_param),
5567 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
5568 					     data, "\xff\xff\xff\xff")),
5569 	},
5570 	[ITEM_RANDOM] = {
5571 		.name = "random",
5572 		.help = "match random value",
5573 		.priv = PRIV_ITEM(RANDOM, sizeof(struct rte_flow_item_random)),
5574 		.next = NEXT(item_random),
5575 		.call = parse_vc,
5576 	},
5577 	[ITEM_RANDOM_VALUE] = {
5578 		.name = "value",
5579 		.help = "random value",
5580 		.next = NEXT(item_random, NEXT_ENTRY(COMMON_UNSIGNED),
5581 			     item_param),
5582 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_random,
5583 					     value, "\xff\xff")),
5584 	},
5585 	[ITEM_GRE_KEY] = {
5586 		.name = "gre_key",
5587 		.help = "match GRE key",
5588 		.priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
5589 		.next = NEXT(item_gre_key),
5590 		.call = parse_vc,
5591 	},
5592 	[ITEM_GRE_KEY_VALUE] = {
5593 		.name = "value",
5594 		.help = "key value",
5595 		.next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
5596 			     item_param),
5597 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5598 	},
5599 	[ITEM_GRE_OPTION] = {
5600 		.name = "gre_option",
5601 		.help = "match GRE optional fields",
5602 		.priv = PRIV_ITEM(GRE_OPTION,
5603 				  sizeof(struct rte_flow_item_gre_opt)),
5604 		.next = NEXT(item_gre_option),
5605 		.call = parse_vc,
5606 	},
5607 	[ITEM_GRE_OPTION_CHECKSUM] = {
5608 		.name = "checksum",
5609 		.help = "match GRE checksum",
5610 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5611 			     item_param),
5612 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5613 					     checksum_rsvd.checksum)),
5614 	},
5615 	[ITEM_GRE_OPTION_KEY] = {
5616 		.name = "key",
5617 		.help = "match GRE key",
5618 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5619 			     item_param),
5620 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5621 					     key.key)),
5622 	},
5623 	[ITEM_GRE_OPTION_SEQUENCE] = {
5624 		.name = "sequence",
5625 		.help = "match GRE sequence",
5626 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5627 			     item_param),
5628 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5629 					     sequence.sequence)),
5630 	},
5631 	[ITEM_GTP_PSC] = {
5632 		.name = "gtp_psc",
5633 		.help = "match GTP extension header with type 0x85",
5634 		.priv = PRIV_ITEM(GTP_PSC,
5635 				sizeof(struct rte_flow_item_gtp_psc)),
5636 		.next = NEXT(item_gtp_psc),
5637 		.call = parse_vc,
5638 	},
5639 	[ITEM_GTP_PSC_QFI] = {
5640 		.name = "qfi",
5641 		.help = "QoS flow identifier",
5642 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5643 			     item_param),
5644 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5645 					hdr.qfi, 6)),
5646 	},
5647 	[ITEM_GTP_PSC_PDU_T] = {
5648 		.name = "pdu_t",
5649 		.help = "PDU type",
5650 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5651 			     item_param),
5652 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5653 					hdr.type, 4)),
5654 	},
5655 	[ITEM_PPPOES] = {
5656 		.name = "pppoes",
5657 		.help = "match PPPoE session header",
5658 		.priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
5659 		.next = NEXT(item_pppoes),
5660 		.call = parse_vc,
5661 	},
5662 	[ITEM_PPPOED] = {
5663 		.name = "pppoed",
5664 		.help = "match PPPoE discovery header",
5665 		.priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
5666 		.next = NEXT(item_pppoed),
5667 		.call = parse_vc,
5668 	},
5669 	[ITEM_PPPOE_SEID] = {
5670 		.name = "seid",
5671 		.help = "session identifier",
5672 		.next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
5673 			     item_param),
5674 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
5675 					session_id)),
5676 	},
5677 	[ITEM_PPPOE_PROTO_ID] = {
5678 		.name = "pppoe_proto_id",
5679 		.help = "match PPPoE session protocol identifier",
5680 		.priv = PRIV_ITEM(PPPOE_PROTO_ID,
5681 				sizeof(struct rte_flow_item_pppoe_proto_id)),
5682 		.next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
5683 			     item_param),
5684 		.args = ARGS(ARGS_ENTRY_HTON
5685 			     (struct rte_flow_item_pppoe_proto_id, proto_id)),
5686 		.call = parse_vc,
5687 	},
5688 	[ITEM_HIGIG2] = {
5689 		.name = "higig2",
5690 		.help = "matches higig2 header",
5691 		.priv = PRIV_ITEM(HIGIG2,
5692 				sizeof(struct rte_flow_item_higig2_hdr)),
5693 		.next = NEXT(item_higig2),
5694 		.call = parse_vc,
5695 	},
5696 	[ITEM_HIGIG2_CLASSIFICATION] = {
5697 		.name = "classification",
5698 		.help = "matches classification of higig2 header",
5699 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5700 			     item_param),
5701 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5702 					hdr.ppt1.classification)),
5703 	},
5704 	[ITEM_HIGIG2_VID] = {
5705 		.name = "vid",
5706 		.help = "matches vid of higig2 header",
5707 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5708 			     item_param),
5709 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5710 					hdr.ppt1.vid)),
5711 	},
5712 	[ITEM_TAG] = {
5713 		.name = "tag",
5714 		.help = "match tag value",
5715 		.priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
5716 		.next = NEXT(item_tag),
5717 		.call = parse_vc,
5718 	},
5719 	[ITEM_TAG_DATA] = {
5720 		.name = "data",
5721 		.help = "tag value to match",
5722 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5723 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
5724 	},
5725 	[ITEM_TAG_INDEX] = {
5726 		.name = "index",
5727 		.help = "index of tag array to match",
5728 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
5729 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5730 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
5731 	},
5732 	[ITEM_L2TPV3OIP] = {
5733 		.name = "l2tpv3oip",
5734 		.help = "match L2TPv3 over IP header",
5735 		.priv = PRIV_ITEM(L2TPV3OIP,
5736 				  sizeof(struct rte_flow_item_l2tpv3oip)),
5737 		.next = NEXT(item_l2tpv3oip),
5738 		.call = parse_vc,
5739 	},
5740 	[ITEM_L2TPV3OIP_SESSION_ID] = {
5741 		.name = "session_id",
5742 		.help = "session identifier",
5743 		.next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
5744 			     item_param),
5745 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
5746 					     session_id)),
5747 	},
5748 	[ITEM_ESP] = {
5749 		.name = "esp",
5750 		.help = "match ESP header",
5751 		.priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
5752 		.next = NEXT(item_esp),
5753 		.call = parse_vc,
5754 	},
5755 	[ITEM_ESP_SPI] = {
5756 		.name = "spi",
5757 		.help = "security policy index",
5758 		.next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5759 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
5760 				hdr.spi)),
5761 	},
5762 	[ITEM_AH] = {
5763 		.name = "ah",
5764 		.help = "match AH header",
5765 		.priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
5766 		.next = NEXT(item_ah),
5767 		.call = parse_vc,
5768 	},
5769 	[ITEM_AH_SPI] = {
5770 		.name = "spi",
5771 		.help = "security parameters index",
5772 		.next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5773 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
5774 	},
5775 	[ITEM_PFCP] = {
5776 		.name = "pfcp",
5777 		.help = "match pfcp header",
5778 		.priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
5779 		.next = NEXT(item_pfcp),
5780 		.call = parse_vc,
5781 	},
5782 	[ITEM_PFCP_S_FIELD] = {
5783 		.name = "s_field",
5784 		.help = "S field",
5785 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5786 			     item_param),
5787 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
5788 				s_field)),
5789 	},
5790 	[ITEM_PFCP_SEID] = {
5791 		.name = "seid",
5792 		.help = "session endpoint identifier",
5793 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5794 			     item_param),
5795 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
5796 	},
5797 	[ITEM_ECPRI] = {
5798 		.name = "ecpri",
5799 		.help = "match eCPRI header",
5800 		.priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
5801 		.next = NEXT(item_ecpri),
5802 		.call = parse_vc,
5803 	},
5804 	[ITEM_ECPRI_COMMON] = {
5805 		.name = "common",
5806 		.help = "eCPRI common header",
5807 		.next = NEXT(item_ecpri_common),
5808 	},
5809 	[ITEM_ECPRI_COMMON_TYPE] = {
5810 		.name = "type",
5811 		.help = "type of common header",
5812 		.next = NEXT(item_ecpri_common_type),
5813 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
5814 	},
5815 	[ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
5816 		.name = "iq_data",
5817 		.help = "Type #0: IQ Data",
5818 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5819 					ITEM_NEXT)),
5820 		.call = parse_vc_item_ecpri_type,
5821 	},
5822 	[ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
5823 		.name = "pc_id",
5824 		.help = "Physical Channel ID",
5825 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5826 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5827 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5828 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5829 				hdr.type0.pc_id)),
5830 	},
5831 	[ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
5832 		.name = "rtc_ctrl",
5833 		.help = "Type #2: Real-Time Control Data",
5834 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5835 					ITEM_NEXT)),
5836 		.call = parse_vc_item_ecpri_type,
5837 	},
5838 	[ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
5839 		.name = "rtc_id",
5840 		.help = "Real-Time Control Data ID",
5841 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5842 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5843 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5844 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5845 				hdr.type2.rtc_id)),
5846 	},
5847 	[ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
5848 		.name = "delay_measure",
5849 		.help = "Type #5: One-Way Delay Measurement",
5850 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5851 					ITEM_NEXT)),
5852 		.call = parse_vc_item_ecpri_type,
5853 	},
5854 	[ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
5855 		.name = "msr_id",
5856 		.help = "Measurement ID",
5857 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5858 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5859 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5860 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5861 				hdr.type5.msr_id)),
5862 	},
5863 	[ITEM_GENEVE_OPT] = {
5864 		.name = "geneve-opt",
5865 		.help = "GENEVE header option",
5866 		.priv = PRIV_ITEM(GENEVE_OPT,
5867 				  sizeof(struct rte_flow_item_geneve_opt) +
5868 				  ITEM_GENEVE_OPT_DATA_SIZE),
5869 		.next = NEXT(item_geneve_opt),
5870 		.call = parse_vc,
5871 	},
5872 	[ITEM_GENEVE_OPT_CLASS]	= {
5873 		.name = "class",
5874 		.help = "GENEVE option class",
5875 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5876 			     item_param),
5877 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
5878 					     option_class)),
5879 	},
5880 	[ITEM_GENEVE_OPT_TYPE] = {
5881 		.name = "type",
5882 		.help = "GENEVE option type",
5883 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5884 			     item_param),
5885 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
5886 					option_type)),
5887 	},
5888 	[ITEM_GENEVE_OPT_LENGTH] = {
5889 		.name = "length",
5890 		.help = "GENEVE option data length (in 32b words)",
5891 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5892 			     item_param),
5893 		.args = ARGS(ARGS_ENTRY_BOUNDED(
5894 				struct rte_flow_item_geneve_opt, option_len,
5895 				0, 31)),
5896 	},
5897 	[ITEM_GENEVE_OPT_DATA] = {
5898 		.name = "data",
5899 		.help = "GENEVE option data pattern",
5900 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
5901 			     item_param),
5902 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
5903 			     ARGS_ENTRY_ARB(0, 0),
5904 			     ARGS_ENTRY_ARB
5905 				(sizeof(struct rte_flow_item_geneve_opt),
5906 				ITEM_GENEVE_OPT_DATA_SIZE)),
5907 	},
5908 	[ITEM_INTEGRITY] = {
5909 		.name = "integrity",
5910 		.help = "match packet integrity",
5911 		.priv = PRIV_ITEM(INTEGRITY,
5912 				  sizeof(struct rte_flow_item_integrity)),
5913 		.next = NEXT(item_integrity),
5914 		.call = parse_vc,
5915 	},
5916 	[ITEM_INTEGRITY_LEVEL] = {
5917 		.name = "level",
5918 		.help = "integrity level",
5919 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5920 			     item_param),
5921 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
5922 	},
5923 	[ITEM_INTEGRITY_VALUE] = {
5924 		.name = "value",
5925 		.help = "integrity value",
5926 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5927 			     item_param),
5928 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
5929 	},
5930 	[ITEM_CONNTRACK] = {
5931 		.name = "conntrack",
5932 		.help = "conntrack state",
5933 		.priv = PRIV_ITEM(CONNTRACK,
5934 				  sizeof(struct rte_flow_item_conntrack)),
5935 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
5936 			     item_param),
5937 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
5938 		.call = parse_vc,
5939 	},
5940 	[ITEM_PORT_REPRESENTOR] = {
5941 		.name = "port_representor",
5942 		.help = "match traffic entering the embedded switch from the given ethdev",
5943 		.priv = PRIV_ITEM(PORT_REPRESENTOR,
5944 				  sizeof(struct rte_flow_item_ethdev)),
5945 		.next = NEXT(item_port_representor),
5946 		.call = parse_vc,
5947 	},
5948 	[ITEM_PORT_REPRESENTOR_PORT_ID] = {
5949 		.name = "port_id",
5950 		.help = "ethdev port ID",
5951 		.next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
5952 			     item_param),
5953 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5954 	},
5955 	[ITEM_REPRESENTED_PORT] = {
5956 		.name = "represented_port",
5957 		.help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
5958 		.priv = PRIV_ITEM(REPRESENTED_PORT,
5959 				  sizeof(struct rte_flow_item_ethdev)),
5960 		.next = NEXT(item_represented_port),
5961 		.call = parse_vc,
5962 	},
5963 	[ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
5964 		.name = "ethdev_port_id",
5965 		.help = "ethdev port ID",
5966 		.next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
5967 			     item_param),
5968 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5969 	},
5970 	[ITEM_FLEX] = {
5971 		.name = "flex",
5972 		.help = "match flex header",
5973 		.priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
5974 		.next = NEXT(item_flex),
5975 		.call = parse_vc,
5976 	},
5977 	[ITEM_FLEX_ITEM_HANDLE] = {
5978 		.name = "item",
5979 		.help = "flex item handle",
5980 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5981 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5982 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
5983 	},
5984 	[ITEM_FLEX_PATTERN_HANDLE] = {
5985 		.name = "pattern",
5986 		.help = "flex pattern handle",
5987 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5988 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5989 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
5990 	},
5991 	[ITEM_L2TPV2] = {
5992 		.name = "l2tpv2",
5993 		.help = "match L2TPv2 header",
5994 		.priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
5995 		.next = NEXT(item_l2tpv2),
5996 		.call = parse_vc,
5997 	},
5998 	[ITEM_L2TPV2_TYPE] = {
5999 		.name = "type",
6000 		.help = "type of l2tpv2",
6001 		.next = NEXT(item_l2tpv2_type),
6002 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
6003 	},
6004 	[ITEM_L2TPV2_TYPE_DATA] = {
6005 		.name = "data",
6006 		.help = "Type #7: data message without any options",
6007 		.next = NEXT(item_l2tpv2_type_data),
6008 		.call = parse_vc_item_l2tpv2_type,
6009 	},
6010 	[ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
6011 		.name = "tunnel_id",
6012 		.help = "tunnel identifier",
6013 		.next = NEXT(item_l2tpv2_type_data,
6014 			     NEXT_ENTRY(COMMON_UNSIGNED),
6015 			     item_param),
6016 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6017 					     hdr.type7.tunnel_id)),
6018 	},
6019 	[ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
6020 		.name = "session_id",
6021 		.help = "session identifier",
6022 		.next = NEXT(item_l2tpv2_type_data,
6023 			     NEXT_ENTRY(COMMON_UNSIGNED),
6024 			     item_param),
6025 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6026 					     hdr.type7.session_id)),
6027 	},
6028 	[ITEM_L2TPV2_TYPE_DATA_L] = {
6029 		.name = "data_l",
6030 		.help = "Type #6: data message with length option",
6031 		.next = NEXT(item_l2tpv2_type_data_l),
6032 		.call = parse_vc_item_l2tpv2_type,
6033 	},
6034 	[ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
6035 		.name = "length",
6036 		.help = "message length",
6037 		.next = NEXT(item_l2tpv2_type_data_l,
6038 			     NEXT_ENTRY(COMMON_UNSIGNED),
6039 			     item_param),
6040 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6041 					     hdr.type6.length)),
6042 	},
6043 	[ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
6044 		.name = "tunnel_id",
6045 		.help = "tunnel identifier",
6046 		.next = NEXT(item_l2tpv2_type_data_l,
6047 			     NEXT_ENTRY(COMMON_UNSIGNED),
6048 			     item_param),
6049 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6050 					     hdr.type6.tunnel_id)),
6051 	},
6052 	[ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
6053 		.name = "session_id",
6054 		.help = "session identifier",
6055 		.next = NEXT(item_l2tpv2_type_data_l,
6056 			     NEXT_ENTRY(COMMON_UNSIGNED),
6057 			     item_param),
6058 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6059 					     hdr.type6.session_id)),
6060 	},
6061 	[ITEM_L2TPV2_TYPE_DATA_S] = {
6062 		.name = "data_s",
6063 		.help = "Type #5: data message with ns, nr option",
6064 		.next = NEXT(item_l2tpv2_type_data_s),
6065 		.call = parse_vc_item_l2tpv2_type,
6066 	},
6067 	[ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
6068 		.name = "tunnel_id",
6069 		.help = "tunnel identifier",
6070 		.next = NEXT(item_l2tpv2_type_data_s,
6071 			     NEXT_ENTRY(COMMON_UNSIGNED),
6072 			     item_param),
6073 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6074 					     hdr.type5.tunnel_id)),
6075 	},
6076 	[ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
6077 		.name = "session_id",
6078 		.help = "session identifier",
6079 		.next = NEXT(item_l2tpv2_type_data_s,
6080 			     NEXT_ENTRY(COMMON_UNSIGNED),
6081 			     item_param),
6082 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6083 					     hdr.type5.session_id)),
6084 	},
6085 	[ITEM_L2TPV2_MSG_DATA_S_NS] = {
6086 		.name = "ns",
6087 		.help = "sequence number for message",
6088 		.next = NEXT(item_l2tpv2_type_data_s,
6089 			     NEXT_ENTRY(COMMON_UNSIGNED),
6090 			     item_param),
6091 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6092 					     hdr.type5.ns)),
6093 	},
6094 	[ITEM_L2TPV2_MSG_DATA_S_NR] = {
6095 		.name = "nr",
6096 		.help = "sequence number for next receive message",
6097 		.next = NEXT(item_l2tpv2_type_data_s,
6098 			     NEXT_ENTRY(COMMON_UNSIGNED),
6099 			     item_param),
6100 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6101 					     hdr.type5.nr)),
6102 	},
6103 	[ITEM_L2TPV2_TYPE_DATA_O] = {
6104 		.name = "data_o",
6105 		.help = "Type #4: data message with offset option",
6106 		.next = NEXT(item_l2tpv2_type_data_o),
6107 		.call = parse_vc_item_l2tpv2_type,
6108 	},
6109 	[ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
6110 		.name = "tunnel_id",
6111 		.help = "tunnel identifier",
6112 		.next = NEXT(item_l2tpv2_type_data_o,
6113 			     NEXT_ENTRY(COMMON_UNSIGNED),
6114 			     item_param),
6115 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6116 					     hdr.type4.tunnel_id)),
6117 	},
6118 	[ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
6119 		.name = "session_id",
6120 		.help = "session identifier",
6121 		.next = NEXT(item_l2tpv2_type_data_o,
6122 			     NEXT_ENTRY(COMMON_UNSIGNED),
6123 			     item_param),
6124 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6125 					     hdr.type5.session_id)),
6126 	},
6127 	[ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
6128 		.name = "offset_size",
6129 		.help = "the size of offset padding",
6130 		.next = NEXT(item_l2tpv2_type_data_o,
6131 			     NEXT_ENTRY(COMMON_UNSIGNED),
6132 			     item_param),
6133 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6134 					     hdr.type4.offset_size)),
6135 	},
6136 	[ITEM_L2TPV2_TYPE_DATA_L_S] = {
6137 		.name = "data_l_s",
6138 		.help = "Type #3: data message contains length, ns, nr "
6139 			"options",
6140 		.next = NEXT(item_l2tpv2_type_data_l_s),
6141 		.call = parse_vc_item_l2tpv2_type,
6142 	},
6143 	[ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
6144 		.name = "length",
6145 		.help = "message length",
6146 		.next = NEXT(item_l2tpv2_type_data_l_s,
6147 			     NEXT_ENTRY(COMMON_UNSIGNED),
6148 			     item_param),
6149 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6150 					     hdr.type3.length)),
6151 	},
6152 	[ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
6153 		.name = "tunnel_id",
6154 		.help = "tunnel identifier",
6155 		.next = NEXT(item_l2tpv2_type_data_l_s,
6156 			     NEXT_ENTRY(COMMON_UNSIGNED),
6157 			     item_param),
6158 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6159 					     hdr.type3.tunnel_id)),
6160 	},
6161 	[ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
6162 		.name = "session_id",
6163 		.help = "session identifier",
6164 		.next = NEXT(item_l2tpv2_type_data_l_s,
6165 			     NEXT_ENTRY(COMMON_UNSIGNED),
6166 			     item_param),
6167 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6168 					     hdr.type3.session_id)),
6169 	},
6170 	[ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
6171 		.name = "ns",
6172 		.help = "sequence number for message",
6173 		.next = NEXT(item_l2tpv2_type_data_l_s,
6174 			     NEXT_ENTRY(COMMON_UNSIGNED),
6175 			     item_param),
6176 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6177 					     hdr.type3.ns)),
6178 	},
6179 	[ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
6180 		.name = "nr",
6181 		.help = "sequence number for next receive message",
6182 		.next = NEXT(item_l2tpv2_type_data_l_s,
6183 			     NEXT_ENTRY(COMMON_UNSIGNED),
6184 			     item_param),
6185 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6186 					     hdr.type3.nr)),
6187 	},
6188 	[ITEM_L2TPV2_TYPE_CTRL] = {
6189 		.name = "control",
6190 		.help = "Type #3: conrtol message contains length, ns, nr "
6191 			"options",
6192 		.next = NEXT(item_l2tpv2_type_ctrl),
6193 		.call = parse_vc_item_l2tpv2_type,
6194 	},
6195 	[ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
6196 		.name = "length",
6197 		.help = "message length",
6198 		.next = NEXT(item_l2tpv2_type_ctrl,
6199 			     NEXT_ENTRY(COMMON_UNSIGNED),
6200 			     item_param),
6201 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6202 					     hdr.type3.length)),
6203 	},
6204 	[ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
6205 		.name = "tunnel_id",
6206 		.help = "tunnel identifier",
6207 		.next = NEXT(item_l2tpv2_type_ctrl,
6208 			     NEXT_ENTRY(COMMON_UNSIGNED),
6209 			     item_param),
6210 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6211 					     hdr.type3.tunnel_id)),
6212 	},
6213 	[ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
6214 		.name = "session_id",
6215 		.help = "session identifier",
6216 		.next = NEXT(item_l2tpv2_type_ctrl,
6217 			     NEXT_ENTRY(COMMON_UNSIGNED),
6218 			     item_param),
6219 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6220 					     hdr.type3.session_id)),
6221 	},
6222 	[ITEM_L2TPV2_MSG_CTRL_NS] = {
6223 		.name = "ns",
6224 		.help = "sequence number for message",
6225 		.next = NEXT(item_l2tpv2_type_ctrl,
6226 			     NEXT_ENTRY(COMMON_UNSIGNED),
6227 			     item_param),
6228 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6229 					     hdr.type3.ns)),
6230 	},
6231 	[ITEM_L2TPV2_MSG_CTRL_NR] = {
6232 		.name = "nr",
6233 		.help = "sequence number for next receive message",
6234 		.next = NEXT(item_l2tpv2_type_ctrl,
6235 			     NEXT_ENTRY(COMMON_UNSIGNED),
6236 			     item_param),
6237 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6238 					     hdr.type3.nr)),
6239 	},
6240 	[ITEM_PPP] = {
6241 		.name = "ppp",
6242 		.help = "match PPP header",
6243 		.priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
6244 		.next = NEXT(item_ppp),
6245 		.call = parse_vc,
6246 	},
6247 	[ITEM_PPP_ADDR] = {
6248 		.name = "addr",
6249 		.help = "PPP address",
6250 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6251 			     item_param),
6252 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
6253 	},
6254 	[ITEM_PPP_CTRL] = {
6255 		.name = "ctrl",
6256 		.help = "PPP control",
6257 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6258 			     item_param),
6259 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
6260 	},
6261 	[ITEM_PPP_PROTO_ID] = {
6262 		.name = "proto_id",
6263 		.help = "PPP protocol identifier",
6264 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6265 			     item_param),
6266 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
6267 					hdr.proto_id)),
6268 	},
6269 	[ITEM_METER] = {
6270 		.name = "meter",
6271 		.help = "match meter color",
6272 		.priv = PRIV_ITEM(METER_COLOR,
6273 				  sizeof(struct rte_flow_item_meter_color)),
6274 		.next = NEXT(item_meter),
6275 		.call = parse_vc,
6276 	},
6277 	[ITEM_METER_COLOR] = {
6278 		.name = "color",
6279 		.help = "meter color",
6280 		.next = NEXT(item_meter,
6281 			     NEXT_ENTRY(ITEM_METER_COLOR_NAME),
6282 			     item_param),
6283 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_meter_color,
6284 					color)),
6285 	},
6286 	[ITEM_METER_COLOR_NAME] = {
6287 		.name = "color_name",
6288 		.help = "meter color name",
6289 		.call = parse_meter_color,
6290 		.comp = comp_meter_color,
6291 	},
6292 	[ITEM_QUOTA] = {
6293 		.name = "quota",
6294 		.help = "match quota",
6295 		.priv = PRIV_ITEM(QUOTA, sizeof(struct rte_flow_item_quota)),
6296 		.next = NEXT(item_quota),
6297 		.call = parse_vc
6298 	},
6299 	[ITEM_QUOTA_STATE] = {
6300 		.name = "quota_state",
6301 		.help = "quota state",
6302 		.next = NEXT(item_quota, NEXT_ENTRY(ITEM_QUOTA_STATE_NAME),
6303 			     NEXT_ENTRY(ITEM_PARAM_SPEC, ITEM_PARAM_MASK)),
6304 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_quota, state))
6305 	},
6306 	[ITEM_QUOTA_STATE_NAME] = {
6307 		.name = "state_name",
6308 		.help = "quota state name",
6309 		.call = parse_quota_state_name,
6310 		.comp = comp_quota_state_name
6311 	},
6312 	[ITEM_IB_BTH] = {
6313 		.name = "ib_bth",
6314 		.help = "match ib bth fields",
6315 		.priv = PRIV_ITEM(IB_BTH,
6316 				  sizeof(struct rte_flow_item_ib_bth)),
6317 		.next = NEXT(item_ib_bth),
6318 		.call = parse_vc,
6319 	},
6320 	[ITEM_IB_BTH_OPCODE] = {
6321 		.name = "opcode",
6322 		.help = "match ib bth opcode",
6323 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6324 				 item_param),
6325 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6326 						 hdr.opcode)),
6327 	},
6328 	[ITEM_IB_BTH_PKEY] = {
6329 		.name = "pkey",
6330 		.help = "partition key",
6331 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6332 				 item_param),
6333 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6334 						 hdr.pkey)),
6335 	},
6336 	[ITEM_IB_BTH_DST_QPN] = {
6337 		.name = "dst_qp",
6338 		.help = "destination qp",
6339 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6340 				 item_param),
6341 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6342 						 hdr.dst_qp)),
6343 	},
6344 	[ITEM_IB_BTH_PSN] = {
6345 		.name = "psn",
6346 		.help = "packet sequence number",
6347 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6348 				 item_param),
6349 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6350 						 hdr.psn)),
6351 	},
6352 	[ITEM_PTYPE] = {
6353 		.name = "ptype",
6354 		.help = "match L2/L3/L4 and tunnel information",
6355 		.priv = PRIV_ITEM(PTYPE,
6356 				  sizeof(struct rte_flow_item_ptype)),
6357 		.next = NEXT(item_ptype),
6358 		.call = parse_vc,
6359 	},
6360 	[ITEM_PTYPE_VALUE] = {
6361 		.name = "packet_type",
6362 		.help = "packet type as defined in rte_mbuf_ptype",
6363 		.next = NEXT(item_ptype, NEXT_ENTRY(COMMON_UNSIGNED),
6364 			     item_param),
6365 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ptype, packet_type)),
6366 	},
6367 	[ITEM_NSH] = {
6368 		.name = "nsh",
6369 		.help = "match NSH header",
6370 		.priv = PRIV_ITEM(NSH,
6371 				  sizeof(struct rte_flow_item_nsh)),
6372 		.next = NEXT(item_nsh),
6373 		.call = parse_vc,
6374 	},
6375 	[ITEM_COMPARE] = {
6376 		.name = "compare",
6377 		.help = "match with the comparison result",
6378 		.priv = PRIV_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
6379 		.next = NEXT(NEXT_ENTRY(ITEM_COMPARE_OP)),
6380 		.call = parse_vc,
6381 	},
6382 	[ITEM_COMPARE_OP] = {
6383 		.name = "op",
6384 		.help = "operation type",
6385 		.next = NEXT(item_compare_field,
6386 			NEXT_ENTRY(ITEM_COMPARE_OP_VALUE), item_param),
6387 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, operation)),
6388 	},
6389 	[ITEM_COMPARE_OP_VALUE] = {
6390 		.name = "{operation}",
6391 		.help = "operation type value",
6392 		.call = parse_vc_compare_op,
6393 		.comp = comp_set_compare_op,
6394 	},
6395 	[ITEM_COMPARE_FIELD_A_TYPE] = {
6396 		.name = "a_type",
6397 		.help = "compared field type",
6398 		.next = NEXT(compare_field_a,
6399 			NEXT_ENTRY(ITEM_COMPARE_FIELD_A_TYPE_VALUE), item_param),
6400 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.field)),
6401 	},
6402 	[ITEM_COMPARE_FIELD_A_TYPE_VALUE] = {
6403 		.name = "{a_type}",
6404 		.help = "compared field type value",
6405 		.call = parse_vc_compare_field_id,
6406 		.comp = comp_set_compare_field_id,
6407 	},
6408 	[ITEM_COMPARE_FIELD_A_LEVEL] = {
6409 		.name = "a_level",
6410 		.help = "compared field level",
6411 		.next = NEXT(compare_field_a,
6412 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_A_LEVEL_VALUE), item_param),
6413 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.level)),
6414 	},
6415 	[ITEM_COMPARE_FIELD_A_LEVEL_VALUE] = {
6416 		.name = "{a_level}",
6417 		.help = "compared field level value",
6418 		.call = parse_vc_compare_field_level,
6419 		.comp = comp_none,
6420 	},
6421 	[ITEM_COMPARE_FIELD_A_TAG_INDEX] = {
6422 		.name = "a_tag_index",
6423 		.help = "compared field tag array",
6424 		.next = NEXT(compare_field_a,
6425 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6426 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6427 					a.tag_index)),
6428 	},
6429 	[ITEM_COMPARE_FIELD_A_TYPE_ID] = {
6430 		.name = "a_type_id",
6431 		.help = "compared field type ID",
6432 		.next = NEXT(compare_field_a,
6433 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6434 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6435 					a.type)),
6436 	},
6437 	[ITEM_COMPARE_FIELD_A_CLASS_ID] = {
6438 		.name = "a_class",
6439 		.help = "compared field class ID",
6440 		.next = NEXT(compare_field_a,
6441 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6442 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6443 					     a.class_id)),
6444 	},
6445 	[ITEM_COMPARE_FIELD_A_OFFSET] = {
6446 		.name = "a_offset",
6447 		.help = "compared field bit offset",
6448 		.next = NEXT(compare_field_a,
6449 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6450 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6451 					a.offset)),
6452 	},
6453 	[ITEM_COMPARE_FIELD_B_TYPE] = {
6454 		.name = "b_type",
6455 		.help = "comparator field type",
6456 		.next = NEXT(compare_field_b,
6457 			NEXT_ENTRY(ITEM_COMPARE_FIELD_B_TYPE_VALUE), item_param),
6458 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6459 					b.field)),
6460 	},
6461 	[ITEM_COMPARE_FIELD_B_TYPE_VALUE] = {
6462 		.name = "{b_type}",
6463 		.help = "comparator field type value",
6464 		.call = parse_vc_compare_field_id,
6465 		.comp = comp_set_compare_field_id,
6466 	},
6467 	[ITEM_COMPARE_FIELD_B_LEVEL] = {
6468 		.name = "b_level",
6469 		.help = "comparator field level",
6470 		.next = NEXT(compare_field_b,
6471 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_B_LEVEL_VALUE), item_param),
6472 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6473 					b.level)),
6474 	},
6475 	[ITEM_COMPARE_FIELD_B_LEVEL_VALUE] = {
6476 		.name = "{b_level}",
6477 		.help = "comparator field level value",
6478 		.call = parse_vc_compare_field_level,
6479 		.comp = comp_none,
6480 	},
6481 	[ITEM_COMPARE_FIELD_B_TAG_INDEX] = {
6482 		.name = "b_tag_index",
6483 		.help = "comparator field tag array",
6484 		.next = NEXT(compare_field_b,
6485 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6486 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6487 					b.tag_index)),
6488 	},
6489 	[ITEM_COMPARE_FIELD_B_TYPE_ID] = {
6490 		.name = "b_type_id",
6491 		.help = "comparator field type ID",
6492 		.next = NEXT(compare_field_b,
6493 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6494 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6495 					b.type)),
6496 	},
6497 	[ITEM_COMPARE_FIELD_B_CLASS_ID] = {
6498 		.name = "b_class",
6499 		.help = "comparator field class ID",
6500 		.next = NEXT(compare_field_b,
6501 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6502 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6503 					     b.class_id)),
6504 	},
6505 	[ITEM_COMPARE_FIELD_B_OFFSET] = {
6506 		.name = "b_offset",
6507 		.help = "comparator field bit offset",
6508 		.next = NEXT(compare_field_b,
6509 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6510 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6511 					b.offset)),
6512 	},
6513 	[ITEM_COMPARE_FIELD_B_VALUE] = {
6514 		.name = "b_value",
6515 		.help = "comparator immediate value",
6516 		.next = NEXT(compare_field_b,
6517 			     NEXT_ENTRY(COMMON_HEX), item_param),
6518 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
6519 			     ARGS_ENTRY_ARB(0, 0),
6520 			     ARGS_ENTRY(struct rte_flow_item_compare,
6521 					b.value)),
6522 	},
6523 	[ITEM_COMPARE_FIELD_B_POINTER] = {
6524 		.name = "b_ptr",
6525 		.help = "pointer to comparator immediate value",
6526 		.next = NEXT(compare_field_b,
6527 			     NEXT_ENTRY(COMMON_HEX), item_param),
6528 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6529 					b.pvalue),
6530 			     ARGS_ENTRY_ARB(0, 0),
6531 			     ARGS_ENTRY_ARB
6532 				(sizeof(struct rte_flow_item_compare),
6533 				 FLOW_FIELD_PATTERN_SIZE)),
6534 	},
6535 	[ITEM_COMPARE_FIELD_WIDTH] = {
6536 		.name = "width",
6537 		.help = "number of bits to compare",
6538 		.next = NEXT(item_compare_field,
6539 			NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6540 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6541 					width)),
6542 	},
6543 
6544 	/* Validate/create actions. */
6545 	[ACTIONS] = {
6546 		.name = "actions",
6547 		.help = "submit a list of associated actions",
6548 		.next = NEXT(next_action),
6549 		.call = parse_vc,
6550 	},
6551 	[ACTION_NEXT] = {
6552 		.name = "/",
6553 		.help = "specify next action",
6554 		.next = NEXT(next_action),
6555 	},
6556 	[ACTION_END] = {
6557 		.name = "end",
6558 		.help = "end list of actions",
6559 		.priv = PRIV_ACTION(END, 0),
6560 		.call = parse_vc,
6561 	},
6562 	[ACTION_VOID] = {
6563 		.name = "void",
6564 		.help = "no-op action",
6565 		.priv = PRIV_ACTION(VOID, 0),
6566 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6567 		.call = parse_vc,
6568 	},
6569 	[ACTION_PASSTHRU] = {
6570 		.name = "passthru",
6571 		.help = "let subsequent rule process matched packets",
6572 		.priv = PRIV_ACTION(PASSTHRU, 0),
6573 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6574 		.call = parse_vc,
6575 	},
6576 	[ACTION_SKIP_CMAN] = {
6577 		.name = "skip_cman",
6578 		.help = "bypass cman on received packets",
6579 		.priv = PRIV_ACTION(SKIP_CMAN, 0),
6580 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6581 		.call = parse_vc,
6582 	},
6583 	[ACTION_JUMP] = {
6584 		.name = "jump",
6585 		.help = "redirect traffic to a given group",
6586 		.priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
6587 		.next = NEXT(action_jump),
6588 		.call = parse_vc,
6589 	},
6590 	[ACTION_JUMP_GROUP] = {
6591 		.name = "group",
6592 		.help = "group to redirect traffic to",
6593 		.next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
6594 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
6595 		.call = parse_vc_conf,
6596 	},
6597 	[ACTION_MARK] = {
6598 		.name = "mark",
6599 		.help = "attach 32 bit value to packets",
6600 		.priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
6601 		.next = NEXT(action_mark),
6602 		.call = parse_vc,
6603 	},
6604 	[ACTION_MARK_ID] = {
6605 		.name = "id",
6606 		.help = "32 bit value to return with packets",
6607 		.next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6608 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
6609 		.call = parse_vc_conf,
6610 	},
6611 	[ACTION_FLAG] = {
6612 		.name = "flag",
6613 		.help = "flag packets",
6614 		.priv = PRIV_ACTION(FLAG, 0),
6615 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6616 		.call = parse_vc,
6617 	},
6618 	[ACTION_QUEUE] = {
6619 		.name = "queue",
6620 		.help = "assign packets to a given queue index",
6621 		.priv = PRIV_ACTION(QUEUE,
6622 				    sizeof(struct rte_flow_action_queue)),
6623 		.next = NEXT(action_queue),
6624 		.call = parse_vc,
6625 	},
6626 	[ACTION_QUEUE_INDEX] = {
6627 		.name = "index",
6628 		.help = "queue index to use",
6629 		.next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
6630 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
6631 		.call = parse_vc_conf,
6632 	},
6633 	[ACTION_DROP] = {
6634 		.name = "drop",
6635 		.help = "drop packets (note: passthru has priority)",
6636 		.priv = PRIV_ACTION(DROP, 0),
6637 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6638 		.call = parse_vc,
6639 	},
6640 	[ACTION_COUNT] = {
6641 		.name = "count",
6642 		.help = "enable counters for this rule",
6643 		.priv = PRIV_ACTION(COUNT,
6644 				    sizeof(struct rte_flow_action_count)),
6645 		.next = NEXT(action_count),
6646 		.call = parse_vc,
6647 	},
6648 	[ACTION_COUNT_ID] = {
6649 		.name = "identifier",
6650 		.help = "counter identifier to use",
6651 		.next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
6652 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
6653 		.call = parse_vc_conf,
6654 	},
6655 	[ACTION_RSS] = {
6656 		.name = "rss",
6657 		.help = "spread packets among several queues",
6658 		.priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
6659 		.next = NEXT(action_rss),
6660 		.call = parse_vc_action_rss,
6661 	},
6662 	[ACTION_RSS_FUNC] = {
6663 		.name = "func",
6664 		.help = "RSS hash function to apply",
6665 		.next = NEXT(action_rss,
6666 			     NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
6667 					ACTION_RSS_FUNC_TOEPLITZ,
6668 					ACTION_RSS_FUNC_SIMPLE_XOR,
6669 					ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
6670 	},
6671 	[ACTION_RSS_FUNC_DEFAULT] = {
6672 		.name = "default",
6673 		.help = "default hash function",
6674 		.call = parse_vc_action_rss_func,
6675 	},
6676 	[ACTION_RSS_FUNC_TOEPLITZ] = {
6677 		.name = "toeplitz",
6678 		.help = "Toeplitz hash function",
6679 		.call = parse_vc_action_rss_func,
6680 	},
6681 	[ACTION_RSS_FUNC_SIMPLE_XOR] = {
6682 		.name = "simple_xor",
6683 		.help = "simple XOR hash function",
6684 		.call = parse_vc_action_rss_func,
6685 	},
6686 	[ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
6687 		.name = "symmetric_toeplitz",
6688 		.help = "Symmetric Toeplitz hash function",
6689 		.call = parse_vc_action_rss_func,
6690 	},
6691 	[ACTION_RSS_LEVEL] = {
6692 		.name = "level",
6693 		.help = "encapsulation level for \"types\"",
6694 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6695 		.args = ARGS(ARGS_ENTRY_ARB
6696 			     (offsetof(struct action_rss_data, conf) +
6697 			      offsetof(struct rte_flow_action_rss, level),
6698 			      sizeof(((struct rte_flow_action_rss *)0)->
6699 				     level))),
6700 	},
6701 	[ACTION_RSS_TYPES] = {
6702 		.name = "types",
6703 		.help = "specific RSS hash types",
6704 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
6705 	},
6706 	[ACTION_RSS_TYPE] = {
6707 		.name = "{type}",
6708 		.help = "RSS hash type",
6709 		.call = parse_vc_action_rss_type,
6710 		.comp = comp_vc_action_rss_type,
6711 	},
6712 	[ACTION_RSS_KEY] = {
6713 		.name = "key",
6714 		.help = "RSS hash key",
6715 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
6716 		.args = ARGS(ARGS_ENTRY_ARB
6717 			     (offsetof(struct action_rss_data, conf) +
6718 			      offsetof(struct rte_flow_action_rss, key),
6719 			      sizeof(((struct rte_flow_action_rss *)0)->key)),
6720 			     ARGS_ENTRY_ARB
6721 			     (offsetof(struct action_rss_data, conf) +
6722 			      offsetof(struct rte_flow_action_rss, key_len),
6723 			      sizeof(((struct rte_flow_action_rss *)0)->
6724 				     key_len)),
6725 			     ARGS_ENTRY(struct action_rss_data, key)),
6726 	},
6727 	[ACTION_RSS_KEY_LEN] = {
6728 		.name = "key_len",
6729 		.help = "RSS hash key length in bytes",
6730 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6731 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
6732 			     (offsetof(struct action_rss_data, conf) +
6733 			      offsetof(struct rte_flow_action_rss, key_len),
6734 			      sizeof(((struct rte_flow_action_rss *)0)->
6735 				     key_len),
6736 			      0,
6737 			      RSS_HASH_KEY_LENGTH)),
6738 	},
6739 	[ACTION_RSS_QUEUES] = {
6740 		.name = "queues",
6741 		.help = "queue indices to use",
6742 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
6743 		.call = parse_vc_conf,
6744 	},
6745 	[ACTION_RSS_QUEUE] = {
6746 		.name = "{queue}",
6747 		.help = "queue index",
6748 		.call = parse_vc_action_rss_queue,
6749 		.comp = comp_vc_action_rss_queue,
6750 	},
6751 	[ACTION_PF] = {
6752 		.name = "pf",
6753 		.help = "direct traffic to physical function",
6754 		.priv = PRIV_ACTION(PF, 0),
6755 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6756 		.call = parse_vc,
6757 	},
6758 	[ACTION_VF] = {
6759 		.name = "vf",
6760 		.help = "direct traffic to a virtual function ID",
6761 		.priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
6762 		.next = NEXT(action_vf),
6763 		.call = parse_vc,
6764 	},
6765 	[ACTION_VF_ORIGINAL] = {
6766 		.name = "original",
6767 		.help = "use original VF ID if possible",
6768 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
6769 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
6770 					   original, 1)),
6771 		.call = parse_vc_conf,
6772 	},
6773 	[ACTION_VF_ID] = {
6774 		.name = "id",
6775 		.help = "VF ID",
6776 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
6777 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
6778 		.call = parse_vc_conf,
6779 	},
6780 	[ACTION_PORT_ID] = {
6781 		.name = "port_id",
6782 		.help = "direct matching traffic to a given DPDK port ID",
6783 		.priv = PRIV_ACTION(PORT_ID,
6784 				    sizeof(struct rte_flow_action_port_id)),
6785 		.next = NEXT(action_port_id),
6786 		.call = parse_vc,
6787 	},
6788 	[ACTION_PORT_ID_ORIGINAL] = {
6789 		.name = "original",
6790 		.help = "use original DPDK port ID if possible",
6791 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
6792 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
6793 					   original, 1)),
6794 		.call = parse_vc_conf,
6795 	},
6796 	[ACTION_PORT_ID_ID] = {
6797 		.name = "id",
6798 		.help = "DPDK port ID",
6799 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
6800 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
6801 		.call = parse_vc_conf,
6802 	},
6803 	[ACTION_METER] = {
6804 		.name = "meter",
6805 		.help = "meter the directed packets at given id",
6806 		.priv = PRIV_ACTION(METER,
6807 				    sizeof(struct rte_flow_action_meter)),
6808 		.next = NEXT(action_meter),
6809 		.call = parse_vc,
6810 	},
6811 	[ACTION_METER_COLOR] = {
6812 		.name = "color",
6813 		.help = "meter color for the packets",
6814 		.priv = PRIV_ACTION(METER_COLOR,
6815 				sizeof(struct rte_flow_action_meter_color)),
6816 		.next = NEXT(action_meter_color),
6817 		.call = parse_vc,
6818 	},
6819 	[ACTION_METER_COLOR_TYPE] = {
6820 		.name = "type",
6821 		.help = "specific meter color",
6822 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
6823 				NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
6824 					ACTION_METER_COLOR_YELLOW,
6825 					ACTION_METER_COLOR_RED)),
6826 	},
6827 	[ACTION_METER_COLOR_GREEN] = {
6828 		.name = "green",
6829 		.help = "meter color green",
6830 		.call = parse_vc_action_meter_color_type,
6831 	},
6832 	[ACTION_METER_COLOR_YELLOW] = {
6833 		.name = "yellow",
6834 		.help = "meter color yellow",
6835 		.call = parse_vc_action_meter_color_type,
6836 	},
6837 	[ACTION_METER_COLOR_RED] = {
6838 		.name = "red",
6839 		.help = "meter color red",
6840 		.call = parse_vc_action_meter_color_type,
6841 	},
6842 	[ACTION_METER_ID] = {
6843 		.name = "mtr_id",
6844 		.help = "meter id to use",
6845 		.next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
6846 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
6847 		.call = parse_vc_conf,
6848 	},
6849 	[ACTION_METER_MARK] = {
6850 		.name = "meter_mark",
6851 		.help = "meter the directed packets using profile and policy",
6852 		.priv = PRIV_ACTION(METER_MARK,
6853 				    sizeof(struct rte_flow_action_meter_mark)),
6854 		.next = NEXT(action_meter_mark),
6855 		.call = parse_vc,
6856 	},
6857 	[ACTION_METER_PROFILE] = {
6858 		.name = "mtr_profile",
6859 		.help = "meter profile id to use",
6860 		.next = NEXT(NEXT_ENTRY(ACTION_METER_PROFILE_ID2PTR)),
6861 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6862 	},
6863 	[ACTION_METER_PROFILE_ID2PTR] = {
6864 		.name = "{mtr_profile_id}",
6865 		.type = "PROFILE_ID",
6866 		.help = "meter profile id",
6867 		.next = NEXT(action_meter_mark),
6868 		.call = parse_meter_profile_id2ptr,
6869 		.comp = comp_none,
6870 	},
6871 	[ACTION_METER_POLICY] = {
6872 		.name = "mtr_policy",
6873 		.help = "meter policy id to use",
6874 		.next = NEXT(NEXT_ENTRY(ACTION_METER_POLICY_ID2PTR)),
6875 		ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6876 	},
6877 	[ACTION_METER_POLICY_ID2PTR] = {
6878 		.name = "{mtr_policy_id}",
6879 		.type = "POLICY_ID",
6880 		.help = "meter policy id",
6881 		.next = NEXT(action_meter_mark),
6882 		.call = parse_meter_policy_id2ptr,
6883 		.comp = comp_none,
6884 	},
6885 	[ACTION_METER_COLOR_MODE] = {
6886 		.name = "mtr_color_mode",
6887 		.help = "meter color awareness mode",
6888 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6889 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, color_mode)),
6890 		.call = parse_vc_conf,
6891 	},
6892 	[ACTION_METER_STATE] = {
6893 		.name = "mtr_state",
6894 		.help = "meter state",
6895 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6896 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, state)),
6897 		.call = parse_vc_conf,
6898 	},
6899 	[ACTION_OF_DEC_NW_TTL] = {
6900 		.name = "of_dec_nw_ttl",
6901 		.help = "OpenFlow's OFPAT_DEC_NW_TTL",
6902 		.priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
6903 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6904 		.call = parse_vc,
6905 	},
6906 	[ACTION_OF_POP_VLAN] = {
6907 		.name = "of_pop_vlan",
6908 		.help = "OpenFlow's OFPAT_POP_VLAN",
6909 		.priv = PRIV_ACTION(OF_POP_VLAN, 0),
6910 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6911 		.call = parse_vc,
6912 	},
6913 	[ACTION_OF_PUSH_VLAN] = {
6914 		.name = "of_push_vlan",
6915 		.help = "OpenFlow's OFPAT_PUSH_VLAN",
6916 		.priv = PRIV_ACTION
6917 			(OF_PUSH_VLAN,
6918 			 sizeof(struct rte_flow_action_of_push_vlan)),
6919 		.next = NEXT(action_of_push_vlan),
6920 		.call = parse_vc,
6921 	},
6922 	[ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
6923 		.name = "ethertype",
6924 		.help = "EtherType",
6925 		.next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
6926 		.args = ARGS(ARGS_ENTRY_HTON
6927 			     (struct rte_flow_action_of_push_vlan,
6928 			      ethertype)),
6929 		.call = parse_vc_conf,
6930 	},
6931 	[ACTION_OF_SET_VLAN_VID] = {
6932 		.name = "of_set_vlan_vid",
6933 		.help = "OpenFlow's OFPAT_SET_VLAN_VID",
6934 		.priv = PRIV_ACTION
6935 			(OF_SET_VLAN_VID,
6936 			 sizeof(struct rte_flow_action_of_set_vlan_vid)),
6937 		.next = NEXT(action_of_set_vlan_vid),
6938 		.call = parse_vc,
6939 	},
6940 	[ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
6941 		.name = "vlan_vid",
6942 		.help = "VLAN id",
6943 		.next = NEXT(action_of_set_vlan_vid,
6944 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6945 		.args = ARGS(ARGS_ENTRY_HTON
6946 			     (struct rte_flow_action_of_set_vlan_vid,
6947 			      vlan_vid)),
6948 		.call = parse_vc_conf,
6949 	},
6950 	[ACTION_OF_SET_VLAN_PCP] = {
6951 		.name = "of_set_vlan_pcp",
6952 		.help = "OpenFlow's OFPAT_SET_VLAN_PCP",
6953 		.priv = PRIV_ACTION
6954 			(OF_SET_VLAN_PCP,
6955 			 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
6956 		.next = NEXT(action_of_set_vlan_pcp),
6957 		.call = parse_vc,
6958 	},
6959 	[ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
6960 		.name = "vlan_pcp",
6961 		.help = "VLAN priority",
6962 		.next = NEXT(action_of_set_vlan_pcp,
6963 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6964 		.args = ARGS(ARGS_ENTRY_HTON
6965 			     (struct rte_flow_action_of_set_vlan_pcp,
6966 			      vlan_pcp)),
6967 		.call = parse_vc_conf,
6968 	},
6969 	[ACTION_OF_POP_MPLS] = {
6970 		.name = "of_pop_mpls",
6971 		.help = "OpenFlow's OFPAT_POP_MPLS",
6972 		.priv = PRIV_ACTION(OF_POP_MPLS,
6973 				    sizeof(struct rte_flow_action_of_pop_mpls)),
6974 		.next = NEXT(action_of_pop_mpls),
6975 		.call = parse_vc,
6976 	},
6977 	[ACTION_OF_POP_MPLS_ETHERTYPE] = {
6978 		.name = "ethertype",
6979 		.help = "EtherType",
6980 		.next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6981 		.args = ARGS(ARGS_ENTRY_HTON
6982 			     (struct rte_flow_action_of_pop_mpls,
6983 			      ethertype)),
6984 		.call = parse_vc_conf,
6985 	},
6986 	[ACTION_OF_PUSH_MPLS] = {
6987 		.name = "of_push_mpls",
6988 		.help = "OpenFlow's OFPAT_PUSH_MPLS",
6989 		.priv = PRIV_ACTION
6990 			(OF_PUSH_MPLS,
6991 			 sizeof(struct rte_flow_action_of_push_mpls)),
6992 		.next = NEXT(action_of_push_mpls),
6993 		.call = parse_vc,
6994 	},
6995 	[ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
6996 		.name = "ethertype",
6997 		.help = "EtherType",
6998 		.next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6999 		.args = ARGS(ARGS_ENTRY_HTON
7000 			     (struct rte_flow_action_of_push_mpls,
7001 			      ethertype)),
7002 		.call = parse_vc_conf,
7003 	},
7004 	[ACTION_VXLAN_ENCAP] = {
7005 		.name = "vxlan_encap",
7006 		.help = "VXLAN encapsulation, uses configuration set by \"set"
7007 			" vxlan\"",
7008 		.priv = PRIV_ACTION(VXLAN_ENCAP,
7009 				    sizeof(struct action_vxlan_encap_data)),
7010 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7011 		.call = parse_vc_action_vxlan_encap,
7012 	},
7013 	[ACTION_VXLAN_DECAP] = {
7014 		.name = "vxlan_decap",
7015 		.help = "Performs a decapsulation action by stripping all"
7016 			" headers of the VXLAN tunnel network overlay from the"
7017 			" matched flow.",
7018 		.priv = PRIV_ACTION(VXLAN_DECAP, 0),
7019 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7020 		.call = parse_vc,
7021 	},
7022 	[ACTION_NVGRE_ENCAP] = {
7023 		.name = "nvgre_encap",
7024 		.help = "NVGRE encapsulation, uses configuration set by \"set"
7025 			" nvgre\"",
7026 		.priv = PRIV_ACTION(NVGRE_ENCAP,
7027 				    sizeof(struct action_nvgre_encap_data)),
7028 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7029 		.call = parse_vc_action_nvgre_encap,
7030 	},
7031 	[ACTION_NVGRE_DECAP] = {
7032 		.name = "nvgre_decap",
7033 		.help = "Performs a decapsulation action by stripping all"
7034 			" headers of the NVGRE tunnel network overlay from the"
7035 			" matched flow.",
7036 		.priv = PRIV_ACTION(NVGRE_DECAP, 0),
7037 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7038 		.call = parse_vc,
7039 	},
7040 	[ACTION_L2_ENCAP] = {
7041 		.name = "l2_encap",
7042 		.help = "l2 encap, uses configuration set by"
7043 			" \"set l2_encap\"",
7044 		.priv = PRIV_ACTION(RAW_ENCAP,
7045 				    sizeof(struct action_raw_encap_data)),
7046 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7047 		.call = parse_vc_action_l2_encap,
7048 	},
7049 	[ACTION_L2_DECAP] = {
7050 		.name = "l2_decap",
7051 		.help = "l2 decap, uses configuration set by"
7052 			" \"set l2_decap\"",
7053 		.priv = PRIV_ACTION(RAW_DECAP,
7054 				    sizeof(struct action_raw_decap_data)),
7055 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7056 		.call = parse_vc_action_l2_decap,
7057 	},
7058 	[ACTION_MPLSOGRE_ENCAP] = {
7059 		.name = "mplsogre_encap",
7060 		.help = "mplsogre encapsulation, uses configuration set by"
7061 			" \"set mplsogre_encap\"",
7062 		.priv = PRIV_ACTION(RAW_ENCAP,
7063 				    sizeof(struct action_raw_encap_data)),
7064 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7065 		.call = parse_vc_action_mplsogre_encap,
7066 	},
7067 	[ACTION_MPLSOGRE_DECAP] = {
7068 		.name = "mplsogre_decap",
7069 		.help = "mplsogre decapsulation, uses configuration set by"
7070 			" \"set mplsogre_decap\"",
7071 		.priv = PRIV_ACTION(RAW_DECAP,
7072 				    sizeof(struct action_raw_decap_data)),
7073 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7074 		.call = parse_vc_action_mplsogre_decap,
7075 	},
7076 	[ACTION_MPLSOUDP_ENCAP] = {
7077 		.name = "mplsoudp_encap",
7078 		.help = "mplsoudp encapsulation, uses configuration set by"
7079 			" \"set mplsoudp_encap\"",
7080 		.priv = PRIV_ACTION(RAW_ENCAP,
7081 				    sizeof(struct action_raw_encap_data)),
7082 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7083 		.call = parse_vc_action_mplsoudp_encap,
7084 	},
7085 	[ACTION_MPLSOUDP_DECAP] = {
7086 		.name = "mplsoudp_decap",
7087 		.help = "mplsoudp decapsulation, uses configuration set by"
7088 			" \"set mplsoudp_decap\"",
7089 		.priv = PRIV_ACTION(RAW_DECAP,
7090 				    sizeof(struct action_raw_decap_data)),
7091 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7092 		.call = parse_vc_action_mplsoudp_decap,
7093 	},
7094 	[ACTION_SET_IPV4_SRC] = {
7095 		.name = "set_ipv4_src",
7096 		.help = "Set a new IPv4 source address in the outermost"
7097 			" IPv4 header",
7098 		.priv = PRIV_ACTION(SET_IPV4_SRC,
7099 			sizeof(struct rte_flow_action_set_ipv4)),
7100 		.next = NEXT(action_set_ipv4_src),
7101 		.call = parse_vc,
7102 	},
7103 	[ACTION_SET_IPV4_SRC_IPV4_SRC] = {
7104 		.name = "ipv4_addr",
7105 		.help = "new IPv4 source address to set",
7106 		.next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
7107 		.args = ARGS(ARGS_ENTRY_HTON
7108 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
7109 		.call = parse_vc_conf,
7110 	},
7111 	[ACTION_SET_IPV4_DST] = {
7112 		.name = "set_ipv4_dst",
7113 		.help = "Set a new IPv4 destination address in the outermost"
7114 			" IPv4 header",
7115 		.priv = PRIV_ACTION(SET_IPV4_DST,
7116 			sizeof(struct rte_flow_action_set_ipv4)),
7117 		.next = NEXT(action_set_ipv4_dst),
7118 		.call = parse_vc,
7119 	},
7120 	[ACTION_SET_IPV4_DST_IPV4_DST] = {
7121 		.name = "ipv4_addr",
7122 		.help = "new IPv4 destination address to set",
7123 		.next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
7124 		.args = ARGS(ARGS_ENTRY_HTON
7125 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
7126 		.call = parse_vc_conf,
7127 	},
7128 	[ACTION_SET_IPV6_SRC] = {
7129 		.name = "set_ipv6_src",
7130 		.help = "Set a new IPv6 source address in the outermost"
7131 			" IPv6 header",
7132 		.priv = PRIV_ACTION(SET_IPV6_SRC,
7133 			sizeof(struct rte_flow_action_set_ipv6)),
7134 		.next = NEXT(action_set_ipv6_src),
7135 		.call = parse_vc,
7136 	},
7137 	[ACTION_SET_IPV6_SRC_IPV6_SRC] = {
7138 		.name = "ipv6_addr",
7139 		.help = "new IPv6 source address to set",
7140 		.next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
7141 		.args = ARGS(ARGS_ENTRY_HTON
7142 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
7143 		.call = parse_vc_conf,
7144 	},
7145 	[ACTION_SET_IPV6_DST] = {
7146 		.name = "set_ipv6_dst",
7147 		.help = "Set a new IPv6 destination address in the outermost"
7148 			" IPv6 header",
7149 		.priv = PRIV_ACTION(SET_IPV6_DST,
7150 			sizeof(struct rte_flow_action_set_ipv6)),
7151 		.next = NEXT(action_set_ipv6_dst),
7152 		.call = parse_vc,
7153 	},
7154 	[ACTION_SET_IPV6_DST_IPV6_DST] = {
7155 		.name = "ipv6_addr",
7156 		.help = "new IPv6 destination address to set",
7157 		.next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
7158 		.args = ARGS(ARGS_ENTRY_HTON
7159 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
7160 		.call = parse_vc_conf,
7161 	},
7162 	[ACTION_SET_TP_SRC] = {
7163 		.name = "set_tp_src",
7164 		.help = "set a new source port number in the outermost"
7165 			" TCP/UDP header",
7166 		.priv = PRIV_ACTION(SET_TP_SRC,
7167 			sizeof(struct rte_flow_action_set_tp)),
7168 		.next = NEXT(action_set_tp_src),
7169 		.call = parse_vc,
7170 	},
7171 	[ACTION_SET_TP_SRC_TP_SRC] = {
7172 		.name = "port",
7173 		.help = "new source port number to set",
7174 		.next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
7175 		.args = ARGS(ARGS_ENTRY_HTON
7176 			     (struct rte_flow_action_set_tp, port)),
7177 		.call = parse_vc_conf,
7178 	},
7179 	[ACTION_SET_TP_DST] = {
7180 		.name = "set_tp_dst",
7181 		.help = "set a new destination port number in the outermost"
7182 			" TCP/UDP header",
7183 		.priv = PRIV_ACTION(SET_TP_DST,
7184 			sizeof(struct rte_flow_action_set_tp)),
7185 		.next = NEXT(action_set_tp_dst),
7186 		.call = parse_vc,
7187 	},
7188 	[ACTION_SET_TP_DST_TP_DST] = {
7189 		.name = "port",
7190 		.help = "new destination port number to set",
7191 		.next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
7192 		.args = ARGS(ARGS_ENTRY_HTON
7193 			     (struct rte_flow_action_set_tp, port)),
7194 		.call = parse_vc_conf,
7195 	},
7196 	[ACTION_MAC_SWAP] = {
7197 		.name = "mac_swap",
7198 		.help = "Swap the source and destination MAC addresses"
7199 			" in the outermost Ethernet header",
7200 		.priv = PRIV_ACTION(MAC_SWAP, 0),
7201 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7202 		.call = parse_vc,
7203 	},
7204 	[ACTION_DEC_TTL] = {
7205 		.name = "dec_ttl",
7206 		.help = "decrease network TTL if available",
7207 		.priv = PRIV_ACTION(DEC_TTL, 0),
7208 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7209 		.call = parse_vc,
7210 	},
7211 	[ACTION_SET_TTL] = {
7212 		.name = "set_ttl",
7213 		.help = "set ttl value",
7214 		.priv = PRIV_ACTION(SET_TTL,
7215 			sizeof(struct rte_flow_action_set_ttl)),
7216 		.next = NEXT(action_set_ttl),
7217 		.call = parse_vc,
7218 	},
7219 	[ACTION_SET_TTL_TTL] = {
7220 		.name = "ttl_value",
7221 		.help = "new ttl value to set",
7222 		.next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
7223 		.args = ARGS(ARGS_ENTRY_HTON
7224 			     (struct rte_flow_action_set_ttl, ttl_value)),
7225 		.call = parse_vc_conf,
7226 	},
7227 	[ACTION_SET_MAC_SRC] = {
7228 		.name = "set_mac_src",
7229 		.help = "set source mac address",
7230 		.priv = PRIV_ACTION(SET_MAC_SRC,
7231 			sizeof(struct rte_flow_action_set_mac)),
7232 		.next = NEXT(action_set_mac_src),
7233 		.call = parse_vc,
7234 	},
7235 	[ACTION_SET_MAC_SRC_MAC_SRC] = {
7236 		.name = "mac_addr",
7237 		.help = "new source mac address",
7238 		.next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
7239 		.args = ARGS(ARGS_ENTRY_HTON
7240 			     (struct rte_flow_action_set_mac, mac_addr)),
7241 		.call = parse_vc_conf,
7242 	},
7243 	[ACTION_SET_MAC_DST] = {
7244 		.name = "set_mac_dst",
7245 		.help = "set destination mac address",
7246 		.priv = PRIV_ACTION(SET_MAC_DST,
7247 			sizeof(struct rte_flow_action_set_mac)),
7248 		.next = NEXT(action_set_mac_dst),
7249 		.call = parse_vc,
7250 	},
7251 	[ACTION_SET_MAC_DST_MAC_DST] = {
7252 		.name = "mac_addr",
7253 		.help = "new destination mac address to set",
7254 		.next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
7255 		.args = ARGS(ARGS_ENTRY_HTON
7256 			     (struct rte_flow_action_set_mac, mac_addr)),
7257 		.call = parse_vc_conf,
7258 	},
7259 	[ACTION_INC_TCP_SEQ] = {
7260 		.name = "inc_tcp_seq",
7261 		.help = "increase TCP sequence number",
7262 		.priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
7263 		.next = NEXT(action_inc_tcp_seq),
7264 		.call = parse_vc,
7265 	},
7266 	[ACTION_INC_TCP_SEQ_VALUE] = {
7267 		.name = "value",
7268 		.help = "the value to increase TCP sequence number by",
7269 		.next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7270 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7271 		.call = parse_vc_conf,
7272 	},
7273 	[ACTION_DEC_TCP_SEQ] = {
7274 		.name = "dec_tcp_seq",
7275 		.help = "decrease TCP sequence number",
7276 		.priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
7277 		.next = NEXT(action_dec_tcp_seq),
7278 		.call = parse_vc,
7279 	},
7280 	[ACTION_DEC_TCP_SEQ_VALUE] = {
7281 		.name = "value",
7282 		.help = "the value to decrease TCP sequence number by",
7283 		.next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7284 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7285 		.call = parse_vc_conf,
7286 	},
7287 	[ACTION_INC_TCP_ACK] = {
7288 		.name = "inc_tcp_ack",
7289 		.help = "increase TCP acknowledgment number",
7290 		.priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
7291 		.next = NEXT(action_inc_tcp_ack),
7292 		.call = parse_vc,
7293 	},
7294 	[ACTION_INC_TCP_ACK_VALUE] = {
7295 		.name = "value",
7296 		.help = "the value to increase TCP acknowledgment number by",
7297 		.next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7298 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7299 		.call = parse_vc_conf,
7300 	},
7301 	[ACTION_DEC_TCP_ACK] = {
7302 		.name = "dec_tcp_ack",
7303 		.help = "decrease TCP acknowledgment number",
7304 		.priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
7305 		.next = NEXT(action_dec_tcp_ack),
7306 		.call = parse_vc,
7307 	},
7308 	[ACTION_DEC_TCP_ACK_VALUE] = {
7309 		.name = "value",
7310 		.help = "the value to decrease TCP acknowledgment number by",
7311 		.next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7312 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7313 		.call = parse_vc_conf,
7314 	},
7315 	[ACTION_RAW_ENCAP] = {
7316 		.name = "raw_encap",
7317 		.help = "encapsulation data, defined by set raw_encap",
7318 		.priv = PRIV_ACTION(RAW_ENCAP,
7319 			sizeof(struct action_raw_encap_data)),
7320 		.next = NEXT(action_raw_encap),
7321 		.call = parse_vc_action_raw_encap,
7322 	},
7323 	[ACTION_RAW_ENCAP_SIZE] = {
7324 		.name = "size",
7325 		.help = "raw encap size",
7326 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7327 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7328 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_raw_encap, size)),
7329 		.call = parse_vc_conf,
7330 	},
7331 	[ACTION_RAW_ENCAP_INDEX] = {
7332 		.name = "index",
7333 		.help = "the index of raw_encap_confs",
7334 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
7335 	},
7336 	[ACTION_RAW_ENCAP_INDEX_VALUE] = {
7337 		.name = "{index}",
7338 		.type = "UNSIGNED",
7339 		.help = "unsigned integer value",
7340 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7341 		.call = parse_vc_action_raw_encap_index,
7342 		.comp = comp_set_raw_index,
7343 	},
7344 	[ACTION_RAW_DECAP] = {
7345 		.name = "raw_decap",
7346 		.help = "decapsulation data, defined by set raw_encap",
7347 		.priv = PRIV_ACTION(RAW_DECAP,
7348 			sizeof(struct action_raw_decap_data)),
7349 		.next = NEXT(action_raw_decap),
7350 		.call = parse_vc_action_raw_decap,
7351 	},
7352 	[ACTION_RAW_DECAP_INDEX] = {
7353 		.name = "index",
7354 		.help = "the index of raw_encap_confs",
7355 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
7356 	},
7357 	[ACTION_RAW_DECAP_INDEX_VALUE] = {
7358 		.name = "{index}",
7359 		.type = "UNSIGNED",
7360 		.help = "unsigned integer value",
7361 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7362 		.call = parse_vc_action_raw_decap_index,
7363 		.comp = comp_set_raw_index,
7364 	},
7365 	[ACTION_MODIFY_FIELD] = {
7366 		.name = "modify_field",
7367 		.help = "modify destination field with data from source field",
7368 		.priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
7369 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
7370 		.call = parse_vc,
7371 	},
7372 	[ACTION_MODIFY_FIELD_OP] = {
7373 		.name = "op",
7374 		.help = "operation type",
7375 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
7376 			NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
7377 		.call = parse_vc_conf,
7378 	},
7379 	[ACTION_MODIFY_FIELD_OP_VALUE] = {
7380 		.name = "{operation}",
7381 		.help = "operation type value",
7382 		.call = parse_vc_modify_field_op,
7383 		.comp = comp_set_modify_field_op,
7384 	},
7385 	[ACTION_MODIFY_FIELD_DST_TYPE] = {
7386 		.name = "dst_type",
7387 		.help = "destination field type",
7388 		.next = NEXT(action_modify_field_dst,
7389 			NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
7390 		.call = parse_vc_conf,
7391 	},
7392 	[ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
7393 		.name = "{dst_type}",
7394 		.help = "destination field type value",
7395 		.call = parse_vc_modify_field_id,
7396 		.comp = comp_set_modify_field_id,
7397 	},
7398 	[ACTION_MODIFY_FIELD_DST_LEVEL] = {
7399 		.name = "dst_level",
7400 		.help = "destination field level",
7401 		.next = NEXT(action_modify_field_dst,
7402 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)),
7403 		.call = parse_vc_conf,
7404 	},
7405 	[ACTION_MODIFY_FIELD_DST_LEVEL_VALUE] = {
7406 		.name = "{dst_level}",
7407 		.help = "destination field level value",
7408 		.call = parse_vc_modify_field_level,
7409 		.comp = comp_none,
7410 	},
7411 	[ACTION_MODIFY_FIELD_DST_TAG_INDEX] = {
7412 		.name = "dst_tag_index",
7413 		.help = "destination field tag array",
7414 		.next = NEXT(action_modify_field_dst,
7415 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7416 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7417 					dst.tag_index)),
7418 		.call = parse_vc_conf,
7419 	},
7420 	[ACTION_MODIFY_FIELD_DST_TYPE_ID] = {
7421 		.name = "dst_type_id",
7422 		.help = "destination field type ID",
7423 		.next = NEXT(action_modify_field_dst,
7424 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7425 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7426 					dst.type)),
7427 		.call = parse_vc_conf,
7428 	},
7429 	[ACTION_MODIFY_FIELD_DST_CLASS_ID] = {
7430 		.name = "dst_class",
7431 		.help = "destination field class ID",
7432 		.next = NEXT(action_modify_field_dst,
7433 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7434 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7435 					     dst.class_id)),
7436 		.call = parse_vc_conf,
7437 	},
7438 	[ACTION_MODIFY_FIELD_DST_OFFSET] = {
7439 		.name = "dst_offset",
7440 		.help = "destination field bit offset",
7441 		.next = NEXT(action_modify_field_dst,
7442 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7443 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7444 					dst.offset)),
7445 		.call = parse_vc_conf,
7446 	},
7447 	[ACTION_MODIFY_FIELD_SRC_TYPE] = {
7448 		.name = "src_type",
7449 		.help = "source field type",
7450 		.next = NEXT(action_modify_field_src,
7451 			NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
7452 		.call = parse_vc_conf,
7453 	},
7454 	[ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
7455 		.name = "{src_type}",
7456 		.help = "source field type value",
7457 		.call = parse_vc_modify_field_id,
7458 		.comp = comp_set_modify_field_id,
7459 	},
7460 	[ACTION_MODIFY_FIELD_SRC_LEVEL] = {
7461 		.name = "src_level",
7462 		.help = "source field level",
7463 		.next = NEXT(action_modify_field_src,
7464 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)),
7465 		.call = parse_vc_conf,
7466 	},
7467 	[ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE] = {
7468 		.name = "{src_level}",
7469 		.help = "source field level value",
7470 		.call = parse_vc_modify_field_level,
7471 		.comp = comp_none,
7472 	},
7473 	[ACTION_MODIFY_FIELD_SRC_TAG_INDEX] = {
7474 		.name = "src_tag_index",
7475 		.help = "source field tag array",
7476 		.next = NEXT(action_modify_field_src,
7477 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7478 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7479 					src.tag_index)),
7480 		.call = parse_vc_conf,
7481 	},
7482 	[ACTION_MODIFY_FIELD_SRC_TYPE_ID] = {
7483 		.name = "src_type_id",
7484 		.help = "source field type ID",
7485 		.next = NEXT(action_modify_field_src,
7486 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7487 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7488 					src.type)),
7489 		.call = parse_vc_conf,
7490 	},
7491 	[ACTION_MODIFY_FIELD_SRC_CLASS_ID] = {
7492 		.name = "src_class",
7493 		.help = "source field class ID",
7494 		.next = NEXT(action_modify_field_src,
7495 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7496 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7497 					     src.class_id)),
7498 		.call = parse_vc_conf,
7499 	},
7500 	[ACTION_MODIFY_FIELD_SRC_OFFSET] = {
7501 		.name = "src_offset",
7502 		.help = "source field bit offset",
7503 		.next = NEXT(action_modify_field_src,
7504 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7505 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7506 					src.offset)),
7507 		.call = parse_vc_conf,
7508 	},
7509 	[ACTION_MODIFY_FIELD_SRC_VALUE] = {
7510 		.name = "src_value",
7511 		.help = "source immediate value",
7512 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7513 			     NEXT_ENTRY(COMMON_HEX)),
7514 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
7515 			     ARGS_ENTRY_ARB(0, 0),
7516 			     ARGS_ENTRY(struct rte_flow_action_modify_field,
7517 					src.value)),
7518 		.call = parse_vc_conf,
7519 	},
7520 	[ACTION_MODIFY_FIELD_SRC_POINTER] = {
7521 		.name = "src_ptr",
7522 		.help = "pointer to source immediate value",
7523 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7524 			     NEXT_ENTRY(COMMON_HEX)),
7525 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7526 					src.pvalue),
7527 			     ARGS_ENTRY_ARB(0, 0),
7528 			     ARGS_ENTRY_ARB
7529 				(sizeof(struct rte_flow_action_modify_field),
7530 				 FLOW_FIELD_PATTERN_SIZE)),
7531 		.call = parse_vc_conf,
7532 	},
7533 	[ACTION_MODIFY_FIELD_WIDTH] = {
7534 		.name = "width",
7535 		.help = "number of bits to copy",
7536 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7537 			NEXT_ENTRY(COMMON_UNSIGNED)),
7538 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7539 					width)),
7540 		.call = parse_vc_conf,
7541 	},
7542 	[ACTION_SEND_TO_KERNEL] = {
7543 		.name = "send_to_kernel",
7544 		.help = "send packets to kernel",
7545 		.priv = PRIV_ACTION(SEND_TO_KERNEL, 0),
7546 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7547 		.call = parse_vc,
7548 	},
7549 	[ACTION_IPV6_EXT_REMOVE] = {
7550 		.name = "ipv6_ext_remove",
7551 		.help = "IPv6 extension type, defined by set ipv6_ext_remove",
7552 		.priv = PRIV_ACTION(IPV6_EXT_REMOVE,
7553 			sizeof(struct action_ipv6_ext_remove_data)),
7554 		.next = NEXT(action_ipv6_ext_remove),
7555 		.call = parse_vc_action_ipv6_ext_remove,
7556 	},
7557 	[ACTION_IPV6_EXT_REMOVE_INDEX] = {
7558 		.name = "index",
7559 		.help = "the index of ipv6_ext_remove",
7560 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_REMOVE_INDEX_VALUE)),
7561 	},
7562 	[ACTION_IPV6_EXT_REMOVE_INDEX_VALUE] = {
7563 		.name = "{index}",
7564 		.type = "UNSIGNED",
7565 		.help = "unsigned integer value",
7566 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7567 		.call = parse_vc_action_ipv6_ext_remove_index,
7568 		.comp = comp_set_ipv6_ext_index,
7569 	},
7570 	[ACTION_IPV6_EXT_PUSH] = {
7571 		.name = "ipv6_ext_push",
7572 		.help = "IPv6 extension data, defined by set ipv6_ext_push",
7573 		.priv = PRIV_ACTION(IPV6_EXT_PUSH,
7574 			sizeof(struct action_ipv6_ext_push_data)),
7575 		.next = NEXT(action_ipv6_ext_push),
7576 		.call = parse_vc_action_ipv6_ext_push,
7577 	},
7578 	[ACTION_IPV6_EXT_PUSH_INDEX] = {
7579 		.name = "index",
7580 		.help = "the index of ipv6_ext_push",
7581 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_PUSH_INDEX_VALUE)),
7582 	},
7583 	[ACTION_IPV6_EXT_PUSH_INDEX_VALUE] = {
7584 		.name = "{index}",
7585 		.type = "UNSIGNED",
7586 		.help = "unsigned integer value",
7587 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7588 		.call = parse_vc_action_ipv6_ext_push_index,
7589 		.comp = comp_set_ipv6_ext_index,
7590 	},
7591 	[ACTION_NAT64] = {
7592 		.name = "nat64",
7593 		.help = "NAT64 IP headers translation",
7594 		.priv = PRIV_ACTION(NAT64, sizeof(struct rte_flow_action_nat64)),
7595 		.next = NEXT(action_nat64),
7596 		.call = parse_vc,
7597 	},
7598 	[ACTION_NAT64_MODE] = {
7599 		.name = "type",
7600 		.help = "NAT64 translation type",
7601 		.next = NEXT(action_nat64, NEXT_ENTRY(COMMON_UNSIGNED)),
7602 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_nat64, type)),
7603 		.call = parse_vc_conf,
7604 	},
7605 	/* Top level command. */
7606 	[SET] = {
7607 		.name = "set",
7608 		.help = "set raw encap/decap/sample data",
7609 		.type = "set raw_encap|raw_decap <index> <pattern>"
7610 				" or set sample_actions <index> <action>",
7611 		.next = NEXT(NEXT_ENTRY
7612 			     (SET_RAW_ENCAP,
7613 			      SET_RAW_DECAP,
7614 			      SET_SAMPLE_ACTIONS,
7615 			      SET_IPV6_EXT_REMOVE,
7616 			      SET_IPV6_EXT_PUSH)),
7617 		.call = parse_set_init,
7618 	},
7619 	/* Sub-level commands. */
7620 	[SET_RAW_ENCAP] = {
7621 		.name = "raw_encap",
7622 		.help = "set raw encap data",
7623 		.next = NEXT(next_set_raw),
7624 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7625 				(offsetof(struct buffer, port),
7626 				 sizeof(((struct buffer *)0)->port),
7627 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7628 		.call = parse_set_raw_encap_decap,
7629 	},
7630 	[SET_RAW_DECAP] = {
7631 		.name = "raw_decap",
7632 		.help = "set raw decap data",
7633 		.next = NEXT(next_set_raw),
7634 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7635 				(offsetof(struct buffer, port),
7636 				 sizeof(((struct buffer *)0)->port),
7637 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7638 		.call = parse_set_raw_encap_decap,
7639 	},
7640 	[SET_RAW_INDEX] = {
7641 		.name = "{index}",
7642 		.type = "COMMON_UNSIGNED",
7643 		.help = "index of raw_encap/raw_decap data",
7644 		.next = NEXT(next_item),
7645 		.call = parse_port,
7646 	},
7647 	[SET_SAMPLE_INDEX] = {
7648 		.name = "{index}",
7649 		.type = "UNSIGNED",
7650 		.help = "index of sample actions",
7651 		.next = NEXT(next_action_sample),
7652 		.call = parse_port,
7653 	},
7654 	[SET_SAMPLE_ACTIONS] = {
7655 		.name = "sample_actions",
7656 		.help = "set sample actions list",
7657 		.next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
7658 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7659 				(offsetof(struct buffer, port),
7660 				 sizeof(((struct buffer *)0)->port),
7661 				 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
7662 		.call = parse_set_sample_action,
7663 	},
7664 	[SET_IPV6_EXT_PUSH] = {
7665 		.name = "ipv6_ext_push",
7666 		.help = "set IPv6 extension header",
7667 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7668 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7669 				(offsetof(struct buffer, port),
7670 				 sizeof(((struct buffer *)0)->port),
7671 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7672 		.call = parse_set_ipv6_ext_action,
7673 	},
7674 	[SET_IPV6_EXT_REMOVE] = {
7675 		.name = "ipv6_ext_remove",
7676 		.help = "set IPv6 extension header",
7677 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7678 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7679 				(offsetof(struct buffer, port),
7680 				 sizeof(((struct buffer *)0)->port),
7681 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7682 		.call = parse_set_ipv6_ext_action,
7683 	},
7684 	[SET_IPV6_EXT_INDEX] = {
7685 		.name = "{index}",
7686 		.type = "UNSIGNED",
7687 		.help = "index of ipv6 extension push/remove actions",
7688 		.next = NEXT(item_ipv6_push_ext),
7689 		.call = parse_port,
7690 	},
7691 	[ITEM_IPV6_PUSH_REMOVE_EXT] = {
7692 		.name = "ipv6_ext",
7693 		.help = "set IPv6 extension header",
7694 		.priv = PRIV_ITEM(IPV6_EXT,
7695 				  sizeof(struct rte_flow_item_ipv6_ext)),
7696 		.next = NEXT(item_ipv6_push_ext_type),
7697 		.call = parse_vc,
7698 	},
7699 	[ITEM_IPV6_PUSH_REMOVE_EXT_TYPE] = {
7700 		.name = "type",
7701 		.help = "set IPv6 extension type",
7702 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
7703 					     next_hdr)),
7704 		.next = NEXT(item_ipv6_push_ext_header, NEXT_ENTRY(COMMON_UNSIGNED),
7705 			     item_param),
7706 	},
7707 	[ACTION_SET_TAG] = {
7708 		.name = "set_tag",
7709 		.help = "set tag",
7710 		.priv = PRIV_ACTION(SET_TAG,
7711 			sizeof(struct rte_flow_action_set_tag)),
7712 		.next = NEXT(action_set_tag),
7713 		.call = parse_vc,
7714 	},
7715 	[ACTION_SET_TAG_INDEX] = {
7716 		.name = "index",
7717 		.help = "index of tag array",
7718 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7719 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
7720 		.call = parse_vc_conf,
7721 	},
7722 	[ACTION_SET_TAG_DATA] = {
7723 		.name = "data",
7724 		.help = "tag value",
7725 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7726 		.args = ARGS(ARGS_ENTRY
7727 			     (struct rte_flow_action_set_tag, data)),
7728 		.call = parse_vc_conf,
7729 	},
7730 	[ACTION_SET_TAG_MASK] = {
7731 		.name = "mask",
7732 		.help = "mask for tag value",
7733 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7734 		.args = ARGS(ARGS_ENTRY
7735 			     (struct rte_flow_action_set_tag, mask)),
7736 		.call = parse_vc_conf,
7737 	},
7738 	[ACTION_SET_META] = {
7739 		.name = "set_meta",
7740 		.help = "set metadata",
7741 		.priv = PRIV_ACTION(SET_META,
7742 			sizeof(struct rte_flow_action_set_meta)),
7743 		.next = NEXT(action_set_meta),
7744 		.call = parse_vc_action_set_meta,
7745 	},
7746 	[ACTION_SET_META_DATA] = {
7747 		.name = "data",
7748 		.help = "metadata value",
7749 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7750 		.args = ARGS(ARGS_ENTRY
7751 			     (struct rte_flow_action_set_meta, data)),
7752 		.call = parse_vc_conf,
7753 	},
7754 	[ACTION_SET_META_MASK] = {
7755 		.name = "mask",
7756 		.help = "mask for metadata value",
7757 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7758 		.args = ARGS(ARGS_ENTRY
7759 			     (struct rte_flow_action_set_meta, mask)),
7760 		.call = parse_vc_conf,
7761 	},
7762 	[ACTION_SET_IPV4_DSCP] = {
7763 		.name = "set_ipv4_dscp",
7764 		.help = "set DSCP value",
7765 		.priv = PRIV_ACTION(SET_IPV4_DSCP,
7766 			sizeof(struct rte_flow_action_set_dscp)),
7767 		.next = NEXT(action_set_ipv4_dscp),
7768 		.call = parse_vc,
7769 	},
7770 	[ACTION_SET_IPV4_DSCP_VALUE] = {
7771 		.name = "dscp_value",
7772 		.help = "new IPv4 DSCP value to set",
7773 		.next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7774 		.args = ARGS(ARGS_ENTRY
7775 			     (struct rte_flow_action_set_dscp, dscp)),
7776 		.call = parse_vc_conf,
7777 	},
7778 	[ACTION_SET_IPV6_DSCP] = {
7779 		.name = "set_ipv6_dscp",
7780 		.help = "set DSCP value",
7781 		.priv = PRIV_ACTION(SET_IPV6_DSCP,
7782 			sizeof(struct rte_flow_action_set_dscp)),
7783 		.next = NEXT(action_set_ipv6_dscp),
7784 		.call = parse_vc,
7785 	},
7786 	[ACTION_SET_IPV6_DSCP_VALUE] = {
7787 		.name = "dscp_value",
7788 		.help = "new IPv6 DSCP value to set",
7789 		.next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7790 		.args = ARGS(ARGS_ENTRY
7791 			     (struct rte_flow_action_set_dscp, dscp)),
7792 		.call = parse_vc_conf,
7793 	},
7794 	[ACTION_AGE] = {
7795 		.name = "age",
7796 		.help = "set a specific metadata header",
7797 		.next = NEXT(action_age),
7798 		.priv = PRIV_ACTION(AGE,
7799 			sizeof(struct rte_flow_action_age)),
7800 		.call = parse_vc,
7801 	},
7802 	[ACTION_AGE_TIMEOUT] = {
7803 		.name = "timeout",
7804 		.help = "flow age timeout value",
7805 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
7806 					   timeout, 24)),
7807 		.next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
7808 		.call = parse_vc_conf,
7809 	},
7810 	[ACTION_AGE_UPDATE] = {
7811 		.name = "age_update",
7812 		.help = "update aging parameter",
7813 		.next = NEXT(action_age_update),
7814 		.priv = PRIV_ACTION(AGE,
7815 				    sizeof(struct rte_flow_update_age)),
7816 		.call = parse_vc,
7817 	},
7818 	[ACTION_AGE_UPDATE_TIMEOUT] = {
7819 		.name = "timeout",
7820 		.help = "age timeout update value",
7821 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7822 					   timeout, 24)),
7823 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_UNSIGNED)),
7824 		.call = parse_vc_conf_timeout,
7825 	},
7826 	[ACTION_AGE_UPDATE_TOUCH] = {
7827 		.name = "touch",
7828 		.help = "this flow is touched",
7829 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_BOOLEAN)),
7830 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7831 					   touch, 1)),
7832 		.call = parse_vc_conf,
7833 	},
7834 	[ACTION_SAMPLE] = {
7835 		.name = "sample",
7836 		.help = "set a sample action",
7837 		.next = NEXT(action_sample),
7838 		.priv = PRIV_ACTION(SAMPLE,
7839 			sizeof(struct action_sample_data)),
7840 		.call = parse_vc_action_sample,
7841 	},
7842 	[ACTION_SAMPLE_RATIO] = {
7843 		.name = "ratio",
7844 		.help = "flow sample ratio value",
7845 		.next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
7846 		.args = ARGS(ARGS_ENTRY_ARB
7847 			     (offsetof(struct action_sample_data, conf) +
7848 			      offsetof(struct rte_flow_action_sample, ratio),
7849 			      sizeof(((struct rte_flow_action_sample *)0)->
7850 				     ratio))),
7851 	},
7852 	[ACTION_SAMPLE_INDEX] = {
7853 		.name = "index",
7854 		.help = "the index of sample actions list",
7855 		.next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
7856 	},
7857 	[ACTION_SAMPLE_INDEX_VALUE] = {
7858 		.name = "{index}",
7859 		.type = "COMMON_UNSIGNED",
7860 		.help = "unsigned integer value",
7861 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7862 		.call = parse_vc_action_sample_index,
7863 		.comp = comp_set_sample_index,
7864 	},
7865 	[ACTION_CONNTRACK] = {
7866 		.name = "conntrack",
7867 		.help = "create a conntrack object",
7868 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7869 		.priv = PRIV_ACTION(CONNTRACK,
7870 				    sizeof(struct rte_flow_action_conntrack)),
7871 		.call = parse_vc,
7872 	},
7873 	[ACTION_CONNTRACK_UPDATE] = {
7874 		.name = "conntrack_update",
7875 		.help = "update a conntrack object",
7876 		.next = NEXT(action_update_conntrack),
7877 		.priv = PRIV_ACTION(CONNTRACK,
7878 				    sizeof(struct rte_flow_modify_conntrack)),
7879 		.call = parse_vc,
7880 	},
7881 	[ACTION_CONNTRACK_UPDATE_DIR] = {
7882 		.name = "dir",
7883 		.help = "update a conntrack object direction",
7884 		.next = NEXT(action_update_conntrack),
7885 		.call = parse_vc_action_conntrack_update,
7886 	},
7887 	[ACTION_CONNTRACK_UPDATE_CTX] = {
7888 		.name = "ctx",
7889 		.help = "update a conntrack object context",
7890 		.next = NEXT(action_update_conntrack),
7891 		.call = parse_vc_action_conntrack_update,
7892 	},
7893 	[ACTION_PORT_REPRESENTOR] = {
7894 		.name = "port_representor",
7895 		.help = "at embedded switch level, send matching traffic to the given ethdev",
7896 		.priv = PRIV_ACTION(PORT_REPRESENTOR,
7897 				    sizeof(struct rte_flow_action_ethdev)),
7898 		.next = NEXT(action_port_representor),
7899 		.call = parse_vc,
7900 	},
7901 	[ACTION_PORT_REPRESENTOR_PORT_ID] = {
7902 		.name = "port_id",
7903 		.help = "ethdev port ID",
7904 		.next = NEXT(action_port_representor,
7905 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7906 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7907 					port_id)),
7908 		.call = parse_vc_conf,
7909 	},
7910 	[ACTION_REPRESENTED_PORT] = {
7911 		.name = "represented_port",
7912 		.help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
7913 		.priv = PRIV_ACTION(REPRESENTED_PORT,
7914 				sizeof(struct rte_flow_action_ethdev)),
7915 		.next = NEXT(action_represented_port),
7916 		.call = parse_vc,
7917 	},
7918 	[ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
7919 		.name = "ethdev_port_id",
7920 		.help = "ethdev port ID",
7921 		.next = NEXT(action_represented_port,
7922 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7923 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7924 					port_id)),
7925 		.call = parse_vc_conf,
7926 	},
7927 	/* Indirect action destroy arguments. */
7928 	[INDIRECT_ACTION_DESTROY_ID] = {
7929 		.name = "action_id",
7930 		.help = "specify a indirect action id to destroy",
7931 		.next = NEXT(next_ia_destroy_attr,
7932 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7933 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
7934 					    args.ia_destroy.action_id)),
7935 		.call = parse_ia_destroy,
7936 	},
7937 	/* Indirect action create arguments. */
7938 	[INDIRECT_ACTION_CREATE_ID] = {
7939 		.name = "action_id",
7940 		.help = "specify a indirect action id to create",
7941 		.next = NEXT(next_ia_create_attr,
7942 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7943 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
7944 	},
7945 	[ACTION_INDIRECT] = {
7946 		.name = "indirect",
7947 		.help = "apply indirect action by id",
7948 		.priv = PRIV_ACTION(INDIRECT, 0),
7949 		.next = NEXT(next_ia),
7950 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7951 		.call = parse_vc,
7952 	},
7953 	[ACTION_INDIRECT_LIST] = {
7954 		.name = "indirect_list",
7955 		.help = "apply indirect list action by id",
7956 		.priv = PRIV_ACTION(INDIRECT_LIST,
7957 				    sizeof(struct
7958 					   rte_flow_action_indirect_list)),
7959 		.next = NEXT(next_ial),
7960 		.call = parse_vc,
7961 	},
7962 	[ACTION_INDIRECT_LIST_HANDLE] = {
7963 		.name = "handle",
7964 		.help = "indirect list handle",
7965 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_HANDLE)),
7966 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7967 	},
7968 	[ACTION_INDIRECT_LIST_CONF] = {
7969 		.name = "conf",
7970 		.help = "indirect list configuration",
7971 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_CONF)),
7972 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7973 	},
7974 	[INDIRECT_LIST_ACTION_ID2PTR_HANDLE] = {
7975 		.type = "UNSIGNED",
7976 		.help = "unsigned integer value",
7977 		.call = parse_indlst_id2ptr,
7978 		.comp = comp_none,
7979 	},
7980 	[INDIRECT_LIST_ACTION_ID2PTR_CONF] = {
7981 		.type = "UNSIGNED",
7982 		.help = "unsigned integer value",
7983 		.call = parse_indlst_id2ptr,
7984 		.comp = comp_none,
7985 	},
7986 	[ACTION_SHARED_INDIRECT] = {
7987 		.name = "shared_indirect",
7988 		.help = "apply indirect action by id and port",
7989 		.priv = PRIV_ACTION(INDIRECT, 0),
7990 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_PORT)),
7991 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t)),
7992 			     ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7993 		.call = parse_vc,
7994 	},
7995 	[INDIRECT_ACTION_PORT] = {
7996 		.name = "{indirect_action_port}",
7997 		.type = "INDIRECT_ACTION_PORT",
7998 		.help = "indirect action port",
7999 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
8000 		.call = parse_ia_port,
8001 		.comp = comp_none,
8002 	},
8003 	[INDIRECT_ACTION_ID2PTR] = {
8004 		.name = "{action_id}",
8005 		.type = "INDIRECT_ACTION_ID",
8006 		.help = "indirect action id",
8007 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
8008 		.call = parse_ia_id2ptr,
8009 		.comp = comp_none,
8010 	},
8011 	[INDIRECT_ACTION_INGRESS] = {
8012 		.name = "ingress",
8013 		.help = "affect rule to ingress",
8014 		.next = NEXT(next_ia_create_attr),
8015 		.call = parse_ia,
8016 	},
8017 	[INDIRECT_ACTION_EGRESS] = {
8018 		.name = "egress",
8019 		.help = "affect rule to egress",
8020 		.next = NEXT(next_ia_create_attr),
8021 		.call = parse_ia,
8022 	},
8023 	[INDIRECT_ACTION_TRANSFER] = {
8024 		.name = "transfer",
8025 		.help = "affect rule to transfer",
8026 		.next = NEXT(next_ia_create_attr),
8027 		.call = parse_ia,
8028 	},
8029 	[INDIRECT_ACTION_SPEC] = {
8030 		.name = "action",
8031 		.help = "specify action to create indirect handle",
8032 		.next = NEXT(next_action),
8033 	},
8034 	[INDIRECT_ACTION_LIST] = {
8035 		.name = "list",
8036 		.help = "specify actions for indirect handle list",
8037 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
8038 		.call = parse_ia,
8039 	},
8040 	[INDIRECT_ACTION_FLOW_CONF] = {
8041 		.name = "flow_conf",
8042 		.help = "specify actions configuration for indirect handle list",
8043 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
8044 		.call = parse_ia,
8045 	},
8046 	[ACTION_POL_G] = {
8047 		.name = "g_actions",
8048 		.help = "submit a list of associated actions for green",
8049 		.next = NEXT(next_action),
8050 		.call = parse_mp,
8051 	},
8052 	[ACTION_POL_Y] = {
8053 		.name = "y_actions",
8054 		.help = "submit a list of associated actions for yellow",
8055 		.next = NEXT(next_action),
8056 	},
8057 	[ACTION_POL_R] = {
8058 		.name = "r_actions",
8059 		.help = "submit a list of associated actions for red",
8060 		.next = NEXT(next_action),
8061 	},
8062 	[ACTION_QUOTA_CREATE] = {
8063 		.name = "quota_create",
8064 		.help = "create quota action",
8065 		.priv = PRIV_ACTION(QUOTA,
8066 				    sizeof(struct rte_flow_action_quota)),
8067 		.next = NEXT(action_quota_create),
8068 		.call = parse_vc
8069 	},
8070 	[ACTION_QUOTA_CREATE_LIMIT] = {
8071 		.name = "limit",
8072 		.help = "quota limit",
8073 		.next = NEXT(action_quota_create, NEXT_ENTRY(COMMON_UNSIGNED)),
8074 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, quota)),
8075 		.call = parse_vc_conf
8076 	},
8077 	[ACTION_QUOTA_CREATE_MODE] = {
8078 		.name = "mode",
8079 		.help = "quota mode",
8080 		.next = NEXT(action_quota_create,
8081 			     NEXT_ENTRY(ACTION_QUOTA_CREATE_MODE_NAME)),
8082 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, mode)),
8083 		.call = parse_vc_conf
8084 	},
8085 	[ACTION_QUOTA_CREATE_MODE_NAME] = {
8086 		.name = "mode_name",
8087 		.help = "quota mode name",
8088 		.call = parse_quota_mode_name,
8089 		.comp = comp_quota_mode_name
8090 	},
8091 	[ACTION_QUOTA_QU] = {
8092 		.name = "quota_update",
8093 		.help = "update quota action",
8094 		.priv = PRIV_ACTION(QUOTA,
8095 				    sizeof(struct rte_flow_update_quota)),
8096 		.next = NEXT(action_quota_update),
8097 		.call = parse_vc
8098 	},
8099 	[ACTION_QUOTA_QU_LIMIT] = {
8100 		.name = "limit",
8101 		.help = "quota limit",
8102 		.next = NEXT(action_quota_update, NEXT_ENTRY(COMMON_UNSIGNED)),
8103 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, quota)),
8104 		.call = parse_vc_conf
8105 	},
8106 	[ACTION_QUOTA_QU_UPDATE_OP] = {
8107 		.name = "update_op",
8108 		.help = "query update op SET|ADD",
8109 		.next = NEXT(action_quota_update,
8110 			     NEXT_ENTRY(ACTION_QUOTA_QU_UPDATE_OP_NAME)),
8111 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, op)),
8112 		.call = parse_vc_conf
8113 	},
8114 	[ACTION_QUOTA_QU_UPDATE_OP_NAME] = {
8115 		.name = "update_op_name",
8116 		.help = "quota update op name",
8117 		.call = parse_quota_update_name,
8118 		.comp = comp_quota_update_name
8119 	},
8120 
8121 	/* Top-level command. */
8122 	[ADD] = {
8123 		.name = "add",
8124 		.type = "port meter policy {port_id} {arg}",
8125 		.help = "add port meter policy",
8126 		.next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
8127 		.call = parse_init,
8128 	},
8129 	/* Sub-level commands. */
8130 	[ITEM_POL_PORT] = {
8131 		.name = "port",
8132 		.help = "add port meter policy",
8133 		.next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
8134 	},
8135 	[ITEM_POL_METER] = {
8136 		.name = "meter",
8137 		.help = "add port meter policy",
8138 		.next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
8139 	},
8140 	[ITEM_POL_POLICY] = {
8141 		.name = "policy",
8142 		.help = "add port meter policy",
8143 		.next = NEXT(NEXT_ENTRY(ACTION_POL_R),
8144 				NEXT_ENTRY(ACTION_POL_Y),
8145 				NEXT_ENTRY(ACTION_POL_G),
8146 				NEXT_ENTRY(COMMON_POLICY_ID),
8147 				NEXT_ENTRY(COMMON_PORT_ID)),
8148 		.args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
8149 				ARGS_ENTRY(struct buffer, port)),
8150 		.call = parse_mp,
8151 	},
8152 	[ITEM_AGGR_AFFINITY] = {
8153 		.name = "aggr_affinity",
8154 		.help = "match on the aggregated port receiving the packets",
8155 		.priv = PRIV_ITEM(AGGR_AFFINITY,
8156 				  sizeof(struct rte_flow_item_aggr_affinity)),
8157 		.next = NEXT(item_aggr_affinity),
8158 		.call = parse_vc,
8159 	},
8160 	[ITEM_AGGR_AFFINITY_VALUE] = {
8161 		.name = "affinity",
8162 		.help = "aggregated affinity value",
8163 		.next = NEXT(item_aggr_affinity, NEXT_ENTRY(COMMON_UNSIGNED),
8164 			     item_param),
8165 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_aggr_affinity,
8166 					affinity)),
8167 	},
8168 	[ITEM_TX_QUEUE] = {
8169 		.name = "tx_queue",
8170 		.help = "match on the tx queue of send packet",
8171 		.priv = PRIV_ITEM(TX_QUEUE,
8172 				  sizeof(struct rte_flow_item_tx_queue)),
8173 		.next = NEXT(item_tx_queue),
8174 		.call = parse_vc,
8175 	},
8176 	[ITEM_TX_QUEUE_VALUE] = {
8177 		.name = "tx_queue_value",
8178 		.help = "tx queue value",
8179 		.next = NEXT(item_tx_queue, NEXT_ENTRY(COMMON_UNSIGNED),
8180 			     item_param),
8181 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tx_queue,
8182 					tx_queue)),
8183 	},
8184 };
8185 
8186 /** Remove and return last entry from argument stack. */
8187 static const struct arg *
8188 pop_args(struct context *ctx)
8189 {
8190 	return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
8191 }
8192 
8193 /** Add entry on top of the argument stack. */
8194 static int
8195 push_args(struct context *ctx, const struct arg *arg)
8196 {
8197 	if (ctx->args_num == CTX_STACK_SIZE)
8198 		return -1;
8199 	ctx->args[ctx->args_num++] = arg;
8200 	return 0;
8201 }
8202 
8203 /** Spread value into buffer according to bit-mask. */
8204 static size_t
8205 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
8206 {
8207 	uint32_t i = arg->size;
8208 	uint32_t end = 0;
8209 	int sub = 1;
8210 	int add = 0;
8211 	size_t len = 0;
8212 
8213 	if (!arg->mask)
8214 		return 0;
8215 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8216 	if (!arg->hton) {
8217 		i = 0;
8218 		end = arg->size;
8219 		sub = 0;
8220 		add = 1;
8221 	}
8222 #endif
8223 	while (i != end) {
8224 		unsigned int shift = 0;
8225 		uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
8226 
8227 		for (shift = 0; arg->mask[i] >> shift; ++shift) {
8228 			if (!(arg->mask[i] & (1 << shift)))
8229 				continue;
8230 			++len;
8231 			if (!dst)
8232 				continue;
8233 			*buf &= ~(1 << shift);
8234 			*buf |= (val & 1) << shift;
8235 			val >>= 1;
8236 		}
8237 		i += add;
8238 	}
8239 	return len;
8240 }
8241 
8242 /** Compare a string with a partial one of a given length. */
8243 static int
8244 strcmp_partial(const char *full, const char *partial, size_t partial_len)
8245 {
8246 	int r = strncmp(full, partial, partial_len);
8247 
8248 	if (r)
8249 		return r;
8250 	if (strlen(full) <= partial_len)
8251 		return 0;
8252 	return full[partial_len];
8253 }
8254 
8255 /**
8256  * Parse a prefix length and generate a bit-mask.
8257  *
8258  * Last argument (ctx->args) is retrieved to determine mask size, storage
8259  * location and whether the result must use network byte ordering.
8260  */
8261 static int
8262 parse_prefix(struct context *ctx, const struct token *token,
8263 	     const char *str, unsigned int len,
8264 	     void *buf, unsigned int size)
8265 {
8266 	const struct arg *arg = pop_args(ctx);
8267 	static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
8268 	char *end;
8269 	uintmax_t u;
8270 	unsigned int bytes;
8271 	unsigned int extra;
8272 
8273 	(void)token;
8274 	/* Argument is expected. */
8275 	if (!arg)
8276 		return -1;
8277 	errno = 0;
8278 	u = strtoumax(str, &end, 0);
8279 	if (errno || (size_t)(end - str) != len)
8280 		goto error;
8281 	if (arg->mask) {
8282 		uintmax_t v = 0;
8283 
8284 		extra = arg_entry_bf_fill(NULL, 0, arg);
8285 		if (u > extra)
8286 			goto error;
8287 		if (!ctx->object)
8288 			return len;
8289 		extra -= u;
8290 		while (u--)
8291 			(v <<= 1, v |= 1);
8292 		v <<= extra;
8293 		if (!arg_entry_bf_fill(ctx->object, v, arg) ||
8294 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
8295 			goto error;
8296 		return len;
8297 	}
8298 	bytes = u / 8;
8299 	extra = u % 8;
8300 	size = arg->size;
8301 	if (bytes > size || bytes + !!extra > size)
8302 		goto error;
8303 	if (!ctx->object)
8304 		return len;
8305 	buf = (uint8_t *)ctx->object + arg->offset;
8306 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8307 	if (!arg->hton) {
8308 		memset((uint8_t *)buf + size - bytes, 0xff, bytes);
8309 		memset(buf, 0x00, size - bytes);
8310 		if (extra)
8311 			((uint8_t *)buf)[size - bytes - 1] = conv[extra];
8312 	} else
8313 #endif
8314 	{
8315 		memset(buf, 0xff, bytes);
8316 		memset((uint8_t *)buf + bytes, 0x00, size - bytes);
8317 		if (extra)
8318 			((uint8_t *)buf)[bytes] = conv[extra];
8319 	}
8320 	if (ctx->objmask)
8321 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8322 	return len;
8323 error:
8324 	push_args(ctx, arg);
8325 	return -1;
8326 }
8327 
8328 /** Default parsing function for token name matching. */
8329 static int
8330 parse_default(struct context *ctx, const struct token *token,
8331 	      const char *str, unsigned int len,
8332 	      void *buf, unsigned int size)
8333 {
8334 	(void)ctx;
8335 	(void)buf;
8336 	(void)size;
8337 	if (strcmp_partial(token->name, str, len))
8338 		return -1;
8339 	return len;
8340 }
8341 
8342 /** Parse flow command, initialize output buffer for subsequent tokens. */
8343 static int
8344 parse_init(struct context *ctx, const struct token *token,
8345 	   const char *str, unsigned int len,
8346 	   void *buf, unsigned int size)
8347 {
8348 	struct buffer *out = buf;
8349 
8350 	/* Token name must match. */
8351 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8352 		return -1;
8353 	/* Nothing else to do if there is no buffer. */
8354 	if (!out)
8355 		return len;
8356 	/* Make sure buffer is large enough. */
8357 	if (size < sizeof(*out))
8358 		return -1;
8359 	/* Initialize buffer. */
8360 	memset(out, 0x00, sizeof(*out));
8361 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
8362 	ctx->objdata = 0;
8363 	ctx->object = out;
8364 	ctx->objmask = NULL;
8365 	return len;
8366 }
8367 
8368 /** Parse tokens for indirect action commands. */
8369 static int
8370 parse_ia(struct context *ctx, const struct token *token,
8371 	 const char *str, unsigned int len,
8372 	 void *buf, unsigned int size)
8373 {
8374 	struct buffer *out = buf;
8375 
8376 	/* Token name must match. */
8377 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8378 		return -1;
8379 	/* Nothing else to do if there is no buffer. */
8380 	if (!out)
8381 		return len;
8382 	if (!out->command) {
8383 		if (ctx->curr != INDIRECT_ACTION)
8384 			return -1;
8385 		if (sizeof(*out) > size)
8386 			return -1;
8387 		out->command = ctx->curr;
8388 		ctx->objdata = 0;
8389 		ctx->object = out;
8390 		ctx->objmask = NULL;
8391 		out->args.vc.data = (uint8_t *)out + size;
8392 		return len;
8393 	}
8394 	switch (ctx->curr) {
8395 	case INDIRECT_ACTION_CREATE:
8396 	case INDIRECT_ACTION_UPDATE:
8397 	case INDIRECT_ACTION_QUERY_UPDATE:
8398 		out->args.vc.actions =
8399 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8400 					       sizeof(double));
8401 		out->args.vc.attr.group = UINT32_MAX;
8402 		/* fallthrough */
8403 	case INDIRECT_ACTION_QUERY:
8404 		out->command = ctx->curr;
8405 		ctx->objdata = 0;
8406 		ctx->object = out;
8407 		ctx->objmask = NULL;
8408 		return len;
8409 	case INDIRECT_ACTION_EGRESS:
8410 		out->args.vc.attr.egress = 1;
8411 		return len;
8412 	case INDIRECT_ACTION_INGRESS:
8413 		out->args.vc.attr.ingress = 1;
8414 		return len;
8415 	case INDIRECT_ACTION_TRANSFER:
8416 		out->args.vc.attr.transfer = 1;
8417 		return len;
8418 	case INDIRECT_ACTION_QU_MODE:
8419 		return len;
8420 	case INDIRECT_ACTION_LIST:
8421 		out->command = INDIRECT_ACTION_LIST_CREATE;
8422 		return len;
8423 	case INDIRECT_ACTION_FLOW_CONF:
8424 		out->command = INDIRECT_ACTION_FLOW_CONF_CREATE;
8425 		return len;
8426 	default:
8427 		return -1;
8428 	}
8429 }
8430 
8431 
8432 /** Parse tokens for indirect action destroy command. */
8433 static int
8434 parse_ia_destroy(struct context *ctx, const struct token *token,
8435 		 const char *str, unsigned int len,
8436 		 void *buf, unsigned int size)
8437 {
8438 	struct buffer *out = buf;
8439 	uint32_t *action_id;
8440 
8441 	/* Token name must match. */
8442 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8443 		return -1;
8444 	/* Nothing else to do if there is no buffer. */
8445 	if (!out)
8446 		return len;
8447 	if (!out->command || out->command == INDIRECT_ACTION) {
8448 		if (ctx->curr != INDIRECT_ACTION_DESTROY)
8449 			return -1;
8450 		if (sizeof(*out) > size)
8451 			return -1;
8452 		out->command = ctx->curr;
8453 		ctx->objdata = 0;
8454 		ctx->object = out;
8455 		ctx->objmask = NULL;
8456 		out->args.ia_destroy.action_id =
8457 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8458 					       sizeof(double));
8459 		return len;
8460 	}
8461 	action_id = out->args.ia_destroy.action_id
8462 		    + out->args.ia_destroy.action_id_n++;
8463 	if ((uint8_t *)action_id > (uint8_t *)out + size)
8464 		return -1;
8465 	ctx->objdata = 0;
8466 	ctx->object = action_id;
8467 	ctx->objmask = NULL;
8468 	return len;
8469 }
8470 
8471 /** Parse tokens for indirect action commands. */
8472 static int
8473 parse_qia(struct context *ctx, const struct token *token,
8474 	  const char *str, unsigned int len,
8475 	  void *buf, unsigned int size)
8476 {
8477 	struct buffer *out = buf;
8478 
8479 	/* Token name must match. */
8480 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8481 		return -1;
8482 	/* Nothing else to do if there is no buffer. */
8483 	if (!out)
8484 		return len;
8485 	if (!out->command) {
8486 		if (ctx->curr != QUEUE)
8487 			return -1;
8488 		if (sizeof(*out) > size)
8489 			return -1;
8490 		out->args.vc.data = (uint8_t *)out + size;
8491 		return len;
8492 	}
8493 	switch (ctx->curr) {
8494 	case QUEUE_INDIRECT_ACTION:
8495 		return len;
8496 	case QUEUE_INDIRECT_ACTION_CREATE:
8497 	case QUEUE_INDIRECT_ACTION_UPDATE:
8498 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
8499 		out->args.vc.actions =
8500 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8501 					       sizeof(double));
8502 		out->args.vc.attr.group = UINT32_MAX;
8503 		/* fallthrough */
8504 	case QUEUE_INDIRECT_ACTION_QUERY:
8505 		out->command = ctx->curr;
8506 		ctx->objdata = 0;
8507 		ctx->object = out;
8508 		ctx->objmask = NULL;
8509 		return len;
8510 	case QUEUE_INDIRECT_ACTION_EGRESS:
8511 		out->args.vc.attr.egress = 1;
8512 		return len;
8513 	case QUEUE_INDIRECT_ACTION_INGRESS:
8514 		out->args.vc.attr.ingress = 1;
8515 		return len;
8516 	case QUEUE_INDIRECT_ACTION_TRANSFER:
8517 		out->args.vc.attr.transfer = 1;
8518 		return len;
8519 	case QUEUE_INDIRECT_ACTION_CREATE_POSTPONE:
8520 		return len;
8521 	case QUEUE_INDIRECT_ACTION_QU_MODE:
8522 		return len;
8523 	case QUEUE_INDIRECT_ACTION_LIST:
8524 		out->command = QUEUE_INDIRECT_ACTION_LIST_CREATE;
8525 		return len;
8526 	default:
8527 		return -1;
8528 	}
8529 }
8530 
8531 /** Parse tokens for indirect action destroy command. */
8532 static int
8533 parse_qia_destroy(struct context *ctx, const struct token *token,
8534 		  const char *str, unsigned int len,
8535 		  void *buf, unsigned int size)
8536 {
8537 	struct buffer *out = buf;
8538 	uint32_t *action_id;
8539 
8540 	/* Token name must match. */
8541 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8542 		return -1;
8543 	/* Nothing else to do if there is no buffer. */
8544 	if (!out)
8545 		return len;
8546 	if (!out->command || out->command == QUEUE) {
8547 		if (ctx->curr != QUEUE_INDIRECT_ACTION_DESTROY)
8548 			return -1;
8549 		if (sizeof(*out) > size)
8550 			return -1;
8551 		out->command = ctx->curr;
8552 		ctx->objdata = 0;
8553 		ctx->object = out;
8554 		ctx->objmask = NULL;
8555 		out->args.ia_destroy.action_id =
8556 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8557 					       sizeof(double));
8558 		return len;
8559 	}
8560 	switch (ctx->curr) {
8561 	case QUEUE_INDIRECT_ACTION:
8562 		out->command = ctx->curr;
8563 		ctx->objdata = 0;
8564 		ctx->object = out;
8565 		ctx->objmask = NULL;
8566 		return len;
8567 	case QUEUE_INDIRECT_ACTION_DESTROY_ID:
8568 		action_id = out->args.ia_destroy.action_id
8569 				+ out->args.ia_destroy.action_id_n++;
8570 		if ((uint8_t *)action_id > (uint8_t *)out + size)
8571 			return -1;
8572 		ctx->objdata = 0;
8573 		ctx->object = action_id;
8574 		ctx->objmask = NULL;
8575 		return len;
8576 	case QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE:
8577 		return len;
8578 	default:
8579 		return -1;
8580 	}
8581 }
8582 
8583 /** Parse tokens for meter policy action commands. */
8584 static int
8585 parse_mp(struct context *ctx, const struct token *token,
8586 	const char *str, unsigned int len,
8587 	void *buf, unsigned int size)
8588 {
8589 	struct buffer *out = buf;
8590 
8591 	/* Token name must match. */
8592 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8593 		return -1;
8594 	/* Nothing else to do if there is no buffer. */
8595 	if (!out)
8596 		return len;
8597 	if (!out->command) {
8598 		if (ctx->curr != ITEM_POL_POLICY)
8599 			return -1;
8600 		if (sizeof(*out) > size)
8601 			return -1;
8602 		out->command = ctx->curr;
8603 		ctx->objdata = 0;
8604 		ctx->object = out;
8605 		ctx->objmask = NULL;
8606 		out->args.vc.data = (uint8_t *)out + size;
8607 		return len;
8608 	}
8609 	switch (ctx->curr) {
8610 	case ACTION_POL_G:
8611 		out->args.vc.actions =
8612 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8613 					sizeof(double));
8614 		out->command = ctx->curr;
8615 		ctx->objdata = 0;
8616 		ctx->object = out;
8617 		ctx->objmask = NULL;
8618 		return len;
8619 	default:
8620 		return -1;
8621 	}
8622 }
8623 
8624 /** Parse tokens for validate/create commands. */
8625 static int
8626 parse_vc(struct context *ctx, const struct token *token,
8627 	 const char *str, unsigned int len,
8628 	 void *buf, unsigned int size)
8629 {
8630 	struct buffer *out = buf;
8631 	uint8_t *data;
8632 	uint32_t data_size;
8633 
8634 	/* Token name must match. */
8635 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8636 		return -1;
8637 	/* Nothing else to do if there is no buffer. */
8638 	if (!out)
8639 		return len;
8640 	if (!out->command) {
8641 		if (ctx->curr != VALIDATE && ctx->curr != CREATE &&
8642 		    ctx->curr != PATTERN_TEMPLATE_CREATE &&
8643 		    ctx->curr != ACTIONS_TEMPLATE_CREATE &&
8644 		    ctx->curr != UPDATE)
8645 			return -1;
8646 		if (ctx->curr == UPDATE)
8647 			out->args.vc.pattern =
8648 				(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8649 						       sizeof(double));
8650 		if (sizeof(*out) > size)
8651 			return -1;
8652 		out->command = ctx->curr;
8653 		ctx->objdata = 0;
8654 		ctx->object = out;
8655 		ctx->objmask = NULL;
8656 		out->args.vc.data = (uint8_t *)out + size;
8657 		return len;
8658 	}
8659 	ctx->objdata = 0;
8660 	switch (ctx->curr) {
8661 	default:
8662 		ctx->object = &out->args.vc.attr;
8663 		break;
8664 	case VC_TUNNEL_SET:
8665 	case VC_TUNNEL_MATCH:
8666 		ctx->object = &out->args.vc.tunnel_ops;
8667 		break;
8668 	case VC_USER_ID:
8669 		ctx->object = out;
8670 		break;
8671 	}
8672 	ctx->objmask = NULL;
8673 	switch (ctx->curr) {
8674 	case VC_GROUP:
8675 	case VC_PRIORITY:
8676 	case VC_USER_ID:
8677 		return len;
8678 	case VC_TUNNEL_SET:
8679 		out->args.vc.tunnel_ops.enabled = 1;
8680 		out->args.vc.tunnel_ops.actions = 1;
8681 		return len;
8682 	case VC_TUNNEL_MATCH:
8683 		out->args.vc.tunnel_ops.enabled = 1;
8684 		out->args.vc.tunnel_ops.items = 1;
8685 		return len;
8686 	case VC_INGRESS:
8687 		out->args.vc.attr.ingress = 1;
8688 		return len;
8689 	case VC_EGRESS:
8690 		out->args.vc.attr.egress = 1;
8691 		return len;
8692 	case VC_TRANSFER:
8693 		out->args.vc.attr.transfer = 1;
8694 		return len;
8695 	case ITEM_PATTERN:
8696 		out->args.vc.pattern =
8697 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8698 					       sizeof(double));
8699 		ctx->object = out->args.vc.pattern;
8700 		ctx->objmask = NULL;
8701 		return len;
8702 	case ITEM_END:
8703 		if ((out->command == VALIDATE || out->command == CREATE) &&
8704 		    ctx->last)
8705 			return -1;
8706 		if (out->command == PATTERN_TEMPLATE_CREATE &&
8707 		    !ctx->last)
8708 			return -1;
8709 		break;
8710 	case ACTIONS:
8711 		out->args.vc.actions = out->args.vc.pattern ?
8712 			(void *)RTE_ALIGN_CEIL((uintptr_t)
8713 					       (out->args.vc.pattern +
8714 						out->args.vc.pattern_n),
8715 					       sizeof(double)) :
8716 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8717 					       sizeof(double));
8718 		ctx->object = out->args.vc.actions;
8719 		ctx->objmask = NULL;
8720 		return len;
8721 	case VC_IS_USER_ID:
8722 		out->args.vc.user_id = true;
8723 		return len;
8724 	default:
8725 		if (!token->priv)
8726 			return -1;
8727 		break;
8728 	}
8729 	if (!out->args.vc.actions) {
8730 		const struct parse_item_priv *priv = token->priv;
8731 		struct rte_flow_item *item =
8732 			out->args.vc.pattern + out->args.vc.pattern_n;
8733 
8734 		data_size = priv->size * 3; /* spec, last, mask */
8735 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8736 					       (out->args.vc.data - data_size),
8737 					       sizeof(double));
8738 		if ((uint8_t *)item + sizeof(*item) > data)
8739 			return -1;
8740 		*item = (struct rte_flow_item){
8741 			.type = priv->type,
8742 		};
8743 		++out->args.vc.pattern_n;
8744 		ctx->object = item;
8745 		ctx->objmask = NULL;
8746 	} else {
8747 		const struct parse_action_priv *priv = token->priv;
8748 		struct rte_flow_action *action =
8749 			out->args.vc.actions + out->args.vc.actions_n;
8750 
8751 		data_size = priv->size; /* configuration */
8752 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8753 					       (out->args.vc.data - data_size),
8754 					       sizeof(double));
8755 		if ((uint8_t *)action + sizeof(*action) > data)
8756 			return -1;
8757 		*action = (struct rte_flow_action){
8758 			.type = priv->type,
8759 			.conf = data_size ? data : NULL,
8760 		};
8761 		++out->args.vc.actions_n;
8762 		ctx->object = action;
8763 		ctx->objmask = NULL;
8764 	}
8765 	memset(data, 0, data_size);
8766 	out->args.vc.data = data;
8767 	ctx->objdata = data_size;
8768 	return len;
8769 }
8770 
8771 /** Parse pattern item parameter type. */
8772 static int
8773 parse_vc_spec(struct context *ctx, const struct token *token,
8774 	      const char *str, unsigned int len,
8775 	      void *buf, unsigned int size)
8776 {
8777 	struct buffer *out = buf;
8778 	struct rte_flow_item *item;
8779 	uint32_t data_size;
8780 	int index;
8781 	int objmask = 0;
8782 
8783 	(void)size;
8784 	/* Token name must match. */
8785 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8786 		return -1;
8787 	/* Parse parameter types. */
8788 	switch (ctx->curr) {
8789 		static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
8790 
8791 	case ITEM_PARAM_IS:
8792 		index = 0;
8793 		objmask = 1;
8794 		break;
8795 	case ITEM_PARAM_SPEC:
8796 		index = 0;
8797 		break;
8798 	case ITEM_PARAM_LAST:
8799 		index = 1;
8800 		break;
8801 	case ITEM_PARAM_PREFIX:
8802 		/* Modify next token to expect a prefix. */
8803 		if (ctx->next_num < 2)
8804 			return -1;
8805 		ctx->next[ctx->next_num - 2] = prefix;
8806 		/* Fall through. */
8807 	case ITEM_PARAM_MASK:
8808 		index = 2;
8809 		break;
8810 	default:
8811 		return -1;
8812 	}
8813 	/* Nothing else to do if there is no buffer. */
8814 	if (!out)
8815 		return len;
8816 	if (!out->args.vc.pattern_n)
8817 		return -1;
8818 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8819 	data_size = ctx->objdata / 3; /* spec, last, mask */
8820 	/* Point to selected object. */
8821 	ctx->object = out->args.vc.data + (data_size * index);
8822 	if (objmask) {
8823 		ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
8824 		item->mask = ctx->objmask;
8825 	} else
8826 		ctx->objmask = NULL;
8827 	/* Update relevant item pointer. */
8828 	*((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
8829 		ctx->object;
8830 	return len;
8831 }
8832 
8833 /** Parse action configuration field. */
8834 static int
8835 parse_vc_conf(struct context *ctx, const struct token *token,
8836 	      const char *str, unsigned int len,
8837 	      void *buf, unsigned int size)
8838 {
8839 	struct buffer *out = buf;
8840 
8841 	(void)size;
8842 	/* Token name must match. */
8843 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8844 		return -1;
8845 	/* Nothing else to do if there is no buffer. */
8846 	if (!out)
8847 		return len;
8848 	/* Point to selected object. */
8849 	ctx->object = out->args.vc.data;
8850 	ctx->objmask = NULL;
8851 	return len;
8852 }
8853 
8854 /** Parse action configuration field. */
8855 static int
8856 parse_vc_conf_timeout(struct context *ctx, const struct token *token,
8857 		      const char *str, unsigned int len,
8858 		      void *buf, unsigned int size)
8859 {
8860 	struct buffer *out = buf;
8861 	struct rte_flow_update_age *update;
8862 
8863 	(void)size;
8864 	if (ctx->curr != ACTION_AGE_UPDATE_TIMEOUT)
8865 		return -1;
8866 	/* Token name must match. */
8867 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8868 		return -1;
8869 	/* Nothing else to do if there is no buffer. */
8870 	if (!out)
8871 		return len;
8872 	/* Point to selected object. */
8873 	ctx->object = out->args.vc.data;
8874 	ctx->objmask = NULL;
8875 	/* Update the timeout is valid. */
8876 	update = (struct rte_flow_update_age *)out->args.vc.data;
8877 	update->timeout_valid = 1;
8878 	return len;
8879 }
8880 
8881 /** Parse eCPRI common header type field. */
8882 static int
8883 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
8884 			 const char *str, unsigned int len,
8885 			 void *buf, unsigned int size)
8886 {
8887 	struct rte_flow_item_ecpri *ecpri;
8888 	struct rte_flow_item_ecpri *ecpri_mask;
8889 	struct rte_flow_item *item;
8890 	uint32_t data_size;
8891 	uint8_t msg_type;
8892 	struct buffer *out = buf;
8893 	const struct arg *arg;
8894 
8895 	(void)size;
8896 	/* Token name must match. */
8897 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8898 		return -1;
8899 	switch (ctx->curr) {
8900 	case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
8901 		msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
8902 		break;
8903 	case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
8904 		msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
8905 		break;
8906 	case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
8907 		msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
8908 		break;
8909 	default:
8910 		return -1;
8911 	}
8912 	if (!ctx->object)
8913 		return len;
8914 	arg = pop_args(ctx);
8915 	if (!arg)
8916 		return -1;
8917 	ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
8918 	ecpri->hdr.common.type = msg_type;
8919 	data_size = ctx->objdata / 3; /* spec, last, mask */
8920 	ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
8921 						    (data_size * 2));
8922 	ecpri_mask->hdr.common.type = 0xFF;
8923 	if (arg->hton) {
8924 		ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
8925 		ecpri_mask->hdr.common.u32 =
8926 				rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
8927 	}
8928 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8929 	item->spec = ecpri;
8930 	item->mask = ecpri_mask;
8931 	return len;
8932 }
8933 
8934 /** Parse L2TPv2 common header type field. */
8935 static int
8936 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
8937 			 const char *str, unsigned int len,
8938 			 void *buf, unsigned int size)
8939 {
8940 	struct rte_flow_item_l2tpv2 *l2tpv2;
8941 	struct rte_flow_item_l2tpv2 *l2tpv2_mask;
8942 	struct rte_flow_item *item;
8943 	uint32_t data_size;
8944 	uint16_t msg_type = 0;
8945 	struct buffer *out = buf;
8946 	const struct arg *arg;
8947 
8948 	(void)size;
8949 	/* Token name must match. */
8950 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8951 		return -1;
8952 	switch (ctx->curr) {
8953 	case ITEM_L2TPV2_TYPE_DATA:
8954 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
8955 		break;
8956 	case ITEM_L2TPV2_TYPE_DATA_L:
8957 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
8958 		break;
8959 	case ITEM_L2TPV2_TYPE_DATA_S:
8960 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
8961 		break;
8962 	case ITEM_L2TPV2_TYPE_DATA_O:
8963 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
8964 		break;
8965 	case ITEM_L2TPV2_TYPE_DATA_L_S:
8966 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
8967 		break;
8968 	case ITEM_L2TPV2_TYPE_CTRL:
8969 		msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
8970 		break;
8971 	default:
8972 		return -1;
8973 	}
8974 	if (!ctx->object)
8975 		return len;
8976 	arg = pop_args(ctx);
8977 	if (!arg)
8978 		return -1;
8979 	l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
8980 	l2tpv2->hdr.common.flags_version |= msg_type;
8981 	data_size = ctx->objdata / 3; /* spec, last, mask */
8982 	l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
8983 						    (data_size * 2));
8984 	l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
8985 	if (arg->hton) {
8986 		l2tpv2->hdr.common.flags_version =
8987 			rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
8988 		l2tpv2_mask->hdr.common.flags_version =
8989 		    rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
8990 	}
8991 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8992 	item->spec = l2tpv2;
8993 	item->mask = l2tpv2_mask;
8994 	return len;
8995 }
8996 
8997 /** Parse operation for compare match item. */
8998 static int
8999 parse_vc_compare_op(struct context *ctx, const struct token *token,
9000 			 const char *str, unsigned int len, void *buf,
9001 			 unsigned int size)
9002 {
9003 	struct rte_flow_item_compare *compare_item;
9004 	unsigned int i;
9005 
9006 	(void)token;
9007 	(void)buf;
9008 	(void)size;
9009 	if (ctx->curr != ITEM_COMPARE_OP_VALUE)
9010 		return -1;
9011 	for (i = 0; compare_ops[i]; ++i)
9012 		if (!strcmp_partial(compare_ops[i], str, len))
9013 			break;
9014 	if (!compare_ops[i])
9015 		return -1;
9016 	if (!ctx->object)
9017 		return len;
9018 	compare_item = ctx->object;
9019 	compare_item->operation = (enum rte_flow_item_compare_op)i;
9020 	return len;
9021 }
9022 
9023 /** Parse id for compare match item. */
9024 static int
9025 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
9026 			  const char *str, unsigned int len, void *buf,
9027 			  unsigned int size)
9028 {
9029 	struct rte_flow_item_compare *compare_item;
9030 	unsigned int i;
9031 
9032 	(void)token;
9033 	(void)buf;
9034 	(void)size;
9035 	if (ctx->curr != ITEM_COMPARE_FIELD_A_TYPE_VALUE &&
9036 		ctx->curr != ITEM_COMPARE_FIELD_B_TYPE_VALUE)
9037 		return -1;
9038 	for (i = 0; flow_field_ids[i]; ++i)
9039 		if (!strcmp_partial(flow_field_ids[i], str, len))
9040 			break;
9041 	if (!flow_field_ids[i])
9042 		return -1;
9043 	if (!ctx->object)
9044 		return len;
9045 	compare_item = ctx->object;
9046 	if (ctx->curr == ITEM_COMPARE_FIELD_A_TYPE_VALUE)
9047 		compare_item->a.field = (enum rte_flow_field_id)i;
9048 	else
9049 		compare_item->b.field = (enum rte_flow_field_id)i;
9050 	return len;
9051 }
9052 
9053 /** Parse level for compare match item. */
9054 static int
9055 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
9056 			     const char *str, unsigned int len, void *buf,
9057 			     unsigned int size)
9058 {
9059 	struct rte_flow_item_compare *compare_item;
9060 	struct flex_item *fp = NULL;
9061 	uint32_t val;
9062 	struct buffer *out = buf;
9063 	char *end;
9064 
9065 	(void)token;
9066 	(void)size;
9067 	if (ctx->curr != ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
9068 		ctx->curr != ITEM_COMPARE_FIELD_B_LEVEL_VALUE)
9069 		return -1;
9070 	if (!ctx->object)
9071 		return len;
9072 	compare_item = ctx->object;
9073 	errno = 0;
9074 	val = strtoumax(str, &end, 0);
9075 	if (errno || (size_t)(end - str) != len)
9076 		return -1;
9077 	/* No need to validate action template mask value */
9078 	if (out->args.vc.masks) {
9079 		if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE)
9080 			compare_item->a.level = val;
9081 		else
9082 			compare_item->b.level = val;
9083 		return len;
9084 	}
9085 	if ((ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
9086 		compare_item->a.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
9087 		(ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE &&
9088 		compare_item->b.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
9089 		if (val >= FLEX_MAX_PARSERS_NUM) {
9090 			printf("Bad flex item handle\n");
9091 			return -1;
9092 		}
9093 		fp = flex_items[ctx->port][val];
9094 		if (!fp) {
9095 			printf("Bad flex item handle\n");
9096 			return -1;
9097 		}
9098 	}
9099 	if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE) {
9100 		if (compare_item->a.field != RTE_FLOW_FIELD_FLEX_ITEM)
9101 			compare_item->a.level = val;
9102 		else
9103 			compare_item->a.flex_handle = fp->flex_handle;
9104 	} else if (ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE) {
9105 		if (compare_item->b.field != RTE_FLOW_FIELD_FLEX_ITEM)
9106 			compare_item->b.level = val;
9107 		else
9108 			compare_item->b.flex_handle = fp->flex_handle;
9109 	}
9110 	return len;
9111 }
9112 
9113 /** Parse meter color action type. */
9114 static int
9115 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
9116 				const char *str, unsigned int len,
9117 				void *buf, unsigned int size)
9118 {
9119 	struct rte_flow_action *action_data;
9120 	struct rte_flow_action_meter_color *conf;
9121 	enum rte_color color;
9122 
9123 	(void)buf;
9124 	(void)size;
9125 	/* Token name must match. */
9126 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9127 		return -1;
9128 	switch (ctx->curr) {
9129 	case ACTION_METER_COLOR_GREEN:
9130 		color = RTE_COLOR_GREEN;
9131 	break;
9132 	case ACTION_METER_COLOR_YELLOW:
9133 		color = RTE_COLOR_YELLOW;
9134 	break;
9135 	case ACTION_METER_COLOR_RED:
9136 		color = RTE_COLOR_RED;
9137 	break;
9138 	default:
9139 		return -1;
9140 	}
9141 
9142 	if (!ctx->object)
9143 		return len;
9144 	action_data = ctx->object;
9145 	conf = (struct rte_flow_action_meter_color *)
9146 					(uintptr_t)(action_data->conf);
9147 	conf->color = color;
9148 	return len;
9149 }
9150 
9151 /** Parse RSS action. */
9152 static int
9153 parse_vc_action_rss(struct context *ctx, const struct token *token,
9154 		    const char *str, unsigned int len,
9155 		    void *buf, unsigned int size)
9156 {
9157 	struct buffer *out = buf;
9158 	struct rte_flow_action *action;
9159 	struct action_rss_data *action_rss_data;
9160 	unsigned int i;
9161 	int ret;
9162 
9163 	ret = parse_vc(ctx, token, str, len, buf, size);
9164 	if (ret < 0)
9165 		return ret;
9166 	/* Nothing else to do if there is no buffer. */
9167 	if (!out)
9168 		return ret;
9169 	if (!out->args.vc.actions_n)
9170 		return -1;
9171 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9172 	/* Point to selected object. */
9173 	ctx->object = out->args.vc.data;
9174 	ctx->objmask = NULL;
9175 	/* Set up default configuration. */
9176 	action_rss_data = ctx->object;
9177 	*action_rss_data = (struct action_rss_data){
9178 		.conf = (struct rte_flow_action_rss){
9179 			.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
9180 			.level = 0,
9181 			.types = rss_hf,
9182 			.key_len = 0,
9183 			.queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
9184 			.key = NULL,
9185 			.queue = action_rss_data->queue,
9186 		},
9187 		.queue = { 0 },
9188 	};
9189 	for (i = 0; i < action_rss_data->conf.queue_num; ++i)
9190 		action_rss_data->queue[i] = i;
9191 	action->conf = &action_rss_data->conf;
9192 	return ret;
9193 }
9194 
9195 /**
9196  * Parse func field for RSS action.
9197  *
9198  * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
9199  * ACTION_RSS_FUNC_* index that called this function.
9200  */
9201 static int
9202 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
9203 			 const char *str, unsigned int len,
9204 			 void *buf, unsigned int size)
9205 {
9206 	struct action_rss_data *action_rss_data;
9207 	enum rte_eth_hash_function func;
9208 
9209 	(void)buf;
9210 	(void)size;
9211 	/* Token name must match. */
9212 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9213 		return -1;
9214 	switch (ctx->curr) {
9215 	case ACTION_RSS_FUNC_DEFAULT:
9216 		func = RTE_ETH_HASH_FUNCTION_DEFAULT;
9217 		break;
9218 	case ACTION_RSS_FUNC_TOEPLITZ:
9219 		func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
9220 		break;
9221 	case ACTION_RSS_FUNC_SIMPLE_XOR:
9222 		func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
9223 		break;
9224 	case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
9225 		func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
9226 		break;
9227 	default:
9228 		return -1;
9229 	}
9230 	if (!ctx->object)
9231 		return len;
9232 	action_rss_data = ctx->object;
9233 	action_rss_data->conf.func = func;
9234 	return len;
9235 }
9236 
9237 /**
9238  * Parse type field for RSS action.
9239  *
9240  * Valid tokens are type field names and the "end" token.
9241  */
9242 static int
9243 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
9244 			  const char *str, unsigned int len,
9245 			  void *buf, unsigned int size)
9246 {
9247 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
9248 	struct action_rss_data *action_rss_data;
9249 	unsigned int i;
9250 
9251 	(void)token;
9252 	(void)buf;
9253 	(void)size;
9254 	if (ctx->curr != ACTION_RSS_TYPE)
9255 		return -1;
9256 	if (!(ctx->objdata >> 16) && ctx->object) {
9257 		action_rss_data = ctx->object;
9258 		action_rss_data->conf.types = 0;
9259 	}
9260 	if (!strcmp_partial("end", str, len)) {
9261 		ctx->objdata &= 0xffff;
9262 		return len;
9263 	}
9264 	for (i = 0; rss_type_table[i].str; ++i)
9265 		if (!strcmp_partial(rss_type_table[i].str, str, len))
9266 			break;
9267 	if (!rss_type_table[i].str)
9268 		return -1;
9269 	ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
9270 	/* Repeat token. */
9271 	if (ctx->next_num == RTE_DIM(ctx->next))
9272 		return -1;
9273 	ctx->next[ctx->next_num++] = next;
9274 	if (!ctx->object)
9275 		return len;
9276 	action_rss_data = ctx->object;
9277 	action_rss_data->conf.types |= rss_type_table[i].rss_type;
9278 	return len;
9279 }
9280 
9281 /**
9282  * Parse queue field for RSS action.
9283  *
9284  * Valid tokens are queue indices and the "end" token.
9285  */
9286 static int
9287 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
9288 			  const char *str, unsigned int len,
9289 			  void *buf, unsigned int size)
9290 {
9291 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
9292 	struct action_rss_data *action_rss_data;
9293 	const struct arg *arg;
9294 	int ret;
9295 	int i;
9296 
9297 	(void)token;
9298 	(void)buf;
9299 	(void)size;
9300 	if (ctx->curr != ACTION_RSS_QUEUE)
9301 		return -1;
9302 	i = ctx->objdata >> 16;
9303 	if (!strcmp_partial("end", str, len)) {
9304 		ctx->objdata &= 0xffff;
9305 		goto end;
9306 	}
9307 	if (i >= ACTION_RSS_QUEUE_NUM)
9308 		return -1;
9309 	arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
9310 			     i * sizeof(action_rss_data->queue[i]),
9311 			     sizeof(action_rss_data->queue[i]));
9312 	if (push_args(ctx, arg))
9313 		return -1;
9314 	ret = parse_int(ctx, token, str, len, NULL, 0);
9315 	if (ret < 0) {
9316 		pop_args(ctx);
9317 		return -1;
9318 	}
9319 	++i;
9320 	ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
9321 	/* Repeat token. */
9322 	if (ctx->next_num == RTE_DIM(ctx->next))
9323 		return -1;
9324 	ctx->next[ctx->next_num++] = next;
9325 end:
9326 	if (!ctx->object)
9327 		return len;
9328 	action_rss_data = ctx->object;
9329 	action_rss_data->conf.queue_num = i;
9330 	action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
9331 	return len;
9332 }
9333 
9334 /** Setup VXLAN encap configuration. */
9335 static int
9336 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
9337 {
9338 	/* Set up default configuration. */
9339 	*action_vxlan_encap_data = (struct action_vxlan_encap_data){
9340 		.conf = (struct rte_flow_action_vxlan_encap){
9341 			.definition = action_vxlan_encap_data->items,
9342 		},
9343 		.items = {
9344 			{
9345 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9346 				.spec = &action_vxlan_encap_data->item_eth,
9347 				.mask = &rte_flow_item_eth_mask,
9348 			},
9349 			{
9350 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9351 				.spec = &action_vxlan_encap_data->item_vlan,
9352 				.mask = &rte_flow_item_vlan_mask,
9353 			},
9354 			{
9355 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9356 				.spec = &action_vxlan_encap_data->item_ipv4,
9357 				.mask = &rte_flow_item_ipv4_mask,
9358 			},
9359 			{
9360 				.type = RTE_FLOW_ITEM_TYPE_UDP,
9361 				.spec = &action_vxlan_encap_data->item_udp,
9362 				.mask = &rte_flow_item_udp_mask,
9363 			},
9364 			{
9365 				.type = RTE_FLOW_ITEM_TYPE_VXLAN,
9366 				.spec = &action_vxlan_encap_data->item_vxlan,
9367 				.mask = &rte_flow_item_vxlan_mask,
9368 			},
9369 			{
9370 				.type = RTE_FLOW_ITEM_TYPE_END,
9371 			},
9372 		},
9373 		.item_eth.hdr.ether_type = 0,
9374 		.item_vlan = {
9375 			.hdr.vlan_tci = vxlan_encap_conf.vlan_tci,
9376 			.hdr.eth_proto = 0,
9377 		},
9378 		.item_ipv4.hdr = {
9379 			.src_addr = vxlan_encap_conf.ipv4_src,
9380 			.dst_addr = vxlan_encap_conf.ipv4_dst,
9381 		},
9382 		.item_udp.hdr = {
9383 			.src_port = vxlan_encap_conf.udp_src,
9384 			.dst_port = vxlan_encap_conf.udp_dst,
9385 		},
9386 		.item_vxlan.hdr.flags = 0,
9387 	};
9388 	memcpy(action_vxlan_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9389 	       vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9390 	memcpy(action_vxlan_encap_data->item_eth.hdr.src_addr.addr_bytes,
9391 	       vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9392 	if (!vxlan_encap_conf.select_ipv4) {
9393 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
9394 		       &vxlan_encap_conf.ipv6_src,
9395 		       sizeof(vxlan_encap_conf.ipv6_src));
9396 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
9397 		       &vxlan_encap_conf.ipv6_dst,
9398 		       sizeof(vxlan_encap_conf.ipv6_dst));
9399 		action_vxlan_encap_data->items[2] = (struct rte_flow_item){
9400 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9401 			.spec = &action_vxlan_encap_data->item_ipv6,
9402 			.mask = &rte_flow_item_ipv6_mask,
9403 		};
9404 	}
9405 	if (!vxlan_encap_conf.select_vlan)
9406 		action_vxlan_encap_data->items[1].type =
9407 			RTE_FLOW_ITEM_TYPE_VOID;
9408 	if (vxlan_encap_conf.select_tos_ttl) {
9409 		if (vxlan_encap_conf.select_ipv4) {
9410 			static struct rte_flow_item_ipv4 ipv4_mask_tos;
9411 
9412 			memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
9413 			       sizeof(ipv4_mask_tos));
9414 			ipv4_mask_tos.hdr.type_of_service = 0xff;
9415 			ipv4_mask_tos.hdr.time_to_live = 0xff;
9416 			action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
9417 					vxlan_encap_conf.ip_tos;
9418 			action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
9419 					vxlan_encap_conf.ip_ttl;
9420 			action_vxlan_encap_data->items[2].mask =
9421 							&ipv4_mask_tos;
9422 		} else {
9423 			static struct rte_flow_item_ipv6 ipv6_mask_tos;
9424 
9425 			memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
9426 			       sizeof(ipv6_mask_tos));
9427 			ipv6_mask_tos.hdr.vtc_flow |=
9428 				RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
9429 			ipv6_mask_tos.hdr.hop_limits = 0xff;
9430 			action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
9431 				rte_cpu_to_be_32
9432 					((uint32_t)vxlan_encap_conf.ip_tos <<
9433 					 RTE_IPV6_HDR_TC_SHIFT);
9434 			action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
9435 					vxlan_encap_conf.ip_ttl;
9436 			action_vxlan_encap_data->items[2].mask =
9437 							&ipv6_mask_tos;
9438 		}
9439 	}
9440 	memcpy(action_vxlan_encap_data->item_vxlan.hdr.vni, vxlan_encap_conf.vni,
9441 	       RTE_DIM(vxlan_encap_conf.vni));
9442 	return 0;
9443 }
9444 
9445 /** Parse VXLAN encap action. */
9446 static int
9447 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
9448 			    const char *str, unsigned int len,
9449 			    void *buf, unsigned int size)
9450 {
9451 	struct buffer *out = buf;
9452 	struct rte_flow_action *action;
9453 	struct action_vxlan_encap_data *action_vxlan_encap_data;
9454 	int ret;
9455 
9456 	ret = parse_vc(ctx, token, str, len, buf, size);
9457 	if (ret < 0)
9458 		return ret;
9459 	/* Nothing else to do if there is no buffer. */
9460 	if (!out)
9461 		return ret;
9462 	if (!out->args.vc.actions_n)
9463 		return -1;
9464 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9465 	/* Point to selected object. */
9466 	ctx->object = out->args.vc.data;
9467 	ctx->objmask = NULL;
9468 	action_vxlan_encap_data = ctx->object;
9469 	parse_setup_vxlan_encap_data(action_vxlan_encap_data);
9470 	action->conf = &action_vxlan_encap_data->conf;
9471 	return ret;
9472 }
9473 
9474 /** Setup NVGRE encap configuration. */
9475 static int
9476 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
9477 {
9478 	/* Set up default configuration. */
9479 	*action_nvgre_encap_data = (struct action_nvgre_encap_data){
9480 		.conf = (struct rte_flow_action_nvgre_encap){
9481 			.definition = action_nvgre_encap_data->items,
9482 		},
9483 		.items = {
9484 			{
9485 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9486 				.spec = &action_nvgre_encap_data->item_eth,
9487 				.mask = &rte_flow_item_eth_mask,
9488 			},
9489 			{
9490 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9491 				.spec = &action_nvgre_encap_data->item_vlan,
9492 				.mask = &rte_flow_item_vlan_mask,
9493 			},
9494 			{
9495 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9496 				.spec = &action_nvgre_encap_data->item_ipv4,
9497 				.mask = &rte_flow_item_ipv4_mask,
9498 			},
9499 			{
9500 				.type = RTE_FLOW_ITEM_TYPE_NVGRE,
9501 				.spec = &action_nvgre_encap_data->item_nvgre,
9502 				.mask = &rte_flow_item_nvgre_mask,
9503 			},
9504 			{
9505 				.type = RTE_FLOW_ITEM_TYPE_END,
9506 			},
9507 		},
9508 		.item_eth.hdr.ether_type = 0,
9509 		.item_vlan = {
9510 			.hdr.vlan_tci = nvgre_encap_conf.vlan_tci,
9511 			.hdr.eth_proto = 0,
9512 		},
9513 		.item_ipv4.hdr = {
9514 		       .src_addr = nvgre_encap_conf.ipv4_src,
9515 		       .dst_addr = nvgre_encap_conf.ipv4_dst,
9516 		},
9517 		.item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
9518 		.item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
9519 		.item_nvgre.flow_id = 0,
9520 	};
9521 	memcpy(action_nvgre_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9522 	       nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9523 	memcpy(action_nvgre_encap_data->item_eth.hdr.src_addr.addr_bytes,
9524 	       nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9525 	if (!nvgre_encap_conf.select_ipv4) {
9526 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
9527 		       &nvgre_encap_conf.ipv6_src,
9528 		       sizeof(nvgre_encap_conf.ipv6_src));
9529 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
9530 		       &nvgre_encap_conf.ipv6_dst,
9531 		       sizeof(nvgre_encap_conf.ipv6_dst));
9532 		action_nvgre_encap_data->items[2] = (struct rte_flow_item){
9533 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9534 			.spec = &action_nvgre_encap_data->item_ipv6,
9535 			.mask = &rte_flow_item_ipv6_mask,
9536 		};
9537 	}
9538 	if (!nvgre_encap_conf.select_vlan)
9539 		action_nvgre_encap_data->items[1].type =
9540 			RTE_FLOW_ITEM_TYPE_VOID;
9541 	memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
9542 	       RTE_DIM(nvgre_encap_conf.tni));
9543 	return 0;
9544 }
9545 
9546 /** Parse NVGRE encap action. */
9547 static int
9548 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
9549 			    const char *str, unsigned int len,
9550 			    void *buf, unsigned int size)
9551 {
9552 	struct buffer *out = buf;
9553 	struct rte_flow_action *action;
9554 	struct action_nvgre_encap_data *action_nvgre_encap_data;
9555 	int ret;
9556 
9557 	ret = parse_vc(ctx, token, str, len, buf, size);
9558 	if (ret < 0)
9559 		return ret;
9560 	/* Nothing else to do if there is no buffer. */
9561 	if (!out)
9562 		return ret;
9563 	if (!out->args.vc.actions_n)
9564 		return -1;
9565 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9566 	/* Point to selected object. */
9567 	ctx->object = out->args.vc.data;
9568 	ctx->objmask = NULL;
9569 	action_nvgre_encap_data = ctx->object;
9570 	parse_setup_nvgre_encap_data(action_nvgre_encap_data);
9571 	action->conf = &action_nvgre_encap_data->conf;
9572 	return ret;
9573 }
9574 
9575 /** Parse l2 encap action. */
9576 static int
9577 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
9578 			 const char *str, unsigned int len,
9579 			 void *buf, unsigned int size)
9580 {
9581 	struct buffer *out = buf;
9582 	struct rte_flow_action *action;
9583 	struct action_raw_encap_data *action_encap_data;
9584 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9585 	struct rte_flow_item_vlan vlan = {
9586 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9587 		.hdr.eth_proto = 0,
9588 	};
9589 	uint8_t *header;
9590 	int ret;
9591 
9592 	ret = parse_vc(ctx, token, str, len, buf, size);
9593 	if (ret < 0)
9594 		return ret;
9595 	/* Nothing else to do if there is no buffer. */
9596 	if (!out)
9597 		return ret;
9598 	if (!out->args.vc.actions_n)
9599 		return -1;
9600 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9601 	/* Point to selected object. */
9602 	ctx->object = out->args.vc.data;
9603 	ctx->objmask = NULL;
9604 	/* Copy the headers to the buffer. */
9605 	action_encap_data = ctx->object;
9606 	*action_encap_data = (struct action_raw_encap_data) {
9607 		.conf = (struct rte_flow_action_raw_encap){
9608 			.data = action_encap_data->data,
9609 		},
9610 		.data = {},
9611 	};
9612 	header = action_encap_data->data;
9613 	if (l2_encap_conf.select_vlan)
9614 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9615 	else if (l2_encap_conf.select_ipv4)
9616 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9617 	else
9618 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9619 	memcpy(eth.hdr.dst_addr.addr_bytes,
9620 	       l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9621 	memcpy(eth.hdr.src_addr.addr_bytes,
9622 	       l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9623 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9624 	header += sizeof(struct rte_ether_hdr);
9625 	if (l2_encap_conf.select_vlan) {
9626 		if (l2_encap_conf.select_ipv4)
9627 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9628 		else
9629 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9630 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9631 		header += sizeof(struct rte_vlan_hdr);
9632 	}
9633 	action_encap_data->conf.size = header -
9634 		action_encap_data->data;
9635 	action->conf = &action_encap_data->conf;
9636 	return ret;
9637 }
9638 
9639 /** Parse l2 decap action. */
9640 static int
9641 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
9642 			 const char *str, unsigned int len,
9643 			 void *buf, unsigned int size)
9644 {
9645 	struct buffer *out = buf;
9646 	struct rte_flow_action *action;
9647 	struct action_raw_decap_data *action_decap_data;
9648 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9649 	struct rte_flow_item_vlan vlan = {
9650 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9651 		.hdr.eth_proto = 0,
9652 	};
9653 	uint8_t *header;
9654 	int ret;
9655 
9656 	ret = parse_vc(ctx, token, str, len, buf, size);
9657 	if (ret < 0)
9658 		return ret;
9659 	/* Nothing else to do if there is no buffer. */
9660 	if (!out)
9661 		return ret;
9662 	if (!out->args.vc.actions_n)
9663 		return -1;
9664 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9665 	/* Point to selected object. */
9666 	ctx->object = out->args.vc.data;
9667 	ctx->objmask = NULL;
9668 	/* Copy the headers to the buffer. */
9669 	action_decap_data = ctx->object;
9670 	*action_decap_data = (struct action_raw_decap_data) {
9671 		.conf = (struct rte_flow_action_raw_decap){
9672 			.data = action_decap_data->data,
9673 		},
9674 		.data = {},
9675 	};
9676 	header = action_decap_data->data;
9677 	if (l2_decap_conf.select_vlan)
9678 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9679 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9680 	header += sizeof(struct rte_ether_hdr);
9681 	if (l2_decap_conf.select_vlan) {
9682 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9683 		header += sizeof(struct rte_vlan_hdr);
9684 	}
9685 	action_decap_data->conf.size = header -
9686 		action_decap_data->data;
9687 	action->conf = &action_decap_data->conf;
9688 	return ret;
9689 }
9690 
9691 #define ETHER_TYPE_MPLS_UNICAST 0x8847
9692 
9693 /** Parse MPLSOGRE encap action. */
9694 static int
9695 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
9696 			       const char *str, unsigned int len,
9697 			       void *buf, unsigned int size)
9698 {
9699 	struct buffer *out = buf;
9700 	struct rte_flow_action *action;
9701 	struct action_raw_encap_data *action_encap_data;
9702 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9703 	struct rte_flow_item_vlan vlan = {
9704 		.hdr.vlan_tci = mplsogre_encap_conf.vlan_tci,
9705 		.hdr.eth_proto = 0,
9706 	};
9707 	struct rte_flow_item_ipv4 ipv4 = {
9708 		.hdr =  {
9709 			.src_addr = mplsogre_encap_conf.ipv4_src,
9710 			.dst_addr = mplsogre_encap_conf.ipv4_dst,
9711 			.next_proto_id = IPPROTO_GRE,
9712 			.version_ihl = RTE_IPV4_VHL_DEF,
9713 			.time_to_live = IPDEFTTL,
9714 		},
9715 	};
9716 	struct rte_flow_item_ipv6 ipv6 = {
9717 		.hdr =  {
9718 			.proto = IPPROTO_GRE,
9719 			.hop_limits = IPDEFTTL,
9720 		},
9721 	};
9722 	struct rte_flow_item_gre gre = {
9723 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9724 	};
9725 	struct rte_flow_item_mpls mpls = {
9726 		.ttl = 0,
9727 	};
9728 	uint8_t *header;
9729 	int ret;
9730 
9731 	ret = parse_vc(ctx, token, str, len, buf, size);
9732 	if (ret < 0)
9733 		return ret;
9734 	/* Nothing else to do if there is no buffer. */
9735 	if (!out)
9736 		return ret;
9737 	if (!out->args.vc.actions_n)
9738 		return -1;
9739 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9740 	/* Point to selected object. */
9741 	ctx->object = out->args.vc.data;
9742 	ctx->objmask = NULL;
9743 	/* Copy the headers to the buffer. */
9744 	action_encap_data = ctx->object;
9745 	*action_encap_data = (struct action_raw_encap_data) {
9746 		.conf = (struct rte_flow_action_raw_encap){
9747 			.data = action_encap_data->data,
9748 		},
9749 		.data = {},
9750 		.preserve = {},
9751 	};
9752 	header = action_encap_data->data;
9753 	if (mplsogre_encap_conf.select_vlan)
9754 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9755 	else if (mplsogre_encap_conf.select_ipv4)
9756 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9757 	else
9758 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9759 	memcpy(eth.hdr.dst_addr.addr_bytes,
9760 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9761 	memcpy(eth.hdr.src_addr.addr_bytes,
9762 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9763 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9764 	header += sizeof(struct rte_ether_hdr);
9765 	if (mplsogre_encap_conf.select_vlan) {
9766 		if (mplsogre_encap_conf.select_ipv4)
9767 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9768 		else
9769 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9770 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9771 		header += sizeof(struct rte_vlan_hdr);
9772 	}
9773 	if (mplsogre_encap_conf.select_ipv4) {
9774 		memcpy(header, &ipv4, sizeof(ipv4));
9775 		header += sizeof(ipv4);
9776 	} else {
9777 		memcpy(&ipv6.hdr.src_addr,
9778 		       &mplsogre_encap_conf.ipv6_src,
9779 		       sizeof(mplsogre_encap_conf.ipv6_src));
9780 		memcpy(&ipv6.hdr.dst_addr,
9781 		       &mplsogre_encap_conf.ipv6_dst,
9782 		       sizeof(mplsogre_encap_conf.ipv6_dst));
9783 		memcpy(header, &ipv6, sizeof(ipv6));
9784 		header += sizeof(ipv6);
9785 	}
9786 	memcpy(header, &gre, sizeof(gre));
9787 	header += sizeof(gre);
9788 	memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
9789 	       RTE_DIM(mplsogre_encap_conf.label));
9790 	mpls.label_tc_s[2] |= 0x1;
9791 	memcpy(header, &mpls, sizeof(mpls));
9792 	header += sizeof(mpls);
9793 	action_encap_data->conf.size = header -
9794 		action_encap_data->data;
9795 	action->conf = &action_encap_data->conf;
9796 	return ret;
9797 }
9798 
9799 /** Parse MPLSOGRE decap action. */
9800 static int
9801 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
9802 			       const char *str, unsigned int len,
9803 			       void *buf, unsigned int size)
9804 {
9805 	struct buffer *out = buf;
9806 	struct rte_flow_action *action;
9807 	struct action_raw_decap_data *action_decap_data;
9808 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9809 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
9810 	struct rte_flow_item_ipv4 ipv4 = {
9811 		.hdr =  {
9812 			.next_proto_id = IPPROTO_GRE,
9813 		},
9814 	};
9815 	struct rte_flow_item_ipv6 ipv6 = {
9816 		.hdr =  {
9817 			.proto = IPPROTO_GRE,
9818 		},
9819 	};
9820 	struct rte_flow_item_gre gre = {
9821 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9822 	};
9823 	struct rte_flow_item_mpls mpls;
9824 	uint8_t *header;
9825 	int ret;
9826 
9827 	ret = parse_vc(ctx, token, str, len, buf, size);
9828 	if (ret < 0)
9829 		return ret;
9830 	/* Nothing else to do if there is no buffer. */
9831 	if (!out)
9832 		return ret;
9833 	if (!out->args.vc.actions_n)
9834 		return -1;
9835 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9836 	/* Point to selected object. */
9837 	ctx->object = out->args.vc.data;
9838 	ctx->objmask = NULL;
9839 	/* Copy the headers to the buffer. */
9840 	action_decap_data = ctx->object;
9841 	*action_decap_data = (struct action_raw_decap_data) {
9842 		.conf = (struct rte_flow_action_raw_decap){
9843 			.data = action_decap_data->data,
9844 		},
9845 		.data = {},
9846 	};
9847 	header = action_decap_data->data;
9848 	if (mplsogre_decap_conf.select_vlan)
9849 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9850 	else if (mplsogre_encap_conf.select_ipv4)
9851 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9852 	else
9853 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9854 	memcpy(eth.hdr.dst_addr.addr_bytes,
9855 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9856 	memcpy(eth.hdr.src_addr.addr_bytes,
9857 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9858 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9859 	header += sizeof(struct rte_ether_hdr);
9860 	if (mplsogre_encap_conf.select_vlan) {
9861 		if (mplsogre_encap_conf.select_ipv4)
9862 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9863 		else
9864 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9865 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9866 		header += sizeof(struct rte_vlan_hdr);
9867 	}
9868 	if (mplsogre_encap_conf.select_ipv4) {
9869 		memcpy(header, &ipv4, sizeof(ipv4));
9870 		header += sizeof(ipv4);
9871 	} else {
9872 		memcpy(header, &ipv6, sizeof(ipv6));
9873 		header += sizeof(ipv6);
9874 	}
9875 	memcpy(header, &gre, sizeof(gre));
9876 	header += sizeof(gre);
9877 	memset(&mpls, 0, sizeof(mpls));
9878 	memcpy(header, &mpls, sizeof(mpls));
9879 	header += sizeof(mpls);
9880 	action_decap_data->conf.size = header -
9881 		action_decap_data->data;
9882 	action->conf = &action_decap_data->conf;
9883 	return ret;
9884 }
9885 
9886 /** Parse MPLSOUDP encap action. */
9887 static int
9888 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
9889 			       const char *str, unsigned int len,
9890 			       void *buf, unsigned int size)
9891 {
9892 	struct buffer *out = buf;
9893 	struct rte_flow_action *action;
9894 	struct action_raw_encap_data *action_encap_data;
9895 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9896 	struct rte_flow_item_vlan vlan = {
9897 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9898 		.hdr.eth_proto = 0,
9899 	};
9900 	struct rte_flow_item_ipv4 ipv4 = {
9901 		.hdr =  {
9902 			.src_addr = mplsoudp_encap_conf.ipv4_src,
9903 			.dst_addr = mplsoudp_encap_conf.ipv4_dst,
9904 			.next_proto_id = IPPROTO_UDP,
9905 			.version_ihl = RTE_IPV4_VHL_DEF,
9906 			.time_to_live = IPDEFTTL,
9907 		},
9908 	};
9909 	struct rte_flow_item_ipv6 ipv6 = {
9910 		.hdr =  {
9911 			.proto = IPPROTO_UDP,
9912 			.hop_limits = IPDEFTTL,
9913 		},
9914 	};
9915 	struct rte_flow_item_udp udp = {
9916 		.hdr = {
9917 			.src_port = mplsoudp_encap_conf.udp_src,
9918 			.dst_port = mplsoudp_encap_conf.udp_dst,
9919 		},
9920 	};
9921 	struct rte_flow_item_mpls mpls;
9922 	uint8_t *header;
9923 	int ret;
9924 
9925 	ret = parse_vc(ctx, token, str, len, buf, size);
9926 	if (ret < 0)
9927 		return ret;
9928 	/* Nothing else to do if there is no buffer. */
9929 	if (!out)
9930 		return ret;
9931 	if (!out->args.vc.actions_n)
9932 		return -1;
9933 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9934 	/* Point to selected object. */
9935 	ctx->object = out->args.vc.data;
9936 	ctx->objmask = NULL;
9937 	/* Copy the headers to the buffer. */
9938 	action_encap_data = ctx->object;
9939 	*action_encap_data = (struct action_raw_encap_data) {
9940 		.conf = (struct rte_flow_action_raw_encap){
9941 			.data = action_encap_data->data,
9942 		},
9943 		.data = {},
9944 		.preserve = {},
9945 	};
9946 	header = action_encap_data->data;
9947 	if (mplsoudp_encap_conf.select_vlan)
9948 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9949 	else if (mplsoudp_encap_conf.select_ipv4)
9950 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9951 	else
9952 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9953 	memcpy(eth.hdr.dst_addr.addr_bytes,
9954 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9955 	memcpy(eth.hdr.src_addr.addr_bytes,
9956 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9957 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9958 	header += sizeof(struct rte_ether_hdr);
9959 	if (mplsoudp_encap_conf.select_vlan) {
9960 		if (mplsoudp_encap_conf.select_ipv4)
9961 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9962 		else
9963 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9964 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9965 		header += sizeof(struct rte_vlan_hdr);
9966 	}
9967 	if (mplsoudp_encap_conf.select_ipv4) {
9968 		memcpy(header, &ipv4, sizeof(ipv4));
9969 		header += sizeof(ipv4);
9970 	} else {
9971 		memcpy(&ipv6.hdr.src_addr,
9972 		       &mplsoudp_encap_conf.ipv6_src,
9973 		       sizeof(mplsoudp_encap_conf.ipv6_src));
9974 		memcpy(&ipv6.hdr.dst_addr,
9975 		       &mplsoudp_encap_conf.ipv6_dst,
9976 		       sizeof(mplsoudp_encap_conf.ipv6_dst));
9977 		memcpy(header, &ipv6, sizeof(ipv6));
9978 		header += sizeof(ipv6);
9979 	}
9980 	memcpy(header, &udp, sizeof(udp));
9981 	header += sizeof(udp);
9982 	memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
9983 	       RTE_DIM(mplsoudp_encap_conf.label));
9984 	mpls.label_tc_s[2] |= 0x1;
9985 	memcpy(header, &mpls, sizeof(mpls));
9986 	header += sizeof(mpls);
9987 	action_encap_data->conf.size = header -
9988 		action_encap_data->data;
9989 	action->conf = &action_encap_data->conf;
9990 	return ret;
9991 }
9992 
9993 /** Parse MPLSOUDP decap action. */
9994 static int
9995 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
9996 			       const char *str, unsigned int len,
9997 			       void *buf, unsigned int size)
9998 {
9999 	struct buffer *out = buf;
10000 	struct rte_flow_action *action;
10001 	struct action_raw_decap_data *action_decap_data;
10002 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
10003 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
10004 	struct rte_flow_item_ipv4 ipv4 = {
10005 		.hdr =  {
10006 			.next_proto_id = IPPROTO_UDP,
10007 		},
10008 	};
10009 	struct rte_flow_item_ipv6 ipv6 = {
10010 		.hdr =  {
10011 			.proto = IPPROTO_UDP,
10012 		},
10013 	};
10014 	struct rte_flow_item_udp udp = {
10015 		.hdr = {
10016 			.dst_port = rte_cpu_to_be_16(6635),
10017 		},
10018 	};
10019 	struct rte_flow_item_mpls mpls;
10020 	uint8_t *header;
10021 	int ret;
10022 
10023 	ret = parse_vc(ctx, token, str, len, buf, size);
10024 	if (ret < 0)
10025 		return ret;
10026 	/* Nothing else to do if there is no buffer. */
10027 	if (!out)
10028 		return ret;
10029 	if (!out->args.vc.actions_n)
10030 		return -1;
10031 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10032 	/* Point to selected object. */
10033 	ctx->object = out->args.vc.data;
10034 	ctx->objmask = NULL;
10035 	/* Copy the headers to the buffer. */
10036 	action_decap_data = ctx->object;
10037 	*action_decap_data = (struct action_raw_decap_data) {
10038 		.conf = (struct rte_flow_action_raw_decap){
10039 			.data = action_decap_data->data,
10040 		},
10041 		.data = {},
10042 	};
10043 	header = action_decap_data->data;
10044 	if (mplsoudp_decap_conf.select_vlan)
10045 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
10046 	else if (mplsoudp_encap_conf.select_ipv4)
10047 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
10048 	else
10049 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
10050 	memcpy(eth.hdr.dst_addr.addr_bytes,
10051 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
10052 	memcpy(eth.hdr.src_addr.addr_bytes,
10053 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
10054 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
10055 	header += sizeof(struct rte_ether_hdr);
10056 	if (mplsoudp_encap_conf.select_vlan) {
10057 		if (mplsoudp_encap_conf.select_ipv4)
10058 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
10059 		else
10060 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
10061 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
10062 		header += sizeof(struct rte_vlan_hdr);
10063 	}
10064 	if (mplsoudp_encap_conf.select_ipv4) {
10065 		memcpy(header, &ipv4, sizeof(ipv4));
10066 		header += sizeof(ipv4);
10067 	} else {
10068 		memcpy(header, &ipv6, sizeof(ipv6));
10069 		header += sizeof(ipv6);
10070 	}
10071 	memcpy(header, &udp, sizeof(udp));
10072 	header += sizeof(udp);
10073 	memset(&mpls, 0, sizeof(mpls));
10074 	memcpy(header, &mpls, sizeof(mpls));
10075 	header += sizeof(mpls);
10076 	action_decap_data->conf.size = header -
10077 		action_decap_data->data;
10078 	action->conf = &action_decap_data->conf;
10079 	return ret;
10080 }
10081 
10082 static int
10083 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
10084 				const char *str, unsigned int len, void *buf,
10085 				unsigned int size)
10086 {
10087 	struct action_raw_decap_data *action_raw_decap_data;
10088 	struct rte_flow_action *action;
10089 	const struct arg *arg;
10090 	struct buffer *out = buf;
10091 	int ret;
10092 	uint16_t idx;
10093 
10094 	RTE_SET_USED(token);
10095 	RTE_SET_USED(buf);
10096 	RTE_SET_USED(size);
10097 	arg = ARGS_ENTRY_ARB_BOUNDED
10098 		(offsetof(struct action_raw_decap_data, idx),
10099 		 sizeof(((struct action_raw_decap_data *)0)->idx),
10100 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
10101 	if (push_args(ctx, arg))
10102 		return -1;
10103 	ret = parse_int(ctx, token, str, len, NULL, 0);
10104 	if (ret < 0) {
10105 		pop_args(ctx);
10106 		return -1;
10107 	}
10108 	if (!ctx->object)
10109 		return len;
10110 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10111 	action_raw_decap_data = ctx->object;
10112 	idx = action_raw_decap_data->idx;
10113 	action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
10114 	action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
10115 	action->conf = &action_raw_decap_data->conf;
10116 	return len;
10117 }
10118 
10119 
10120 static int
10121 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
10122 				const char *str, unsigned int len, void *buf,
10123 				unsigned int size)
10124 {
10125 	struct action_raw_encap_data *action_raw_encap_data;
10126 	struct rte_flow_action *action;
10127 	const struct arg *arg;
10128 	struct buffer *out = buf;
10129 	int ret;
10130 	uint16_t idx;
10131 
10132 	RTE_SET_USED(token);
10133 	RTE_SET_USED(buf);
10134 	RTE_SET_USED(size);
10135 	if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
10136 		return -1;
10137 	arg = ARGS_ENTRY_ARB_BOUNDED
10138 		(offsetof(struct action_raw_encap_data, idx),
10139 		 sizeof(((struct action_raw_encap_data *)0)->idx),
10140 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
10141 	if (push_args(ctx, arg))
10142 		return -1;
10143 	ret = parse_int(ctx, token, str, len, NULL, 0);
10144 	if (ret < 0) {
10145 		pop_args(ctx);
10146 		return -1;
10147 	}
10148 	if (!ctx->object)
10149 		return len;
10150 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10151 	action_raw_encap_data = ctx->object;
10152 	idx = action_raw_encap_data->idx;
10153 	action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
10154 	action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
10155 	action_raw_encap_data->conf.preserve = NULL;
10156 	action->conf = &action_raw_encap_data->conf;
10157 	return len;
10158 }
10159 
10160 static int
10161 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
10162 			  const char *str, unsigned int len, void *buf,
10163 			  unsigned int size)
10164 {
10165 	struct buffer *out = buf;
10166 	int ret;
10167 
10168 	ret = parse_vc(ctx, token, str, len, buf, size);
10169 	if (ret < 0)
10170 		return ret;
10171 	/* Nothing else to do if there is no buffer. */
10172 	if (!out)
10173 		return ret;
10174 	if (!out->args.vc.actions_n)
10175 		return -1;
10176 	/* Point to selected object. */
10177 	ctx->object = out->args.vc.data;
10178 	ctx->objmask = NULL;
10179 	return ret;
10180 }
10181 
10182 static int
10183 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
10184 			  const char *str, unsigned int len, void *buf,
10185 			  unsigned int size)
10186 {
10187 	struct buffer *out = buf;
10188 	struct rte_flow_action *action;
10189 	struct action_raw_decap_data *action_raw_decap_data = NULL;
10190 	int ret;
10191 
10192 	ret = parse_vc(ctx, token, str, len, buf, size);
10193 	if (ret < 0)
10194 		return ret;
10195 	/* Nothing else to do if there is no buffer. */
10196 	if (!out)
10197 		return ret;
10198 	if (!out->args.vc.actions_n)
10199 		return -1;
10200 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10201 	/* Point to selected object. */
10202 	ctx->object = out->args.vc.data;
10203 	ctx->objmask = NULL;
10204 	/* Copy the headers to the buffer. */
10205 	action_raw_decap_data = ctx->object;
10206 	action_raw_decap_data->conf.data = raw_decap_confs[0].data;
10207 	action_raw_decap_data->conf.size = raw_decap_confs[0].size;
10208 	action->conf = &action_raw_decap_data->conf;
10209 	return ret;
10210 }
10211 
10212 static int
10213 parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
10214 				const char *str, unsigned int len, void *buf,
10215 				unsigned int size)
10216 {
10217 	struct buffer *out = buf;
10218 	struct rte_flow_action *action;
10219 	struct action_ipv6_ext_remove_data *ipv6_ext_remove_data = NULL;
10220 	int ret;
10221 
10222 	ret = parse_vc(ctx, token, str, len, buf, size);
10223 	if (ret < 0)
10224 		return ret;
10225 	/* Nothing else to do if there is no buffer. */
10226 	if (!out)
10227 		return ret;
10228 	if (!out->args.vc.actions_n)
10229 		return -1;
10230 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10231 	/* Point to selected object. */
10232 	ctx->object = out->args.vc.data;
10233 	ctx->objmask = NULL;
10234 	/* Copy the headers to the buffer. */
10235 	ipv6_ext_remove_data = ctx->object;
10236 	ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[0].type;
10237 	action->conf = &ipv6_ext_remove_data->conf;
10238 	return ret;
10239 }
10240 
10241 static int
10242 parse_vc_action_ipv6_ext_remove_index(struct context *ctx, const struct token *token,
10243 				      const char *str, unsigned int len, void *buf,
10244 				      unsigned int size)
10245 {
10246 	struct action_ipv6_ext_remove_data *action_ipv6_ext_remove_data;
10247 	struct rte_flow_action *action;
10248 	const struct arg *arg;
10249 	struct buffer *out = buf;
10250 	int ret;
10251 	uint16_t idx;
10252 
10253 	RTE_SET_USED(token);
10254 	RTE_SET_USED(buf);
10255 	RTE_SET_USED(size);
10256 	arg = ARGS_ENTRY_ARB_BOUNDED
10257 		(offsetof(struct action_ipv6_ext_remove_data, idx),
10258 		 sizeof(((struct action_ipv6_ext_remove_data *)0)->idx),
10259 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10260 	if (push_args(ctx, arg))
10261 		return -1;
10262 	ret = parse_int(ctx, token, str, len, NULL, 0);
10263 	if (ret < 0) {
10264 		pop_args(ctx);
10265 		return -1;
10266 	}
10267 	if (!ctx->object)
10268 		return len;
10269 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10270 	action_ipv6_ext_remove_data = ctx->object;
10271 	idx = action_ipv6_ext_remove_data->idx;
10272 	action_ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[idx].type;
10273 	action->conf = &action_ipv6_ext_remove_data->conf;
10274 	return len;
10275 }
10276 
10277 static int
10278 parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
10279 			      const char *str, unsigned int len, void *buf,
10280 			      unsigned int size)
10281 {
10282 	struct buffer *out = buf;
10283 	struct rte_flow_action *action;
10284 	struct action_ipv6_ext_push_data *ipv6_ext_push_data = NULL;
10285 	int ret;
10286 
10287 	ret = parse_vc(ctx, token, str, len, buf, size);
10288 	if (ret < 0)
10289 		return ret;
10290 	/* Nothing else to do if there is no buffer. */
10291 	if (!out)
10292 		return ret;
10293 	if (!out->args.vc.actions_n)
10294 		return -1;
10295 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10296 	/* Point to selected object. */
10297 	ctx->object = out->args.vc.data;
10298 	ctx->objmask = NULL;
10299 	/* Copy the headers to the buffer. */
10300 	ipv6_ext_push_data = ctx->object;
10301 	ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[0].type;
10302 	ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[0].data;
10303 	ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[0].size;
10304 	action->conf = &ipv6_ext_push_data->conf;
10305 	return ret;
10306 }
10307 
10308 static int
10309 parse_vc_action_ipv6_ext_push_index(struct context *ctx, const struct token *token,
10310 				    const char *str, unsigned int len, void *buf,
10311 				    unsigned int size)
10312 {
10313 	struct action_ipv6_ext_push_data *action_ipv6_ext_push_data;
10314 	struct rte_flow_action *action;
10315 	const struct arg *arg;
10316 	struct buffer *out = buf;
10317 	int ret;
10318 	uint16_t idx;
10319 
10320 	RTE_SET_USED(token);
10321 	RTE_SET_USED(buf);
10322 	RTE_SET_USED(size);
10323 	arg = ARGS_ENTRY_ARB_BOUNDED
10324 		(offsetof(struct action_ipv6_ext_push_data, idx),
10325 		 sizeof(((struct action_ipv6_ext_push_data *)0)->idx),
10326 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10327 	if (push_args(ctx, arg))
10328 		return -1;
10329 	ret = parse_int(ctx, token, str, len, NULL, 0);
10330 	if (ret < 0) {
10331 		pop_args(ctx);
10332 		return -1;
10333 	}
10334 	if (!ctx->object)
10335 		return len;
10336 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10337 	action_ipv6_ext_push_data = ctx->object;
10338 	idx = action_ipv6_ext_push_data->idx;
10339 	action_ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[idx].type;
10340 	action_ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[idx].size;
10341 	action_ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[idx].data;
10342 	action->conf = &action_ipv6_ext_push_data->conf;
10343 	return len;
10344 }
10345 
10346 static int
10347 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
10348 			 const char *str, unsigned int len, void *buf,
10349 			 unsigned int size)
10350 {
10351 	int ret;
10352 
10353 	ret = parse_vc(ctx, token, str, len, buf, size);
10354 	if (ret < 0)
10355 		return ret;
10356 	ret = rte_flow_dynf_metadata_register();
10357 	if (ret < 0)
10358 		return -1;
10359 	return len;
10360 }
10361 
10362 static int
10363 parse_vc_action_sample(struct context *ctx, const struct token *token,
10364 			 const char *str, unsigned int len, void *buf,
10365 			 unsigned int size)
10366 {
10367 	struct buffer *out = buf;
10368 	struct rte_flow_action *action;
10369 	struct action_sample_data *action_sample_data = NULL;
10370 	static struct rte_flow_action end_action = {
10371 		RTE_FLOW_ACTION_TYPE_END, 0
10372 	};
10373 	int ret;
10374 
10375 	ret = parse_vc(ctx, token, str, len, buf, size);
10376 	if (ret < 0)
10377 		return ret;
10378 	/* Nothing else to do if there is no buffer. */
10379 	if (!out)
10380 		return ret;
10381 	if (!out->args.vc.actions_n)
10382 		return -1;
10383 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10384 	/* Point to selected object. */
10385 	ctx->object = out->args.vc.data;
10386 	ctx->objmask = NULL;
10387 	/* Copy the headers to the buffer. */
10388 	action_sample_data = ctx->object;
10389 	action_sample_data->conf.actions = &end_action;
10390 	action->conf = &action_sample_data->conf;
10391 	return ret;
10392 }
10393 
10394 static int
10395 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
10396 				const char *str, unsigned int len, void *buf,
10397 				unsigned int size)
10398 {
10399 	struct action_sample_data *action_sample_data;
10400 	struct rte_flow_action *action;
10401 	const struct arg *arg;
10402 	struct buffer *out = buf;
10403 	int ret;
10404 	uint16_t idx;
10405 
10406 	RTE_SET_USED(token);
10407 	RTE_SET_USED(buf);
10408 	RTE_SET_USED(size);
10409 	if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
10410 		return -1;
10411 	arg = ARGS_ENTRY_ARB_BOUNDED
10412 		(offsetof(struct action_sample_data, idx),
10413 		 sizeof(((struct action_sample_data *)0)->idx),
10414 		 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
10415 	if (push_args(ctx, arg))
10416 		return -1;
10417 	ret = parse_int(ctx, token, str, len, NULL, 0);
10418 	if (ret < 0) {
10419 		pop_args(ctx);
10420 		return -1;
10421 	}
10422 	if (!ctx->object)
10423 		return len;
10424 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10425 	action_sample_data = ctx->object;
10426 	idx = action_sample_data->idx;
10427 	action_sample_data->conf.actions = raw_sample_confs[idx].data;
10428 	action->conf = &action_sample_data->conf;
10429 	return len;
10430 }
10431 
10432 /** Parse operation for modify_field command. */
10433 static int
10434 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
10435 			 const char *str, unsigned int len, void *buf,
10436 			 unsigned int size)
10437 {
10438 	struct rte_flow_action_modify_field *action_modify_field;
10439 	unsigned int i;
10440 
10441 	(void)token;
10442 	(void)buf;
10443 	(void)size;
10444 	if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
10445 		return -1;
10446 	for (i = 0; modify_field_ops[i]; ++i)
10447 		if (!strcmp_partial(modify_field_ops[i], str, len))
10448 			break;
10449 	if (!modify_field_ops[i])
10450 		return -1;
10451 	if (!ctx->object)
10452 		return len;
10453 	action_modify_field = ctx->object;
10454 	action_modify_field->operation = (enum rte_flow_modify_op)i;
10455 	return len;
10456 }
10457 
10458 /** Parse id for modify_field command. */
10459 static int
10460 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
10461 			 const char *str, unsigned int len, void *buf,
10462 			 unsigned int size)
10463 {
10464 	struct rte_flow_action_modify_field *action_modify_field;
10465 	unsigned int i;
10466 
10467 	(void)token;
10468 	(void)buf;
10469 	(void)size;
10470 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
10471 		ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
10472 		return -1;
10473 	for (i = 0; flow_field_ids[i]; ++i)
10474 		if (!strcmp_partial(flow_field_ids[i], str, len))
10475 			break;
10476 	if (!flow_field_ids[i])
10477 		return -1;
10478 	if (!ctx->object)
10479 		return len;
10480 	action_modify_field = ctx->object;
10481 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
10482 		action_modify_field->dst.field = (enum rte_flow_field_id)i;
10483 	else
10484 		action_modify_field->src.field = (enum rte_flow_field_id)i;
10485 	return len;
10486 }
10487 
10488 /** Parse level for modify_field command. */
10489 static int
10490 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
10491 			 const char *str, unsigned int len, void *buf,
10492 			 unsigned int size)
10493 {
10494 	struct rte_flow_action_modify_field *action;
10495 	struct flex_item *fp = NULL;
10496 	uint32_t val;
10497 	struct buffer *out = buf;
10498 	char *end;
10499 
10500 	(void)token;
10501 	(void)size;
10502 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10503 		ctx->curr != ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)
10504 		return -1;
10505 	if (!ctx->object)
10506 		return len;
10507 	action = ctx->object;
10508 	errno = 0;
10509 	val = strtoumax(str, &end, 0);
10510 	if (errno || (size_t)(end - str) != len)
10511 		return -1;
10512 	/* No need to validate action template mask value */
10513 	if (out->args.vc.masks) {
10514 		if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)
10515 			action->dst.level = val;
10516 		else
10517 			action->src.level = val;
10518 		return len;
10519 	}
10520 	if ((ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10521 		action->dst.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
10522 		(ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE &&
10523 		action->src.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
10524 		if (val >= FLEX_MAX_PARSERS_NUM) {
10525 			printf("Bad flex item handle\n");
10526 			return -1;
10527 		}
10528 		fp = flex_items[ctx->port][val];
10529 		if (!fp) {
10530 			printf("Bad flex item handle\n");
10531 			return -1;
10532 		}
10533 	}
10534 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE) {
10535 		if (action->dst.field != RTE_FLOW_FIELD_FLEX_ITEM)
10536 			action->dst.level = val;
10537 		else
10538 			action->dst.flex_handle = fp->flex_handle;
10539 	} else if (ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE) {
10540 		if (action->src.field != RTE_FLOW_FIELD_FLEX_ITEM)
10541 			action->src.level = val;
10542 		else
10543 			action->src.flex_handle = fp->flex_handle;
10544 	}
10545 	return len;
10546 }
10547 
10548 /** Parse the conntrack update, not a rte_flow_action. */
10549 static int
10550 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
10551 			 const char *str, unsigned int len, void *buf,
10552 			 unsigned int size)
10553 {
10554 	struct buffer *out = buf;
10555 	struct rte_flow_modify_conntrack *ct_modify = NULL;
10556 
10557 	(void)size;
10558 	if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
10559 	    ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
10560 		return -1;
10561 	/* Token name must match. */
10562 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10563 		return -1;
10564 	/* Nothing else to do if there is no buffer. */
10565 	if (!out)
10566 		return len;
10567 	ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
10568 	if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
10569 		ct_modify->new_ct.is_original_dir =
10570 				conntrack_context.is_original_dir;
10571 		ct_modify->direction = 1;
10572 	} else {
10573 		uint32_t old_dir;
10574 
10575 		old_dir = ct_modify->new_ct.is_original_dir;
10576 		memcpy(&ct_modify->new_ct, &conntrack_context,
10577 		       sizeof(conntrack_context));
10578 		ct_modify->new_ct.is_original_dir = old_dir;
10579 		ct_modify->state = 1;
10580 	}
10581 	return len;
10582 }
10583 
10584 /** Parse tokens for destroy command. */
10585 static int
10586 parse_destroy(struct context *ctx, const struct token *token,
10587 	      const char *str, unsigned int len,
10588 	      void *buf, unsigned int size)
10589 {
10590 	struct buffer *out = buf;
10591 
10592 	/* Token name must match. */
10593 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10594 		return -1;
10595 	/* Nothing else to do if there is no buffer. */
10596 	if (!out)
10597 		return len;
10598 	if (!out->command) {
10599 		if (ctx->curr != DESTROY)
10600 			return -1;
10601 		if (sizeof(*out) > size)
10602 			return -1;
10603 		out->command = ctx->curr;
10604 		ctx->objdata = 0;
10605 		ctx->object = out;
10606 		ctx->objmask = NULL;
10607 		out->args.destroy.rule =
10608 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10609 					       sizeof(double));
10610 		return len;
10611 	}
10612 	if (ctx->curr == DESTROY_IS_USER_ID) {
10613 		out->args.destroy.is_user_id = true;
10614 		return len;
10615 	}
10616 	if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
10617 	     sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
10618 		return -1;
10619 	ctx->objdata = 0;
10620 	ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
10621 	ctx->objmask = NULL;
10622 	return len;
10623 }
10624 
10625 /** Parse tokens for flush command. */
10626 static int
10627 parse_flush(struct context *ctx, const struct token *token,
10628 	    const char *str, unsigned int len,
10629 	    void *buf, unsigned int size)
10630 {
10631 	struct buffer *out = buf;
10632 
10633 	/* Token name must match. */
10634 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10635 		return -1;
10636 	/* Nothing else to do if there is no buffer. */
10637 	if (!out)
10638 		return len;
10639 	if (!out->command) {
10640 		if (ctx->curr != FLUSH)
10641 			return -1;
10642 		if (sizeof(*out) > size)
10643 			return -1;
10644 		out->command = ctx->curr;
10645 		ctx->objdata = 0;
10646 		ctx->object = out;
10647 		ctx->objmask = NULL;
10648 	}
10649 	return len;
10650 }
10651 
10652 /** Parse tokens for dump command. */
10653 static int
10654 parse_dump(struct context *ctx, const struct token *token,
10655 	    const char *str, unsigned int len,
10656 	    void *buf, unsigned int size)
10657 {
10658 	struct buffer *out = buf;
10659 
10660 	/* Token name must match. */
10661 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10662 		return -1;
10663 	/* Nothing else to do if there is no buffer. */
10664 	if (!out)
10665 		return len;
10666 	if (!out->command) {
10667 		if (ctx->curr != DUMP)
10668 			return -1;
10669 		if (sizeof(*out) > size)
10670 			return -1;
10671 		out->command = ctx->curr;
10672 		ctx->objdata = 0;
10673 		ctx->object = out;
10674 		ctx->objmask = NULL;
10675 		return len;
10676 	}
10677 	switch (ctx->curr) {
10678 	case DUMP_ALL:
10679 	case DUMP_ONE:
10680 		out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
10681 		out->command = ctx->curr;
10682 		ctx->objdata = 0;
10683 		ctx->object = out;
10684 		ctx->objmask = NULL;
10685 		return len;
10686 	case DUMP_IS_USER_ID:
10687 		out->args.dump.is_user_id = true;
10688 		return len;
10689 	default:
10690 		return -1;
10691 	}
10692 }
10693 
10694 /** Parse tokens for query command. */
10695 static int
10696 parse_query(struct context *ctx, const struct token *token,
10697 	    const char *str, unsigned int len,
10698 	    void *buf, unsigned int size)
10699 {
10700 	struct buffer *out = buf;
10701 
10702 	/* Token name must match. */
10703 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10704 		return -1;
10705 	/* Nothing else to do if there is no buffer. */
10706 	if (!out)
10707 		return len;
10708 	if (!out->command) {
10709 		if (ctx->curr != QUERY)
10710 			return -1;
10711 		if (sizeof(*out) > size)
10712 			return -1;
10713 		out->command = ctx->curr;
10714 		ctx->objdata = 0;
10715 		ctx->object = out;
10716 		ctx->objmask = NULL;
10717 	}
10718 	if (ctx->curr == QUERY_IS_USER_ID) {
10719 		out->args.query.is_user_id = true;
10720 		return len;
10721 	}
10722 	return len;
10723 }
10724 
10725 /** Parse action names. */
10726 static int
10727 parse_action(struct context *ctx, const struct token *token,
10728 	     const char *str, unsigned int len,
10729 	     void *buf, unsigned int size)
10730 {
10731 	struct buffer *out = buf;
10732 	const struct arg *arg = pop_args(ctx);
10733 	unsigned int i;
10734 
10735 	(void)size;
10736 	/* Argument is expected. */
10737 	if (!arg)
10738 		return -1;
10739 	/* Parse action name. */
10740 	for (i = 0; next_action[i]; ++i) {
10741 		const struct parse_action_priv *priv;
10742 
10743 		token = &token_list[next_action[i]];
10744 		if (strcmp_partial(token->name, str, len))
10745 			continue;
10746 		priv = token->priv;
10747 		if (!priv)
10748 			goto error;
10749 		if (out)
10750 			memcpy((uint8_t *)ctx->object + arg->offset,
10751 			       &priv->type,
10752 			       arg->size);
10753 		return len;
10754 	}
10755 error:
10756 	push_args(ctx, arg);
10757 	return -1;
10758 }
10759 
10760 /** Parse tokens for list command. */
10761 static int
10762 parse_list(struct context *ctx, const struct token *token,
10763 	   const char *str, unsigned int len,
10764 	   void *buf, unsigned int size)
10765 {
10766 	struct buffer *out = buf;
10767 
10768 	/* Token name must match. */
10769 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10770 		return -1;
10771 	/* Nothing else to do if there is no buffer. */
10772 	if (!out)
10773 		return len;
10774 	if (!out->command) {
10775 		if (ctx->curr != LIST)
10776 			return -1;
10777 		if (sizeof(*out) > size)
10778 			return -1;
10779 		out->command = ctx->curr;
10780 		ctx->objdata = 0;
10781 		ctx->object = out;
10782 		ctx->objmask = NULL;
10783 		out->args.list.group =
10784 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10785 					       sizeof(double));
10786 		return len;
10787 	}
10788 	if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
10789 	     sizeof(*out->args.list.group)) > (uint8_t *)out + size)
10790 		return -1;
10791 	ctx->objdata = 0;
10792 	ctx->object = out->args.list.group + out->args.list.group_n++;
10793 	ctx->objmask = NULL;
10794 	return len;
10795 }
10796 
10797 /** Parse tokens for list all aged flows command. */
10798 static int
10799 parse_aged(struct context *ctx, const struct token *token,
10800 	   const char *str, unsigned int len,
10801 	   void *buf, unsigned int size)
10802 {
10803 	struct buffer *out = buf;
10804 
10805 	/* Token name must match. */
10806 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10807 		return -1;
10808 	/* Nothing else to do if there is no buffer. */
10809 	if (!out)
10810 		return len;
10811 	if (!out->command || out->command == QUEUE) {
10812 		if (ctx->curr != AGED && ctx->curr != QUEUE_AGED)
10813 			return -1;
10814 		if (sizeof(*out) > size)
10815 			return -1;
10816 		out->command = ctx->curr;
10817 		ctx->objdata = 0;
10818 		ctx->object = out;
10819 		ctx->objmask = NULL;
10820 	}
10821 	if (ctx->curr == AGED_DESTROY)
10822 		out->args.aged.destroy = 1;
10823 	return len;
10824 }
10825 
10826 /** Parse tokens for isolate command. */
10827 static int
10828 parse_isolate(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 	if (!out->command) {
10841 		if (ctx->curr != ISOLATE)
10842 			return -1;
10843 		if (sizeof(*out) > size)
10844 			return -1;
10845 		out->command = ctx->curr;
10846 		ctx->objdata = 0;
10847 		ctx->object = out;
10848 		ctx->objmask = NULL;
10849 	}
10850 	return len;
10851 }
10852 
10853 /** Parse tokens for info/configure command. */
10854 static int
10855 parse_configure(struct context *ctx, const struct token *token,
10856 		const char *str, unsigned int len,
10857 		void *buf, unsigned int size)
10858 {
10859 	struct buffer *out = buf;
10860 
10861 	/* Token name must match. */
10862 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10863 		return -1;
10864 	/* Nothing else to do if there is no buffer. */
10865 	if (!out)
10866 		return len;
10867 	if (!out->command) {
10868 		if (ctx->curr != INFO && ctx->curr != CONFIGURE)
10869 			return -1;
10870 		if (sizeof(*out) > size)
10871 			return -1;
10872 		out->command = ctx->curr;
10873 		ctx->objdata = 0;
10874 		ctx->object = out;
10875 		ctx->objmask = NULL;
10876 	}
10877 	return len;
10878 }
10879 
10880 /** Parse tokens for template create command. */
10881 static int
10882 parse_template(struct context *ctx, const struct token *token,
10883 	       const char *str, unsigned int len,
10884 	       void *buf, unsigned int size)
10885 {
10886 	struct buffer *out = buf;
10887 
10888 	/* Token name must match. */
10889 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10890 		return -1;
10891 	/* Nothing else to do if there is no buffer. */
10892 	if (!out)
10893 		return len;
10894 	if (!out->command) {
10895 		if (ctx->curr != PATTERN_TEMPLATE &&
10896 		    ctx->curr != ACTIONS_TEMPLATE)
10897 			return -1;
10898 		if (sizeof(*out) > size)
10899 			return -1;
10900 		out->command = ctx->curr;
10901 		ctx->objdata = 0;
10902 		ctx->object = out;
10903 		ctx->objmask = NULL;
10904 		out->args.vc.data = (uint8_t *)out + size;
10905 		return len;
10906 	}
10907 	switch (ctx->curr) {
10908 	case PATTERN_TEMPLATE_CREATE:
10909 		out->args.vc.pattern =
10910 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10911 					       sizeof(double));
10912 		out->args.vc.pat_templ_id = UINT32_MAX;
10913 		out->command = ctx->curr;
10914 		ctx->objdata = 0;
10915 		ctx->object = out;
10916 		ctx->objmask = NULL;
10917 		return len;
10918 	case PATTERN_TEMPLATE_EGRESS:
10919 		out->args.vc.attr.egress = 1;
10920 		return len;
10921 	case PATTERN_TEMPLATE_INGRESS:
10922 		out->args.vc.attr.ingress = 1;
10923 		return len;
10924 	case PATTERN_TEMPLATE_TRANSFER:
10925 		out->args.vc.attr.transfer = 1;
10926 		return len;
10927 	case ACTIONS_TEMPLATE_CREATE:
10928 		out->args.vc.act_templ_id = UINT32_MAX;
10929 		out->command = ctx->curr;
10930 		ctx->objdata = 0;
10931 		ctx->object = out;
10932 		ctx->objmask = NULL;
10933 		return len;
10934 	case ACTIONS_TEMPLATE_SPEC:
10935 		out->args.vc.actions =
10936 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10937 					       sizeof(double));
10938 		ctx->object = out->args.vc.actions;
10939 		ctx->objmask = NULL;
10940 		return len;
10941 	case ACTIONS_TEMPLATE_MASK:
10942 		out->args.vc.masks =
10943 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10944 					       (out->args.vc.actions +
10945 						out->args.vc.actions_n),
10946 					       sizeof(double));
10947 		ctx->object = out->args.vc.masks;
10948 		ctx->objmask = NULL;
10949 		return len;
10950 	case ACTIONS_TEMPLATE_EGRESS:
10951 		out->args.vc.attr.egress = 1;
10952 		return len;
10953 	case ACTIONS_TEMPLATE_INGRESS:
10954 		out->args.vc.attr.ingress = 1;
10955 		return len;
10956 	case ACTIONS_TEMPLATE_TRANSFER:
10957 		out->args.vc.attr.transfer = 1;
10958 		return len;
10959 	default:
10960 		return -1;
10961 	}
10962 }
10963 
10964 /** Parse tokens for template destroy command. */
10965 static int
10966 parse_template_destroy(struct context *ctx, const struct token *token,
10967 		       const char *str, unsigned int len,
10968 		       void *buf, unsigned int size)
10969 {
10970 	struct buffer *out = buf;
10971 	uint32_t *template_id;
10972 
10973 	/* Token name must match. */
10974 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10975 		return -1;
10976 	/* Nothing else to do if there is no buffer. */
10977 	if (!out)
10978 		return len;
10979 	if (!out->command ||
10980 		out->command == PATTERN_TEMPLATE ||
10981 		out->command == ACTIONS_TEMPLATE) {
10982 		if (ctx->curr != PATTERN_TEMPLATE_DESTROY &&
10983 			ctx->curr != ACTIONS_TEMPLATE_DESTROY)
10984 			return -1;
10985 		if (sizeof(*out) > size)
10986 			return -1;
10987 		out->command = ctx->curr;
10988 		ctx->objdata = 0;
10989 		ctx->object = out;
10990 		ctx->objmask = NULL;
10991 		out->args.templ_destroy.template_id =
10992 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10993 					       sizeof(double));
10994 		return len;
10995 	}
10996 	template_id = out->args.templ_destroy.template_id
10997 		    + out->args.templ_destroy.template_id_n++;
10998 	if ((uint8_t *)template_id > (uint8_t *)out + size)
10999 		return -1;
11000 	ctx->objdata = 0;
11001 	ctx->object = template_id;
11002 	ctx->objmask = NULL;
11003 	return len;
11004 }
11005 
11006 /** Parse tokens for table create command. */
11007 static int
11008 parse_table(struct context *ctx, const struct token *token,
11009 	    const char *str, unsigned int len,
11010 	    void *buf, unsigned int size)
11011 {
11012 	struct buffer *out = buf;
11013 	uint32_t *template_id;
11014 
11015 	/* Token name must match. */
11016 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11017 		return -1;
11018 	/* Nothing else to do if there is no buffer. */
11019 	if (!out)
11020 		return len;
11021 	if (!out->command) {
11022 		if (ctx->curr != TABLE)
11023 			return -1;
11024 		if (sizeof(*out) > size)
11025 			return -1;
11026 		out->command = ctx->curr;
11027 		ctx->objdata = 0;
11028 		ctx->object = out;
11029 		ctx->objmask = NULL;
11030 		return len;
11031 	}
11032 	switch (ctx->curr) {
11033 	case TABLE_CREATE:
11034 	case TABLE_RESIZE:
11035 		out->command = ctx->curr;
11036 		ctx->objdata = 0;
11037 		ctx->object = out;
11038 		ctx->objmask = NULL;
11039 		out->args.table.id = UINT32_MAX;
11040 		return len;
11041 	case TABLE_PATTERN_TEMPLATE:
11042 		out->args.table.pat_templ_id =
11043 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11044 					       sizeof(double));
11045 		template_id = out->args.table.pat_templ_id
11046 				+ out->args.table.pat_templ_id_n++;
11047 		if ((uint8_t *)template_id > (uint8_t *)out + size)
11048 			return -1;
11049 		ctx->objdata = 0;
11050 		ctx->object = template_id;
11051 		ctx->objmask = NULL;
11052 		return len;
11053 	case TABLE_ACTIONS_TEMPLATE:
11054 		out->args.table.act_templ_id =
11055 			(void *)RTE_ALIGN_CEIL((uintptr_t)
11056 					       (out->args.table.pat_templ_id +
11057 						out->args.table.pat_templ_id_n),
11058 					       sizeof(double));
11059 		template_id = out->args.table.act_templ_id
11060 				+ out->args.table.act_templ_id_n++;
11061 		if ((uint8_t *)template_id > (uint8_t *)out + size)
11062 			return -1;
11063 		ctx->objdata = 0;
11064 		ctx->object = template_id;
11065 		ctx->objmask = NULL;
11066 		return len;
11067 	case TABLE_INGRESS:
11068 		out->args.table.attr.flow_attr.ingress = 1;
11069 		return len;
11070 	case TABLE_EGRESS:
11071 		out->args.table.attr.flow_attr.egress = 1;
11072 		return len;
11073 	case TABLE_TRANSFER:
11074 		out->args.table.attr.flow_attr.transfer = 1;
11075 		return len;
11076 	case TABLE_TRANSFER_WIRE_ORIG:
11077 		if (!out->args.table.attr.flow_attr.transfer)
11078 			return -1;
11079 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_WIRE_ORIG;
11080 		return len;
11081 	case TABLE_TRANSFER_VPORT_ORIG:
11082 		if (!out->args.table.attr.flow_attr.transfer)
11083 			return -1;
11084 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_VPORT_ORIG;
11085 		return len;
11086 	case TABLE_RESIZABLE:
11087 		out->args.table.attr.specialize |=
11088 			RTE_FLOW_TABLE_SPECIALIZE_RESIZABLE;
11089 		return len;
11090 	case TABLE_RULES_NUMBER:
11091 		ctx->objdata = 0;
11092 		ctx->object = out;
11093 		ctx->objmask = NULL;
11094 		return len;
11095 	case TABLE_RESIZE_ID:
11096 	case TABLE_RESIZE_RULES_NUMBER:
11097 		return len;
11098 	default:
11099 		return -1;
11100 	}
11101 }
11102 
11103 /** Parse tokens for table destroy command. */
11104 static int
11105 parse_table_destroy(struct context *ctx, const struct token *token,
11106 		    const char *str, unsigned int len,
11107 		    void *buf, unsigned int size)
11108 {
11109 	struct buffer *out = buf;
11110 	uint32_t *table_id;
11111 
11112 	/* Token name must match. */
11113 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11114 		return -1;
11115 	/* Nothing else to do if there is no buffer. */
11116 	if (!out)
11117 		return len;
11118 	if (!out->command || out->command == TABLE) {
11119 		if (ctx->curr != TABLE_DESTROY &&
11120 		    ctx->curr != TABLE_RESIZE_COMPLETE)
11121 			return -1;
11122 		if (sizeof(*out) > size)
11123 			return -1;
11124 		out->command = ctx->curr;
11125 		ctx->objdata = 0;
11126 		ctx->object = out;
11127 		ctx->objmask = NULL;
11128 		out->args.table_destroy.table_id =
11129 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11130 					       sizeof(double));
11131 		return len;
11132 	}
11133 	table_id = out->args.table_destroy.table_id
11134 		    + out->args.table_destroy.table_id_n++;
11135 	if ((uint8_t *)table_id > (uint8_t *)out + size)
11136 		return -1;
11137 	ctx->objdata = 0;
11138 	ctx->object = table_id;
11139 	ctx->objmask = NULL;
11140 	return len;
11141 }
11142 
11143 /** Parse tokens for queue create commands. */
11144 static int
11145 parse_qo(struct context *ctx, const struct token *token,
11146 	 const char *str, unsigned int len,
11147 	 void *buf, unsigned int size)
11148 {
11149 	struct buffer *out = buf;
11150 
11151 	/* Token name must match. */
11152 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11153 		return -1;
11154 	/* Nothing else to do if there is no buffer. */
11155 	if (!out)
11156 		return len;
11157 	if (!out->command) {
11158 		if (ctx->curr != QUEUE)
11159 			return -1;
11160 		if (sizeof(*out) > size)
11161 			return -1;
11162 		out->command = ctx->curr;
11163 		ctx->objdata = 0;
11164 		ctx->object = out;
11165 		ctx->objmask = NULL;
11166 		out->args.vc.data = (uint8_t *)out + size;
11167 		return len;
11168 	}
11169 	switch (ctx->curr) {
11170 	case QUEUE_CREATE:
11171 	case QUEUE_UPDATE:
11172 		out->command = ctx->curr;
11173 		ctx->objdata = 0;
11174 		ctx->object = out;
11175 		ctx->objmask = NULL;
11176 		out->args.vc.rule_id = UINT32_MAX;
11177 		return len;
11178 	case QUEUE_TEMPLATE_TABLE:
11179 	case QUEUE_PATTERN_TEMPLATE:
11180 	case QUEUE_ACTIONS_TEMPLATE:
11181 	case QUEUE_CREATE_POSTPONE:
11182 	case QUEUE_RULE_ID:
11183 	case QUEUE_UPDATE_ID:
11184 		return len;
11185 	case ITEM_PATTERN:
11186 		out->args.vc.pattern =
11187 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11188 					       sizeof(double));
11189 		ctx->object = out->args.vc.pattern;
11190 		ctx->objmask = NULL;
11191 		return len;
11192 	case ACTIONS:
11193 		out->args.vc.actions =
11194 			(void *)RTE_ALIGN_CEIL((uintptr_t)
11195 					       (out->args.vc.pattern +
11196 						out->args.vc.pattern_n),
11197 					       sizeof(double));
11198 		ctx->object = out->args.vc.actions;
11199 		ctx->objmask = NULL;
11200 		return len;
11201 	default:
11202 		return -1;
11203 	}
11204 }
11205 
11206 /** Parse tokens for queue destroy command. */
11207 static int
11208 parse_qo_destroy(struct context *ctx, const struct token *token,
11209 		 const char *str, unsigned int len,
11210 		 void *buf, unsigned int size)
11211 {
11212 	struct buffer *out = buf;
11213 	uint64_t *flow_id;
11214 
11215 	/* Token name must match. */
11216 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11217 		return -1;
11218 	/* Nothing else to do if there is no buffer. */
11219 	if (!out)
11220 		return len;
11221 	if (!out->command || out->command == QUEUE) {
11222 		if (ctx->curr != QUEUE_DESTROY &&
11223 		    ctx->curr != QUEUE_FLOW_UPDATE_RESIZED)
11224 			return -1;
11225 		if (sizeof(*out) > size)
11226 			return -1;
11227 		out->command = ctx->curr;
11228 		ctx->objdata = 0;
11229 		ctx->object = out;
11230 		ctx->objmask = NULL;
11231 		out->args.destroy.rule =
11232 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11233 					       sizeof(double));
11234 		return len;
11235 	}
11236 	switch (ctx->curr) {
11237 	case QUEUE_DESTROY_ID:
11238 		flow_id = out->args.destroy.rule
11239 				+ out->args.destroy.rule_n++;
11240 		if ((uint8_t *)flow_id > (uint8_t *)out + size)
11241 			return -1;
11242 		ctx->objdata = 0;
11243 		ctx->object = flow_id;
11244 		ctx->objmask = NULL;
11245 		return len;
11246 	case QUEUE_DESTROY_POSTPONE:
11247 		return len;
11248 	default:
11249 		return -1;
11250 	}
11251 }
11252 
11253 /** Parse tokens for push queue command. */
11254 static int
11255 parse_push(struct context *ctx, const struct token *token,
11256 	   const char *str, unsigned int len,
11257 	   void *buf, unsigned int size)
11258 {
11259 	struct buffer *out = buf;
11260 
11261 	/* Token name must match. */
11262 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11263 		return -1;
11264 	/* Nothing else to do if there is no buffer. */
11265 	if (!out)
11266 		return len;
11267 	if (!out->command) {
11268 		if (ctx->curr != PUSH)
11269 			return -1;
11270 		if (sizeof(*out) > size)
11271 			return -1;
11272 		out->command = ctx->curr;
11273 		ctx->objdata = 0;
11274 		ctx->object = out;
11275 		ctx->objmask = NULL;
11276 		out->args.vc.data = (uint8_t *)out + size;
11277 	}
11278 	return len;
11279 }
11280 
11281 /** Parse tokens for pull command. */
11282 static int
11283 parse_pull(struct context *ctx, const struct token *token,
11284 	   const char *str, unsigned int len,
11285 	   void *buf, unsigned int size)
11286 {
11287 	struct buffer *out = buf;
11288 
11289 	/* Token name must match. */
11290 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11291 		return -1;
11292 	/* Nothing else to do if there is no buffer. */
11293 	if (!out)
11294 		return len;
11295 	if (!out->command) {
11296 		if (ctx->curr != PULL)
11297 			return -1;
11298 		if (sizeof(*out) > size)
11299 			return -1;
11300 		out->command = ctx->curr;
11301 		ctx->objdata = 0;
11302 		ctx->object = out;
11303 		ctx->objmask = NULL;
11304 		out->args.vc.data = (uint8_t *)out + size;
11305 	}
11306 	return len;
11307 }
11308 
11309 /** Parse tokens for hash calculation commands. */
11310 static int
11311 parse_hash(struct context *ctx, const struct token *token,
11312 	 const char *str, unsigned int len,
11313 	 void *buf, unsigned int size)
11314 {
11315 	struct buffer *out = buf;
11316 
11317 	/* Token name must match. */
11318 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11319 		return -1;
11320 	/* Nothing else to do if there is no buffer. */
11321 	if (!out)
11322 		return len;
11323 	if (!out->command) {
11324 		if (ctx->curr != HASH)
11325 			return -1;
11326 		if (sizeof(*out) > size)
11327 			return -1;
11328 		out->command = ctx->curr;
11329 		ctx->objdata = 0;
11330 		ctx->object = out;
11331 		ctx->objmask = NULL;
11332 		out->args.vc.data = (uint8_t *)out + size;
11333 		return len;
11334 	}
11335 	switch (ctx->curr) {
11336 	case HASH_CALC_TABLE:
11337 	case HASH_CALC_PATTERN_INDEX:
11338 		return len;
11339 	case ITEM_PATTERN:
11340 		out->args.vc.pattern =
11341 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11342 					       sizeof(double));
11343 		ctx->object = out->args.vc.pattern;
11344 		ctx->objmask = NULL;
11345 		return len;
11346 	case HASH_CALC_ENCAP:
11347 		out->args.vc.encap_hash = 1;
11348 		return len;
11349 	case ENCAP_HASH_FIELD_SRC_PORT:
11350 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_SRC_PORT;
11351 		return len;
11352 	case ENCAP_HASH_FIELD_GRE_FLOW_ID:
11353 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_NVGRE_FLOW_ID;
11354 		return len;
11355 	default:
11356 		return -1;
11357 	}
11358 }
11359 
11360 static int
11361 parse_group(struct context *ctx, const struct token *token,
11362 	    const char *str, unsigned int len,
11363 	    void *buf, unsigned int size)
11364 {
11365 	struct buffer *out = buf;
11366 
11367 	/* Token name must match. */
11368 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11369 		return -1;
11370 	/* Nothing else to do if there is no buffer. */
11371 	if (!out)
11372 		return len;
11373 	if (!out->command) {
11374 		if (ctx->curr != FLOW_GROUP)
11375 			return -1;
11376 		if (sizeof(*out) > size)
11377 			return -1;
11378 		out->command = ctx->curr;
11379 		ctx->objdata = 0;
11380 		ctx->object = out;
11381 		ctx->objmask = NULL;
11382 		out->args.vc.data = (uint8_t *)out + size;
11383 		return len;
11384 	}
11385 	switch (ctx->curr) {
11386 	case GROUP_INGRESS:
11387 		out->args.vc.attr.ingress = 1;
11388 		return len;
11389 	case GROUP_EGRESS:
11390 		out->args.vc.attr.egress = 1;
11391 		return len;
11392 	case GROUP_TRANSFER:
11393 		out->args.vc.attr.transfer = 1;
11394 		return len;
11395 	case GROUP_SET_MISS_ACTIONS:
11396 		out->command = ctx->curr;
11397 		ctx->objdata = 0;
11398 		ctx->object = out;
11399 		ctx->objmask = NULL;
11400 		out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11401 							       sizeof(double));
11402 		return len;
11403 	default:
11404 		return -1;
11405 	}
11406 }
11407 
11408 static int
11409 parse_flex(struct context *ctx, const struct token *token,
11410 	     const char *str, unsigned int len,
11411 	     void *buf, unsigned int size)
11412 {
11413 	struct buffer *out = buf;
11414 
11415 	/* Token name must match. */
11416 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11417 		return -1;
11418 	/* Nothing else to do if there is no buffer. */
11419 	if (!out)
11420 		return len;
11421 	if (out->command == ZERO) {
11422 		if (ctx->curr != FLEX)
11423 			return -1;
11424 		if (sizeof(*out) > size)
11425 			return -1;
11426 		out->command = ctx->curr;
11427 		ctx->objdata = 0;
11428 		ctx->object = out;
11429 		ctx->objmask = NULL;
11430 	} else {
11431 		switch (ctx->curr) {
11432 		default:
11433 			break;
11434 		case FLEX_ITEM_INIT:
11435 		case FLEX_ITEM_CREATE:
11436 		case FLEX_ITEM_DESTROY:
11437 			out->command = ctx->curr;
11438 			break;
11439 		}
11440 	}
11441 
11442 	return len;
11443 }
11444 
11445 static int
11446 parse_tunnel(struct context *ctx, const struct token *token,
11447 	     const char *str, unsigned int len,
11448 	     void *buf, unsigned int size)
11449 {
11450 	struct buffer *out = buf;
11451 
11452 	/* Token name must match. */
11453 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11454 		return -1;
11455 	/* Nothing else to do if there is no buffer. */
11456 	if (!out)
11457 		return len;
11458 	if (!out->command) {
11459 		if (ctx->curr != TUNNEL)
11460 			return -1;
11461 		if (sizeof(*out) > size)
11462 			return -1;
11463 		out->command = ctx->curr;
11464 		ctx->objdata = 0;
11465 		ctx->object = out;
11466 		ctx->objmask = NULL;
11467 	} else {
11468 		switch (ctx->curr) {
11469 		default:
11470 			break;
11471 		case TUNNEL_CREATE:
11472 		case TUNNEL_DESTROY:
11473 		case TUNNEL_LIST:
11474 			out->command = ctx->curr;
11475 			break;
11476 		case TUNNEL_CREATE_TYPE:
11477 		case TUNNEL_DESTROY_ID:
11478 			ctx->object = &out->args.vc.tunnel_ops;
11479 			break;
11480 		}
11481 	}
11482 
11483 	return len;
11484 }
11485 
11486 /**
11487  * Parse signed/unsigned integers 8 to 64-bit long.
11488  *
11489  * Last argument (ctx->args) is retrieved to determine integer type and
11490  * storage location.
11491  */
11492 static int
11493 parse_int(struct context *ctx, const struct token *token,
11494 	  const char *str, unsigned int len,
11495 	  void *buf, unsigned int size)
11496 {
11497 	const struct arg *arg = pop_args(ctx);
11498 	uintmax_t u;
11499 	char *end;
11500 
11501 	(void)token;
11502 	/* Argument is expected. */
11503 	if (!arg)
11504 		return -1;
11505 	errno = 0;
11506 	u = arg->sign ?
11507 		(uintmax_t)strtoimax(str, &end, 0) :
11508 		strtoumax(str, &end, 0);
11509 	if (errno || (size_t)(end - str) != len)
11510 		goto error;
11511 	if (arg->bounded &&
11512 	    ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
11513 			    (intmax_t)u > (intmax_t)arg->max)) ||
11514 	     (!arg->sign && (u < arg->min || u > arg->max))))
11515 		goto error;
11516 	if (!ctx->object)
11517 		return len;
11518 	if (arg->mask) {
11519 		if (!arg_entry_bf_fill(ctx->object, u, arg) ||
11520 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
11521 			goto error;
11522 		return len;
11523 	}
11524 	buf = (uint8_t *)ctx->object + arg->offset;
11525 	size = arg->size;
11526 	if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
11527 		return -1;
11528 objmask:
11529 	switch (size) {
11530 	case sizeof(uint8_t):
11531 		*(uint8_t *)buf = u;
11532 		break;
11533 	case sizeof(uint16_t):
11534 		*(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
11535 		break;
11536 	case sizeof(uint8_t [3]):
11537 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
11538 		if (!arg->hton) {
11539 			((uint8_t *)buf)[0] = u;
11540 			((uint8_t *)buf)[1] = u >> 8;
11541 			((uint8_t *)buf)[2] = u >> 16;
11542 			break;
11543 		}
11544 #endif
11545 		((uint8_t *)buf)[0] = u >> 16;
11546 		((uint8_t *)buf)[1] = u >> 8;
11547 		((uint8_t *)buf)[2] = u;
11548 		break;
11549 	case sizeof(uint32_t):
11550 		*(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
11551 		break;
11552 	case sizeof(uint64_t):
11553 		*(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
11554 		break;
11555 	default:
11556 		goto error;
11557 	}
11558 	if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
11559 		u = -1;
11560 		buf = (uint8_t *)ctx->objmask + arg->offset;
11561 		goto objmask;
11562 	}
11563 	return len;
11564 error:
11565 	push_args(ctx, arg);
11566 	return -1;
11567 }
11568 
11569 /**
11570  * Parse a string.
11571  *
11572  * Three arguments (ctx->args) are retrieved from the stack to store data,
11573  * its actual length and address (in that order).
11574  */
11575 static int
11576 parse_string(struct context *ctx, const struct token *token,
11577 	     const char *str, unsigned int len,
11578 	     void *buf, unsigned int size)
11579 {
11580 	const struct arg *arg_data = pop_args(ctx);
11581 	const struct arg *arg_len = pop_args(ctx);
11582 	const struct arg *arg_addr = pop_args(ctx);
11583 	char tmp[16]; /* Ought to be enough. */
11584 	int ret;
11585 
11586 	/* Arguments are expected. */
11587 	if (!arg_data)
11588 		return -1;
11589 	if (!arg_len) {
11590 		push_args(ctx, arg_data);
11591 		return -1;
11592 	}
11593 	if (!arg_addr) {
11594 		push_args(ctx, arg_len);
11595 		push_args(ctx, arg_data);
11596 		return -1;
11597 	}
11598 	size = arg_data->size;
11599 	/* Bit-mask fill is not supported. */
11600 	if (arg_data->mask || size < len)
11601 		goto error;
11602 	if (!ctx->object)
11603 		return len;
11604 	/* Let parse_int() fill length information first. */
11605 	ret = snprintf(tmp, sizeof(tmp), "%u", len);
11606 	if (ret < 0)
11607 		goto error;
11608 	push_args(ctx, arg_len);
11609 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11610 	if (ret < 0) {
11611 		pop_args(ctx);
11612 		goto error;
11613 	}
11614 	buf = (uint8_t *)ctx->object + arg_data->offset;
11615 	/* Output buffer is not necessarily NUL-terminated. */
11616 	memcpy(buf, str, len);
11617 	memset((uint8_t *)buf + len, 0x00, size - len);
11618 	if (ctx->objmask)
11619 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11620 	/* Save address if requested. */
11621 	if (arg_addr->size) {
11622 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11623 		       (void *[]){
11624 			(uint8_t *)ctx->object + arg_data->offset
11625 		       },
11626 		       arg_addr->size);
11627 		if (ctx->objmask)
11628 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11629 			       (void *[]){
11630 				(uint8_t *)ctx->objmask + arg_data->offset
11631 			       },
11632 			       arg_addr->size);
11633 	}
11634 	return len;
11635 error:
11636 	push_args(ctx, arg_addr);
11637 	push_args(ctx, arg_len);
11638 	push_args(ctx, arg_data);
11639 	return -1;
11640 }
11641 
11642 static int
11643 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
11644 {
11645 	const uint8_t *head = dst;
11646 	uint32_t left;
11647 
11648 	if (*size == 0)
11649 		return -1;
11650 
11651 	left = *size;
11652 
11653 	/* Convert chars to bytes */
11654 	while (left) {
11655 		char tmp[3], *end = tmp;
11656 		uint32_t read_lim = left & 1 ? 1 : 2;
11657 
11658 		snprintf(tmp, read_lim + 1, "%s", src);
11659 		*dst = strtoul(tmp, &end, 16);
11660 		if (*end) {
11661 			*dst = 0;
11662 			*size = (uint32_t)(dst - head);
11663 			return -1;
11664 		}
11665 		left -= read_lim;
11666 		src += read_lim;
11667 		dst++;
11668 	}
11669 	*dst = 0;
11670 	*size = (uint32_t)(dst - head);
11671 	return 0;
11672 }
11673 
11674 static int
11675 parse_hex(struct context *ctx, const struct token *token,
11676 		const char *str, unsigned int len,
11677 		void *buf, unsigned int size)
11678 {
11679 	const struct arg *arg_data = pop_args(ctx);
11680 	const struct arg *arg_len = pop_args(ctx);
11681 	const struct arg *arg_addr = pop_args(ctx);
11682 	char tmp[16]; /* Ought to be enough. */
11683 	int ret;
11684 	unsigned int hexlen = len;
11685 	unsigned int length = 256;
11686 	uint8_t hex_tmp[length];
11687 
11688 	/* Arguments are expected. */
11689 	if (!arg_data)
11690 		return -1;
11691 	if (!arg_len) {
11692 		push_args(ctx, arg_data);
11693 		return -1;
11694 	}
11695 	if (!arg_addr) {
11696 		push_args(ctx, arg_len);
11697 		push_args(ctx, arg_data);
11698 		return -1;
11699 	}
11700 	size = arg_data->size;
11701 	/* Bit-mask fill is not supported. */
11702 	if (arg_data->mask)
11703 		goto error;
11704 	if (!ctx->object)
11705 		return len;
11706 
11707 	/* translate bytes string to array. */
11708 	if (str[0] == '0' && ((str[1] == 'x') ||
11709 			(str[1] == 'X'))) {
11710 		str += 2;
11711 		hexlen -= 2;
11712 	}
11713 	if (hexlen > length)
11714 		goto error;
11715 	ret = parse_hex_string(str, hex_tmp, &hexlen);
11716 	if (ret < 0)
11717 		goto error;
11718 	/* Check the converted binary fits into data buffer. */
11719 	if (hexlen > size)
11720 		goto error;
11721 	/* Let parse_int() fill length information first. */
11722 	ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
11723 	if (ret < 0)
11724 		goto error;
11725 	/* Save length if requested. */
11726 	if (arg_len->size) {
11727 		push_args(ctx, arg_len);
11728 		ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11729 		if (ret < 0) {
11730 			pop_args(ctx);
11731 			goto error;
11732 		}
11733 	}
11734 	buf = (uint8_t *)ctx->object + arg_data->offset;
11735 	/* Output buffer is not necessarily NUL-terminated. */
11736 	memcpy(buf, hex_tmp, hexlen);
11737 	memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
11738 	if (ctx->objmask)
11739 		memset((uint8_t *)ctx->objmask + arg_data->offset,
11740 					0xff, hexlen);
11741 	/* Save address if requested. */
11742 	if (arg_addr->size) {
11743 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11744 		       (void *[]){
11745 			(uint8_t *)ctx->object + arg_data->offset
11746 		       },
11747 		       arg_addr->size);
11748 		if (ctx->objmask)
11749 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11750 			       (void *[]){
11751 				(uint8_t *)ctx->objmask + arg_data->offset
11752 			       },
11753 			       arg_addr->size);
11754 	}
11755 	return len;
11756 error:
11757 	push_args(ctx, arg_addr);
11758 	push_args(ctx, arg_len);
11759 	push_args(ctx, arg_data);
11760 	return -1;
11761 
11762 }
11763 
11764 /**
11765  * Parse a zero-ended string.
11766  */
11767 static int
11768 parse_string0(struct context *ctx, const struct token *token __rte_unused,
11769 	     const char *str, unsigned int len,
11770 	     void *buf, unsigned int size)
11771 {
11772 	const struct arg *arg_data = pop_args(ctx);
11773 
11774 	/* Arguments are expected. */
11775 	if (!arg_data)
11776 		return -1;
11777 	size = arg_data->size;
11778 	/* Bit-mask fill is not supported. */
11779 	if (arg_data->mask || size < len + 1)
11780 		goto error;
11781 	if (!ctx->object)
11782 		return len;
11783 	buf = (uint8_t *)ctx->object + arg_data->offset;
11784 	strncpy(buf, str, len);
11785 	if (ctx->objmask)
11786 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11787 	return len;
11788 error:
11789 	push_args(ctx, arg_data);
11790 	return -1;
11791 }
11792 
11793 /**
11794  * Parse a MAC address.
11795  *
11796  * Last argument (ctx->args) is retrieved to determine storage size and
11797  * location.
11798  */
11799 static int
11800 parse_mac_addr(struct context *ctx, const struct token *token,
11801 	       const char *str, unsigned int len,
11802 	       void *buf, unsigned int size)
11803 {
11804 	const struct arg *arg = pop_args(ctx);
11805 	struct rte_ether_addr tmp;
11806 	int ret;
11807 
11808 	(void)token;
11809 	/* Argument is expected. */
11810 	if (!arg)
11811 		return -1;
11812 	size = arg->size;
11813 	/* Bit-mask fill is not supported. */
11814 	if (arg->mask || size != sizeof(tmp))
11815 		goto error;
11816 	/* Only network endian is supported. */
11817 	if (!arg->hton)
11818 		goto error;
11819 	ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
11820 	if (ret < 0 || (unsigned int)ret != len)
11821 		goto error;
11822 	if (!ctx->object)
11823 		return len;
11824 	buf = (uint8_t *)ctx->object + arg->offset;
11825 	memcpy(buf, &tmp, size);
11826 	if (ctx->objmask)
11827 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11828 	return len;
11829 error:
11830 	push_args(ctx, arg);
11831 	return -1;
11832 }
11833 
11834 /**
11835  * Parse an IPv4 address.
11836  *
11837  * Last argument (ctx->args) is retrieved to determine storage size and
11838  * location.
11839  */
11840 static int
11841 parse_ipv4_addr(struct context *ctx, const struct token *token,
11842 		const char *str, unsigned int len,
11843 		void *buf, unsigned int size)
11844 {
11845 	const struct arg *arg = pop_args(ctx);
11846 	char str2[len + 1];
11847 	struct in_addr tmp;
11848 	int ret;
11849 
11850 	/* Argument is expected. */
11851 	if (!arg)
11852 		return -1;
11853 	size = arg->size;
11854 	/* Bit-mask fill is not supported. */
11855 	if (arg->mask || size != sizeof(tmp))
11856 		goto error;
11857 	/* Only network endian is supported. */
11858 	if (!arg->hton)
11859 		goto error;
11860 	memcpy(str2, str, len);
11861 	str2[len] = '\0';
11862 	ret = inet_pton(AF_INET, str2, &tmp);
11863 	if (ret != 1) {
11864 		/* Attempt integer parsing. */
11865 		push_args(ctx, arg);
11866 		return parse_int(ctx, token, str, len, buf, size);
11867 	}
11868 	if (!ctx->object)
11869 		return len;
11870 	buf = (uint8_t *)ctx->object + arg->offset;
11871 	memcpy(buf, &tmp, size);
11872 	if (ctx->objmask)
11873 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11874 	return len;
11875 error:
11876 	push_args(ctx, arg);
11877 	return -1;
11878 }
11879 
11880 /**
11881  * Parse an IPv6 address.
11882  *
11883  * Last argument (ctx->args) is retrieved to determine storage size and
11884  * location.
11885  */
11886 static int
11887 parse_ipv6_addr(struct context *ctx, const struct token *token,
11888 		const char *str, unsigned int len,
11889 		void *buf, unsigned int size)
11890 {
11891 	const struct arg *arg = pop_args(ctx);
11892 	char str2[len + 1];
11893 	struct in6_addr tmp;
11894 	int ret;
11895 
11896 	(void)token;
11897 	/* Argument is expected. */
11898 	if (!arg)
11899 		return -1;
11900 	size = arg->size;
11901 	/* Bit-mask fill is not supported. */
11902 	if (arg->mask || size != sizeof(tmp))
11903 		goto error;
11904 	/* Only network endian is supported. */
11905 	if (!arg->hton)
11906 		goto error;
11907 	memcpy(str2, str, len);
11908 	str2[len] = '\0';
11909 	ret = inet_pton(AF_INET6, str2, &tmp);
11910 	if (ret != 1)
11911 		goto error;
11912 	if (!ctx->object)
11913 		return len;
11914 	buf = (uint8_t *)ctx->object + arg->offset;
11915 	memcpy(buf, &tmp, size);
11916 	if (ctx->objmask)
11917 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11918 	return len;
11919 error:
11920 	push_args(ctx, arg);
11921 	return -1;
11922 }
11923 
11924 /** Boolean values (even indices stand for false). */
11925 static const char *const boolean_name[] = {
11926 	"0", "1",
11927 	"false", "true",
11928 	"no", "yes",
11929 	"N", "Y",
11930 	"off", "on",
11931 	NULL,
11932 };
11933 
11934 /**
11935  * Parse a boolean value.
11936  *
11937  * Last argument (ctx->args) is retrieved to determine storage size and
11938  * location.
11939  */
11940 static int
11941 parse_boolean(struct context *ctx, const struct token *token,
11942 	      const char *str, unsigned int len,
11943 	      void *buf, unsigned int size)
11944 {
11945 	const struct arg *arg = pop_args(ctx);
11946 	unsigned int i;
11947 	int ret;
11948 
11949 	/* Argument is expected. */
11950 	if (!arg)
11951 		return -1;
11952 	for (i = 0; boolean_name[i]; ++i)
11953 		if (!strcmp_partial(boolean_name[i], str, len))
11954 			break;
11955 	/* Process token as integer. */
11956 	if (boolean_name[i])
11957 		str = i & 1 ? "1" : "0";
11958 	push_args(ctx, arg);
11959 	ret = parse_int(ctx, token, str, strlen(str), buf, size);
11960 	return ret > 0 ? (int)len : ret;
11961 }
11962 
11963 /** Parse port and update context. */
11964 static int
11965 parse_port(struct context *ctx, const struct token *token,
11966 	   const char *str, unsigned int len,
11967 	   void *buf, unsigned int size)
11968 {
11969 	struct buffer *out = &(struct buffer){ .port = 0 };
11970 	int ret;
11971 
11972 	if (buf)
11973 		out = buf;
11974 	else {
11975 		ctx->objdata = 0;
11976 		ctx->object = out;
11977 		ctx->objmask = NULL;
11978 		size = sizeof(*out);
11979 	}
11980 	ret = parse_int(ctx, token, str, len, out, size);
11981 	if (ret >= 0)
11982 		ctx->port = out->port;
11983 	if (!buf)
11984 		ctx->object = NULL;
11985 	return ret;
11986 }
11987 
11988 /** Parse tokens for shared indirect actions. */
11989 static int
11990 parse_ia_port(struct context *ctx, const struct token *token,
11991 	      const char *str, unsigned int len,
11992 	      void *buf, unsigned int size)
11993 {
11994 	struct rte_flow_action *action = ctx->object;
11995 	uint32_t id;
11996 	int ret;
11997 
11998 	(void)buf;
11999 	(void)size;
12000 	ctx->objdata = 0;
12001 	ctx->object = &id;
12002 	ctx->objmask = NULL;
12003 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12004 	ctx->object = action;
12005 	if (ret != (int)len)
12006 		return ret;
12007 	/* set indirect action */
12008 	if (action)
12009 		action->conf = (void *)(uintptr_t)id;
12010 	return ret;
12011 }
12012 
12013 static int
12014 parse_ia_id2ptr(struct context *ctx, const struct token *token,
12015 		const char *str, unsigned int len,
12016 		void *buf, unsigned int size)
12017 {
12018 	struct rte_flow_action *action = ctx->object;
12019 	uint32_t id;
12020 	int ret;
12021 
12022 	(void)buf;
12023 	(void)size;
12024 	ctx->objdata = 0;
12025 	ctx->object = &id;
12026 	ctx->objmask = NULL;
12027 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12028 	ctx->object = action;
12029 	if (ret != (int)len)
12030 		return ret;
12031 	/* set indirect action */
12032 	if (action) {
12033 		portid_t port_id = ctx->port;
12034 		if (ctx->prev == INDIRECT_ACTION_PORT)
12035 			port_id = (portid_t)(uintptr_t)action->conf;
12036 		action->conf = port_action_handle_get_by_id(port_id, id);
12037 		ret = (action->conf) ? ret : -1;
12038 	}
12039 	return ret;
12040 }
12041 
12042 static int
12043 parse_indlst_id2ptr(struct context *ctx, const struct token *token,
12044 		    const char *str, unsigned int len,
12045 		    __rte_unused void *buf, __rte_unused unsigned int size)
12046 {
12047 	struct rte_flow_action *action = ctx->object;
12048 	struct rte_flow_action_indirect_list *action_conf;
12049 	const struct indlst_conf *indlst_conf;
12050 	uint32_t id;
12051 	int ret;
12052 
12053 	ctx->objdata = 0;
12054 	ctx->object = &id;
12055 	ctx->objmask = NULL;
12056 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12057 	ctx->object = action;
12058 	if (ret != (int)len)
12059 		return ret;
12060 
12061 	/* set handle and conf */
12062 	if (action) {
12063 		action_conf = (void *)(uintptr_t)action->conf;
12064 		action_conf->conf = NULL;
12065 		switch (ctx->curr) {
12066 		case INDIRECT_LIST_ACTION_ID2PTR_HANDLE:
12067 		action_conf->handle = (typeof(action_conf->handle))
12068 					port_action_handle_get_by_id(ctx->port, id);
12069 			if (!action_conf->handle) {
12070 				printf("no indirect list handle for id %u\n", id);
12071 				return -1;
12072 			}
12073 			break;
12074 		case INDIRECT_LIST_ACTION_ID2PTR_CONF:
12075 			indlst_conf = indirect_action_list_conf_get(id);
12076 			if (!indlst_conf)
12077 				return -1;
12078 			action_conf->conf = (const void **)indlst_conf->conf;
12079 			break;
12080 		default:
12081 			break;
12082 		}
12083 	}
12084 	return ret;
12085 }
12086 
12087 static int
12088 parse_meter_profile_id2ptr(struct context *ctx, const struct token *token,
12089 		const char *str, unsigned int len,
12090 		void *buf, unsigned int size)
12091 {
12092 	struct rte_flow_action *action = ctx->object;
12093 	struct rte_flow_action_meter_mark *meter;
12094 	struct rte_flow_meter_profile *profile = NULL;
12095 	uint32_t id = 0;
12096 	int ret;
12097 
12098 	(void)buf;
12099 	(void)size;
12100 	ctx->objdata = 0;
12101 	ctx->object = &id;
12102 	ctx->objmask = NULL;
12103 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12104 	ctx->object = action;
12105 	if (ret != (int)len)
12106 		return ret;
12107 	/* set meter profile */
12108 	if (action) {
12109 		meter = (struct rte_flow_action_meter_mark *)
12110 			(uintptr_t)(action->conf);
12111 		profile = port_meter_profile_get_by_id(ctx->port, id);
12112 		meter->profile = profile;
12113 		ret = (profile) ? ret : -1;
12114 	}
12115 	return ret;
12116 }
12117 
12118 static int
12119 parse_meter_policy_id2ptr(struct context *ctx, const struct token *token,
12120 		const char *str, unsigned int len,
12121 		void *buf, unsigned int size)
12122 {
12123 	struct rte_flow_action *action = ctx->object;
12124 	struct rte_flow_action_meter_mark *meter;
12125 	struct rte_flow_meter_policy *policy = NULL;
12126 	uint32_t id = 0;
12127 	int ret;
12128 
12129 	(void)buf;
12130 	(void)size;
12131 	ctx->objdata = 0;
12132 	ctx->object = &id;
12133 	ctx->objmask = NULL;
12134 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12135 	ctx->object = action;
12136 	if (ret != (int)len)
12137 		return ret;
12138 	/* set meter policy */
12139 	if (action) {
12140 		meter = (struct rte_flow_action_meter_mark *)
12141 			(uintptr_t)(action->conf);
12142 		policy = port_meter_policy_get_by_id(ctx->port, id);
12143 		meter->policy = policy;
12144 		ret = (policy) ? ret : -1;
12145 	}
12146 	return ret;
12147 }
12148 
12149 /** Parse set command, initialize output buffer for subsequent tokens. */
12150 static int
12151 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
12152 			  const char *str, unsigned int len,
12153 			  void *buf, unsigned int size)
12154 {
12155 	struct buffer *out = buf;
12156 
12157 	/* Token name must match. */
12158 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12159 		return -1;
12160 	/* Nothing else to do if there is no buffer. */
12161 	if (!out)
12162 		return len;
12163 	/* Make sure buffer is large enough. */
12164 	if (size < sizeof(*out))
12165 		return -1;
12166 	ctx->objdata = 0;
12167 	ctx->objmask = NULL;
12168 	ctx->object = out;
12169 	if (!out->command)
12170 		return -1;
12171 	out->command = ctx->curr;
12172 	/* For encap/decap we need is pattern */
12173 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12174 						       sizeof(double));
12175 	return len;
12176 }
12177 
12178 /** Parse set command, initialize output buffer for subsequent tokens. */
12179 static int
12180 parse_set_sample_action(struct context *ctx, const struct token *token,
12181 			  const char *str, unsigned int len,
12182 			  void *buf, unsigned int size)
12183 {
12184 	struct buffer *out = buf;
12185 
12186 	/* Token name must match. */
12187 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12188 		return -1;
12189 	/* Nothing else to do if there is no buffer. */
12190 	if (!out)
12191 		return len;
12192 	/* Make sure buffer is large enough. */
12193 	if (size < sizeof(*out))
12194 		return -1;
12195 	ctx->objdata = 0;
12196 	ctx->objmask = NULL;
12197 	ctx->object = out;
12198 	if (!out->command)
12199 		return -1;
12200 	out->command = ctx->curr;
12201 	/* For sampler we need is actions */
12202 	out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12203 						       sizeof(double));
12204 	return len;
12205 }
12206 
12207 /** Parse set command, initialize output buffer for subsequent tokens. */
12208 static int
12209 parse_set_ipv6_ext_action(struct context *ctx, const struct token *token,
12210 			  const char *str, unsigned int len,
12211 			  void *buf, unsigned int size)
12212 {
12213 	struct buffer *out = buf;
12214 
12215 	/* Token name must match. */
12216 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12217 		return -1;
12218 	/* Nothing else to do if there is no buffer. */
12219 	if (!out)
12220 		return len;
12221 	/* Make sure buffer is large enough. */
12222 	if (size < sizeof(*out))
12223 		return -1;
12224 	ctx->objdata = 0;
12225 	ctx->objmask = NULL;
12226 	ctx->object = out;
12227 	if (!out->command)
12228 		return -1;
12229 	out->command = ctx->curr;
12230 	/* For ipv6_ext_push/remove we need is pattern */
12231 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12232 						       sizeof(double));
12233 	return len;
12234 }
12235 
12236 /**
12237  * Parse set raw_encap/raw_decap command,
12238  * initialize output buffer for subsequent tokens.
12239  */
12240 static int
12241 parse_set_init(struct context *ctx, const struct token *token,
12242 	       const char *str, unsigned int len,
12243 	       void *buf, unsigned int size)
12244 {
12245 	struct buffer *out = buf;
12246 
12247 	/* Token name must match. */
12248 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12249 		return -1;
12250 	/* Nothing else to do if there is no buffer. */
12251 	if (!out)
12252 		return len;
12253 	/* Make sure buffer is large enough. */
12254 	if (size < sizeof(*out))
12255 		return -1;
12256 	/* Initialize buffer. */
12257 	memset(out, 0x00, sizeof(*out));
12258 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
12259 	ctx->objdata = 0;
12260 	ctx->object = out;
12261 	ctx->objmask = NULL;
12262 	if (!out->command) {
12263 		if (ctx->curr != SET)
12264 			return -1;
12265 		if (sizeof(*out) > size)
12266 			return -1;
12267 		out->command = ctx->curr;
12268 		out->args.vc.data = (uint8_t *)out + size;
12269 		ctx->object  = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12270 						       sizeof(double));
12271 	}
12272 	return len;
12273 }
12274 
12275 /*
12276  * Replace testpmd handles in a flex flow item with real values.
12277  */
12278 static int
12279 parse_flex_handle(struct context *ctx, const struct token *token,
12280 		  const char *str, unsigned int len,
12281 		  void *buf, unsigned int size)
12282 {
12283 	struct rte_flow_item_flex *spec, *mask;
12284 	const struct rte_flow_item_flex *src_spec, *src_mask;
12285 	const struct arg *arg = pop_args(ctx);
12286 	uint32_t offset;
12287 	uint16_t handle;
12288 	int ret;
12289 
12290 	if (!arg) {
12291 		printf("Bad environment\n");
12292 		return -1;
12293 	}
12294 	offset = arg->offset;
12295 	push_args(ctx, arg);
12296 	ret = parse_int(ctx, token, str, len, buf, size);
12297 	if (ret <= 0 || !ctx->object)
12298 		return ret;
12299 	if (ctx->port >= RTE_MAX_ETHPORTS) {
12300 		printf("Bad port\n");
12301 		return -1;
12302 	}
12303 	if (offset == offsetof(struct rte_flow_item_flex, handle)) {
12304 		const struct flex_item *fp;
12305 		spec = ctx->object;
12306 		handle = (uint16_t)(uintptr_t)spec->handle;
12307 		if (handle >= FLEX_MAX_PARSERS_NUM) {
12308 			printf("Bad flex item handle\n");
12309 			return -1;
12310 		}
12311 		fp = flex_items[ctx->port][handle];
12312 		if (!fp) {
12313 			printf("Bad flex item handle\n");
12314 			return -1;
12315 		}
12316 		spec->handle = fp->flex_handle;
12317 		mask = spec + 2; /* spec, last, mask */
12318 		mask->handle = fp->flex_handle;
12319 	} else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
12320 		handle = (uint16_t)(uintptr_t)
12321 			((struct rte_flow_item_flex *)ctx->object)->pattern;
12322 		if (handle >= FLEX_MAX_PATTERNS_NUM) {
12323 			printf("Bad pattern handle\n");
12324 			return -1;
12325 		}
12326 		src_spec = &flex_patterns[handle].spec;
12327 		src_mask = &flex_patterns[handle].mask;
12328 		spec = ctx->object;
12329 		mask = spec + 2; /* spec, last, mask */
12330 		/* fill flow rule spec and mask parameters */
12331 		spec->length = src_spec->length;
12332 		spec->pattern = src_spec->pattern;
12333 		mask->length = src_mask->length;
12334 		mask->pattern = src_mask->pattern;
12335 	} else {
12336 		printf("Bad arguments - unknown flex item offset\n");
12337 		return -1;
12338 	}
12339 	return ret;
12340 }
12341 
12342 /** Parse Meter color name */
12343 static int
12344 parse_meter_color(struct context *ctx, const struct token *token,
12345 		  const char *str, unsigned int len, void *buf,
12346 		  unsigned int size)
12347 {
12348 	struct rte_flow_item_meter_color *meter_color;
12349 	unsigned int i;
12350 
12351 	(void)token;
12352 	(void)buf;
12353 	(void)size;
12354 	for (i = 0; meter_colors[i]; ++i)
12355 		if (!strcmp_partial(meter_colors[i], str, len))
12356 			break;
12357 	if (!meter_colors[i])
12358 		return -1;
12359 	if (!ctx->object)
12360 		return len;
12361 	meter_color = ctx->object;
12362 	meter_color->color = (enum rte_color)i;
12363 	return len;
12364 }
12365 
12366 /** Parse Insertion Table Type name */
12367 static int
12368 parse_insertion_table_type(struct context *ctx, const struct token *token,
12369 			   const char *str, unsigned int len, void *buf,
12370 			   unsigned int size)
12371 {
12372 	const struct arg *arg = pop_args(ctx);
12373 	unsigned int i;
12374 	char tmp[2];
12375 	int ret;
12376 
12377 	(void)size;
12378 	/* Argument is expected. */
12379 	if (!arg)
12380 		return -1;
12381 	for (i = 0; table_insertion_types[i]; ++i)
12382 		if (!strcmp_partial(table_insertion_types[i], str, len))
12383 			break;
12384 	if (!table_insertion_types[i])
12385 		return -1;
12386 	push_args(ctx, arg);
12387 	snprintf(tmp, sizeof(tmp), "%u", i);
12388 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12389 	return ret > 0 ? (int)len : ret;
12390 }
12391 
12392 /** Parse Hash Calculation Table Type name */
12393 static int
12394 parse_hash_table_type(struct context *ctx, const struct token *token,
12395 		      const char *str, unsigned int len, void *buf,
12396 		      unsigned int size)
12397 {
12398 	const struct arg *arg = pop_args(ctx);
12399 	unsigned int i;
12400 	char tmp[2];
12401 	int ret;
12402 
12403 	(void)size;
12404 	/* Argument is expected. */
12405 	if (!arg)
12406 		return -1;
12407 	for (i = 0; table_hash_funcs[i]; ++i)
12408 		if (!strcmp_partial(table_hash_funcs[i], str, len))
12409 			break;
12410 	if (!table_hash_funcs[i])
12411 		return -1;
12412 	push_args(ctx, arg);
12413 	snprintf(tmp, sizeof(tmp), "%u", i);
12414 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12415 	return ret > 0 ? (int)len : ret;
12416 }
12417 
12418 static int
12419 parse_name_to_index(struct context *ctx, const struct token *token,
12420 		    const char *str, unsigned int len, void *buf,
12421 		    unsigned int size,
12422 		    const char *const names[], size_t names_size, uint32_t *dst)
12423 {
12424 	int ret;
12425 	uint32_t i;
12426 
12427 	RTE_SET_USED(token);
12428 	RTE_SET_USED(buf);
12429 	RTE_SET_USED(size);
12430 	if (!ctx->object)
12431 		return len;
12432 	for (i = 0; i < names_size; i++) {
12433 		if (!names[i])
12434 			continue;
12435 		ret = strcmp_partial(names[i], str,
12436 				     RTE_MIN(len, strlen(names[i])));
12437 		if (!ret) {
12438 			*dst = i;
12439 			return len;
12440 		}
12441 	}
12442 	return -1;
12443 }
12444 
12445 static const char *const quota_mode_names[] = {
12446 	NULL,
12447 	[RTE_FLOW_QUOTA_MODE_PACKET] = "packet",
12448 	[RTE_FLOW_QUOTA_MODE_L2] = "l2",
12449 	[RTE_FLOW_QUOTA_MODE_L3] = "l3"
12450 };
12451 
12452 static const char *const quota_state_names[] = {
12453 	[RTE_FLOW_QUOTA_STATE_PASS] = "pass",
12454 	[RTE_FLOW_QUOTA_STATE_BLOCK] = "block"
12455 };
12456 
12457 static const char *const quota_update_names[] = {
12458 	[RTE_FLOW_UPDATE_QUOTA_SET] = "set",
12459 	[RTE_FLOW_UPDATE_QUOTA_ADD] = "add"
12460 };
12461 
12462 static const char *const query_update_mode_names[] = {
12463 	[RTE_FLOW_QU_QUERY_FIRST] = "query_first",
12464 	[RTE_FLOW_QU_UPDATE_FIRST] = "update_first"
12465 };
12466 
12467 static int
12468 parse_quota_state_name(struct context *ctx, const struct token *token,
12469 		       const char *str, unsigned int len, void *buf,
12470 		       unsigned int size)
12471 {
12472 	struct rte_flow_item_quota *quota = ctx->object;
12473 
12474 	return parse_name_to_index(ctx, token, str, len, buf, size,
12475 				   quota_state_names,
12476 				   RTE_DIM(quota_state_names),
12477 				   (uint32_t *)&quota->state);
12478 }
12479 
12480 static int
12481 parse_quota_mode_name(struct context *ctx, const struct token *token,
12482 		      const char *str, unsigned int len, void *buf,
12483 		      unsigned int size)
12484 {
12485 	struct rte_flow_action_quota *quota = ctx->object;
12486 
12487 	return parse_name_to_index(ctx, token, str, len, buf, size,
12488 				   quota_mode_names,
12489 				   RTE_DIM(quota_mode_names),
12490 				   (uint32_t *)&quota->mode);
12491 }
12492 
12493 static int
12494 parse_quota_update_name(struct context *ctx, const struct token *token,
12495 			const char *str, unsigned int len, void *buf,
12496 			unsigned int size)
12497 {
12498 	struct rte_flow_update_quota *update = ctx->object;
12499 
12500 	return parse_name_to_index(ctx, token, str, len, buf, size,
12501 				   quota_update_names,
12502 				   RTE_DIM(quota_update_names),
12503 				   (uint32_t *)&update->op);
12504 }
12505 
12506 static int
12507 parse_qu_mode_name(struct context *ctx, const struct token *token,
12508 		   const char *str, unsigned int len, void *buf,
12509 		   unsigned int size)
12510 {
12511 	struct buffer *out = ctx->object;
12512 
12513 	return parse_name_to_index(ctx, token, str, len, buf, size,
12514 				   query_update_mode_names,
12515 				   RTE_DIM(query_update_mode_names),
12516 				   (uint32_t *)&out->args.ia.qu_mode);
12517 }
12518 
12519 /** No completion. */
12520 static int
12521 comp_none(struct context *ctx, const struct token *token,
12522 	  unsigned int ent, char *buf, unsigned int size)
12523 {
12524 	(void)ctx;
12525 	(void)token;
12526 	(void)ent;
12527 	(void)buf;
12528 	(void)size;
12529 	return 0;
12530 }
12531 
12532 /** Complete boolean values. */
12533 static int
12534 comp_boolean(struct context *ctx, const struct token *token,
12535 	     unsigned int ent, char *buf, unsigned int size)
12536 {
12537 	unsigned int i;
12538 
12539 	(void)ctx;
12540 	(void)token;
12541 	for (i = 0; boolean_name[i]; ++i)
12542 		if (buf && i == ent)
12543 			return strlcpy(buf, boolean_name[i], size);
12544 	if (buf)
12545 		return -1;
12546 	return i;
12547 }
12548 
12549 /** Complete action names. */
12550 static int
12551 comp_action(struct context *ctx, const struct token *token,
12552 	    unsigned int ent, char *buf, unsigned int size)
12553 {
12554 	unsigned int i;
12555 
12556 	(void)ctx;
12557 	(void)token;
12558 	for (i = 0; next_action[i]; ++i)
12559 		if (buf && i == ent)
12560 			return strlcpy(buf, token_list[next_action[i]].name,
12561 				       size);
12562 	if (buf)
12563 		return -1;
12564 	return i;
12565 }
12566 
12567 /** Complete available ports. */
12568 static int
12569 comp_port(struct context *ctx, const struct token *token,
12570 	  unsigned int ent, char *buf, unsigned int size)
12571 {
12572 	unsigned int i = 0;
12573 	portid_t p;
12574 
12575 	(void)ctx;
12576 	(void)token;
12577 	RTE_ETH_FOREACH_DEV(p) {
12578 		if (buf && i == ent)
12579 			return snprintf(buf, size, "%u", p);
12580 		++i;
12581 	}
12582 	if (buf)
12583 		return -1;
12584 	return i;
12585 }
12586 
12587 /** Complete available rule IDs. */
12588 static int
12589 comp_rule_id(struct context *ctx, const struct token *token,
12590 	     unsigned int ent, char *buf, unsigned int size)
12591 {
12592 	unsigned int i = 0;
12593 	struct rte_port *port;
12594 	struct port_flow *pf;
12595 
12596 	(void)token;
12597 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12598 	    ctx->port == (portid_t)RTE_PORT_ALL)
12599 		return -1;
12600 	port = &ports[ctx->port];
12601 	for (pf = port->flow_list; pf != NULL; pf = pf->next) {
12602 		if (buf && i == ent)
12603 			return snprintf(buf, size, "%"PRIu64, pf->id);
12604 		++i;
12605 	}
12606 	if (buf)
12607 		return -1;
12608 	return i;
12609 }
12610 
12611 /** Complete operation for compare match item. */
12612 static int
12613 comp_set_compare_op(struct context *ctx, const struct token *token,
12614 		    unsigned int ent, char *buf, unsigned int size)
12615 {
12616 	RTE_SET_USED(ctx);
12617 	RTE_SET_USED(token);
12618 	if (!buf)
12619 		return RTE_DIM(compare_ops);
12620 	if (ent < RTE_DIM(compare_ops) - 1)
12621 		return strlcpy(buf, compare_ops[ent], size);
12622 	return -1;
12623 }
12624 
12625 /** Complete field id for compare match item. */
12626 static int
12627 comp_set_compare_field_id(struct context *ctx, const struct token *token,
12628 			  unsigned int ent, char *buf, unsigned int size)
12629 {
12630 	const char *name;
12631 
12632 	RTE_SET_USED(token);
12633 	if (!buf)
12634 		return RTE_DIM(flow_field_ids);
12635 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12636 		return -1;
12637 	name = flow_field_ids[ent];
12638 	if (ctx->curr == ITEM_COMPARE_FIELD_B_TYPE ||
12639 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12640 		return strlcpy(buf, name, size);
12641 	return -1;
12642 }
12643 
12644 /** Complete type field for RSS action. */
12645 static int
12646 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
12647 			unsigned int ent, char *buf, unsigned int size)
12648 {
12649 	unsigned int i;
12650 
12651 	(void)ctx;
12652 	(void)token;
12653 	for (i = 0; rss_type_table[i].str; ++i)
12654 		;
12655 	if (!buf)
12656 		return i + 1;
12657 	if (ent < i)
12658 		return strlcpy(buf, rss_type_table[ent].str, size);
12659 	if (ent == i)
12660 		return snprintf(buf, size, "end");
12661 	return -1;
12662 }
12663 
12664 /** Complete queue field for RSS action. */
12665 static int
12666 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
12667 			 unsigned int ent, char *buf, unsigned int size)
12668 {
12669 	(void)ctx;
12670 	(void)token;
12671 	if (!buf)
12672 		return nb_rxq + 1;
12673 	if (ent < nb_rxq)
12674 		return snprintf(buf, size, "%u", ent);
12675 	if (ent == nb_rxq)
12676 		return snprintf(buf, size, "end");
12677 	return -1;
12678 }
12679 
12680 /** Complete index number for set raw_encap/raw_decap commands. */
12681 static int
12682 comp_set_raw_index(struct context *ctx, const struct token *token,
12683 		   unsigned int ent, char *buf, unsigned int size)
12684 {
12685 	uint16_t idx = 0;
12686 	uint16_t nb = 0;
12687 
12688 	RTE_SET_USED(ctx);
12689 	RTE_SET_USED(token);
12690 	for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
12691 		if (buf && idx == ent)
12692 			return snprintf(buf, size, "%u", idx);
12693 		++nb;
12694 	}
12695 	return nb;
12696 }
12697 
12698 /** Complete index number for set raw_ipv6_ext_push/ipv6_ext_remove commands. */
12699 static int
12700 comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
12701 			unsigned int ent, char *buf, unsigned int size)
12702 {
12703 	uint16_t idx = 0;
12704 	uint16_t nb = 0;
12705 
12706 	RTE_SET_USED(ctx);
12707 	RTE_SET_USED(token);
12708 	for (idx = 0; idx < IPV6_EXT_PUSH_CONFS_MAX_NUM; ++idx) {
12709 		if (buf && idx == ent)
12710 			return snprintf(buf, size, "%u", idx);
12711 		++nb;
12712 	}
12713 	return nb;
12714 }
12715 
12716 /** Complete index number for set raw_encap/raw_decap commands. */
12717 static int
12718 comp_set_sample_index(struct context *ctx, const struct token *token,
12719 		   unsigned int ent, char *buf, unsigned int size)
12720 {
12721 	uint16_t idx = 0;
12722 	uint16_t nb = 0;
12723 
12724 	RTE_SET_USED(ctx);
12725 	RTE_SET_USED(token);
12726 	for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
12727 		if (buf && idx == ent)
12728 			return snprintf(buf, size, "%u", idx);
12729 		++nb;
12730 	}
12731 	return nb;
12732 }
12733 
12734 /** Complete operation for modify_field command. */
12735 static int
12736 comp_set_modify_field_op(struct context *ctx, const struct token *token,
12737 		   unsigned int ent, char *buf, unsigned int size)
12738 {
12739 	RTE_SET_USED(ctx);
12740 	RTE_SET_USED(token);
12741 	if (!buf)
12742 		return RTE_DIM(modify_field_ops);
12743 	if (ent < RTE_DIM(modify_field_ops) - 1)
12744 		return strlcpy(buf, modify_field_ops[ent], size);
12745 	return -1;
12746 }
12747 
12748 /** Complete field id for modify_field command. */
12749 static int
12750 comp_set_modify_field_id(struct context *ctx, const struct token *token,
12751 		   unsigned int ent, char *buf, unsigned int size)
12752 {
12753 	const char *name;
12754 
12755 	RTE_SET_USED(token);
12756 	if (!buf)
12757 		return RTE_DIM(flow_field_ids);
12758 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12759 		return -1;
12760 	name = flow_field_ids[ent];
12761 	if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
12762 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12763 		return strlcpy(buf, name, size);
12764 	return -1;
12765 }
12766 
12767 /** Complete available pattern template IDs. */
12768 static int
12769 comp_pattern_template_id(struct context *ctx, const struct token *token,
12770 			 unsigned int ent, char *buf, unsigned int size)
12771 {
12772 	unsigned int i = 0;
12773 	struct rte_port *port;
12774 	struct port_template *pt;
12775 
12776 	(void)token;
12777 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12778 	    ctx->port == (portid_t)RTE_PORT_ALL)
12779 		return -1;
12780 	port = &ports[ctx->port];
12781 	for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) {
12782 		if (buf && i == ent)
12783 			return snprintf(buf, size, "%u", pt->id);
12784 		++i;
12785 	}
12786 	if (buf)
12787 		return -1;
12788 	return i;
12789 }
12790 
12791 /** Complete available actions template IDs. */
12792 static int
12793 comp_actions_template_id(struct context *ctx, const struct token *token,
12794 			 unsigned int ent, char *buf, unsigned int size)
12795 {
12796 	unsigned int i = 0;
12797 	struct rte_port *port;
12798 	struct port_template *pt;
12799 
12800 	(void)token;
12801 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12802 	    ctx->port == (portid_t)RTE_PORT_ALL)
12803 		return -1;
12804 	port = &ports[ctx->port];
12805 	for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) {
12806 		if (buf && i == ent)
12807 			return snprintf(buf, size, "%u", pt->id);
12808 		++i;
12809 	}
12810 	if (buf)
12811 		return -1;
12812 	return i;
12813 }
12814 
12815 /** Complete available table IDs. */
12816 static int
12817 comp_table_id(struct context *ctx, const struct token *token,
12818 	      unsigned int ent, char *buf, unsigned int size)
12819 {
12820 	unsigned int i = 0;
12821 	struct rte_port *port;
12822 	struct port_table *pt;
12823 
12824 	(void)token;
12825 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12826 	    ctx->port == (portid_t)RTE_PORT_ALL)
12827 		return -1;
12828 	port = &ports[ctx->port];
12829 	for (pt = port->table_list; pt != NULL; pt = pt->next) {
12830 		if (buf && i == ent)
12831 			return snprintf(buf, size, "%u", pt->id);
12832 		++i;
12833 	}
12834 	if (buf)
12835 		return -1;
12836 	return i;
12837 }
12838 
12839 /** Complete available queue IDs. */
12840 static int
12841 comp_queue_id(struct context *ctx, const struct token *token,
12842 	      unsigned int ent, char *buf, unsigned int size)
12843 {
12844 	unsigned int i = 0;
12845 	struct rte_port *port;
12846 
12847 	(void)token;
12848 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12849 	    ctx->port == (portid_t)RTE_PORT_ALL)
12850 		return -1;
12851 	port = &ports[ctx->port];
12852 	for (i = 0; i < port->queue_nb; i++) {
12853 		if (buf && i == ent)
12854 			return snprintf(buf, size, "%u", i);
12855 	}
12856 	if (buf)
12857 		return -1;
12858 	return i;
12859 }
12860 
12861 static int
12862 comp_names_to_index(struct context *ctx, const struct token *token,
12863 		    unsigned int ent, char *buf, unsigned int size,
12864 		    const char *const names[], size_t names_size)
12865 {
12866 	RTE_SET_USED(ctx);
12867 	RTE_SET_USED(token);
12868 	if (!buf)
12869 		return names_size;
12870 	if (names[ent] && ent < names_size)
12871 		return rte_strscpy(buf, names[ent], size);
12872 	return -1;
12873 
12874 }
12875 
12876 /** Complete available Meter colors. */
12877 static int
12878 comp_meter_color(struct context *ctx, const struct token *token,
12879 		 unsigned int ent, char *buf, unsigned int size)
12880 {
12881 	RTE_SET_USED(ctx);
12882 	RTE_SET_USED(token);
12883 	if (!buf)
12884 		return RTE_DIM(meter_colors);
12885 	if (ent < RTE_DIM(meter_colors) - 1)
12886 		return strlcpy(buf, meter_colors[ent], size);
12887 	return -1;
12888 }
12889 
12890 /** Complete available Insertion Table types. */
12891 static int
12892 comp_insertion_table_type(struct context *ctx, const struct token *token,
12893 			  unsigned int ent, char *buf, unsigned int size)
12894 {
12895 	RTE_SET_USED(ctx);
12896 	RTE_SET_USED(token);
12897 	if (!buf)
12898 		return RTE_DIM(table_insertion_types);
12899 	if (ent < RTE_DIM(table_insertion_types) - 1)
12900 		return rte_strscpy(buf, table_insertion_types[ent], size);
12901 	return -1;
12902 }
12903 
12904 /** Complete available Hash Calculation Table types. */
12905 static int
12906 comp_hash_table_type(struct context *ctx, const struct token *token,
12907 		     unsigned int ent, char *buf, unsigned int size)
12908 {
12909 	RTE_SET_USED(ctx);
12910 	RTE_SET_USED(token);
12911 	if (!buf)
12912 		return RTE_DIM(table_hash_funcs);
12913 	if (ent < RTE_DIM(table_hash_funcs) - 1)
12914 		return rte_strscpy(buf, table_hash_funcs[ent], size);
12915 	return -1;
12916 }
12917 
12918 static int
12919 comp_quota_state_name(struct context *ctx, const struct token *token,
12920 		      unsigned int ent, char *buf, unsigned int size)
12921 {
12922 	return comp_names_to_index(ctx, token, ent, buf, size,
12923 				   quota_state_names,
12924 				   RTE_DIM(quota_state_names));
12925 }
12926 
12927 static int
12928 comp_quota_mode_name(struct context *ctx, const struct token *token,
12929 		     unsigned int ent, char *buf, unsigned int size)
12930 {
12931 	return comp_names_to_index(ctx, token, ent, buf, size,
12932 				   quota_mode_names,
12933 				   RTE_DIM(quota_mode_names));
12934 }
12935 
12936 static int
12937 comp_quota_update_name(struct context *ctx, const struct token *token,
12938 		       unsigned int ent, char *buf, unsigned int size)
12939 {
12940 	return comp_names_to_index(ctx, token, ent, buf, size,
12941 				   quota_update_names,
12942 				   RTE_DIM(quota_update_names));
12943 }
12944 
12945 static int
12946 comp_qu_mode_name(struct context *ctx, const struct token *token,
12947 		  unsigned int ent, char *buf, unsigned int size)
12948 {
12949 	return comp_names_to_index(ctx, token, ent, buf, size,
12950 				   query_update_mode_names,
12951 				   RTE_DIM(query_update_mode_names));
12952 }
12953 
12954 /** Internal context. */
12955 static struct context cmd_flow_context;
12956 
12957 /** Global parser instance (cmdline API). */
12958 cmdline_parse_inst_t cmd_flow;
12959 cmdline_parse_inst_t cmd_set_raw;
12960 
12961 /** Initialize context. */
12962 static void
12963 cmd_flow_context_init(struct context *ctx)
12964 {
12965 	/* A full memset() is not necessary. */
12966 	ctx->curr = ZERO;
12967 	ctx->prev = ZERO;
12968 	ctx->next_num = 0;
12969 	ctx->args_num = 0;
12970 	ctx->eol = 0;
12971 	ctx->last = 0;
12972 	ctx->port = 0;
12973 	ctx->objdata = 0;
12974 	ctx->object = NULL;
12975 	ctx->objmask = NULL;
12976 }
12977 
12978 /** Parse a token (cmdline API). */
12979 static int
12980 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
12981 	       unsigned int size)
12982 {
12983 	struct context *ctx = &cmd_flow_context;
12984 	const struct token *token;
12985 	const enum index *list;
12986 	int len;
12987 	int i;
12988 
12989 	(void)hdr;
12990 	token = &token_list[ctx->curr];
12991 	/* Check argument length. */
12992 	ctx->eol = 0;
12993 	ctx->last = 1;
12994 	for (len = 0; src[len]; ++len)
12995 		if (src[len] == '#' || isspace(src[len]))
12996 			break;
12997 	if (!len)
12998 		return -1;
12999 	/* Last argument and EOL detection. */
13000 	for (i = len; src[i]; ++i)
13001 		if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
13002 			break;
13003 		else if (!isspace(src[i])) {
13004 			ctx->last = 0;
13005 			break;
13006 		}
13007 	for (; src[i]; ++i)
13008 		if (src[i] == '\r' || src[i] == '\n') {
13009 			ctx->eol = 1;
13010 			break;
13011 		}
13012 	/* Initialize context if necessary. */
13013 	if (!ctx->next_num) {
13014 		if (!token->next)
13015 			return 0;
13016 		ctx->next[ctx->next_num++] = token->next[0];
13017 	}
13018 	/* Process argument through candidates. */
13019 	ctx->prev = ctx->curr;
13020 	list = ctx->next[ctx->next_num - 1];
13021 	for (i = 0; list[i]; ++i) {
13022 		const struct token *next = &token_list[list[i]];
13023 		int tmp;
13024 
13025 		ctx->curr = list[i];
13026 		if (next->call)
13027 			tmp = next->call(ctx, next, src, len, result, size);
13028 		else
13029 			tmp = parse_default(ctx, next, src, len, result, size);
13030 		if (tmp == -1 || tmp != len)
13031 			continue;
13032 		token = next;
13033 		break;
13034 	}
13035 	if (!list[i])
13036 		return -1;
13037 	--ctx->next_num;
13038 	/* Push subsequent tokens if any. */
13039 	if (token->next)
13040 		for (i = 0; token->next[i]; ++i) {
13041 			if (ctx->next_num == RTE_DIM(ctx->next))
13042 				return -1;
13043 			ctx->next[ctx->next_num++] = token->next[i];
13044 		}
13045 	/* Push arguments if any. */
13046 	if (token->args)
13047 		for (i = 0; token->args[i]; ++i) {
13048 			if (ctx->args_num == RTE_DIM(ctx->args))
13049 				return -1;
13050 			ctx->args[ctx->args_num++] = token->args[i];
13051 		}
13052 	return len;
13053 }
13054 
13055 int
13056 flow_parse(const char *src, void *result, unsigned int size,
13057 	   struct rte_flow_attr **attr,
13058 	   struct rte_flow_item **pattern, struct rte_flow_action **actions)
13059 {
13060 	int ret;
13061 	struct context saved_flow_ctx = cmd_flow_context;
13062 
13063 	cmd_flow_context_init(&cmd_flow_context);
13064 	do {
13065 		ret = cmd_flow_parse(NULL, src, result, size);
13066 		if (ret > 0) {
13067 			src += ret;
13068 			while (isspace(*src))
13069 				src++;
13070 		}
13071 	} while (ret > 0 && strlen(src));
13072 	cmd_flow_context = saved_flow_ctx;
13073 	*attr = &((struct buffer *)result)->args.vc.attr;
13074 	*pattern = ((struct buffer *)result)->args.vc.pattern;
13075 	*actions = ((struct buffer *)result)->args.vc.actions;
13076 	return (ret >= 0 && !strlen(src)) ? 0 : -1;
13077 }
13078 
13079 /** Return number of completion entries (cmdline API). */
13080 static int
13081 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
13082 {
13083 	struct context *ctx = &cmd_flow_context;
13084 	const struct token *token = &token_list[ctx->curr];
13085 	const enum index *list;
13086 	int i;
13087 
13088 	(void)hdr;
13089 	/* Count number of tokens in current list. */
13090 	if (ctx->next_num)
13091 		list = ctx->next[ctx->next_num - 1];
13092 	else
13093 		list = token->next[0];
13094 	for (i = 0; list[i]; ++i)
13095 		;
13096 	if (!i)
13097 		return 0;
13098 	/*
13099 	 * If there is a single token, use its completion callback, otherwise
13100 	 * return the number of entries.
13101 	 */
13102 	token = &token_list[list[0]];
13103 	if (i == 1 && token->comp) {
13104 		/* Save index for cmd_flow_get_help(). */
13105 		ctx->prev = list[0];
13106 		return token->comp(ctx, token, 0, NULL, 0);
13107 	}
13108 	return i;
13109 }
13110 
13111 /** Return a completion entry (cmdline API). */
13112 static int
13113 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
13114 			  char *dst, unsigned int size)
13115 {
13116 	struct context *ctx = &cmd_flow_context;
13117 	const struct token *token = &token_list[ctx->curr];
13118 	const enum index *list;
13119 	int i;
13120 
13121 	(void)hdr;
13122 	/* Count number of tokens in current list. */
13123 	if (ctx->next_num)
13124 		list = ctx->next[ctx->next_num - 1];
13125 	else
13126 		list = token->next[0];
13127 	for (i = 0; list[i]; ++i)
13128 		;
13129 	if (!i)
13130 		return -1;
13131 	/* If there is a single token, use its completion callback. */
13132 	token = &token_list[list[0]];
13133 	if (i == 1 && token->comp) {
13134 		/* Save index for cmd_flow_get_help(). */
13135 		ctx->prev = list[0];
13136 		return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
13137 	}
13138 	/* Otherwise make sure the index is valid and use defaults. */
13139 	if (index >= i)
13140 		return -1;
13141 	token = &token_list[list[index]];
13142 	strlcpy(dst, token->name, size);
13143 	/* Save index for cmd_flow_get_help(). */
13144 	ctx->prev = list[index];
13145 	return 0;
13146 }
13147 
13148 /** Populate help strings for current token (cmdline API). */
13149 static int
13150 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
13151 {
13152 	struct context *ctx = &cmd_flow_context;
13153 	const struct token *token = &token_list[ctx->prev];
13154 
13155 	(void)hdr;
13156 	if (!size)
13157 		return -1;
13158 	/* Set token type and update global help with details. */
13159 	strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
13160 	if (token->help)
13161 		cmd_flow.help_str = token->help;
13162 	else
13163 		cmd_flow.help_str = token->name;
13164 	return 0;
13165 }
13166 
13167 /** Token definition template (cmdline API). */
13168 static struct cmdline_token_hdr cmd_flow_token_hdr = {
13169 	.ops = &(struct cmdline_token_ops){
13170 		.parse = cmd_flow_parse,
13171 		.complete_get_nb = cmd_flow_complete_get_nb,
13172 		.complete_get_elt = cmd_flow_complete_get_elt,
13173 		.get_help = cmd_flow_get_help,
13174 	},
13175 	.offset = 0,
13176 };
13177 
13178 /** Populate the next dynamic token. */
13179 static void
13180 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
13181 	     cmdline_parse_token_hdr_t **hdr_inst)
13182 {
13183 	struct context *ctx = &cmd_flow_context;
13184 
13185 	/* Always reinitialize context before requesting the first token. */
13186 	if (!(hdr_inst - cmd_flow.tokens))
13187 		cmd_flow_context_init(ctx);
13188 	/* Return NULL when no more tokens are expected. */
13189 	if (!ctx->next_num && ctx->curr) {
13190 		*hdr = NULL;
13191 		return;
13192 	}
13193 	/* Determine if command should end here. */
13194 	if (ctx->eol && ctx->last && ctx->next_num) {
13195 		const enum index *list = ctx->next[ctx->next_num - 1];
13196 		int i;
13197 
13198 		for (i = 0; list[i]; ++i) {
13199 			if (list[i] != END)
13200 				continue;
13201 			*hdr = NULL;
13202 			return;
13203 		}
13204 	}
13205 	*hdr = &cmd_flow_token_hdr;
13206 }
13207 
13208 static SLIST_HEAD(, indlst_conf) indlst_conf_head =
13209 	SLIST_HEAD_INITIALIZER();
13210 
13211 static void
13212 indirect_action_flow_conf_create(const struct buffer *in)
13213 {
13214 	int len, ret;
13215 	uint32_t i;
13216 	struct indlst_conf *indlst_conf = NULL;
13217 	size_t base = RTE_ALIGN(sizeof(*indlst_conf), 8);
13218 	struct rte_flow_action *src = in->args.vc.actions;
13219 
13220 	if (!in->args.vc.actions_n)
13221 		goto end;
13222 	len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, src, NULL);
13223 	if (len <= 0)
13224 		goto end;
13225 	len = RTE_ALIGN(len, 16);
13226 
13227 	indlst_conf = calloc(1, base + len +
13228 			     in->args.vc.actions_n * sizeof(uintptr_t));
13229 	if (!indlst_conf)
13230 		goto end;
13231 	indlst_conf->id = in->args.vc.attr.group;
13232 	indlst_conf->conf_num = in->args.vc.actions_n - 1;
13233 	indlst_conf->actions = RTE_PTR_ADD(indlst_conf, base);
13234 	ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, indlst_conf->actions,
13235 			    len, src, NULL);
13236 	if (ret <= 0) {
13237 		free(indlst_conf);
13238 		indlst_conf = NULL;
13239 		goto end;
13240 	}
13241 	indlst_conf->conf = RTE_PTR_ADD(indlst_conf, base + len);
13242 	for (i = 0; i < indlst_conf->conf_num; i++)
13243 		indlst_conf->conf[i] = indlst_conf->actions[i].conf;
13244 	SLIST_INSERT_HEAD(&indlst_conf_head, indlst_conf, next);
13245 end:
13246 	if (indlst_conf)
13247 		printf("created indirect action list configuration %u\n",
13248 		       in->args.vc.attr.group);
13249 	else
13250 		printf("cannot create indirect action list configuration %u\n",
13251 		       in->args.vc.attr.group);
13252 }
13253 
13254 static const struct indlst_conf *
13255 indirect_action_list_conf_get(uint32_t conf_id)
13256 {
13257 	const struct indlst_conf *conf;
13258 
13259 	SLIST_FOREACH(conf, &indlst_conf_head, next) {
13260 		if (conf->id == conf_id)
13261 			return conf;
13262 	}
13263 	return NULL;
13264 }
13265 
13266 /** Dispatch parsed buffer to function calls. */
13267 static void
13268 cmd_flow_parsed(const struct buffer *in)
13269 {
13270 	switch (in->command) {
13271 	case INFO:
13272 		port_flow_get_info(in->port);
13273 		break;
13274 	case CONFIGURE:
13275 		port_flow_configure(in->port,
13276 				    &in->args.configure.port_attr,
13277 				    in->args.configure.nb_queue,
13278 				    &in->args.configure.queue_attr);
13279 		break;
13280 	case PATTERN_TEMPLATE_CREATE:
13281 		port_flow_pattern_template_create(in->port,
13282 				in->args.vc.pat_templ_id,
13283 				&((const struct rte_flow_pattern_template_attr) {
13284 					.relaxed_matching = in->args.vc.attr.reserved,
13285 					.ingress = in->args.vc.attr.ingress,
13286 					.egress = in->args.vc.attr.egress,
13287 					.transfer = in->args.vc.attr.transfer,
13288 				}),
13289 				in->args.vc.pattern);
13290 		break;
13291 	case PATTERN_TEMPLATE_DESTROY:
13292 		port_flow_pattern_template_destroy(in->port,
13293 				in->args.templ_destroy.template_id_n,
13294 				in->args.templ_destroy.template_id);
13295 		break;
13296 	case ACTIONS_TEMPLATE_CREATE:
13297 		port_flow_actions_template_create(in->port,
13298 				in->args.vc.act_templ_id,
13299 				&((const struct rte_flow_actions_template_attr) {
13300 					.ingress = in->args.vc.attr.ingress,
13301 					.egress = in->args.vc.attr.egress,
13302 					.transfer = in->args.vc.attr.transfer,
13303 				}),
13304 				in->args.vc.actions,
13305 				in->args.vc.masks);
13306 		break;
13307 	case ACTIONS_TEMPLATE_DESTROY:
13308 		port_flow_actions_template_destroy(in->port,
13309 				in->args.templ_destroy.template_id_n,
13310 				in->args.templ_destroy.template_id);
13311 		break;
13312 	case TABLE_CREATE:
13313 		port_flow_template_table_create(in->port, in->args.table.id,
13314 			&in->args.table.attr, in->args.table.pat_templ_id_n,
13315 			in->args.table.pat_templ_id, in->args.table.act_templ_id_n,
13316 			in->args.table.act_templ_id);
13317 		break;
13318 	case TABLE_DESTROY:
13319 		port_flow_template_table_destroy(in->port,
13320 					in->args.table_destroy.table_id_n,
13321 					in->args.table_destroy.table_id);
13322 		break;
13323 	case TABLE_RESIZE_COMPLETE:
13324 		port_flow_template_table_resize_complete
13325 			(in->port, in->args.table_destroy.table_id[0]);
13326 		break;
13327 	case GROUP_SET_MISS_ACTIONS:
13328 		port_queue_group_set_miss_actions(in->port, &in->args.vc.attr,
13329 						  in->args.vc.actions);
13330 		break;
13331 	case TABLE_RESIZE:
13332 		port_flow_template_table_resize(in->port, in->args.table.id,
13333 						in->args.table.attr.nb_flows);
13334 		break;
13335 	case QUEUE_CREATE:
13336 		port_queue_flow_create(in->port, in->queue, in->postpone,
13337 			in->args.vc.table_id, in->args.vc.rule_id,
13338 			in->args.vc.pat_templ_id, in->args.vc.act_templ_id,
13339 			in->args.vc.pattern, in->args.vc.actions);
13340 		break;
13341 	case QUEUE_DESTROY:
13342 		port_queue_flow_destroy(in->port, in->queue, in->postpone,
13343 					in->args.destroy.rule_n,
13344 					in->args.destroy.rule);
13345 		break;
13346 	case QUEUE_FLOW_UPDATE_RESIZED:
13347 		port_queue_flow_update_resized(in->port, in->queue,
13348 					       in->postpone,
13349 					       in->args.destroy.rule[0]);
13350 		break;
13351 	case QUEUE_UPDATE:
13352 		port_queue_flow_update(in->port, in->queue, in->postpone,
13353 				in->args.vc.rule_id, in->args.vc.act_templ_id,
13354 				in->args.vc.actions);
13355 		break;
13356 	case PUSH:
13357 		port_queue_flow_push(in->port, in->queue);
13358 		break;
13359 	case PULL:
13360 		port_queue_flow_pull(in->port, in->queue);
13361 		break;
13362 	case HASH:
13363 		if (!in->args.vc.encap_hash)
13364 			port_flow_hash_calc(in->port, in->args.vc.table_id,
13365 					    in->args.vc.pat_templ_id,
13366 					    in->args.vc.pattern);
13367 		else
13368 			port_flow_hash_calc_encap(in->port, in->args.vc.field,
13369 						  in->args.vc.pattern);
13370 		break;
13371 	case QUEUE_AGED:
13372 		port_queue_flow_aged(in->port, in->queue,
13373 				     in->args.aged.destroy);
13374 		break;
13375 	case QUEUE_INDIRECT_ACTION_CREATE:
13376 	case QUEUE_INDIRECT_ACTION_LIST_CREATE:
13377 		port_queue_action_handle_create(
13378 				in->port, in->queue, in->postpone,
13379 				in->args.vc.attr.group,
13380 				in->command == QUEUE_INDIRECT_ACTION_LIST_CREATE,
13381 				&((const struct rte_flow_indir_action_conf) {
13382 					.ingress = in->args.vc.attr.ingress,
13383 					.egress = in->args.vc.attr.egress,
13384 					.transfer = in->args.vc.attr.transfer,
13385 				}),
13386 				in->args.vc.actions);
13387 		break;
13388 	case QUEUE_INDIRECT_ACTION_DESTROY:
13389 		port_queue_action_handle_destroy(in->port,
13390 					   in->queue, in->postpone,
13391 					   in->args.ia_destroy.action_id_n,
13392 					   in->args.ia_destroy.action_id);
13393 		break;
13394 	case QUEUE_INDIRECT_ACTION_UPDATE:
13395 		port_queue_action_handle_update(in->port,
13396 						in->queue, in->postpone,
13397 						in->args.vc.attr.group,
13398 						in->args.vc.actions);
13399 		break;
13400 	case QUEUE_INDIRECT_ACTION_QUERY:
13401 		port_queue_action_handle_query(in->port,
13402 					       in->queue, in->postpone,
13403 					       in->args.ia.action_id);
13404 		break;
13405 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
13406 		port_queue_action_handle_query_update(in->port, in->queue,
13407 						      in->postpone,
13408 						      in->args.ia.action_id,
13409 						      in->args.ia.qu_mode,
13410 						      in->args.vc.actions);
13411 		break;
13412 	case INDIRECT_ACTION_CREATE:
13413 	case INDIRECT_ACTION_LIST_CREATE:
13414 		port_action_handle_create(
13415 				in->port, in->args.vc.attr.group,
13416 				in->command == INDIRECT_ACTION_LIST_CREATE,
13417 				&((const struct rte_flow_indir_action_conf) {
13418 					.ingress = in->args.vc.attr.ingress,
13419 					.egress = in->args.vc.attr.egress,
13420 					.transfer = in->args.vc.attr.transfer,
13421 				}),
13422 				in->args.vc.actions);
13423 		break;
13424 	case INDIRECT_ACTION_FLOW_CONF_CREATE:
13425 		indirect_action_flow_conf_create(in);
13426 		break;
13427 	case INDIRECT_ACTION_DESTROY:
13428 		port_action_handle_destroy(in->port,
13429 					   in->args.ia_destroy.action_id_n,
13430 					   in->args.ia_destroy.action_id);
13431 		break;
13432 	case INDIRECT_ACTION_UPDATE:
13433 		port_action_handle_update(in->port, in->args.vc.attr.group,
13434 					  in->args.vc.actions);
13435 		break;
13436 	case INDIRECT_ACTION_QUERY:
13437 		port_action_handle_query(in->port, in->args.ia.action_id);
13438 		break;
13439 	case INDIRECT_ACTION_QUERY_UPDATE:
13440 		port_action_handle_query_update(in->port,
13441 						in->args.ia.action_id,
13442 						in->args.ia.qu_mode,
13443 						in->args.vc.actions);
13444 		break;
13445 	case VALIDATE:
13446 		port_flow_validate(in->port, &in->args.vc.attr,
13447 				   in->args.vc.pattern, in->args.vc.actions,
13448 				   &in->args.vc.tunnel_ops);
13449 		break;
13450 	case CREATE:
13451 		port_flow_create(in->port, &in->args.vc.attr,
13452 				 in->args.vc.pattern, in->args.vc.actions,
13453 				 &in->args.vc.tunnel_ops, in->args.vc.user_id);
13454 		break;
13455 	case DESTROY:
13456 		port_flow_destroy(in->port, in->args.destroy.rule_n,
13457 				  in->args.destroy.rule,
13458 				  in->args.destroy.is_user_id);
13459 		break;
13460 	case UPDATE:
13461 		port_flow_update(in->port, in->args.vc.rule_id,
13462 				 in->args.vc.actions, in->args.vc.user_id);
13463 		break;
13464 	case FLUSH:
13465 		port_flow_flush(in->port);
13466 		break;
13467 	case DUMP_ONE:
13468 	case DUMP_ALL:
13469 		port_flow_dump(in->port, in->args.dump.mode,
13470 				in->args.dump.rule, in->args.dump.file,
13471 				in->args.dump.is_user_id);
13472 		break;
13473 	case QUERY:
13474 		port_flow_query(in->port, in->args.query.rule,
13475 				&in->args.query.action,
13476 				in->args.query.is_user_id);
13477 		break;
13478 	case LIST:
13479 		port_flow_list(in->port, in->args.list.group_n,
13480 			       in->args.list.group);
13481 		break;
13482 	case ISOLATE:
13483 		port_flow_isolate(in->port, in->args.isolate.set);
13484 		break;
13485 	case AGED:
13486 		port_flow_aged(in->port, in->args.aged.destroy);
13487 		break;
13488 	case TUNNEL_CREATE:
13489 		port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
13490 		break;
13491 	case TUNNEL_DESTROY:
13492 		port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
13493 		break;
13494 	case TUNNEL_LIST:
13495 		port_flow_tunnel_list(in->port);
13496 		break;
13497 	case ACTION_POL_G:
13498 		port_meter_policy_add(in->port, in->args.policy.policy_id,
13499 					in->args.vc.actions);
13500 		break;
13501 	case FLEX_ITEM_CREATE:
13502 		flex_item_create(in->port, in->args.flex.token,
13503 				 in->args.flex.filename);
13504 		break;
13505 	case FLEX_ITEM_DESTROY:
13506 		flex_item_destroy(in->port, in->args.flex.token);
13507 		break;
13508 	default:
13509 		break;
13510 	}
13511 	fflush(stdout);
13512 }
13513 
13514 /** Token generator and output processing callback (cmdline API). */
13515 static void
13516 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
13517 {
13518 	if (cl == NULL)
13519 		cmd_flow_tok(arg0, arg2);
13520 	else
13521 		cmd_flow_parsed(arg0);
13522 }
13523 
13524 /** Global parser instance (cmdline API). */
13525 cmdline_parse_inst_t cmd_flow = {
13526 	.f = cmd_flow_cb,
13527 	.data = NULL, /**< Unused. */
13528 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
13529 	.tokens = {
13530 		NULL,
13531 	}, /**< Tokens are returned by cmd_flow_tok(). */
13532 };
13533 
13534 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
13535 
13536 static void
13537 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
13538 {
13539 	struct rte_ipv4_hdr *ipv4;
13540 	struct rte_ether_hdr *eth;
13541 	struct rte_ipv6_hdr *ipv6;
13542 	struct rte_vxlan_hdr *vxlan;
13543 	struct rte_vxlan_gpe_hdr *gpe;
13544 	struct rte_flow_item_nvgre *nvgre;
13545 	uint32_t ipv6_vtc_flow;
13546 
13547 	switch (item->type) {
13548 	case RTE_FLOW_ITEM_TYPE_ETH:
13549 		eth = (struct rte_ether_hdr *)buf;
13550 		if (next_proto)
13551 			eth->ether_type = rte_cpu_to_be_16(next_proto);
13552 		break;
13553 	case RTE_FLOW_ITEM_TYPE_IPV4:
13554 		ipv4 = (struct rte_ipv4_hdr *)buf;
13555 		if (!ipv4->version_ihl)
13556 			ipv4->version_ihl = RTE_IPV4_VHL_DEF;
13557 		if (next_proto && ipv4->next_proto_id == 0)
13558 			ipv4->next_proto_id = (uint8_t)next_proto;
13559 		break;
13560 	case RTE_FLOW_ITEM_TYPE_IPV6:
13561 		ipv6 = (struct rte_ipv6_hdr *)buf;
13562 		if (next_proto && ipv6->proto == 0)
13563 			ipv6->proto = (uint8_t)next_proto;
13564 		ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
13565 		ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
13566 		ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
13567 		ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
13568 		break;
13569 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13570 		vxlan = (struct rte_vxlan_hdr *)buf;
13571 		vxlan->vx_flags = 0x08;
13572 		break;
13573 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13574 		gpe = (struct rte_vxlan_gpe_hdr *)buf;
13575 		gpe->vx_flags = 0x0C;
13576 		break;
13577 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13578 		nvgre = (struct rte_flow_item_nvgre *)buf;
13579 		nvgre->protocol = rte_cpu_to_be_16(0x6558);
13580 		nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
13581 		break;
13582 	default:
13583 		break;
13584 	}
13585 }
13586 
13587 /** Helper of get item's default mask. */
13588 static const void *
13589 flow_item_default_mask(const struct rte_flow_item *item)
13590 {
13591 	const void *mask = NULL;
13592 	static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
13593 	static struct rte_flow_item_ipv6_routing_ext ipv6_routing_ext_default_mask = {
13594 		.hdr = {
13595 			.next_hdr = 0xff,
13596 			.type = 0xff,
13597 			.segments_left = 0xff,
13598 		},
13599 	};
13600 
13601 	switch (item->type) {
13602 	case RTE_FLOW_ITEM_TYPE_ANY:
13603 		mask = &rte_flow_item_any_mask;
13604 		break;
13605 	case RTE_FLOW_ITEM_TYPE_PORT_ID:
13606 		mask = &rte_flow_item_port_id_mask;
13607 		break;
13608 	case RTE_FLOW_ITEM_TYPE_RAW:
13609 		mask = &rte_flow_item_raw_mask;
13610 		break;
13611 	case RTE_FLOW_ITEM_TYPE_ETH:
13612 		mask = &rte_flow_item_eth_mask;
13613 		break;
13614 	case RTE_FLOW_ITEM_TYPE_VLAN:
13615 		mask = &rte_flow_item_vlan_mask;
13616 		break;
13617 	case RTE_FLOW_ITEM_TYPE_IPV4:
13618 		mask = &rte_flow_item_ipv4_mask;
13619 		break;
13620 	case RTE_FLOW_ITEM_TYPE_IPV6:
13621 		mask = &rte_flow_item_ipv6_mask;
13622 		break;
13623 	case RTE_FLOW_ITEM_TYPE_ICMP:
13624 		mask = &rte_flow_item_icmp_mask;
13625 		break;
13626 	case RTE_FLOW_ITEM_TYPE_UDP:
13627 		mask = &rte_flow_item_udp_mask;
13628 		break;
13629 	case RTE_FLOW_ITEM_TYPE_TCP:
13630 		mask = &rte_flow_item_tcp_mask;
13631 		break;
13632 	case RTE_FLOW_ITEM_TYPE_SCTP:
13633 		mask = &rte_flow_item_sctp_mask;
13634 		break;
13635 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13636 		mask = &rte_flow_item_vxlan_mask;
13637 		break;
13638 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13639 		mask = &rte_flow_item_vxlan_gpe_mask;
13640 		break;
13641 	case RTE_FLOW_ITEM_TYPE_E_TAG:
13642 		mask = &rte_flow_item_e_tag_mask;
13643 		break;
13644 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13645 		mask = &rte_flow_item_nvgre_mask;
13646 		break;
13647 	case RTE_FLOW_ITEM_TYPE_MPLS:
13648 		mask = &rte_flow_item_mpls_mask;
13649 		break;
13650 	case RTE_FLOW_ITEM_TYPE_GRE:
13651 		mask = &rte_flow_item_gre_mask;
13652 		break;
13653 	case RTE_FLOW_ITEM_TYPE_GRE_KEY:
13654 		mask = &gre_key_default_mask;
13655 		break;
13656 	case RTE_FLOW_ITEM_TYPE_META:
13657 		mask = &rte_flow_item_meta_mask;
13658 		break;
13659 	case RTE_FLOW_ITEM_TYPE_RANDOM:
13660 		mask = &rte_flow_item_random_mask;
13661 		break;
13662 	case RTE_FLOW_ITEM_TYPE_FUZZY:
13663 		mask = &rte_flow_item_fuzzy_mask;
13664 		break;
13665 	case RTE_FLOW_ITEM_TYPE_GTP:
13666 		mask = &rte_flow_item_gtp_mask;
13667 		break;
13668 	case RTE_FLOW_ITEM_TYPE_GTP_PSC:
13669 		mask = &rte_flow_item_gtp_psc_mask;
13670 		break;
13671 	case RTE_FLOW_ITEM_TYPE_GENEVE:
13672 		mask = &rte_flow_item_geneve_mask;
13673 		break;
13674 	case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
13675 		mask = &rte_flow_item_geneve_opt_mask;
13676 		break;
13677 	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
13678 		mask = &rte_flow_item_pppoe_proto_id_mask;
13679 		break;
13680 	case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
13681 		mask = &rte_flow_item_l2tpv3oip_mask;
13682 		break;
13683 	case RTE_FLOW_ITEM_TYPE_ESP:
13684 		mask = &rte_flow_item_esp_mask;
13685 		break;
13686 	case RTE_FLOW_ITEM_TYPE_AH:
13687 		mask = &rte_flow_item_ah_mask;
13688 		break;
13689 	case RTE_FLOW_ITEM_TYPE_PFCP:
13690 		mask = &rte_flow_item_pfcp_mask;
13691 		break;
13692 	case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
13693 	case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
13694 		mask = &rte_flow_item_ethdev_mask;
13695 		break;
13696 	case RTE_FLOW_ITEM_TYPE_L2TPV2:
13697 		mask = &rte_flow_item_l2tpv2_mask;
13698 		break;
13699 	case RTE_FLOW_ITEM_TYPE_PPP:
13700 		mask = &rte_flow_item_ppp_mask;
13701 		break;
13702 	case RTE_FLOW_ITEM_TYPE_METER_COLOR:
13703 		mask = &rte_flow_item_meter_color_mask;
13704 		break;
13705 	case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13706 		mask = &ipv6_routing_ext_default_mask;
13707 		break;
13708 	case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
13709 		mask = &rte_flow_item_aggr_affinity_mask;
13710 		break;
13711 	case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
13712 		mask = &rte_flow_item_tx_queue_mask;
13713 		break;
13714 	case RTE_FLOW_ITEM_TYPE_IB_BTH:
13715 		mask = &rte_flow_item_ib_bth_mask;
13716 		break;
13717 	case RTE_FLOW_ITEM_TYPE_PTYPE:
13718 		mask = &rte_flow_item_ptype_mask;
13719 		break;
13720 	default:
13721 		break;
13722 	}
13723 	return mask;
13724 }
13725 
13726 /** Dispatch parsed buffer to function calls. */
13727 static void
13728 cmd_set_ipv6_ext_parsed(const struct buffer *in)
13729 {
13730 	uint32_t n = in->args.vc.pattern_n;
13731 	int i = 0;
13732 	struct rte_flow_item *item = NULL;
13733 	size_t size = 0;
13734 	uint8_t *data = NULL;
13735 	uint8_t *type = NULL;
13736 	size_t *total_size = NULL;
13737 	uint16_t idx = in->port; /* We borrow port field as index */
13738 	struct rte_flow_item_ipv6_routing_ext *ext;
13739 	const struct rte_flow_item_ipv6_ext *ipv6_ext;
13740 
13741 	RTE_ASSERT(in->command == SET_IPV6_EXT_PUSH ||
13742 		   in->command == SET_IPV6_EXT_REMOVE);
13743 
13744 	if (in->command == SET_IPV6_EXT_REMOVE) {
13745 		if (n != 1 || in->args.vc.pattern->type !=
13746 		    RTE_FLOW_ITEM_TYPE_IPV6_EXT) {
13747 			fprintf(stderr, "Error - Not supported item\n");
13748 			return;
13749 		}
13750 		type = (uint8_t *)&ipv6_ext_remove_confs[idx].type;
13751 		item = in->args.vc.pattern;
13752 		ipv6_ext = item->spec;
13753 		*type = ipv6_ext->next_hdr;
13754 		return;
13755 	}
13756 
13757 	total_size = &ipv6_ext_push_confs[idx].size;
13758 	data = (uint8_t *)&ipv6_ext_push_confs[idx].data;
13759 	type = (uint8_t *)&ipv6_ext_push_confs[idx].type;
13760 
13761 	*total_size = 0;
13762 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13763 	for (i = n - 1 ; i >= 0; --i) {
13764 		item = in->args.vc.pattern + i;
13765 		switch (item->type) {
13766 		case RTE_FLOW_ITEM_TYPE_IPV6_EXT:
13767 			ipv6_ext = item->spec;
13768 			*type = ipv6_ext->next_hdr;
13769 			break;
13770 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13771 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13772 			if (!ext->hdr.hdr_len) {
13773 				size = sizeof(struct rte_ipv6_routing_ext) +
13774 				(ext->hdr.segments_left << 4);
13775 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
13776 				/* Indicate no TLV once SRH. */
13777 				if (ext->hdr.type == 4)
13778 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
13779 			} else {
13780 				size = sizeof(struct rte_ipv6_routing_ext) +
13781 				(ext->hdr.hdr_len << 3);
13782 			}
13783 			*total_size += size;
13784 			memcpy(data, ext, size);
13785 			break;
13786 		default:
13787 			fprintf(stderr, "Error - Not supported item\n");
13788 			goto error;
13789 		}
13790 	}
13791 	RTE_ASSERT((*total_size) <= ACTION_IPV6_EXT_PUSH_MAX_DATA);
13792 	return;
13793 error:
13794 	*total_size = 0;
13795 	memset(data, 0x00, ACTION_IPV6_EXT_PUSH_MAX_DATA);
13796 }
13797 
13798 /** Dispatch parsed buffer to function calls. */
13799 static void
13800 cmd_set_raw_parsed_sample(const struct buffer *in)
13801 {
13802 	uint32_t n = in->args.vc.actions_n;
13803 	uint32_t i = 0;
13804 	struct rte_flow_action *action = NULL;
13805 	struct rte_flow_action *data = NULL;
13806 	const struct rte_flow_action_rss *rss = NULL;
13807 	size_t size = 0;
13808 	uint16_t idx = in->port; /* We borrow port field as index */
13809 	uint32_t max_size = sizeof(struct rte_flow_action) *
13810 						ACTION_SAMPLE_ACTIONS_NUM;
13811 
13812 	RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
13813 	data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
13814 	memset(data, 0x00, max_size);
13815 	for (; i <= n - 1; i++) {
13816 		action = in->args.vc.actions + i;
13817 		if (action->type == RTE_FLOW_ACTION_TYPE_END)
13818 			break;
13819 		switch (action->type) {
13820 		case RTE_FLOW_ACTION_TYPE_MARK:
13821 			size = sizeof(struct rte_flow_action_mark);
13822 			rte_memcpy(&sample_mark[idx],
13823 				(const void *)action->conf, size);
13824 			action->conf = &sample_mark[idx];
13825 			break;
13826 		case RTE_FLOW_ACTION_TYPE_COUNT:
13827 			size = sizeof(struct rte_flow_action_count);
13828 			rte_memcpy(&sample_count[idx],
13829 				(const void *)action->conf, size);
13830 			action->conf = &sample_count[idx];
13831 			break;
13832 		case RTE_FLOW_ACTION_TYPE_QUEUE:
13833 			size = sizeof(struct rte_flow_action_queue);
13834 			rte_memcpy(&sample_queue[idx],
13835 				(const void *)action->conf, size);
13836 			action->conf = &sample_queue[idx];
13837 			break;
13838 		case RTE_FLOW_ACTION_TYPE_RSS:
13839 			size = sizeof(struct rte_flow_action_rss);
13840 			rss = action->conf;
13841 			rte_memcpy(&sample_rss_data[idx].conf,
13842 				   (const void *)rss, size);
13843 			if (rss->key_len && rss->key) {
13844 				sample_rss_data[idx].conf.key =
13845 						sample_rss_data[idx].key;
13846 				rte_memcpy((void *)((uintptr_t)
13847 					   sample_rss_data[idx].conf.key),
13848 					   (const void *)rss->key,
13849 					   sizeof(uint8_t) * rss->key_len);
13850 			}
13851 			if (rss->queue_num && rss->queue) {
13852 				sample_rss_data[idx].conf.queue =
13853 						sample_rss_data[idx].queue;
13854 				rte_memcpy((void *)((uintptr_t)
13855 					   sample_rss_data[idx].conf.queue),
13856 					   (const void *)rss->queue,
13857 					   sizeof(uint16_t) * rss->queue_num);
13858 			}
13859 			action->conf = &sample_rss_data[idx].conf;
13860 			break;
13861 		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
13862 			size = sizeof(struct rte_flow_action_raw_encap);
13863 			rte_memcpy(&sample_encap[idx],
13864 				(const void *)action->conf, size);
13865 			action->conf = &sample_encap[idx];
13866 			break;
13867 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
13868 			size = sizeof(struct rte_flow_action_port_id);
13869 			rte_memcpy(&sample_port_id[idx],
13870 				(const void *)action->conf, size);
13871 			action->conf = &sample_port_id[idx];
13872 			break;
13873 		case RTE_FLOW_ACTION_TYPE_PF:
13874 			break;
13875 		case RTE_FLOW_ACTION_TYPE_VF:
13876 			size = sizeof(struct rte_flow_action_vf);
13877 			rte_memcpy(&sample_vf[idx],
13878 					(const void *)action->conf, size);
13879 			action->conf = &sample_vf[idx];
13880 			break;
13881 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
13882 			size = sizeof(struct rte_flow_action_vxlan_encap);
13883 			parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
13884 			action->conf = &sample_vxlan_encap[idx].conf;
13885 			break;
13886 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
13887 			size = sizeof(struct rte_flow_action_nvgre_encap);
13888 			parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
13889 			action->conf = &sample_nvgre_encap[idx];
13890 			break;
13891 		case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
13892 			size = sizeof(struct rte_flow_action_ethdev);
13893 			rte_memcpy(&sample_port_representor[idx],
13894 					(const void *)action->conf, size);
13895 			action->conf = &sample_port_representor[idx];
13896 			break;
13897 		case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
13898 			size = sizeof(struct rte_flow_action_ethdev);
13899 			rte_memcpy(&sample_represented_port[idx],
13900 					(const void *)action->conf, size);
13901 			action->conf = &sample_represented_port[idx];
13902 			break;
13903 		default:
13904 			fprintf(stderr, "Error - Not supported action\n");
13905 			return;
13906 		}
13907 		rte_memcpy(data, action, sizeof(struct rte_flow_action));
13908 		data++;
13909 	}
13910 }
13911 
13912 /** Dispatch parsed buffer to function calls. */
13913 static void
13914 cmd_set_raw_parsed(const struct buffer *in)
13915 {
13916 	uint32_t n = in->args.vc.pattern_n;
13917 	int i = 0;
13918 	struct rte_flow_item *item = NULL;
13919 	size_t size = 0;
13920 	uint8_t *data = NULL;
13921 	uint8_t *data_tail = NULL;
13922 	size_t *total_size = NULL;
13923 	uint16_t upper_layer = 0;
13924 	uint16_t proto = 0;
13925 	uint16_t idx = in->port; /* We borrow port field as index */
13926 	int gtp_psc = -1; /* GTP PSC option index. */
13927 	const void *src_spec;
13928 
13929 	if (in->command == SET_SAMPLE_ACTIONS)
13930 		return cmd_set_raw_parsed_sample(in);
13931 	else if (in->command == SET_IPV6_EXT_PUSH ||
13932 		 in->command == SET_IPV6_EXT_REMOVE)
13933 		return cmd_set_ipv6_ext_parsed(in);
13934 	RTE_ASSERT(in->command == SET_RAW_ENCAP ||
13935 		   in->command == SET_RAW_DECAP);
13936 	if (in->command == SET_RAW_ENCAP) {
13937 		total_size = &raw_encap_confs[idx].size;
13938 		data = (uint8_t *)&raw_encap_confs[idx].data;
13939 	} else {
13940 		total_size = &raw_decap_confs[idx].size;
13941 		data = (uint8_t *)&raw_decap_confs[idx].data;
13942 	}
13943 	*total_size = 0;
13944 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13945 	/* process hdr from upper layer to low layer (L3/L4 -> L2). */
13946 	data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
13947 	for (i = n - 1 ; i >= 0; --i) {
13948 		const struct rte_flow_item_gtp *gtp;
13949 		const struct rte_flow_item_geneve_opt *opt;
13950 		struct rte_flow_item_ipv6_routing_ext *ext;
13951 
13952 		item = in->args.vc.pattern + i;
13953 		if (item->spec == NULL)
13954 			item->spec = flow_item_default_mask(item);
13955 		src_spec = item->spec;
13956 		switch (item->type) {
13957 		case RTE_FLOW_ITEM_TYPE_ETH:
13958 			size = sizeof(struct rte_ether_hdr);
13959 			break;
13960 		case RTE_FLOW_ITEM_TYPE_VLAN:
13961 			size = sizeof(struct rte_vlan_hdr);
13962 			proto = RTE_ETHER_TYPE_VLAN;
13963 			break;
13964 		case RTE_FLOW_ITEM_TYPE_IPV4:
13965 			size = sizeof(struct rte_ipv4_hdr);
13966 			proto = RTE_ETHER_TYPE_IPV4;
13967 			break;
13968 		case RTE_FLOW_ITEM_TYPE_IPV6:
13969 			size = sizeof(struct rte_ipv6_hdr);
13970 			proto = RTE_ETHER_TYPE_IPV6;
13971 			break;
13972 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13973 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13974 			if (!ext->hdr.hdr_len) {
13975 				size = sizeof(struct rte_ipv6_routing_ext) +
13976 					(ext->hdr.segments_left << 4);
13977 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
13978 				/* SRv6 without TLV. */
13979 				if (ext->hdr.type == RTE_IPV6_SRCRT_TYPE_4)
13980 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
13981 			} else {
13982 				size = sizeof(struct rte_ipv6_routing_ext) +
13983 					(ext->hdr.hdr_len << 3);
13984 			}
13985 			proto = IPPROTO_ROUTING;
13986 			break;
13987 		case RTE_FLOW_ITEM_TYPE_UDP:
13988 			size = sizeof(struct rte_udp_hdr);
13989 			proto = 0x11;
13990 			break;
13991 		case RTE_FLOW_ITEM_TYPE_TCP:
13992 			size = sizeof(struct rte_tcp_hdr);
13993 			proto = 0x06;
13994 			break;
13995 		case RTE_FLOW_ITEM_TYPE_VXLAN:
13996 			size = sizeof(struct rte_vxlan_hdr);
13997 			break;
13998 		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13999 			size = sizeof(struct rte_vxlan_gpe_hdr);
14000 			break;
14001 		case RTE_FLOW_ITEM_TYPE_GRE:
14002 			size = sizeof(struct rte_gre_hdr);
14003 			proto = 0x2F;
14004 			break;
14005 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
14006 			size = sizeof(rte_be32_t);
14007 			proto = 0x0;
14008 			break;
14009 		case RTE_FLOW_ITEM_TYPE_MPLS:
14010 			size = sizeof(struct rte_mpls_hdr);
14011 			proto = 0x0;
14012 			break;
14013 		case RTE_FLOW_ITEM_TYPE_NVGRE:
14014 			size = sizeof(struct rte_flow_item_nvgre);
14015 			proto = 0x2F;
14016 			break;
14017 		case RTE_FLOW_ITEM_TYPE_GENEVE:
14018 			size = sizeof(struct rte_geneve_hdr);
14019 			break;
14020 		case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
14021 			opt = (const struct rte_flow_item_geneve_opt *)
14022 								item->spec;
14023 			size = offsetof(struct rte_flow_item_geneve_opt,
14024 					option_len) + sizeof(uint8_t);
14025 			if (opt->option_len && opt->data) {
14026 				*total_size += opt->option_len *
14027 					       sizeof(uint32_t);
14028 				rte_memcpy(data_tail - (*total_size),
14029 					   opt->data,
14030 					   opt->option_len * sizeof(uint32_t));
14031 			}
14032 			break;
14033 		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
14034 			size = sizeof(rte_be32_t);
14035 			proto = 0x73;
14036 			break;
14037 		case RTE_FLOW_ITEM_TYPE_ESP:
14038 			size = sizeof(struct rte_esp_hdr);
14039 			proto = 0x32;
14040 			break;
14041 		case RTE_FLOW_ITEM_TYPE_AH:
14042 			size = sizeof(struct rte_flow_item_ah);
14043 			proto = 0x33;
14044 			break;
14045 		case RTE_FLOW_ITEM_TYPE_GTP:
14046 			if (gtp_psc < 0) {
14047 				size = sizeof(struct rte_gtp_hdr);
14048 				break;
14049 			}
14050 			if (gtp_psc != i + 1) {
14051 				fprintf(stderr,
14052 					"Error - GTP PSC does not follow GTP\n");
14053 				goto error;
14054 			}
14055 			gtp = item->spec;
14056 			if (gtp->hdr.s == 1 || gtp->hdr.pn == 1) {
14057 				/* Only E flag should be set. */
14058 				fprintf(stderr,
14059 					"Error - GTP unsupported flags\n");
14060 				goto error;
14061 			} else {
14062 				struct rte_gtp_hdr_ext_word ext_word = {
14063 					.next_ext = 0x85
14064 				};
14065 
14066 				/* We have to add GTP header extra word. */
14067 				*total_size += sizeof(ext_word);
14068 				rte_memcpy(data_tail - (*total_size),
14069 					   &ext_word, sizeof(ext_word));
14070 			}
14071 			size = sizeof(struct rte_gtp_hdr);
14072 			break;
14073 		case RTE_FLOW_ITEM_TYPE_GTP_PSC:
14074 			if (gtp_psc >= 0) {
14075 				fprintf(stderr,
14076 					"Error - Multiple GTP PSC items\n");
14077 				goto error;
14078 			} else {
14079 				const struct rte_flow_item_gtp_psc
14080 					*opt = item->spec;
14081 				struct rte_gtp_psc_generic_hdr *hdr;
14082 				size_t hdr_size = RTE_ALIGN(sizeof(*hdr),
14083 							 sizeof(int32_t));
14084 
14085 				*total_size += hdr_size;
14086 				hdr = (typeof(hdr))(data_tail - (*total_size));
14087 				memset(hdr, 0, hdr_size);
14088 				*hdr = opt->hdr;
14089 				hdr->ext_hdr_len = 1;
14090 				gtp_psc = i;
14091 				size = 0;
14092 			}
14093 			break;
14094 		case RTE_FLOW_ITEM_TYPE_PFCP:
14095 			size = sizeof(struct rte_flow_item_pfcp);
14096 			break;
14097 		case RTE_FLOW_ITEM_TYPE_FLEX:
14098 			if (item->spec != NULL) {
14099 				size = ((const struct rte_flow_item_flex *)item->spec)->length;
14100 				src_spec = ((const struct rte_flow_item_flex *)item->spec)->pattern;
14101 			} else {
14102 				size = 0;
14103 				src_spec = NULL;
14104 			}
14105 			break;
14106 		case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
14107 			size = 0;
14108 			if (item->spec) {
14109 				const struct rte_flow_item_gre_opt
14110 					*opt = item->spec;
14111 				if (opt->checksum_rsvd.checksum) {
14112 					*total_size +=
14113 						sizeof(opt->checksum_rsvd);
14114 					rte_memcpy(data_tail - (*total_size),
14115 						   &opt->checksum_rsvd,
14116 						   sizeof(opt->checksum_rsvd));
14117 				}
14118 				if (opt->key.key) {
14119 					*total_size += sizeof(opt->key.key);
14120 					rte_memcpy(data_tail - (*total_size),
14121 						   &opt->key.key,
14122 						   sizeof(opt->key.key));
14123 				}
14124 				if (opt->sequence.sequence) {
14125 					*total_size += sizeof(opt->sequence.sequence);
14126 					rte_memcpy(data_tail - (*total_size),
14127 						   &opt->sequence.sequence,
14128 						   sizeof(opt->sequence.sequence));
14129 				}
14130 			}
14131 			proto = 0x2F;
14132 			break;
14133 		default:
14134 			fprintf(stderr, "Error - Not supported item\n");
14135 			goto error;
14136 		}
14137 		if (size) {
14138 			*total_size += size;
14139 			rte_memcpy(data_tail - (*total_size), src_spec, size);
14140 			/* update some fields which cannot be set by cmdline */
14141 			update_fields((data_tail - (*total_size)), item,
14142 				      upper_layer);
14143 			upper_layer = proto;
14144 		}
14145 	}
14146 	if (verbose_level & 0x1)
14147 		printf("total data size is %zu\n", (*total_size));
14148 	RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
14149 	memmove(data, (data_tail - (*total_size)), *total_size);
14150 	return;
14151 
14152 error:
14153 	*total_size = 0;
14154 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
14155 }
14156 
14157 /** Populate help strings for current token (cmdline API). */
14158 static int
14159 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
14160 		     unsigned int size)
14161 {
14162 	struct context *ctx = &cmd_flow_context;
14163 	const struct token *token = &token_list[ctx->prev];
14164 
14165 	(void)hdr;
14166 	if (!size)
14167 		return -1;
14168 	/* Set token type and update global help with details. */
14169 	snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
14170 	if (token->help)
14171 		cmd_set_raw.help_str = token->help;
14172 	else
14173 		cmd_set_raw.help_str = token->name;
14174 	return 0;
14175 }
14176 
14177 /** Token definition template (cmdline API). */
14178 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
14179 	.ops = &(struct cmdline_token_ops){
14180 		.parse = cmd_flow_parse,
14181 		.complete_get_nb = cmd_flow_complete_get_nb,
14182 		.complete_get_elt = cmd_flow_complete_get_elt,
14183 		.get_help = cmd_set_raw_get_help,
14184 	},
14185 	.offset = 0,
14186 };
14187 
14188 /** Populate the next dynamic token. */
14189 static void
14190 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
14191 	     cmdline_parse_token_hdr_t **hdr_inst)
14192 {
14193 	struct context *ctx = &cmd_flow_context;
14194 
14195 	/* Always reinitialize context before requesting the first token. */
14196 	if (!(hdr_inst - cmd_set_raw.tokens)) {
14197 		cmd_flow_context_init(ctx);
14198 		ctx->curr = START_SET;
14199 	}
14200 	/* Return NULL when no more tokens are expected. */
14201 	if (!ctx->next_num && (ctx->curr != START_SET)) {
14202 		*hdr = NULL;
14203 		return;
14204 	}
14205 	/* Determine if command should end here. */
14206 	if (ctx->eol && ctx->last && ctx->next_num) {
14207 		const enum index *list = ctx->next[ctx->next_num - 1];
14208 		int i;
14209 
14210 		for (i = 0; list[i]; ++i) {
14211 			if (list[i] != END)
14212 				continue;
14213 			*hdr = NULL;
14214 			return;
14215 		}
14216 	}
14217 	*hdr = &cmd_set_raw_token_hdr;
14218 }
14219 
14220 /** Token generator and output processing callback (cmdline API). */
14221 static void
14222 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
14223 {
14224 	if (cl == NULL)
14225 		cmd_set_raw_tok(arg0, arg2);
14226 	else
14227 		cmd_set_raw_parsed(arg0);
14228 }
14229 
14230 /** Global parser instance (cmdline API). */
14231 cmdline_parse_inst_t cmd_set_raw = {
14232 	.f = cmd_set_raw_cb,
14233 	.data = NULL, /**< Unused. */
14234 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
14235 	.tokens = {
14236 		NULL,
14237 	}, /**< Tokens are returned by cmd_flow_tok(). */
14238 };
14239 
14240 /* *** display raw_encap/raw_decap buf */
14241 struct cmd_show_set_raw_result {
14242 	cmdline_fixed_string_t cmd_show;
14243 	cmdline_fixed_string_t cmd_what;
14244 	cmdline_fixed_string_t cmd_all;
14245 	uint16_t cmd_index;
14246 };
14247 
14248 static void
14249 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
14250 {
14251 	struct cmd_show_set_raw_result *res = parsed_result;
14252 	uint16_t index = res->cmd_index;
14253 	uint8_t all = 0;
14254 	uint8_t *raw_data = NULL;
14255 	size_t raw_size = 0;
14256 	char title[16] = {0};
14257 
14258 	RTE_SET_USED(cl);
14259 	RTE_SET_USED(data);
14260 	if (!strcmp(res->cmd_all, "all")) {
14261 		all = 1;
14262 		index = 0;
14263 	} else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
14264 		fprintf(stderr, "index should be 0-%u\n",
14265 			RAW_ENCAP_CONFS_MAX_NUM - 1);
14266 		return;
14267 	}
14268 	do {
14269 		if (!strcmp(res->cmd_what, "raw_encap")) {
14270 			raw_data = (uint8_t *)&raw_encap_confs[index].data;
14271 			raw_size = raw_encap_confs[index].size;
14272 			snprintf(title, 16, "\nindex: %u", index);
14273 			rte_hexdump(stdout, title, raw_data, raw_size);
14274 		} else {
14275 			raw_data = (uint8_t *)&raw_decap_confs[index].data;
14276 			raw_size = raw_decap_confs[index].size;
14277 			snprintf(title, 16, "\nindex: %u", index);
14278 			rte_hexdump(stdout, title, raw_data, raw_size);
14279 		}
14280 	} while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
14281 }
14282 
14283 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
14284 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14285 			cmd_show, "show");
14286 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
14287 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14288 			cmd_what, "raw_encap#raw_decap");
14289 static cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
14290 	TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
14291 			cmd_index, RTE_UINT16);
14292 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
14293 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14294 			cmd_all, "all");
14295 cmdline_parse_inst_t cmd_show_set_raw = {
14296 	.f = cmd_show_set_raw_parsed,
14297 	.data = NULL,
14298 	.help_str = "show <raw_encap|raw_decap> <index>",
14299 	.tokens = {
14300 		(void *)&cmd_show_set_raw_cmd_show,
14301 		(void *)&cmd_show_set_raw_cmd_what,
14302 		(void *)&cmd_show_set_raw_cmd_index,
14303 		NULL,
14304 	},
14305 };
14306 cmdline_parse_inst_t cmd_show_set_raw_all = {
14307 	.f = cmd_show_set_raw_parsed,
14308 	.data = NULL,
14309 	.help_str = "show <raw_encap|raw_decap> all",
14310 	.tokens = {
14311 		(void *)&cmd_show_set_raw_cmd_show,
14312 		(void *)&cmd_show_set_raw_cmd_what,
14313 		(void *)&cmd_show_set_raw_cmd_all,
14314 		NULL,
14315 	},
14316 };
14317