xref: /dpdk/app/test-pmd/cmdline_flow.c (revision 25a2a0dc3de31ca0a6fbc9371cf3dd85dfd74b07)
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 	ACTION_JUMP_TO_TABLE_INDEX,
789 	ACTION_JUMP_TO_TABLE_INDEX_TABLE,
790 	ACTION_JUMP_TO_TABLE_INDEX_INDEX,
791 };
792 
793 /** Maximum size for pattern in struct rte_flow_item_raw. */
794 #define ITEM_RAW_PATTERN_SIZE 512
795 
796 /** Maximum size for GENEVE option data pattern in bytes. */
797 #define ITEM_GENEVE_OPT_DATA_SIZE 124
798 
799 /** Storage size for struct rte_flow_item_raw including pattern. */
800 #define ITEM_RAW_SIZE \
801 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
802 
803 static const char *const compare_ops[] = {
804 	"eq", "ne", "lt", "le", "gt", "ge", NULL
805 };
806 
807 /** Maximum size for external pattern in struct rte_flow_field_data. */
808 #define FLOW_FIELD_PATTERN_SIZE 32
809 
810 /** Storage size for struct rte_flow_action_modify_field including pattern. */
811 #define ACTION_MODIFY_SIZE \
812 	(sizeof(struct rte_flow_action_modify_field) + \
813 	FLOW_FIELD_PATTERN_SIZE)
814 
815 /** Maximum number of queue indices in struct rte_flow_action_rss. */
816 #define ACTION_RSS_QUEUE_NUM 128
817 
818 /** Storage for struct rte_flow_action_rss including external data. */
819 struct action_rss_data {
820 	struct rte_flow_action_rss conf;
821 	uint8_t key[RSS_HASH_KEY_LENGTH];
822 	uint16_t queue[ACTION_RSS_QUEUE_NUM];
823 };
824 
825 /** Maximum data size in struct rte_flow_action_raw_encap. */
826 #define ACTION_RAW_ENCAP_MAX_DATA 512
827 #define RAW_ENCAP_CONFS_MAX_NUM 8
828 
829 /** Storage for struct rte_flow_action_raw_encap. */
830 struct raw_encap_conf {
831 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
832 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
833 	size_t size;
834 };
835 
836 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
837 
838 /** Storage for struct rte_flow_action_raw_encap including external data. */
839 struct action_raw_encap_data {
840 	struct rte_flow_action_raw_encap conf;
841 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
842 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
843 	uint16_t idx;
844 };
845 
846 /** Storage for struct rte_flow_action_raw_decap. */
847 struct raw_decap_conf {
848 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
849 	size_t size;
850 };
851 
852 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
853 
854 /** Storage for struct rte_flow_action_raw_decap including external data. */
855 struct action_raw_decap_data {
856 	struct rte_flow_action_raw_decap conf;
857 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
858 	uint16_t idx;
859 };
860 
861 /** Maximum data size in struct rte_flow_action_ipv6_ext_push. */
862 #define ACTION_IPV6_EXT_PUSH_MAX_DATA 512
863 #define IPV6_EXT_PUSH_CONFS_MAX_NUM 8
864 
865 /** Storage for struct rte_flow_action_ipv6_ext_push. */
866 struct ipv6_ext_push_conf {
867 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
868 	size_t size;
869 	uint8_t type;
870 };
871 
872 struct ipv6_ext_push_conf ipv6_ext_push_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
873 
874 /** Storage for struct rte_flow_action_ipv6_ext_push including external data. */
875 struct action_ipv6_ext_push_data {
876 	struct rte_flow_action_ipv6_ext_push conf;
877 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
878 	uint8_t type;
879 	uint16_t idx;
880 };
881 
882 /** Storage for struct rte_flow_action_ipv6_ext_remove. */
883 struct ipv6_ext_remove_conf {
884 	struct rte_flow_action_ipv6_ext_remove conf;
885 	uint8_t type;
886 };
887 
888 struct ipv6_ext_remove_conf ipv6_ext_remove_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
889 
890 /** Storage for struct rte_flow_action_ipv6_ext_remove including external data. */
891 struct action_ipv6_ext_remove_data {
892 	struct rte_flow_action_ipv6_ext_remove conf;
893 	uint8_t type;
894 	uint16_t idx;
895 };
896 
897 struct vxlan_encap_conf vxlan_encap_conf = {
898 	.select_ipv4 = 1,
899 	.select_vlan = 0,
900 	.select_tos_ttl = 0,
901 	.vni = { 0x00, 0x00, 0x00 },
902 	.udp_src = 0,
903 	.udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
904 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
905 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
906 	.ipv6_src = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
907 		      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
908 	.ipv6_dst = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
909 		      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11 },
910 	.vlan_tci = 0,
911 	.ip_tos = 0,
912 	.ip_ttl = 255,
913 	.eth_src = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
914 	.eth_dst = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
915 };
916 
917 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
918 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
919 
920 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
921 struct action_vxlan_encap_data {
922 	struct rte_flow_action_vxlan_encap conf;
923 	struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
924 	struct rte_flow_item_eth item_eth;
925 	struct rte_flow_item_vlan item_vlan;
926 	union {
927 		struct rte_flow_item_ipv4 item_ipv4;
928 		struct rte_flow_item_ipv6 item_ipv6;
929 	};
930 	struct rte_flow_item_udp item_udp;
931 	struct rte_flow_item_vxlan item_vxlan;
932 };
933 
934 struct nvgre_encap_conf nvgre_encap_conf = {
935 	.select_ipv4 = 1,
936 	.select_vlan = 0,
937 	.tni = { 0x00, 0x00, 0x00 },
938 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
939 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
940 	.ipv6_src = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
941 		      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
942 	.ipv6_dst = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
943 		      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11 },
944 	.vlan_tci = 0,
945 	.eth_src = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
946 	.eth_dst = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
947 };
948 
949 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
950 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
951 
952 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
953 struct action_nvgre_encap_data {
954 	struct rte_flow_action_nvgre_encap conf;
955 	struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
956 	struct rte_flow_item_eth item_eth;
957 	struct rte_flow_item_vlan item_vlan;
958 	union {
959 		struct rte_flow_item_ipv4 item_ipv4;
960 		struct rte_flow_item_ipv6 item_ipv6;
961 	};
962 	struct rte_flow_item_nvgre item_nvgre;
963 };
964 
965 struct l2_encap_conf l2_encap_conf;
966 
967 struct l2_decap_conf l2_decap_conf;
968 
969 struct mplsogre_encap_conf mplsogre_encap_conf;
970 
971 struct mplsogre_decap_conf mplsogre_decap_conf;
972 
973 struct mplsoudp_encap_conf mplsoudp_encap_conf;
974 
975 struct mplsoudp_decap_conf mplsoudp_decap_conf;
976 
977 struct rte_flow_action_conntrack conntrack_context;
978 
979 #define ACTION_SAMPLE_ACTIONS_NUM 10
980 #define RAW_SAMPLE_CONFS_MAX_NUM 8
981 /** Storage for struct rte_flow_action_sample including external data. */
982 struct action_sample_data {
983 	struct rte_flow_action_sample conf;
984 	uint32_t idx;
985 };
986 /** Storage for struct rte_flow_action_sample. */
987 struct raw_sample_conf {
988 	struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
989 };
990 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
991 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
992 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
993 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
994 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
995 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
996 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
997 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
998 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
999 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
1000 struct rte_flow_action_ethdev sample_port_representor[RAW_SAMPLE_CONFS_MAX_NUM];
1001 struct rte_flow_action_ethdev sample_represented_port[RAW_SAMPLE_CONFS_MAX_NUM];
1002 
1003 static const char *const modify_field_ops[] = {
1004 	"set", "add", "sub", NULL
1005 };
1006 
1007 static const char *const flow_field_ids[] = {
1008 	"start", "mac_dst", "mac_src",
1009 	"vlan_type", "vlan_id", "mac_type",
1010 	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
1011 	"ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
1012 	"tcp_port_src", "tcp_port_dst",
1013 	"tcp_seq_num", "tcp_ack_num", "tcp_flags",
1014 	"udp_port_src", "udp_port_dst",
1015 	"vxlan_vni", "geneve_vni", "gtp_teid",
1016 	"tag", "mark", "meta", "pointer", "value",
1017 	"ipv4_ecn", "ipv6_ecn", "gtp_psc_qfi", "meter_color",
1018 	"ipv6_proto",
1019 	"flex_item",
1020 	"hash_result",
1021 	"geneve_opt_type", "geneve_opt_class", "geneve_opt_data", "mpls",
1022 	"tcp_data_off", "ipv4_ihl", "ipv4_total_len", "ipv6_payload_len",
1023 	"ipv4_proto",
1024 	"ipv6_flow_label", "ipv6_traffic_class",
1025 	"esp_spi", "esp_seq_num", "esp_proto",
1026 	"random",
1027 	"vxlan_last_rsvd",
1028 	NULL
1029 };
1030 
1031 static const char *const meter_colors[] = {
1032 	"green", "yellow", "red", "all", NULL
1033 };
1034 
1035 static const char *const table_insertion_types[] = {
1036 	"pattern", "index", "index_with_pattern", NULL
1037 };
1038 
1039 static const char *const table_hash_funcs[] = {
1040 	"default", "linear", "crc32", "crc16", NULL
1041 };
1042 
1043 #define RAW_IPSEC_CONFS_MAX_NUM 8
1044 
1045 /** Maximum number of subsequent tokens and arguments on the stack. */
1046 #define CTX_STACK_SIZE 16
1047 
1048 /** Parser context. */
1049 struct context {
1050 	/** Stack of subsequent token lists to process. */
1051 	const enum index *next[CTX_STACK_SIZE];
1052 	/** Arguments for stacked tokens. */
1053 	const void *args[CTX_STACK_SIZE];
1054 	enum index curr; /**< Current token index. */
1055 	enum index prev; /**< Index of the last token seen. */
1056 	int next_num; /**< Number of entries in next[]. */
1057 	int args_num; /**< Number of entries in args[]. */
1058 	uint32_t eol:1; /**< EOL has been detected. */
1059 	uint32_t last:1; /**< No more arguments. */
1060 	portid_t port; /**< Current port ID (for completions). */
1061 	uint32_t objdata; /**< Object-specific data. */
1062 	void *object; /**< Address of current object for relative offsets. */
1063 	void *objmask; /**< Object a full mask must be written to. */
1064 };
1065 
1066 /** Token argument. */
1067 struct arg {
1068 	uint32_t hton:1; /**< Use network byte ordering. */
1069 	uint32_t sign:1; /**< Value is signed. */
1070 	uint32_t bounded:1; /**< Value is bounded. */
1071 	uintmax_t min; /**< Minimum value if bounded. */
1072 	uintmax_t max; /**< Maximum value if bounded. */
1073 	uint32_t offset; /**< Relative offset from ctx->object. */
1074 	uint32_t size; /**< Field size. */
1075 	const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
1076 };
1077 
1078 /** Parser token definition. */
1079 struct token {
1080 	/** Type displayed during completion (defaults to "TOKEN"). */
1081 	const char *type;
1082 	/** Help displayed during completion (defaults to token name). */
1083 	const char *help;
1084 	/** Private data used by parser functions. */
1085 	const void *priv;
1086 	/**
1087 	 * Lists of subsequent tokens to push on the stack. Each call to the
1088 	 * parser consumes the last entry of that stack.
1089 	 */
1090 	const enum index *const *next;
1091 	/** Arguments stack for subsequent tokens that need them. */
1092 	const struct arg *const *args;
1093 	/**
1094 	 * Token-processing callback, returns -1 in case of error, the
1095 	 * length of the matched string otherwise. If NULL, attempts to
1096 	 * match the token name.
1097 	 *
1098 	 * If buf is not NULL, the result should be stored in it according
1099 	 * to context. An error is returned if not large enough.
1100 	 */
1101 	int (*call)(struct context *ctx, const struct token *token,
1102 		    const char *str, unsigned int len,
1103 		    void *buf, unsigned int size);
1104 	/**
1105 	 * Callback that provides possible values for this token, used for
1106 	 * completion. Returns -1 in case of error, the number of possible
1107 	 * values otherwise. If NULL, the token name is used.
1108 	 *
1109 	 * If buf is not NULL, entry index ent is written to buf and the
1110 	 * full length of the entry is returned (same behavior as
1111 	 * snprintf()).
1112 	 */
1113 	int (*comp)(struct context *ctx, const struct token *token,
1114 		    unsigned int ent, char *buf, unsigned int size);
1115 	/** Mandatory token name, no default value. */
1116 	const char *name;
1117 };
1118 
1119 /** Static initializer for the next field. */
1120 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
1121 
1122 /** Static initializer for a NEXT() entry. */
1123 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
1124 
1125 /** Static initializer for the args field. */
1126 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
1127 
1128 /** Static initializer for ARGS() to target a field. */
1129 #define ARGS_ENTRY(s, f) \
1130 	(&(const struct arg){ \
1131 		.offset = offsetof(s, f), \
1132 		.size = sizeof(((s *)0)->f), \
1133 	})
1134 
1135 /** Static initializer for ARGS() to target a bit-field. */
1136 #define ARGS_ENTRY_BF(s, f, b) \
1137 	(&(const struct arg){ \
1138 		.size = sizeof(s), \
1139 		.mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
1140 	})
1141 
1142 /** Static initializer for ARGS() to target a field with limits. */
1143 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
1144 	(&(const struct arg){ \
1145 		.bounded = 1, \
1146 		.min = (i), \
1147 		.max = (a), \
1148 		.offset = offsetof(s, f), \
1149 		.size = sizeof(((s *)0)->f), \
1150 	})
1151 
1152 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
1153 #define ARGS_ENTRY_MASK(s, f, m) \
1154 	(&(const struct arg){ \
1155 		.offset = offsetof(s, f), \
1156 		.size = sizeof(((s *)0)->f), \
1157 		.mask = (const void *)(m), \
1158 	})
1159 
1160 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
1161 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
1162 	(&(const struct arg){ \
1163 		.hton = 1, \
1164 		.offset = offsetof(s, f), \
1165 		.size = sizeof(((s *)0)->f), \
1166 		.mask = (const void *)(m), \
1167 	})
1168 
1169 /** Static initializer for ARGS() to target a pointer. */
1170 #define ARGS_ENTRY_PTR(s, f) \
1171 	(&(const struct arg){ \
1172 		.size = sizeof(*((s *)0)->f), \
1173 	})
1174 
1175 /** Static initializer for ARGS() with arbitrary offset and size. */
1176 #define ARGS_ENTRY_ARB(o, s) \
1177 	(&(const struct arg){ \
1178 		.offset = (o), \
1179 		.size = (s), \
1180 	})
1181 
1182 /** Same as ARGS_ENTRY_ARB() with bounded values. */
1183 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
1184 	(&(const struct arg){ \
1185 		.bounded = 1, \
1186 		.min = (i), \
1187 		.max = (a), \
1188 		.offset = (o), \
1189 		.size = (s), \
1190 	})
1191 
1192 /** Same as ARGS_ENTRY() using network byte ordering. */
1193 #define ARGS_ENTRY_HTON(s, f) \
1194 	(&(const struct arg){ \
1195 		.hton = 1, \
1196 		.offset = offsetof(s, f), \
1197 		.size = sizeof(((s *)0)->f), \
1198 	})
1199 
1200 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
1201 #define ARG_ENTRY_HTON(s) \
1202 	(&(const struct arg){ \
1203 		.hton = 1, \
1204 		.offset = 0, \
1205 		.size = sizeof(s), \
1206 	})
1207 
1208 /** Parser output buffer layout expected by cmd_flow_parsed(). */
1209 struct buffer {
1210 	enum index command; /**< Flow command. */
1211 	portid_t port; /**< Affected port ID. */
1212 	queueid_t queue; /** Async queue ID. */
1213 	bool postpone; /** Postpone async operation */
1214 	union {
1215 		struct {
1216 			struct rte_flow_port_attr port_attr;
1217 			uint32_t nb_queue;
1218 			struct rte_flow_queue_attr queue_attr;
1219 		} configure; /**< Configuration arguments. */
1220 		struct {
1221 			uint32_t *template_id;
1222 			uint32_t template_id_n;
1223 		} templ_destroy; /**< Template destroy arguments. */
1224 		struct {
1225 			uint32_t id;
1226 			struct rte_flow_template_table_attr attr;
1227 			uint32_t *pat_templ_id;
1228 			uint32_t pat_templ_id_n;
1229 			uint32_t *act_templ_id;
1230 			uint32_t act_templ_id_n;
1231 		} table; /**< Table arguments. */
1232 		struct {
1233 			uint32_t *table_id;
1234 			uint32_t table_id_n;
1235 		} table_destroy; /**< Template destroy arguments. */
1236 		struct {
1237 			uint32_t *action_id;
1238 			uint32_t action_id_n;
1239 		} ia_destroy; /**< Indirect action destroy arguments. */
1240 		struct {
1241 			uint32_t action_id;
1242 			enum rte_flow_query_update_mode qu_mode;
1243 		} ia; /* Indirect action query arguments */
1244 		struct {
1245 			uint32_t table_id;
1246 			uint32_t pat_templ_id;
1247 			uint32_t rule_id;
1248 			uint32_t act_templ_id;
1249 			struct rte_flow_attr attr;
1250 			struct tunnel_ops tunnel_ops;
1251 			uintptr_t user_id;
1252 			struct rte_flow_item *pattern;
1253 			struct rte_flow_action *actions;
1254 			struct rte_flow_action *masks;
1255 			uint32_t pattern_n;
1256 			uint32_t actions_n;
1257 			uint8_t *data;
1258 			enum rte_flow_encap_hash_field field;
1259 			uint8_t encap_hash;
1260 		} vc; /**< Validate/create arguments. */
1261 		struct {
1262 			uint64_t *rule;
1263 			uint64_t rule_n;
1264 			bool is_user_id;
1265 		} destroy; /**< Destroy arguments. */
1266 		struct {
1267 			char file[128];
1268 			bool mode;
1269 			uint64_t rule;
1270 			bool is_user_id;
1271 		} dump; /**< Dump arguments. */
1272 		struct {
1273 			uint64_t rule;
1274 			struct rte_flow_action action;
1275 			bool is_user_id;
1276 		} query; /**< Query arguments. */
1277 		struct {
1278 			uint32_t *group;
1279 			uint32_t group_n;
1280 		} list; /**< List arguments. */
1281 		struct {
1282 			int set;
1283 		} isolate; /**< Isolated mode arguments. */
1284 		struct {
1285 			int destroy;
1286 		} aged; /**< Aged arguments. */
1287 		struct {
1288 			uint32_t policy_id;
1289 		} policy;/**< Policy arguments. */
1290 		struct {
1291 			uint16_t token;
1292 			uintptr_t uintptr;
1293 			char filename[128];
1294 		} flex; /**< Flex arguments*/
1295 	} args; /**< Command arguments. */
1296 };
1297 
1298 /** Private data for pattern items. */
1299 struct parse_item_priv {
1300 	enum rte_flow_item_type type; /**< Item type. */
1301 	uint32_t size; /**< Size of item specification structure. */
1302 };
1303 
1304 #define PRIV_ITEM(t, s) \
1305 	(&(const struct parse_item_priv){ \
1306 		.type = RTE_FLOW_ITEM_TYPE_ ## t, \
1307 		.size = s, \
1308 	})
1309 
1310 /** Private data for actions. */
1311 struct parse_action_priv {
1312 	enum rte_flow_action_type type; /**< Action type. */
1313 	uint32_t size; /**< Size of action configuration structure. */
1314 };
1315 
1316 #define PRIV_ACTION(t, s) \
1317 	(&(const struct parse_action_priv){ \
1318 		.type = RTE_FLOW_ACTION_TYPE_ ## t, \
1319 		.size = s, \
1320 	})
1321 
1322 static const enum index next_flex_item[] = {
1323 	FLEX_ITEM_INIT,
1324 	FLEX_ITEM_CREATE,
1325 	FLEX_ITEM_DESTROY,
1326 	ZERO,
1327 };
1328 
1329 static const enum index next_config_attr[] = {
1330 	CONFIG_QUEUES_NUMBER,
1331 	CONFIG_QUEUES_SIZE,
1332 	CONFIG_COUNTERS_NUMBER,
1333 	CONFIG_AGING_OBJECTS_NUMBER,
1334 	CONFIG_METERS_NUMBER,
1335 	CONFIG_CONN_TRACK_NUMBER,
1336 	CONFIG_QUOTAS_NUMBER,
1337 	CONFIG_FLAGS,
1338 	CONFIG_HOST_PORT,
1339 	END,
1340 	ZERO,
1341 };
1342 
1343 static const enum index next_pt_subcmd[] = {
1344 	PATTERN_TEMPLATE_CREATE,
1345 	PATTERN_TEMPLATE_DESTROY,
1346 	ZERO,
1347 };
1348 
1349 static const enum index next_pt_attr[] = {
1350 	PATTERN_TEMPLATE_CREATE_ID,
1351 	PATTERN_TEMPLATE_RELAXED_MATCHING,
1352 	PATTERN_TEMPLATE_INGRESS,
1353 	PATTERN_TEMPLATE_EGRESS,
1354 	PATTERN_TEMPLATE_TRANSFER,
1355 	PATTERN_TEMPLATE_SPEC,
1356 	ZERO,
1357 };
1358 
1359 static const enum index next_pt_destroy_attr[] = {
1360 	PATTERN_TEMPLATE_DESTROY_ID,
1361 	END,
1362 	ZERO,
1363 };
1364 
1365 static const enum index next_at_subcmd[] = {
1366 	ACTIONS_TEMPLATE_CREATE,
1367 	ACTIONS_TEMPLATE_DESTROY,
1368 	ZERO,
1369 };
1370 
1371 static const enum index next_at_attr[] = {
1372 	ACTIONS_TEMPLATE_CREATE_ID,
1373 	ACTIONS_TEMPLATE_INGRESS,
1374 	ACTIONS_TEMPLATE_EGRESS,
1375 	ACTIONS_TEMPLATE_TRANSFER,
1376 	ACTIONS_TEMPLATE_SPEC,
1377 	ZERO,
1378 };
1379 
1380 static const enum index next_at_destroy_attr[] = {
1381 	ACTIONS_TEMPLATE_DESTROY_ID,
1382 	END,
1383 	ZERO,
1384 };
1385 
1386 static const enum index next_group_attr[] = {
1387 	GROUP_INGRESS,
1388 	GROUP_EGRESS,
1389 	GROUP_TRANSFER,
1390 	GROUP_SET_MISS_ACTIONS,
1391 	ZERO,
1392 };
1393 
1394 static const enum index next_table_subcmd[] = {
1395 	TABLE_CREATE,
1396 	TABLE_DESTROY,
1397 	TABLE_RESIZE,
1398 	TABLE_RESIZE_COMPLETE,
1399 	ZERO,
1400 };
1401 
1402 static const enum index next_table_attr[] = {
1403 	TABLE_CREATE_ID,
1404 	TABLE_GROUP,
1405 	TABLE_INSERTION_TYPE,
1406 	TABLE_HASH_FUNC,
1407 	TABLE_PRIORITY,
1408 	TABLE_INGRESS,
1409 	TABLE_EGRESS,
1410 	TABLE_TRANSFER,
1411 	TABLE_TRANSFER_WIRE_ORIG,
1412 	TABLE_TRANSFER_VPORT_ORIG,
1413 	TABLE_RESIZABLE,
1414 	TABLE_RULES_NUMBER,
1415 	TABLE_PATTERN_TEMPLATE,
1416 	TABLE_ACTIONS_TEMPLATE,
1417 	END,
1418 	ZERO,
1419 };
1420 
1421 static const enum index next_table_destroy_attr[] = {
1422 	TABLE_DESTROY_ID,
1423 	END,
1424 	ZERO,
1425 };
1426 
1427 static const enum index next_queue_subcmd[] = {
1428 	QUEUE_CREATE,
1429 	QUEUE_DESTROY,
1430 	QUEUE_FLOW_UPDATE_RESIZED,
1431 	QUEUE_UPDATE,
1432 	QUEUE_AGED,
1433 	QUEUE_INDIRECT_ACTION,
1434 	ZERO,
1435 };
1436 
1437 static const enum index next_queue_destroy_attr[] = {
1438 	QUEUE_DESTROY_ID,
1439 	END,
1440 	ZERO,
1441 };
1442 
1443 static const enum index next_qia_subcmd[] = {
1444 	QUEUE_INDIRECT_ACTION_CREATE,
1445 	QUEUE_INDIRECT_ACTION_UPDATE,
1446 	QUEUE_INDIRECT_ACTION_DESTROY,
1447 	QUEUE_INDIRECT_ACTION_QUERY,
1448 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
1449 	ZERO,
1450 };
1451 
1452 static const enum index next_qia_create_attr[] = {
1453 	QUEUE_INDIRECT_ACTION_CREATE_ID,
1454 	QUEUE_INDIRECT_ACTION_INGRESS,
1455 	QUEUE_INDIRECT_ACTION_EGRESS,
1456 	QUEUE_INDIRECT_ACTION_TRANSFER,
1457 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
1458 	QUEUE_INDIRECT_ACTION_SPEC,
1459 	QUEUE_INDIRECT_ACTION_LIST,
1460 	ZERO,
1461 };
1462 
1463 static const enum index next_qia_update_attr[] = {
1464 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1465 	QUEUE_INDIRECT_ACTION_SPEC,
1466 	ZERO,
1467 };
1468 
1469 static const enum index next_qia_destroy_attr[] = {
1470 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
1471 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
1472 	END,
1473 	ZERO,
1474 };
1475 
1476 static const enum index next_qia_query_attr[] = {
1477 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
1478 	END,
1479 	ZERO,
1480 };
1481 
1482 static const enum index next_ia_create_attr[] = {
1483 	INDIRECT_ACTION_CREATE_ID,
1484 	INDIRECT_ACTION_INGRESS,
1485 	INDIRECT_ACTION_EGRESS,
1486 	INDIRECT_ACTION_TRANSFER,
1487 	INDIRECT_ACTION_SPEC,
1488 	INDIRECT_ACTION_LIST,
1489 	INDIRECT_ACTION_FLOW_CONF,
1490 	ZERO,
1491 };
1492 
1493 static const enum index next_ia[] = {
1494 	INDIRECT_ACTION_ID2PTR,
1495 	ACTION_NEXT,
1496 	ZERO
1497 };
1498 
1499 static const enum index next_ial[] = {
1500 	ACTION_INDIRECT_LIST_HANDLE,
1501 	ACTION_INDIRECT_LIST_CONF,
1502 	ACTION_NEXT,
1503 	ZERO
1504 };
1505 
1506 static const enum index next_qia_qu_attr[] = {
1507 	QUEUE_INDIRECT_ACTION_QU_MODE,
1508 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1509 	INDIRECT_ACTION_SPEC,
1510 	ZERO
1511 };
1512 
1513 static const enum index next_ia_qu_attr[] = {
1514 	INDIRECT_ACTION_QU_MODE,
1515 	INDIRECT_ACTION_SPEC,
1516 	ZERO
1517 };
1518 
1519 static const enum index next_dump_subcmd[] = {
1520 	DUMP_ALL,
1521 	DUMP_ONE,
1522 	DUMP_IS_USER_ID,
1523 	ZERO,
1524 };
1525 
1526 static const enum index next_ia_subcmd[] = {
1527 	INDIRECT_ACTION_CREATE,
1528 	INDIRECT_ACTION_UPDATE,
1529 	INDIRECT_ACTION_DESTROY,
1530 	INDIRECT_ACTION_QUERY,
1531 	INDIRECT_ACTION_QUERY_UPDATE,
1532 	ZERO,
1533 };
1534 
1535 static const enum index next_vc_attr[] = {
1536 	VC_GROUP,
1537 	VC_PRIORITY,
1538 	VC_INGRESS,
1539 	VC_EGRESS,
1540 	VC_TRANSFER,
1541 	VC_TUNNEL_SET,
1542 	VC_TUNNEL_MATCH,
1543 	VC_USER_ID,
1544 	ITEM_PATTERN,
1545 	ZERO,
1546 };
1547 
1548 static const enum index next_destroy_attr[] = {
1549 	DESTROY_RULE,
1550 	DESTROY_IS_USER_ID,
1551 	END,
1552 	ZERO,
1553 };
1554 
1555 static const enum index next_dump_attr[] = {
1556 	COMMON_FILE_PATH,
1557 	END,
1558 	ZERO,
1559 };
1560 
1561 static const enum index next_query_attr[] = {
1562 	QUERY_IS_USER_ID,
1563 	END,
1564 	ZERO,
1565 };
1566 
1567 static const enum index next_list_attr[] = {
1568 	LIST_GROUP,
1569 	END,
1570 	ZERO,
1571 };
1572 
1573 static const enum index next_aged_attr[] = {
1574 	AGED_DESTROY,
1575 	END,
1576 	ZERO,
1577 };
1578 
1579 static const enum index next_ia_destroy_attr[] = {
1580 	INDIRECT_ACTION_DESTROY_ID,
1581 	END,
1582 	ZERO,
1583 };
1584 
1585 static const enum index next_async_insert_subcmd[] = {
1586 	QUEUE_PATTERN_TEMPLATE,
1587 	QUEUE_RULE_ID,
1588 	ZERO,
1589 };
1590 
1591 static const enum index next_async_pattern_subcmd[] = {
1592 	QUEUE_PATTERN_TEMPLATE,
1593 	QUEUE_ACTIONS_TEMPLATE,
1594 	ZERO,
1595 };
1596 
1597 static const enum index item_param[] = {
1598 	ITEM_PARAM_IS,
1599 	ITEM_PARAM_SPEC,
1600 	ITEM_PARAM_LAST,
1601 	ITEM_PARAM_MASK,
1602 	ITEM_PARAM_PREFIX,
1603 	ZERO,
1604 };
1605 
1606 static const enum index next_item[] = {
1607 	ITEM_END,
1608 	ITEM_VOID,
1609 	ITEM_INVERT,
1610 	ITEM_ANY,
1611 	ITEM_PORT_ID,
1612 	ITEM_MARK,
1613 	ITEM_RAW,
1614 	ITEM_ETH,
1615 	ITEM_VLAN,
1616 	ITEM_IPV4,
1617 	ITEM_IPV6,
1618 	ITEM_ICMP,
1619 	ITEM_UDP,
1620 	ITEM_TCP,
1621 	ITEM_SCTP,
1622 	ITEM_VXLAN,
1623 	ITEM_E_TAG,
1624 	ITEM_NVGRE,
1625 	ITEM_MPLS,
1626 	ITEM_GRE,
1627 	ITEM_FUZZY,
1628 	ITEM_GTP,
1629 	ITEM_GTPC,
1630 	ITEM_GTPU,
1631 	ITEM_GENEVE,
1632 	ITEM_VXLAN_GPE,
1633 	ITEM_ARP_ETH_IPV4,
1634 	ITEM_IPV6_EXT,
1635 	ITEM_IPV6_FRAG_EXT,
1636 	ITEM_IPV6_ROUTING_EXT,
1637 	ITEM_ICMP6,
1638 	ITEM_ICMP6_ECHO_REQUEST,
1639 	ITEM_ICMP6_ECHO_REPLY,
1640 	ITEM_ICMP6_ND_NS,
1641 	ITEM_ICMP6_ND_NA,
1642 	ITEM_ICMP6_ND_OPT,
1643 	ITEM_ICMP6_ND_OPT_SLA_ETH,
1644 	ITEM_ICMP6_ND_OPT_TLA_ETH,
1645 	ITEM_META,
1646 	ITEM_RANDOM,
1647 	ITEM_GRE_KEY,
1648 	ITEM_GRE_OPTION,
1649 	ITEM_GTP_PSC,
1650 	ITEM_PPPOES,
1651 	ITEM_PPPOED,
1652 	ITEM_PPPOE_PROTO_ID,
1653 	ITEM_HIGIG2,
1654 	ITEM_TAG,
1655 	ITEM_L2TPV3OIP,
1656 	ITEM_ESP,
1657 	ITEM_AH,
1658 	ITEM_PFCP,
1659 	ITEM_ECPRI,
1660 	ITEM_GENEVE_OPT,
1661 	ITEM_INTEGRITY,
1662 	ITEM_CONNTRACK,
1663 	ITEM_PORT_REPRESENTOR,
1664 	ITEM_REPRESENTED_PORT,
1665 	ITEM_FLEX,
1666 	ITEM_L2TPV2,
1667 	ITEM_PPP,
1668 	ITEM_METER,
1669 	ITEM_QUOTA,
1670 	ITEM_AGGR_AFFINITY,
1671 	ITEM_TX_QUEUE,
1672 	ITEM_IB_BTH,
1673 	ITEM_PTYPE,
1674 	ITEM_NSH,
1675 	ITEM_COMPARE,
1676 	END_SET,
1677 	ZERO,
1678 };
1679 
1680 static const enum index item_fuzzy[] = {
1681 	ITEM_FUZZY_THRESH,
1682 	ITEM_NEXT,
1683 	ZERO,
1684 };
1685 
1686 static const enum index item_any[] = {
1687 	ITEM_ANY_NUM,
1688 	ITEM_NEXT,
1689 	ZERO,
1690 };
1691 
1692 static const enum index item_port_id[] = {
1693 	ITEM_PORT_ID_ID,
1694 	ITEM_NEXT,
1695 	ZERO,
1696 };
1697 
1698 static const enum index item_mark[] = {
1699 	ITEM_MARK_ID,
1700 	ITEM_NEXT,
1701 	ZERO,
1702 };
1703 
1704 static const enum index item_raw[] = {
1705 	ITEM_RAW_RELATIVE,
1706 	ITEM_RAW_SEARCH,
1707 	ITEM_RAW_OFFSET,
1708 	ITEM_RAW_LIMIT,
1709 	ITEM_RAW_PATTERN,
1710 	ITEM_RAW_PATTERN_HEX,
1711 	ITEM_NEXT,
1712 	ZERO,
1713 };
1714 
1715 static const enum index item_eth[] = {
1716 	ITEM_ETH_DST,
1717 	ITEM_ETH_SRC,
1718 	ITEM_ETH_TYPE,
1719 	ITEM_ETH_HAS_VLAN,
1720 	ITEM_NEXT,
1721 	ZERO,
1722 };
1723 
1724 static const enum index item_vlan[] = {
1725 	ITEM_VLAN_TCI,
1726 	ITEM_VLAN_PCP,
1727 	ITEM_VLAN_DEI,
1728 	ITEM_VLAN_VID,
1729 	ITEM_VLAN_INNER_TYPE,
1730 	ITEM_VLAN_HAS_MORE_VLAN,
1731 	ITEM_NEXT,
1732 	ZERO,
1733 };
1734 
1735 static const enum index item_ipv4[] = {
1736 	ITEM_IPV4_VER_IHL,
1737 	ITEM_IPV4_TOS,
1738 	ITEM_IPV4_LENGTH,
1739 	ITEM_IPV4_ID,
1740 	ITEM_IPV4_FRAGMENT_OFFSET,
1741 	ITEM_IPV4_TTL,
1742 	ITEM_IPV4_PROTO,
1743 	ITEM_IPV4_SRC,
1744 	ITEM_IPV4_DST,
1745 	ITEM_NEXT,
1746 	ZERO,
1747 };
1748 
1749 static const enum index item_ipv6[] = {
1750 	ITEM_IPV6_TC,
1751 	ITEM_IPV6_FLOW,
1752 	ITEM_IPV6_LEN,
1753 	ITEM_IPV6_PROTO,
1754 	ITEM_IPV6_HOP,
1755 	ITEM_IPV6_SRC,
1756 	ITEM_IPV6_DST,
1757 	ITEM_IPV6_HAS_FRAG_EXT,
1758 	ITEM_IPV6_ROUTING_EXT,
1759 	ITEM_NEXT,
1760 	ZERO,
1761 };
1762 
1763 static const enum index item_ipv6_routing_ext[] = {
1764 	ITEM_IPV6_ROUTING_EXT_TYPE,
1765 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
1766 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
1767 	ITEM_NEXT,
1768 	ZERO,
1769 };
1770 
1771 static const enum index item_icmp[] = {
1772 	ITEM_ICMP_TYPE,
1773 	ITEM_ICMP_CODE,
1774 	ITEM_ICMP_IDENT,
1775 	ITEM_ICMP_SEQ,
1776 	ITEM_NEXT,
1777 	ZERO,
1778 };
1779 
1780 static const enum index item_udp[] = {
1781 	ITEM_UDP_SRC,
1782 	ITEM_UDP_DST,
1783 	ITEM_NEXT,
1784 	ZERO,
1785 };
1786 
1787 static const enum index item_tcp[] = {
1788 	ITEM_TCP_SRC,
1789 	ITEM_TCP_DST,
1790 	ITEM_TCP_FLAGS,
1791 	ITEM_NEXT,
1792 	ZERO,
1793 };
1794 
1795 static const enum index item_sctp[] = {
1796 	ITEM_SCTP_SRC,
1797 	ITEM_SCTP_DST,
1798 	ITEM_SCTP_TAG,
1799 	ITEM_SCTP_CKSUM,
1800 	ITEM_NEXT,
1801 	ZERO,
1802 };
1803 
1804 static const enum index item_vxlan[] = {
1805 	ITEM_VXLAN_VNI,
1806 	ITEM_VXLAN_FLAG_G,
1807 	ITEM_VXLAN_FLAG_VER,
1808 	ITEM_VXLAN_FLAG_I,
1809 	ITEM_VXLAN_FLAG_P,
1810 	ITEM_VXLAN_FLAG_B,
1811 	ITEM_VXLAN_FLAG_O,
1812 	ITEM_VXLAN_FLAG_D,
1813 	ITEM_VXLAN_FLAG_A,
1814 	ITEM_VXLAN_GBP_ID,
1815 	ITEM_VXLAN_GPE_PROTO,
1816 	ITEM_VXLAN_FIRST_RSVD,
1817 	ITEM_VXLAN_SECND_RSVD,
1818 	ITEM_VXLAN_THIRD_RSVD,
1819 	ITEM_VXLAN_LAST_RSVD,
1820 	ITEM_NEXT,
1821 	ZERO,
1822 };
1823 
1824 static const enum index item_e_tag[] = {
1825 	ITEM_E_TAG_GRP_ECID_B,
1826 	ITEM_NEXT,
1827 	ZERO,
1828 };
1829 
1830 static const enum index item_nvgre[] = {
1831 	ITEM_NVGRE_TNI,
1832 	ITEM_NEXT,
1833 	ZERO,
1834 };
1835 
1836 static const enum index item_mpls[] = {
1837 	ITEM_MPLS_LABEL,
1838 	ITEM_MPLS_TC,
1839 	ITEM_MPLS_S,
1840 	ITEM_MPLS_TTL,
1841 	ITEM_NEXT,
1842 	ZERO,
1843 };
1844 
1845 static const enum index item_gre[] = {
1846 	ITEM_GRE_PROTO,
1847 	ITEM_GRE_C_RSVD0_VER,
1848 	ITEM_GRE_C_BIT,
1849 	ITEM_GRE_K_BIT,
1850 	ITEM_GRE_S_BIT,
1851 	ITEM_NEXT,
1852 	ZERO,
1853 };
1854 
1855 static const enum index item_gre_key[] = {
1856 	ITEM_GRE_KEY_VALUE,
1857 	ITEM_NEXT,
1858 	ZERO,
1859 };
1860 
1861 static const enum index item_gre_option[] = {
1862 	ITEM_GRE_OPTION_CHECKSUM,
1863 	ITEM_GRE_OPTION_KEY,
1864 	ITEM_GRE_OPTION_SEQUENCE,
1865 	ITEM_NEXT,
1866 	ZERO,
1867 };
1868 
1869 static const enum index item_gtp[] = {
1870 	ITEM_GTP_FLAGS,
1871 	ITEM_GTP_MSG_TYPE,
1872 	ITEM_GTP_TEID,
1873 	ITEM_NEXT,
1874 	ZERO,
1875 };
1876 
1877 static const enum index item_geneve[] = {
1878 	ITEM_GENEVE_VNI,
1879 	ITEM_GENEVE_PROTO,
1880 	ITEM_GENEVE_OPTLEN,
1881 	ITEM_NEXT,
1882 	ZERO,
1883 };
1884 
1885 static const enum index item_vxlan_gpe[] = {
1886 	ITEM_VXLAN_GPE_VNI,
1887 	ITEM_VXLAN_GPE_PROTO_IN_DEPRECATED_VXLAN_GPE_HDR,
1888 	ITEM_VXLAN_GPE_FLAGS,
1889 	ITEM_VXLAN_GPE_RSVD0,
1890 	ITEM_VXLAN_GPE_RSVD1,
1891 	ITEM_NEXT,
1892 	ZERO,
1893 };
1894 
1895 static const enum index item_arp_eth_ipv4[] = {
1896 	ITEM_ARP_ETH_IPV4_SHA,
1897 	ITEM_ARP_ETH_IPV4_SPA,
1898 	ITEM_ARP_ETH_IPV4_THA,
1899 	ITEM_ARP_ETH_IPV4_TPA,
1900 	ITEM_NEXT,
1901 	ZERO,
1902 };
1903 
1904 static const enum index item_ipv6_ext[] = {
1905 	ITEM_IPV6_EXT_NEXT_HDR,
1906 	ITEM_NEXT,
1907 	ZERO,
1908 };
1909 
1910 static const enum index item_ipv6_frag_ext[] = {
1911 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1912 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1913 	ITEM_IPV6_FRAG_EXT_ID,
1914 	ITEM_NEXT,
1915 	ZERO,
1916 };
1917 
1918 static const enum index item_icmp6[] = {
1919 	ITEM_ICMP6_TYPE,
1920 	ITEM_ICMP6_CODE,
1921 	ITEM_NEXT,
1922 	ZERO,
1923 };
1924 
1925 static const enum index item_icmp6_echo_request[] = {
1926 	ITEM_ICMP6_ECHO_REQUEST_ID,
1927 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
1928 	ITEM_NEXT,
1929 	ZERO,
1930 };
1931 
1932 static const enum index item_icmp6_echo_reply[] = {
1933 	ITEM_ICMP6_ECHO_REPLY_ID,
1934 	ITEM_ICMP6_ECHO_REPLY_SEQ,
1935 	ITEM_NEXT,
1936 	ZERO,
1937 };
1938 
1939 static const enum index item_icmp6_nd_ns[] = {
1940 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
1941 	ITEM_NEXT,
1942 	ZERO,
1943 };
1944 
1945 static const enum index item_icmp6_nd_na[] = {
1946 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
1947 	ITEM_NEXT,
1948 	ZERO,
1949 };
1950 
1951 static const enum index item_icmp6_nd_opt[] = {
1952 	ITEM_ICMP6_ND_OPT_TYPE,
1953 	ITEM_NEXT,
1954 	ZERO,
1955 };
1956 
1957 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1958 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1959 	ITEM_NEXT,
1960 	ZERO,
1961 };
1962 
1963 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1964 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1965 	ITEM_NEXT,
1966 	ZERO,
1967 };
1968 
1969 static const enum index item_meta[] = {
1970 	ITEM_META_DATA,
1971 	ITEM_NEXT,
1972 	ZERO,
1973 };
1974 
1975 static const enum index item_random[] = {
1976 	ITEM_RANDOM_VALUE,
1977 	ITEM_NEXT,
1978 	ZERO,
1979 };
1980 
1981 static const enum index item_gtp_psc[] = {
1982 	ITEM_GTP_PSC_QFI,
1983 	ITEM_GTP_PSC_PDU_T,
1984 	ITEM_NEXT,
1985 	ZERO,
1986 };
1987 
1988 static const enum index item_pppoed[] = {
1989 	ITEM_PPPOE_SEID,
1990 	ITEM_NEXT,
1991 	ZERO,
1992 };
1993 
1994 static const enum index item_pppoes[] = {
1995 	ITEM_PPPOE_SEID,
1996 	ITEM_NEXT,
1997 	ZERO,
1998 };
1999 
2000 static const enum index item_pppoe_proto_id[] = {
2001 	ITEM_NEXT,
2002 	ZERO,
2003 };
2004 
2005 static const enum index item_higig2[] = {
2006 	ITEM_HIGIG2_CLASSIFICATION,
2007 	ITEM_HIGIG2_VID,
2008 	ITEM_NEXT,
2009 	ZERO,
2010 };
2011 
2012 static const enum index item_esp[] = {
2013 	ITEM_ESP_SPI,
2014 	ITEM_NEXT,
2015 	ZERO,
2016 };
2017 
2018 static const enum index item_ah[] = {
2019 	ITEM_AH_SPI,
2020 	ITEM_NEXT,
2021 	ZERO,
2022 };
2023 
2024 static const enum index item_pfcp[] = {
2025 	ITEM_PFCP_S_FIELD,
2026 	ITEM_PFCP_SEID,
2027 	ITEM_NEXT,
2028 	ZERO,
2029 };
2030 
2031 static const enum index next_set_raw[] = {
2032 	SET_RAW_INDEX,
2033 	ITEM_ETH,
2034 	ZERO,
2035 };
2036 
2037 static const enum index item_tag[] = {
2038 	ITEM_TAG_DATA,
2039 	ITEM_TAG_INDEX,
2040 	ITEM_NEXT,
2041 	ZERO,
2042 };
2043 
2044 static const enum index item_l2tpv3oip[] = {
2045 	ITEM_L2TPV3OIP_SESSION_ID,
2046 	ITEM_NEXT,
2047 	ZERO,
2048 };
2049 
2050 static const enum index item_ecpri[] = {
2051 	ITEM_ECPRI_COMMON,
2052 	ITEM_NEXT,
2053 	ZERO,
2054 };
2055 
2056 static const enum index item_ecpri_common[] = {
2057 	ITEM_ECPRI_COMMON_TYPE,
2058 	ZERO,
2059 };
2060 
2061 static const enum index item_ecpri_common_type[] = {
2062 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
2063 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
2064 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
2065 	ZERO,
2066 };
2067 
2068 static const enum index item_geneve_opt[] = {
2069 	ITEM_GENEVE_OPT_CLASS,
2070 	ITEM_GENEVE_OPT_TYPE,
2071 	ITEM_GENEVE_OPT_LENGTH,
2072 	ITEM_GENEVE_OPT_DATA,
2073 	ITEM_NEXT,
2074 	ZERO,
2075 };
2076 
2077 static const enum index item_integrity[] = {
2078 	ITEM_INTEGRITY_LEVEL,
2079 	ITEM_INTEGRITY_VALUE,
2080 	ZERO,
2081 };
2082 
2083 static const enum index item_integrity_lv[] = {
2084 	ITEM_INTEGRITY_LEVEL,
2085 	ITEM_INTEGRITY_VALUE,
2086 	ITEM_NEXT,
2087 	ZERO,
2088 };
2089 
2090 static const enum index item_port_representor[] = {
2091 	ITEM_PORT_REPRESENTOR_PORT_ID,
2092 	ITEM_NEXT,
2093 	ZERO,
2094 };
2095 
2096 static const enum index item_represented_port[] = {
2097 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
2098 	ITEM_NEXT,
2099 	ZERO,
2100 };
2101 
2102 static const enum index item_flex[] = {
2103 	ITEM_FLEX_PATTERN_HANDLE,
2104 	ITEM_FLEX_ITEM_HANDLE,
2105 	ITEM_NEXT,
2106 	ZERO,
2107 };
2108 
2109 static const enum index item_l2tpv2[] = {
2110 	ITEM_L2TPV2_TYPE,
2111 	ITEM_NEXT,
2112 	ZERO,
2113 };
2114 
2115 static const enum index item_l2tpv2_type[] = {
2116 	ITEM_L2TPV2_TYPE_DATA,
2117 	ITEM_L2TPV2_TYPE_DATA_L,
2118 	ITEM_L2TPV2_TYPE_DATA_S,
2119 	ITEM_L2TPV2_TYPE_DATA_O,
2120 	ITEM_L2TPV2_TYPE_DATA_L_S,
2121 	ITEM_L2TPV2_TYPE_CTRL,
2122 	ZERO,
2123 };
2124 
2125 static const enum index item_l2tpv2_type_data[] = {
2126 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
2127 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
2128 	ITEM_NEXT,
2129 	ZERO,
2130 };
2131 
2132 static const enum index item_l2tpv2_type_data_l[] = {
2133 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
2134 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
2135 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
2136 	ITEM_NEXT,
2137 	ZERO,
2138 };
2139 
2140 static const enum index item_l2tpv2_type_data_s[] = {
2141 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
2142 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
2143 	ITEM_L2TPV2_MSG_DATA_S_NS,
2144 	ITEM_L2TPV2_MSG_DATA_S_NR,
2145 	ITEM_NEXT,
2146 	ZERO,
2147 };
2148 
2149 static const enum index item_l2tpv2_type_data_o[] = {
2150 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
2151 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
2152 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
2153 	ITEM_NEXT,
2154 	ZERO,
2155 };
2156 
2157 static const enum index item_l2tpv2_type_data_l_s[] = {
2158 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
2159 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
2160 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
2161 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
2162 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
2163 	ITEM_NEXT,
2164 	ZERO,
2165 };
2166 
2167 static const enum index item_l2tpv2_type_ctrl[] = {
2168 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
2169 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
2170 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
2171 	ITEM_L2TPV2_MSG_CTRL_NS,
2172 	ITEM_L2TPV2_MSG_CTRL_NR,
2173 	ITEM_NEXT,
2174 	ZERO,
2175 };
2176 
2177 static const enum index item_ppp[] = {
2178 	ITEM_PPP_ADDR,
2179 	ITEM_PPP_CTRL,
2180 	ITEM_PPP_PROTO_ID,
2181 	ITEM_NEXT,
2182 	ZERO,
2183 };
2184 
2185 static const enum index item_meter[] = {
2186 	ITEM_METER_COLOR,
2187 	ITEM_NEXT,
2188 	ZERO,
2189 };
2190 
2191 static const enum index item_quota[] = {
2192 	ITEM_QUOTA_STATE,
2193 	ITEM_NEXT,
2194 	ZERO,
2195 };
2196 
2197 static const enum index item_aggr_affinity[] = {
2198 	ITEM_AGGR_AFFINITY_VALUE,
2199 	ITEM_NEXT,
2200 	ZERO,
2201 };
2202 
2203 static const enum index item_tx_queue[] = {
2204 	ITEM_TX_QUEUE_VALUE,
2205 	ITEM_NEXT,
2206 	ZERO,
2207 };
2208 
2209 static const enum index item_ib_bth[] = {
2210 	ITEM_IB_BTH_OPCODE,
2211 	ITEM_IB_BTH_PKEY,
2212 	ITEM_IB_BTH_DST_QPN,
2213 	ITEM_IB_BTH_PSN,
2214 	ITEM_NEXT,
2215 	ZERO,
2216 };
2217 
2218 static const enum index item_ptype[] = {
2219 	ITEM_PTYPE_VALUE,
2220 	ITEM_NEXT,
2221 	ZERO,
2222 };
2223 
2224 static const enum index item_nsh[] = {
2225 	ITEM_NEXT,
2226 	ZERO,
2227 };
2228 
2229 static const enum index item_compare_field[] = {
2230 	ITEM_COMPARE_OP,
2231 	ITEM_COMPARE_FIELD_A_TYPE,
2232 	ITEM_COMPARE_FIELD_B_TYPE,
2233 	ITEM_NEXT,
2234 	ZERO,
2235 };
2236 
2237 static const enum index compare_field_a[] = {
2238 	ITEM_COMPARE_FIELD_A_TYPE,
2239 	ITEM_COMPARE_FIELD_A_LEVEL,
2240 	ITEM_COMPARE_FIELD_A_TAG_INDEX,
2241 	ITEM_COMPARE_FIELD_A_TYPE_ID,
2242 	ITEM_COMPARE_FIELD_A_CLASS_ID,
2243 	ITEM_COMPARE_FIELD_A_OFFSET,
2244 	ITEM_COMPARE_FIELD_B_TYPE,
2245 	ZERO,
2246 };
2247 
2248 static const enum index compare_field_b[] = {
2249 	ITEM_COMPARE_FIELD_B_TYPE,
2250 	ITEM_COMPARE_FIELD_B_LEVEL,
2251 	ITEM_COMPARE_FIELD_B_TAG_INDEX,
2252 	ITEM_COMPARE_FIELD_B_TYPE_ID,
2253 	ITEM_COMPARE_FIELD_B_CLASS_ID,
2254 	ITEM_COMPARE_FIELD_B_OFFSET,
2255 	ITEM_COMPARE_FIELD_B_VALUE,
2256 	ITEM_COMPARE_FIELD_B_POINTER,
2257 	ITEM_COMPARE_FIELD_WIDTH,
2258 	ZERO,
2259 };
2260 
2261 static const enum index next_action[] = {
2262 	ACTION_END,
2263 	ACTION_VOID,
2264 	ACTION_PASSTHRU,
2265 	ACTION_SKIP_CMAN,
2266 	ACTION_JUMP,
2267 	ACTION_MARK,
2268 	ACTION_FLAG,
2269 	ACTION_QUEUE,
2270 	ACTION_DROP,
2271 	ACTION_COUNT,
2272 	ACTION_RSS,
2273 	ACTION_PF,
2274 	ACTION_VF,
2275 	ACTION_PORT_ID,
2276 	ACTION_METER,
2277 	ACTION_METER_COLOR,
2278 	ACTION_METER_MARK,
2279 	ACTION_OF_DEC_NW_TTL,
2280 	ACTION_OF_POP_VLAN,
2281 	ACTION_OF_PUSH_VLAN,
2282 	ACTION_OF_SET_VLAN_VID,
2283 	ACTION_OF_SET_VLAN_PCP,
2284 	ACTION_OF_POP_MPLS,
2285 	ACTION_OF_PUSH_MPLS,
2286 	ACTION_VXLAN_ENCAP,
2287 	ACTION_VXLAN_DECAP,
2288 	ACTION_NVGRE_ENCAP,
2289 	ACTION_NVGRE_DECAP,
2290 	ACTION_L2_ENCAP,
2291 	ACTION_L2_DECAP,
2292 	ACTION_MPLSOGRE_ENCAP,
2293 	ACTION_MPLSOGRE_DECAP,
2294 	ACTION_MPLSOUDP_ENCAP,
2295 	ACTION_MPLSOUDP_DECAP,
2296 	ACTION_SET_IPV4_SRC,
2297 	ACTION_SET_IPV4_DST,
2298 	ACTION_SET_IPV6_SRC,
2299 	ACTION_SET_IPV6_DST,
2300 	ACTION_SET_TP_SRC,
2301 	ACTION_SET_TP_DST,
2302 	ACTION_MAC_SWAP,
2303 	ACTION_DEC_TTL,
2304 	ACTION_SET_TTL,
2305 	ACTION_SET_MAC_SRC,
2306 	ACTION_SET_MAC_DST,
2307 	ACTION_INC_TCP_SEQ,
2308 	ACTION_DEC_TCP_SEQ,
2309 	ACTION_INC_TCP_ACK,
2310 	ACTION_DEC_TCP_ACK,
2311 	ACTION_RAW_ENCAP,
2312 	ACTION_RAW_DECAP,
2313 	ACTION_SET_TAG,
2314 	ACTION_SET_META,
2315 	ACTION_SET_IPV4_DSCP,
2316 	ACTION_SET_IPV6_DSCP,
2317 	ACTION_AGE,
2318 	ACTION_AGE_UPDATE,
2319 	ACTION_SAMPLE,
2320 	ACTION_INDIRECT,
2321 	ACTION_INDIRECT_LIST,
2322 	ACTION_SHARED_INDIRECT,
2323 	ACTION_MODIFY_FIELD,
2324 	ACTION_CONNTRACK,
2325 	ACTION_CONNTRACK_UPDATE,
2326 	ACTION_PORT_REPRESENTOR,
2327 	ACTION_REPRESENTED_PORT,
2328 	ACTION_SEND_TO_KERNEL,
2329 	ACTION_QUOTA_CREATE,
2330 	ACTION_QUOTA_QU,
2331 	ACTION_IPV6_EXT_REMOVE,
2332 	ACTION_IPV6_EXT_PUSH,
2333 	ACTION_NAT64,
2334 	ACTION_JUMP_TO_TABLE_INDEX,
2335 	ZERO,
2336 };
2337 
2338 static const enum index action_quota_create[] = {
2339 	ACTION_QUOTA_CREATE_LIMIT,
2340 	ACTION_QUOTA_CREATE_MODE,
2341 	ACTION_NEXT,
2342 	ZERO
2343 };
2344 
2345 static const enum index action_quota_update[] = {
2346 	ACTION_QUOTA_QU_LIMIT,
2347 	ACTION_QUOTA_QU_UPDATE_OP,
2348 	ACTION_NEXT,
2349 	ZERO
2350 };
2351 
2352 static const enum index action_mark[] = {
2353 	ACTION_MARK_ID,
2354 	ACTION_NEXT,
2355 	ZERO,
2356 };
2357 
2358 static const enum index action_queue[] = {
2359 	ACTION_QUEUE_INDEX,
2360 	ACTION_NEXT,
2361 	ZERO,
2362 };
2363 
2364 static const enum index action_count[] = {
2365 	ACTION_COUNT_ID,
2366 	ACTION_NEXT,
2367 	ZERO,
2368 };
2369 
2370 static const enum index action_rss[] = {
2371 	ACTION_RSS_FUNC,
2372 	ACTION_RSS_LEVEL,
2373 	ACTION_RSS_TYPES,
2374 	ACTION_RSS_KEY,
2375 	ACTION_RSS_KEY_LEN,
2376 	ACTION_RSS_QUEUES,
2377 	ACTION_NEXT,
2378 	ZERO,
2379 };
2380 
2381 static const enum index action_vf[] = {
2382 	ACTION_VF_ORIGINAL,
2383 	ACTION_VF_ID,
2384 	ACTION_NEXT,
2385 	ZERO,
2386 };
2387 
2388 static const enum index action_port_id[] = {
2389 	ACTION_PORT_ID_ORIGINAL,
2390 	ACTION_PORT_ID_ID,
2391 	ACTION_NEXT,
2392 	ZERO,
2393 };
2394 
2395 static const enum index action_meter[] = {
2396 	ACTION_METER_ID,
2397 	ACTION_NEXT,
2398 	ZERO,
2399 };
2400 
2401 static const enum index action_meter_color[] = {
2402 	ACTION_METER_COLOR_TYPE,
2403 	ACTION_NEXT,
2404 	ZERO,
2405 };
2406 
2407 static const enum index action_meter_mark[] = {
2408 	ACTION_METER_PROFILE,
2409 	ACTION_METER_POLICY,
2410 	ACTION_METER_COLOR_MODE,
2411 	ACTION_METER_STATE,
2412 	ACTION_NEXT,
2413 	ZERO,
2414 };
2415 
2416 static const enum index action_of_push_vlan[] = {
2417 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
2418 	ACTION_NEXT,
2419 	ZERO,
2420 };
2421 
2422 static const enum index action_of_set_vlan_vid[] = {
2423 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
2424 	ACTION_NEXT,
2425 	ZERO,
2426 };
2427 
2428 static const enum index action_of_set_vlan_pcp[] = {
2429 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
2430 	ACTION_NEXT,
2431 	ZERO,
2432 };
2433 
2434 static const enum index action_of_pop_mpls[] = {
2435 	ACTION_OF_POP_MPLS_ETHERTYPE,
2436 	ACTION_NEXT,
2437 	ZERO,
2438 };
2439 
2440 static const enum index action_of_push_mpls[] = {
2441 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
2442 	ACTION_NEXT,
2443 	ZERO,
2444 };
2445 
2446 static const enum index action_set_ipv4_src[] = {
2447 	ACTION_SET_IPV4_SRC_IPV4_SRC,
2448 	ACTION_NEXT,
2449 	ZERO,
2450 };
2451 
2452 static const enum index action_set_mac_src[] = {
2453 	ACTION_SET_MAC_SRC_MAC_SRC,
2454 	ACTION_NEXT,
2455 	ZERO,
2456 };
2457 
2458 static const enum index action_set_ipv4_dst[] = {
2459 	ACTION_SET_IPV4_DST_IPV4_DST,
2460 	ACTION_NEXT,
2461 	ZERO,
2462 };
2463 
2464 static const enum index action_set_ipv6_src[] = {
2465 	ACTION_SET_IPV6_SRC_IPV6_SRC,
2466 	ACTION_NEXT,
2467 	ZERO,
2468 };
2469 
2470 static const enum index action_set_ipv6_dst[] = {
2471 	ACTION_SET_IPV6_DST_IPV6_DST,
2472 	ACTION_NEXT,
2473 	ZERO,
2474 };
2475 
2476 static const enum index action_set_tp_src[] = {
2477 	ACTION_SET_TP_SRC_TP_SRC,
2478 	ACTION_NEXT,
2479 	ZERO,
2480 };
2481 
2482 static const enum index action_set_tp_dst[] = {
2483 	ACTION_SET_TP_DST_TP_DST,
2484 	ACTION_NEXT,
2485 	ZERO,
2486 };
2487 
2488 static const enum index action_set_ttl[] = {
2489 	ACTION_SET_TTL_TTL,
2490 	ACTION_NEXT,
2491 	ZERO,
2492 };
2493 
2494 static const enum index action_jump[] = {
2495 	ACTION_JUMP_GROUP,
2496 	ACTION_NEXT,
2497 	ZERO,
2498 };
2499 
2500 static const enum index action_set_mac_dst[] = {
2501 	ACTION_SET_MAC_DST_MAC_DST,
2502 	ACTION_NEXT,
2503 	ZERO,
2504 };
2505 
2506 static const enum index action_inc_tcp_seq[] = {
2507 	ACTION_INC_TCP_SEQ_VALUE,
2508 	ACTION_NEXT,
2509 	ZERO,
2510 };
2511 
2512 static const enum index action_dec_tcp_seq[] = {
2513 	ACTION_DEC_TCP_SEQ_VALUE,
2514 	ACTION_NEXT,
2515 	ZERO,
2516 };
2517 
2518 static const enum index action_inc_tcp_ack[] = {
2519 	ACTION_INC_TCP_ACK_VALUE,
2520 	ACTION_NEXT,
2521 	ZERO,
2522 };
2523 
2524 static const enum index action_dec_tcp_ack[] = {
2525 	ACTION_DEC_TCP_ACK_VALUE,
2526 	ACTION_NEXT,
2527 	ZERO,
2528 };
2529 
2530 static const enum index action_raw_encap[] = {
2531 	ACTION_RAW_ENCAP_SIZE,
2532 	ACTION_RAW_ENCAP_INDEX,
2533 	ACTION_NEXT,
2534 	ZERO,
2535 };
2536 
2537 static const enum index action_raw_decap[] = {
2538 	ACTION_RAW_DECAP_INDEX,
2539 	ACTION_NEXT,
2540 	ZERO,
2541 };
2542 
2543 static const enum index action_ipv6_ext_remove[] = {
2544 	ACTION_IPV6_EXT_REMOVE_INDEX,
2545 	ACTION_NEXT,
2546 	ZERO,
2547 };
2548 
2549 static const enum index action_ipv6_ext_push[] = {
2550 	ACTION_IPV6_EXT_PUSH_INDEX,
2551 	ACTION_NEXT,
2552 	ZERO,
2553 };
2554 
2555 static const enum index action_set_tag[] = {
2556 	ACTION_SET_TAG_DATA,
2557 	ACTION_SET_TAG_INDEX,
2558 	ACTION_SET_TAG_MASK,
2559 	ACTION_NEXT,
2560 	ZERO,
2561 };
2562 
2563 static const enum index action_set_meta[] = {
2564 	ACTION_SET_META_DATA,
2565 	ACTION_SET_META_MASK,
2566 	ACTION_NEXT,
2567 	ZERO,
2568 };
2569 
2570 static const enum index action_set_ipv4_dscp[] = {
2571 	ACTION_SET_IPV4_DSCP_VALUE,
2572 	ACTION_NEXT,
2573 	ZERO,
2574 };
2575 
2576 static const enum index action_set_ipv6_dscp[] = {
2577 	ACTION_SET_IPV6_DSCP_VALUE,
2578 	ACTION_NEXT,
2579 	ZERO,
2580 };
2581 
2582 static const enum index action_age[] = {
2583 	ACTION_AGE,
2584 	ACTION_AGE_TIMEOUT,
2585 	ACTION_NEXT,
2586 	ZERO,
2587 };
2588 
2589 static const enum index action_age_update[] = {
2590 	ACTION_AGE_UPDATE,
2591 	ACTION_AGE_UPDATE_TIMEOUT,
2592 	ACTION_AGE_UPDATE_TOUCH,
2593 	ACTION_NEXT,
2594 	ZERO,
2595 };
2596 
2597 static const enum index action_sample[] = {
2598 	ACTION_SAMPLE,
2599 	ACTION_SAMPLE_RATIO,
2600 	ACTION_SAMPLE_INDEX,
2601 	ACTION_NEXT,
2602 	ZERO,
2603 };
2604 
2605 static const enum index next_action_sample[] = {
2606 	ACTION_QUEUE,
2607 	ACTION_RSS,
2608 	ACTION_MARK,
2609 	ACTION_COUNT,
2610 	ACTION_PORT_ID,
2611 	ACTION_RAW_ENCAP,
2612 	ACTION_VXLAN_ENCAP,
2613 	ACTION_NVGRE_ENCAP,
2614 	ACTION_REPRESENTED_PORT,
2615 	ACTION_PORT_REPRESENTOR,
2616 	ACTION_NEXT,
2617 	ZERO,
2618 };
2619 
2620 static const enum index item_ipv6_push_ext[] = {
2621 	ITEM_IPV6_PUSH_REMOVE_EXT,
2622 	ZERO,
2623 };
2624 
2625 static const enum index item_ipv6_push_ext_type[] = {
2626 	ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
2627 	ZERO,
2628 };
2629 
2630 static const enum index item_ipv6_push_ext_header[] = {
2631 	ITEM_IPV6_ROUTING_EXT,
2632 	ITEM_NEXT,
2633 	ZERO,
2634 };
2635 
2636 static const enum index action_modify_field_dst[] = {
2637 	ACTION_MODIFY_FIELD_DST_LEVEL,
2638 	ACTION_MODIFY_FIELD_DST_TAG_INDEX,
2639 	ACTION_MODIFY_FIELD_DST_TYPE_ID,
2640 	ACTION_MODIFY_FIELD_DST_CLASS_ID,
2641 	ACTION_MODIFY_FIELD_DST_OFFSET,
2642 	ACTION_MODIFY_FIELD_SRC_TYPE,
2643 	ZERO,
2644 };
2645 
2646 static const enum index action_modify_field_src[] = {
2647 	ACTION_MODIFY_FIELD_SRC_LEVEL,
2648 	ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
2649 	ACTION_MODIFY_FIELD_SRC_TYPE_ID,
2650 	ACTION_MODIFY_FIELD_SRC_CLASS_ID,
2651 	ACTION_MODIFY_FIELD_SRC_OFFSET,
2652 	ACTION_MODIFY_FIELD_SRC_VALUE,
2653 	ACTION_MODIFY_FIELD_SRC_POINTER,
2654 	ACTION_MODIFY_FIELD_WIDTH,
2655 	ZERO,
2656 };
2657 
2658 static const enum index action_update_conntrack[] = {
2659 	ACTION_CONNTRACK_UPDATE_DIR,
2660 	ACTION_CONNTRACK_UPDATE_CTX,
2661 	ACTION_NEXT,
2662 	ZERO,
2663 };
2664 
2665 static const enum index action_port_representor[] = {
2666 	ACTION_PORT_REPRESENTOR_PORT_ID,
2667 	ACTION_NEXT,
2668 	ZERO,
2669 };
2670 
2671 static const enum index action_represented_port[] = {
2672 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
2673 	ACTION_NEXT,
2674 	ZERO,
2675 };
2676 
2677 static const enum index action_nat64[] = {
2678 	ACTION_NAT64_MODE,
2679 	ACTION_NEXT,
2680 	ZERO,
2681 };
2682 
2683 static const enum index next_hash_subcmd[] = {
2684 	HASH_CALC_TABLE,
2685 	HASH_CALC_ENCAP,
2686 	ZERO,
2687 };
2688 
2689 static const enum index next_hash_encap_dest_subcmd[] = {
2690 	ENCAP_HASH_FIELD_SRC_PORT,
2691 	ENCAP_HASH_FIELD_GRE_FLOW_ID,
2692 	ZERO,
2693 };
2694 
2695 static const enum index action_jump_to_table_index[] = {
2696 	ACTION_JUMP_TO_TABLE_INDEX_TABLE,
2697 	ACTION_JUMP_TO_TABLE_INDEX_INDEX,
2698 	ACTION_NEXT,
2699 	ZERO,
2700 };
2701 
2702 static int parse_set_raw_encap_decap(struct context *, const struct token *,
2703 				     const char *, unsigned int,
2704 				     void *, unsigned int);
2705 static int parse_set_sample_action(struct context *, const struct token *,
2706 				   const char *, unsigned int,
2707 				   void *, unsigned int);
2708 static int parse_set_ipv6_ext_action(struct context *, const struct token *,
2709 				     const char *, unsigned int,
2710 				     void *, unsigned int);
2711 static int parse_set_init(struct context *, const struct token *,
2712 			  const char *, unsigned int,
2713 			  void *, unsigned int);
2714 static int
2715 parse_flex_handle(struct context *, const struct token *,
2716 		  const char *, unsigned int, void *, unsigned int);
2717 static int parse_init(struct context *, const struct token *,
2718 		      const char *, unsigned int,
2719 		      void *, unsigned int);
2720 static int parse_vc(struct context *, const struct token *,
2721 		    const char *, unsigned int,
2722 		    void *, unsigned int);
2723 static int parse_vc_spec(struct context *, const struct token *,
2724 			 const char *, unsigned int, void *, unsigned int);
2725 static int parse_vc_conf(struct context *, const struct token *,
2726 			 const char *, unsigned int, void *, unsigned int);
2727 static int parse_vc_conf_timeout(struct context *, const struct token *,
2728 				 const char *, unsigned int, void *,
2729 				 unsigned int);
2730 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
2731 				    const char *, unsigned int,
2732 				    void *, unsigned int);
2733 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *,
2734 				    const char *, unsigned int,
2735 				    void *, unsigned int);
2736 static int parse_vc_action_meter_color_type(struct context *,
2737 					const struct token *,
2738 					const char *, unsigned int, void *,
2739 					unsigned int);
2740 static int parse_vc_action_rss(struct context *, const struct token *,
2741 			       const char *, unsigned int, void *,
2742 			       unsigned int);
2743 static int parse_vc_action_rss_func(struct context *, const struct token *,
2744 				    const char *, unsigned int, void *,
2745 				    unsigned int);
2746 static int parse_vc_action_rss_type(struct context *, const struct token *,
2747 				    const char *, unsigned int, void *,
2748 				    unsigned int);
2749 static int parse_vc_action_rss_queue(struct context *, const struct token *,
2750 				     const char *, unsigned int, void *,
2751 				     unsigned int);
2752 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
2753 				       const char *, unsigned int, void *,
2754 				       unsigned int);
2755 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
2756 				       const char *, unsigned int, void *,
2757 				       unsigned int);
2758 static int parse_vc_action_l2_encap(struct context *, const struct token *,
2759 				    const char *, unsigned int, void *,
2760 				    unsigned int);
2761 static int parse_vc_action_l2_decap(struct context *, const struct token *,
2762 				    const char *, unsigned int, void *,
2763 				    unsigned int);
2764 static int parse_vc_action_mplsogre_encap(struct context *,
2765 					  const struct token *, const char *,
2766 					  unsigned int, void *, unsigned int);
2767 static int parse_vc_action_mplsogre_decap(struct context *,
2768 					  const struct token *, const char *,
2769 					  unsigned int, void *, unsigned int);
2770 static int parse_vc_action_mplsoudp_encap(struct context *,
2771 					  const struct token *, const char *,
2772 					  unsigned int, void *, unsigned int);
2773 static int parse_vc_action_mplsoudp_decap(struct context *,
2774 					  const struct token *, const char *,
2775 					  unsigned int, void *, unsigned int);
2776 static int parse_vc_action_raw_encap(struct context *,
2777 				     const struct token *, const char *,
2778 				     unsigned int, void *, unsigned int);
2779 static int parse_vc_action_raw_decap(struct context *,
2780 				     const struct token *, const char *,
2781 				     unsigned int, void *, unsigned int);
2782 static int parse_vc_action_raw_encap_index(struct context *,
2783 					   const struct token *, const char *,
2784 					   unsigned int, void *, unsigned int);
2785 static int parse_vc_action_raw_decap_index(struct context *,
2786 					   const struct token *, const char *,
2787 					   unsigned int, void *, unsigned int);
2788 static int parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
2789 					   const char *str, unsigned int len, void *buf,
2790 					   unsigned int size);
2791 static int parse_vc_action_ipv6_ext_remove_index(struct context *ctx,
2792 						 const struct token *token,
2793 						 const char *str, unsigned int len,
2794 						 void *buf,
2795 						 unsigned int size);
2796 static int parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
2797 					 const char *str, unsigned int len, void *buf,
2798 					 unsigned int size);
2799 static int parse_vc_action_ipv6_ext_push_index(struct context *ctx,
2800 					       const struct token *token,
2801 					       const char *str, unsigned int len,
2802 					       void *buf,
2803 					       unsigned int size);
2804 static int parse_vc_action_set_meta(struct context *ctx,
2805 				    const struct token *token, const char *str,
2806 				    unsigned int len, void *buf,
2807 					unsigned int size);
2808 static int parse_vc_action_sample(struct context *ctx,
2809 				    const struct token *token, const char *str,
2810 				    unsigned int len, void *buf,
2811 				    unsigned int size);
2812 static int
2813 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
2814 				const char *str, unsigned int len, void *buf,
2815 				unsigned int size);
2816 static int
2817 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
2818 				const char *str, unsigned int len, void *buf,
2819 				unsigned int size);
2820 static int
2821 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
2822 				const char *str, unsigned int len, void *buf,
2823 				unsigned int size);
2824 static int
2825 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
2826 				const char *str, unsigned int len, void *buf,
2827 				unsigned int size);
2828 static int
2829 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
2830 			 const char *str, unsigned int len, void *buf,
2831 			 unsigned int size);
2832 static int parse_destroy(struct context *, const struct token *,
2833 			 const char *, unsigned int,
2834 			 void *, unsigned int);
2835 static int parse_flush(struct context *, const struct token *,
2836 		       const char *, unsigned int,
2837 		       void *, unsigned int);
2838 static int parse_dump(struct context *, const struct token *,
2839 		      const char *, unsigned int,
2840 		      void *, unsigned int);
2841 static int parse_query(struct context *, const struct token *,
2842 		       const char *, unsigned int,
2843 		       void *, unsigned int);
2844 static int parse_action(struct context *, const struct token *,
2845 			const char *, unsigned int,
2846 			void *, unsigned int);
2847 static int parse_list(struct context *, const struct token *,
2848 		      const char *, unsigned int,
2849 		      void *, unsigned int);
2850 static int parse_aged(struct context *, const struct token *,
2851 		      const char *, unsigned int,
2852 		      void *, unsigned int);
2853 static int parse_isolate(struct context *, const struct token *,
2854 			 const char *, unsigned int,
2855 			 void *, unsigned int);
2856 static int parse_configure(struct context *, const struct token *,
2857 			   const char *, unsigned int,
2858 			   void *, unsigned int);
2859 static int parse_template(struct context *, const struct token *,
2860 			  const char *, unsigned int,
2861 			  void *, unsigned int);
2862 static int parse_template_destroy(struct context *, const struct token *,
2863 				  const char *, unsigned int,
2864 				  void *, unsigned int);
2865 static int parse_table(struct context *, const struct token *,
2866 		       const char *, unsigned int, void *, unsigned int);
2867 static int parse_table_destroy(struct context *, const struct token *,
2868 			       const char *, unsigned int,
2869 			       void *, unsigned int);
2870 static int parse_qo(struct context *, const struct token *,
2871 		    const char *, unsigned int,
2872 		    void *, unsigned int);
2873 static int parse_qo_destroy(struct context *, const struct token *,
2874 			    const char *, unsigned int,
2875 			    void *, unsigned int);
2876 static int parse_qia(struct context *, const struct token *,
2877 		     const char *, unsigned int,
2878 		     void *, unsigned int);
2879 static int parse_qia_destroy(struct context *, const struct token *,
2880 			     const char *, unsigned int,
2881 			     void *, unsigned int);
2882 static int parse_push(struct context *, const struct token *,
2883 		      const char *, unsigned int,
2884 		      void *, unsigned int);
2885 static int parse_pull(struct context *, const struct token *,
2886 		      const char *, unsigned int,
2887 		      void *, unsigned int);
2888 static int parse_group(struct context *, const struct token *,
2889 		       const char *, unsigned int,
2890 		       void *, unsigned int);
2891 static int parse_hash(struct context *, const struct token *,
2892 		      const char *, unsigned int,
2893 		      void *, unsigned int);
2894 static int parse_tunnel(struct context *, const struct token *,
2895 			const char *, unsigned int,
2896 			void *, unsigned int);
2897 static int parse_flex(struct context *, const struct token *,
2898 		      const char *, unsigned int, void *, unsigned int);
2899 static int parse_int(struct context *, const struct token *,
2900 		     const char *, unsigned int,
2901 		     void *, unsigned int);
2902 static int parse_prefix(struct context *, const struct token *,
2903 			const char *, unsigned int,
2904 			void *, unsigned int);
2905 static int parse_boolean(struct context *, const struct token *,
2906 			 const char *, unsigned int,
2907 			 void *, unsigned int);
2908 static int parse_string(struct context *, const struct token *,
2909 			const char *, unsigned int,
2910 			void *, unsigned int);
2911 static int parse_hex(struct context *ctx, const struct token *token,
2912 			const char *str, unsigned int len,
2913 			void *buf, unsigned int size);
2914 static int parse_string0(struct context *, const struct token *,
2915 			const char *, unsigned int,
2916 			void *, unsigned int);
2917 static int parse_mac_addr(struct context *, const struct token *,
2918 			  const char *, unsigned int,
2919 			  void *, unsigned int);
2920 static int parse_ipv4_addr(struct context *, const struct token *,
2921 			   const char *, unsigned int,
2922 			   void *, unsigned int);
2923 static int parse_ipv6_addr(struct context *, const struct token *,
2924 			   const char *, unsigned int,
2925 			   void *, unsigned int);
2926 static int parse_port(struct context *, const struct token *,
2927 		      const char *, unsigned int,
2928 		      void *, unsigned int);
2929 static int parse_ia(struct context *, const struct token *,
2930 		    const char *, unsigned int,
2931 		    void *, unsigned int);
2932 static int parse_ia_destroy(struct context *ctx, const struct token *token,
2933 			    const char *str, unsigned int len,
2934 			    void *buf, unsigned int size);
2935 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
2936 			   const char *str, unsigned int len, void *buf,
2937 			   unsigned int size);
2938 
2939 static int parse_indlst_id2ptr(struct context *ctx, const struct token *token,
2940 			       const char *str, unsigned int len, void *buf,
2941 			       unsigned int size);
2942 static int parse_ia_port(struct context *ctx, const struct token *token,
2943 			 const char *str, unsigned int len, void *buf,
2944 			 unsigned int size);
2945 static int parse_mp(struct context *, const struct token *,
2946 		    const char *, unsigned int,
2947 		    void *, unsigned int);
2948 static int parse_meter_profile_id2ptr(struct context *ctx,
2949 				      const struct token *token,
2950 				      const char *str, unsigned int len,
2951 				      void *buf, unsigned int size);
2952 static int parse_meter_policy_id2ptr(struct context *ctx,
2953 				     const struct token *token,
2954 				     const char *str, unsigned int len,
2955 				     void *buf, unsigned int size);
2956 static int parse_meter_color(struct context *ctx, const struct token *token,
2957 			     const char *str, unsigned int len, void *buf,
2958 			     unsigned int size);
2959 static int parse_insertion_table_type(struct context *ctx, const struct token *token,
2960 				      const char *str, unsigned int len, void *buf,
2961 				      unsigned int size);
2962 static int parse_hash_table_type(struct context *ctx, const struct token *token,
2963 				 const char *str, unsigned int len, void *buf,
2964 				 unsigned int size);
2965 static int
2966 parse_quota_state_name(struct context *ctx, const struct token *token,
2967 		       const char *str, unsigned int len, void *buf,
2968 		       unsigned int size);
2969 static int
2970 parse_quota_mode_name(struct context *ctx, const struct token *token,
2971 		      const char *str, unsigned int len, void *buf,
2972 		      unsigned int size);
2973 static int
2974 parse_quota_update_name(struct context *ctx, const struct token *token,
2975 			const char *str, unsigned int len, void *buf,
2976 			unsigned int size);
2977 static int
2978 parse_qu_mode_name(struct context *ctx, const struct token *token,
2979 		   const char *str, unsigned int len, void *buf,
2980 		   unsigned int size);
2981 static int comp_none(struct context *, const struct token *,
2982 		     unsigned int, char *, unsigned int);
2983 static int comp_boolean(struct context *, const struct token *,
2984 			unsigned int, char *, unsigned int);
2985 static int comp_action(struct context *, const struct token *,
2986 		       unsigned int, char *, unsigned int);
2987 static int comp_port(struct context *, const struct token *,
2988 		     unsigned int, char *, unsigned int);
2989 static int comp_rule_id(struct context *, const struct token *,
2990 			unsigned int, char *, unsigned int);
2991 static int comp_vc_action_rss_type(struct context *, const struct token *,
2992 				   unsigned int, char *, unsigned int);
2993 static int comp_vc_action_rss_queue(struct context *, const struct token *,
2994 				    unsigned int, char *, unsigned int);
2995 static int comp_set_raw_index(struct context *, const struct token *,
2996 			      unsigned int, char *, unsigned int);
2997 static int comp_set_sample_index(struct context *, const struct token *,
2998 			      unsigned int, char *, unsigned int);
2999 static int comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
3000 				   unsigned int ent, char *buf, unsigned int size);
3001 static int comp_set_modify_field_op(struct context *, const struct token *,
3002 			      unsigned int, char *, unsigned int);
3003 static int comp_set_modify_field_id(struct context *, const struct token *,
3004 			      unsigned int, char *, unsigned int);
3005 static int comp_pattern_template_id(struct context *, const struct token *,
3006 				    unsigned int, char *, unsigned int);
3007 static int comp_actions_template_id(struct context *, const struct token *,
3008 				    unsigned int, char *, unsigned int);
3009 static int comp_table_id(struct context *, const struct token *,
3010 			 unsigned int, char *, unsigned int);
3011 static int comp_queue_id(struct context *, const struct token *,
3012 			 unsigned int, char *, unsigned int);
3013 static int comp_meter_color(struct context *, const struct token *,
3014 			    unsigned int, char *, unsigned int);
3015 static int comp_insertion_table_type(struct context *, const struct token *,
3016 				     unsigned int, char *, unsigned int);
3017 static int comp_hash_table_type(struct context *, const struct token *,
3018 				unsigned int, char *, unsigned int);
3019 static int
3020 comp_quota_state_name(struct context *ctx, const struct token *token,
3021 		      unsigned int ent, char *buf, unsigned int size);
3022 static int
3023 comp_quota_mode_name(struct context *ctx, const struct token *token,
3024 		     unsigned int ent, char *buf, unsigned int size);
3025 static int
3026 comp_quota_update_name(struct context *ctx, const struct token *token,
3027 		       unsigned int ent, char *buf, unsigned int size);
3028 static int
3029 comp_qu_mode_name(struct context *ctx, const struct token *token,
3030 		  unsigned int ent, char *buf, unsigned int size);
3031 static int
3032 comp_set_compare_field_id(struct context *ctx, const struct token *token,
3033 			  unsigned int ent, char *buf, unsigned int size);
3034 static int
3035 comp_set_compare_op(struct context *ctx, const struct token *token,
3036 		    unsigned int ent, char *buf, unsigned int size);
3037 static int
3038 parse_vc_compare_op(struct context *ctx, const struct token *token,
3039 			 const char *str, unsigned int len, void *buf,
3040 			 unsigned int size);
3041 static int
3042 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
3043 			  const char *str, unsigned int len, void *buf,
3044 			  unsigned int size);
3045 static int
3046 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
3047 			     const char *str, unsigned int len, void *buf,
3048 			     unsigned int size);
3049 
3050 struct indlst_conf {
3051 	uint32_t id;
3052 	uint32_t conf_num;
3053 	struct rte_flow_action *actions;
3054 	const void **conf;
3055 	SLIST_ENTRY(indlst_conf) next;
3056 };
3057 
3058 static const struct indlst_conf *indirect_action_list_conf_get(uint32_t conf_id);
3059 
3060 /** Token definitions. */
3061 static const struct token token_list[] = {
3062 	/* Special tokens. */
3063 	[ZERO] = {
3064 		.name = "ZERO",
3065 		.help = "null entry, abused as the entry point",
3066 		.next = NEXT(NEXT_ENTRY(FLOW, ADD)),
3067 	},
3068 	[END] = {
3069 		.name = "",
3070 		.type = "RETURN",
3071 		.help = "command may end here",
3072 	},
3073 	[START_SET] = {
3074 		.name = "START_SET",
3075 		.help = "null entry, abused as the entry point for set",
3076 		.next = NEXT(NEXT_ENTRY(SET)),
3077 	},
3078 	[END_SET] = {
3079 		.name = "end_set",
3080 		.type = "RETURN",
3081 		.help = "set command may end here",
3082 	},
3083 	/* Common tokens. */
3084 	[COMMON_INTEGER] = {
3085 		.name = "{int}",
3086 		.type = "INTEGER",
3087 		.help = "integer value",
3088 		.call = parse_int,
3089 		.comp = comp_none,
3090 	},
3091 	[COMMON_UNSIGNED] = {
3092 		.name = "{unsigned}",
3093 		.type = "UNSIGNED",
3094 		.help = "unsigned integer value",
3095 		.call = parse_int,
3096 		.comp = comp_none,
3097 	},
3098 	[COMMON_PREFIX] = {
3099 		.name = "{prefix}",
3100 		.type = "PREFIX",
3101 		.help = "prefix length for bit-mask",
3102 		.call = parse_prefix,
3103 		.comp = comp_none,
3104 	},
3105 	[COMMON_BOOLEAN] = {
3106 		.name = "{boolean}",
3107 		.type = "BOOLEAN",
3108 		.help = "any boolean value",
3109 		.call = parse_boolean,
3110 		.comp = comp_boolean,
3111 	},
3112 	[COMMON_STRING] = {
3113 		.name = "{string}",
3114 		.type = "STRING",
3115 		.help = "fixed string",
3116 		.call = parse_string,
3117 		.comp = comp_none,
3118 	},
3119 	[COMMON_HEX] = {
3120 		.name = "{hex}",
3121 		.type = "HEX",
3122 		.help = "fixed string",
3123 		.call = parse_hex,
3124 	},
3125 	[COMMON_FILE_PATH] = {
3126 		.name = "{file path}",
3127 		.type = "STRING",
3128 		.help = "file path",
3129 		.call = parse_string0,
3130 		.comp = comp_none,
3131 	},
3132 	[COMMON_MAC_ADDR] = {
3133 		.name = "{MAC address}",
3134 		.type = "MAC-48",
3135 		.help = "standard MAC address notation",
3136 		.call = parse_mac_addr,
3137 		.comp = comp_none,
3138 	},
3139 	[COMMON_IPV4_ADDR] = {
3140 		.name = "{IPv4 address}",
3141 		.type = "IPV4 ADDRESS",
3142 		.help = "standard IPv4 address notation",
3143 		.call = parse_ipv4_addr,
3144 		.comp = comp_none,
3145 	},
3146 	[COMMON_IPV6_ADDR] = {
3147 		.name = "{IPv6 address}",
3148 		.type = "IPV6 ADDRESS",
3149 		.help = "standard IPv6 address notation",
3150 		.call = parse_ipv6_addr,
3151 		.comp = comp_none,
3152 	},
3153 	[COMMON_RULE_ID] = {
3154 		.name = "{rule id}",
3155 		.type = "RULE ID",
3156 		.help = "rule identifier",
3157 		.call = parse_int,
3158 		.comp = comp_rule_id,
3159 	},
3160 	[COMMON_PORT_ID] = {
3161 		.name = "{port_id}",
3162 		.type = "PORT ID",
3163 		.help = "port identifier",
3164 		.call = parse_port,
3165 		.comp = comp_port,
3166 	},
3167 	[COMMON_GROUP_ID] = {
3168 		.name = "{group_id}",
3169 		.type = "GROUP ID",
3170 		.help = "group identifier",
3171 		.call = parse_int,
3172 		.comp = comp_none,
3173 	},
3174 	[COMMON_PRIORITY_LEVEL] = {
3175 		.name = "{level}",
3176 		.type = "PRIORITY",
3177 		.help = "priority level",
3178 		.call = parse_int,
3179 		.comp = comp_none,
3180 	},
3181 	[COMMON_INDIRECT_ACTION_ID] = {
3182 		.name = "{indirect_action_id}",
3183 		.type = "INDIRECT_ACTION_ID",
3184 		.help = "indirect action id",
3185 		.call = parse_int,
3186 		.comp = comp_none,
3187 	},
3188 	[COMMON_PROFILE_ID] = {
3189 		.name = "{profile_id}",
3190 		.type = "PROFILE_ID",
3191 		.help = "profile id",
3192 		.call = parse_int,
3193 		.comp = comp_none,
3194 	},
3195 	[COMMON_POLICY_ID] = {
3196 		.name = "{policy_id}",
3197 		.type = "POLICY_ID",
3198 		.help = "policy id",
3199 		.call = parse_int,
3200 		.comp = comp_none,
3201 	},
3202 	[COMMON_FLEX_TOKEN] = {
3203 		.name = "{flex token}",
3204 		.type = "flex token",
3205 		.help = "flex token",
3206 		.call = parse_int,
3207 		.comp = comp_none,
3208 	},
3209 	[COMMON_FLEX_HANDLE] = {
3210 		.name = "{flex handle}",
3211 		.type = "FLEX HANDLE",
3212 		.help = "fill flex item data",
3213 		.call = parse_flex_handle,
3214 		.comp = comp_none,
3215 	},
3216 	[COMMON_PATTERN_TEMPLATE_ID] = {
3217 		.name = "{pattern_template_id}",
3218 		.type = "PATTERN_TEMPLATE_ID",
3219 		.help = "pattern template id",
3220 		.call = parse_int,
3221 		.comp = comp_pattern_template_id,
3222 	},
3223 	[COMMON_ACTIONS_TEMPLATE_ID] = {
3224 		.name = "{actions_template_id}",
3225 		.type = "ACTIONS_TEMPLATE_ID",
3226 		.help = "actions template id",
3227 		.call = parse_int,
3228 		.comp = comp_actions_template_id,
3229 	},
3230 	[COMMON_TABLE_ID] = {
3231 		.name = "{table_id}",
3232 		.type = "TABLE_ID",
3233 		.help = "table id",
3234 		.call = parse_int,
3235 		.comp = comp_table_id,
3236 	},
3237 	[COMMON_QUEUE_ID] = {
3238 		.name = "{queue_id}",
3239 		.type = "QUEUE_ID",
3240 		.help = "queue id",
3241 		.call = parse_int,
3242 		.comp = comp_queue_id,
3243 	},
3244 	/* Top-level command. */
3245 	[FLOW] = {
3246 		.name = "flow",
3247 		.type = "{command} {port_id} [{arg} [...]]",
3248 		.help = "manage ingress/egress flow rules",
3249 		.next = NEXT(NEXT_ENTRY
3250 			     (INFO,
3251 			      CONFIGURE,
3252 			      PATTERN_TEMPLATE,
3253 			      ACTIONS_TEMPLATE,
3254 			      TABLE,
3255 			      FLOW_GROUP,
3256 			      INDIRECT_ACTION,
3257 			      VALIDATE,
3258 			      CREATE,
3259 			      DESTROY,
3260 			      UPDATE,
3261 			      FLUSH,
3262 			      DUMP,
3263 			      LIST,
3264 			      AGED,
3265 			      QUERY,
3266 			      ISOLATE,
3267 			      TUNNEL,
3268 			      FLEX,
3269 			      QUEUE,
3270 			      PUSH,
3271 			      PULL,
3272 			      HASH)),
3273 		.call = parse_init,
3274 	},
3275 	/* Top-level command. */
3276 	[INFO] = {
3277 		.name = "info",
3278 		.help = "get information about flow engine",
3279 		.next = NEXT(NEXT_ENTRY(END),
3280 			     NEXT_ENTRY(COMMON_PORT_ID)),
3281 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3282 		.call = parse_configure,
3283 	},
3284 	/* Top-level command. */
3285 	[CONFIGURE] = {
3286 		.name = "configure",
3287 		.help = "configure flow engine",
3288 		.next = NEXT(next_config_attr,
3289 			     NEXT_ENTRY(COMMON_PORT_ID)),
3290 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3291 		.call = parse_configure,
3292 	},
3293 	/* Configure arguments. */
3294 	[CONFIG_QUEUES_NUMBER] = {
3295 		.name = "queues_number",
3296 		.help = "number of queues",
3297 		.next = NEXT(next_config_attr,
3298 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3299 		.args = ARGS(ARGS_ENTRY(struct buffer,
3300 					args.configure.nb_queue)),
3301 	},
3302 	[CONFIG_QUEUES_SIZE] = {
3303 		.name = "queues_size",
3304 		.help = "number of elements in queues",
3305 		.next = NEXT(next_config_attr,
3306 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3307 		.args = ARGS(ARGS_ENTRY(struct buffer,
3308 					args.configure.queue_attr.size)),
3309 	},
3310 	[CONFIG_COUNTERS_NUMBER] = {
3311 		.name = "counters_number",
3312 		.help = "number of counters",
3313 		.next = NEXT(next_config_attr,
3314 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3315 		.args = ARGS(ARGS_ENTRY(struct buffer,
3316 					args.configure.port_attr.nb_counters)),
3317 	},
3318 	[CONFIG_AGING_OBJECTS_NUMBER] = {
3319 		.name = "aging_counters_number",
3320 		.help = "number of aging objects",
3321 		.next = NEXT(next_config_attr,
3322 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3323 		.args = ARGS(ARGS_ENTRY(struct buffer,
3324 					args.configure.port_attr.nb_aging_objects)),
3325 	},
3326 	[CONFIG_QUOTAS_NUMBER] = {
3327 		.name = "quotas_number",
3328 		.help = "number of quotas",
3329 		.next = NEXT(next_config_attr,
3330 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3331 		.args = ARGS(ARGS_ENTRY(struct buffer,
3332 				     args.configure.port_attr.nb_quotas)),
3333 	},
3334 	[CONFIG_METERS_NUMBER] = {
3335 		.name = "meters_number",
3336 		.help = "number of meters",
3337 		.next = NEXT(next_config_attr,
3338 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3339 		.args = ARGS(ARGS_ENTRY(struct buffer,
3340 					args.configure.port_attr.nb_meters)),
3341 	},
3342 	[CONFIG_CONN_TRACK_NUMBER] = {
3343 		.name = "conn_tracks_number",
3344 		.help = "number of connection trackings",
3345 		.next = NEXT(next_config_attr,
3346 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3347 		.args = ARGS(ARGS_ENTRY(struct buffer,
3348 					args.configure.port_attr.nb_conn_tracks)),
3349 	},
3350 	[CONFIG_FLAGS] = {
3351 		.name = "flags",
3352 		.help = "configuration flags",
3353 		.next = NEXT(next_config_attr,
3354 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3355 		.args = ARGS(ARGS_ENTRY(struct buffer,
3356 					args.configure.port_attr.flags)),
3357 	},
3358 	[CONFIG_HOST_PORT] = {
3359 		.name = "host_port",
3360 		.help = "host port for shared objects",
3361 		.next = NEXT(next_config_attr,
3362 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3363 		.args = ARGS(ARGS_ENTRY(struct buffer,
3364 					args.configure.port_attr.host_port_id)),
3365 	},
3366 	/* Top-level command. */
3367 	[PATTERN_TEMPLATE] = {
3368 		.name = "pattern_template",
3369 		.type = "{command} {port_id} [{arg} [...]]",
3370 		.help = "manage pattern templates",
3371 		.next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3372 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3373 		.call = parse_template,
3374 	},
3375 	/* Sub-level commands. */
3376 	[PATTERN_TEMPLATE_CREATE] = {
3377 		.name = "create",
3378 		.help = "create pattern template",
3379 		.next = NEXT(next_pt_attr),
3380 		.call = parse_template,
3381 	},
3382 	[PATTERN_TEMPLATE_DESTROY] = {
3383 		.name = "destroy",
3384 		.help = "destroy pattern template",
3385 		.next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)),
3386 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3387 		.call = parse_template_destroy,
3388 	},
3389 	/* Pattern template arguments. */
3390 	[PATTERN_TEMPLATE_CREATE_ID] = {
3391 		.name = "pattern_template_id",
3392 		.help = "specify a pattern template id to create",
3393 		.next = NEXT(next_pt_attr,
3394 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3395 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)),
3396 	},
3397 	[PATTERN_TEMPLATE_DESTROY_ID] = {
3398 		.name = "pattern_template",
3399 		.help = "specify a pattern template id to destroy",
3400 		.next = NEXT(next_pt_destroy_attr,
3401 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3402 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3403 					    args.templ_destroy.template_id)),
3404 		.call = parse_template_destroy,
3405 	},
3406 	[PATTERN_TEMPLATE_RELAXED_MATCHING] = {
3407 		.name = "relaxed",
3408 		.help = "is matching relaxed",
3409 		.next = NEXT(next_pt_attr,
3410 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3411 		.args = ARGS(ARGS_ENTRY_BF(struct buffer,
3412 			     args.vc.attr.reserved, 1)),
3413 	},
3414 	[PATTERN_TEMPLATE_INGRESS] = {
3415 		.name = "ingress",
3416 		.help = "attribute pattern to ingress",
3417 		.next = NEXT(next_pt_attr),
3418 		.call = parse_template,
3419 	},
3420 	[PATTERN_TEMPLATE_EGRESS] = {
3421 		.name = "egress",
3422 		.help = "attribute pattern to egress",
3423 		.next = NEXT(next_pt_attr),
3424 		.call = parse_template,
3425 	},
3426 	[PATTERN_TEMPLATE_TRANSFER] = {
3427 		.name = "transfer",
3428 		.help = "attribute pattern to transfer",
3429 		.next = NEXT(next_pt_attr),
3430 		.call = parse_template,
3431 	},
3432 	[PATTERN_TEMPLATE_SPEC] = {
3433 		.name = "template",
3434 		.help = "specify item to create pattern template",
3435 		.next = NEXT(next_item),
3436 	},
3437 	/* Top-level command. */
3438 	[ACTIONS_TEMPLATE] = {
3439 		.name = "actions_template",
3440 		.type = "{command} {port_id} [{arg} [...]]",
3441 		.help = "manage actions templates",
3442 		.next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3443 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3444 		.call = parse_template,
3445 	},
3446 	/* Sub-level commands. */
3447 	[ACTIONS_TEMPLATE_CREATE] = {
3448 		.name = "create",
3449 		.help = "create actions template",
3450 		.next = NEXT(next_at_attr),
3451 		.call = parse_template,
3452 	},
3453 	[ACTIONS_TEMPLATE_DESTROY] = {
3454 		.name = "destroy",
3455 		.help = "destroy actions template",
3456 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)),
3457 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3458 		.call = parse_template_destroy,
3459 	},
3460 	/* Actions template arguments. */
3461 	[ACTIONS_TEMPLATE_CREATE_ID] = {
3462 		.name = "actions_template_id",
3463 		.help = "specify an actions template id to create",
3464 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK),
3465 			     NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC),
3466 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3467 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)),
3468 	},
3469 	[ACTIONS_TEMPLATE_DESTROY_ID] = {
3470 		.name = "actions_template",
3471 		.help = "specify an actions template id to destroy",
3472 		.next = NEXT(next_at_destroy_attr,
3473 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3474 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3475 					    args.templ_destroy.template_id)),
3476 		.call = parse_template_destroy,
3477 	},
3478 	[ACTIONS_TEMPLATE_INGRESS] = {
3479 		.name = "ingress",
3480 		.help = "attribute actions to ingress",
3481 		.next = NEXT(next_at_attr),
3482 		.call = parse_template,
3483 	},
3484 	[ACTIONS_TEMPLATE_EGRESS] = {
3485 		.name = "egress",
3486 		.help = "attribute actions to egress",
3487 		.next = NEXT(next_at_attr),
3488 		.call = parse_template,
3489 	},
3490 	[ACTIONS_TEMPLATE_TRANSFER] = {
3491 		.name = "transfer",
3492 		.help = "attribute actions to transfer",
3493 		.next = NEXT(next_at_attr),
3494 		.call = parse_template,
3495 	},
3496 	[ACTIONS_TEMPLATE_SPEC] = {
3497 		.name = "template",
3498 		.help = "specify action to create actions template",
3499 		.next = NEXT(next_action),
3500 		.call = parse_template,
3501 	},
3502 	[ACTIONS_TEMPLATE_MASK] = {
3503 		.name = "mask",
3504 		.help = "specify action mask to create actions template",
3505 		.next = NEXT(next_action),
3506 		.call = parse_template,
3507 	},
3508 	/* Top-level command. */
3509 	[TABLE] = {
3510 		.name = "template_table",
3511 		.type = "{command} {port_id} [{arg} [...]]",
3512 		.help = "manage template tables",
3513 		.next = NEXT(next_table_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3514 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3515 		.call = parse_table,
3516 	},
3517 	/* Sub-level commands. */
3518 	[TABLE_CREATE] = {
3519 		.name = "create",
3520 		.help = "create template table",
3521 		.next = NEXT(next_table_attr),
3522 		.call = parse_table,
3523 	},
3524 	[TABLE_DESTROY] = {
3525 		.name = "destroy",
3526 		.help = "destroy template table",
3527 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3528 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3529 		.call = parse_table_destroy,
3530 	},
3531 	[TABLE_RESIZE] = {
3532 		.name = "resize",
3533 		.help = "resize template table",
3534 		.next = NEXT(NEXT_ENTRY(TABLE_RESIZE_ID)),
3535 		.call = parse_table
3536 	},
3537 	[TABLE_RESIZE_COMPLETE] = {
3538 		.name = "resize_complete",
3539 		.help = "complete table resize",
3540 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3541 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3542 		.call = parse_table_destroy,
3543 	},
3544 	/* Table  arguments. */
3545 	[TABLE_CREATE_ID] = {
3546 		.name = "table_id",
3547 		.help = "specify table id to create",
3548 		.next = NEXT(next_table_attr,
3549 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3550 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3551 	},
3552 	[TABLE_DESTROY_ID] = {
3553 		.name = "table",
3554 		.help = "table id",
3555 		.next = NEXT(next_table_destroy_attr,
3556 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3557 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3558 					    args.table_destroy.table_id)),
3559 		.call = parse_table_destroy,
3560 	},
3561 	[TABLE_RESIZE_ID] = {
3562 		.name = "table_resize_id",
3563 		.help = "table resize id",
3564 		.next = NEXT(NEXT_ENTRY(TABLE_RESIZE_RULES_NUMBER),
3565 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3566 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3567 		.call = parse_table
3568 	},
3569 	[TABLE_RESIZE_RULES_NUMBER] = {
3570 		.name = "table_resize_rules_num",
3571 		.help = "table resize rules number",
3572 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_UNSIGNED)),
3573 		.args = ARGS(ARGS_ENTRY(struct buffer,
3574 					args.table.attr.nb_flows)),
3575 		.call = parse_table
3576 	},
3577 	[TABLE_INSERTION_TYPE] = {
3578 		.name = "insertion_type",
3579 		.help = "specify insertion type",
3580 		.next = NEXT(next_table_attr,
3581 			     NEXT_ENTRY(TABLE_INSERTION_TYPE_NAME)),
3582 		.args = ARGS(ARGS_ENTRY(struct buffer,
3583 					args.table.attr.insertion_type)),
3584 	},
3585 	[TABLE_INSERTION_TYPE_NAME] = {
3586 		.name = "insertion_type_name",
3587 		.help = "insertion type name",
3588 		.call = parse_insertion_table_type,
3589 		.comp = comp_insertion_table_type,
3590 	},
3591 	[TABLE_HASH_FUNC] = {
3592 		.name = "hash_func",
3593 		.help = "specify hash calculation function",
3594 		.next = NEXT(next_table_attr,
3595 			     NEXT_ENTRY(TABLE_HASH_FUNC_NAME)),
3596 		.args = ARGS(ARGS_ENTRY(struct buffer,
3597 					args.table.attr.hash_func)),
3598 	},
3599 	[TABLE_HASH_FUNC_NAME] = {
3600 		.name = "hash_func_name",
3601 		.help = "hash calculation function name",
3602 		.call = parse_hash_table_type,
3603 		.comp = comp_hash_table_type,
3604 	},
3605 	[TABLE_GROUP] = {
3606 		.name = "group",
3607 		.help = "specify a group",
3608 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3609 		.args = ARGS(ARGS_ENTRY(struct buffer,
3610 					args.table.attr.flow_attr.group)),
3611 	},
3612 	[TABLE_PRIORITY] = {
3613 		.name = "priority",
3614 		.help = "specify a priority level",
3615 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
3616 		.args = ARGS(ARGS_ENTRY(struct buffer,
3617 					args.table.attr.flow_attr.priority)),
3618 	},
3619 	[TABLE_EGRESS] = {
3620 		.name = "egress",
3621 		.help = "affect rule to egress",
3622 		.next = NEXT(next_table_attr),
3623 		.call = parse_table,
3624 	},
3625 	[TABLE_INGRESS] = {
3626 		.name = "ingress",
3627 		.help = "affect rule to ingress",
3628 		.next = NEXT(next_table_attr),
3629 		.call = parse_table,
3630 	},
3631 	[TABLE_TRANSFER] = {
3632 		.name = "transfer",
3633 		.help = "affect rule to transfer",
3634 		.next = NEXT(next_table_attr),
3635 		.call = parse_table,
3636 	},
3637 	[TABLE_TRANSFER_WIRE_ORIG] = {
3638 		.name = "wire_orig",
3639 		.help = "affect rule direction to transfer",
3640 		.next = NEXT(next_table_attr),
3641 		.call = parse_table,
3642 	},
3643 	[TABLE_TRANSFER_VPORT_ORIG] = {
3644 		.name = "vport_orig",
3645 		.help = "affect rule direction to transfer",
3646 		.next = NEXT(next_table_attr),
3647 		.call = parse_table,
3648 	},
3649 	[TABLE_RESIZABLE] = {
3650 		.name = "resizable",
3651 		.help = "set resizable attribute",
3652 		.next = NEXT(next_table_attr),
3653 		.call = parse_table,
3654 	},
3655 	[TABLE_RULES_NUMBER] = {
3656 		.name = "rules_number",
3657 		.help = "number of rules in table",
3658 		.next = NEXT(next_table_attr,
3659 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3660 		.args = ARGS(ARGS_ENTRY(struct buffer,
3661 					args.table.attr.nb_flows)),
3662 		.call = parse_table,
3663 	},
3664 	[TABLE_PATTERN_TEMPLATE] = {
3665 		.name = "pattern_template",
3666 		.help = "specify pattern template id",
3667 		.next = NEXT(next_table_attr,
3668 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3669 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3670 					    args.table.pat_templ_id)),
3671 		.call = parse_table,
3672 	},
3673 	[TABLE_ACTIONS_TEMPLATE] = {
3674 		.name = "actions_template",
3675 		.help = "specify actions template id",
3676 		.next = NEXT(next_table_attr,
3677 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3678 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3679 					    args.table.act_templ_id)),
3680 		.call = parse_table,
3681 	},
3682 	/* Top-level command. */
3683 	[FLOW_GROUP] = {
3684 		.name = "group",
3685 		.help = "manage flow groups",
3686 		.next = NEXT(NEXT_ENTRY(GROUP_ID), NEXT_ENTRY(COMMON_PORT_ID)),
3687 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3688 		.call = parse_group,
3689 	},
3690 	/* Sub-level commands. */
3691 	[GROUP_SET_MISS_ACTIONS] = {
3692 		.name = "set_miss_actions",
3693 		.help = "set group miss actions",
3694 		.next = NEXT(next_action),
3695 		.call = parse_group,
3696 	},
3697 	/* Group arguments */
3698 	[GROUP_ID]	= {
3699 		.name = "group_id",
3700 		.help = "group id",
3701 		.next = NEXT(next_group_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3702 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3703 	},
3704 	[GROUP_INGRESS] = {
3705 		.name = "ingress",
3706 		.help = "group ingress attr",
3707 		.next = NEXT(next_group_attr),
3708 		.call = parse_group,
3709 	},
3710 	[GROUP_EGRESS] = {
3711 		.name = "egress",
3712 		.help = "group egress attr",
3713 		.next = NEXT(next_group_attr),
3714 		.call = parse_group,
3715 	},
3716 	[GROUP_TRANSFER] = {
3717 		.name = "transfer",
3718 		.help = "group transfer attr",
3719 		.next = NEXT(next_group_attr),
3720 		.call = parse_group,
3721 	},
3722 	/* Top-level command. */
3723 	[QUEUE] = {
3724 		.name = "queue",
3725 		.help = "queue a flow rule operation",
3726 		.next = NEXT(next_queue_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3727 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3728 		.call = parse_qo,
3729 	},
3730 	/* Sub-level commands. */
3731 	[QUEUE_CREATE] = {
3732 		.name = "create",
3733 		.help = "create a flow rule",
3734 		.next = NEXT(NEXT_ENTRY(QUEUE_TEMPLATE_TABLE),
3735 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3736 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3737 		.call = parse_qo,
3738 	},
3739 	[QUEUE_DESTROY] = {
3740 		.name = "destroy",
3741 		.help = "destroy a flow rule",
3742 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_POSTPONE),
3743 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3744 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3745 		.call = parse_qo_destroy,
3746 	},
3747 	[QUEUE_FLOW_UPDATE_RESIZED] = {
3748 		.name = "update_resized",
3749 		.help = "update a flow after table resize",
3750 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3751 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3752 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3753 		.call = parse_qo_destroy,
3754 	},
3755 	[QUEUE_UPDATE] = {
3756 		.name = "update",
3757 		.help = "update a flow rule",
3758 		.next = NEXT(NEXT_ENTRY(QUEUE_UPDATE_ID),
3759 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3760 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3761 		.call = parse_qo,
3762 	},
3763 	[QUEUE_AGED] = {
3764 		.name = "aged",
3765 		.help = "list and destroy aged flows",
3766 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_QUEUE_ID)),
3767 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3768 		.call = parse_aged,
3769 	},
3770 	[QUEUE_INDIRECT_ACTION] = {
3771 		.name = "indirect_action",
3772 		.help = "queue indirect actions",
3773 		.next = NEXT(next_qia_subcmd, NEXT_ENTRY(COMMON_QUEUE_ID)),
3774 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3775 		.call = parse_qia,
3776 	},
3777 	/* Queue  arguments. */
3778 	[QUEUE_TEMPLATE_TABLE] = {
3779 		.name = "template_table",
3780 		.help = "specify table id",
3781 		.next = NEXT(next_async_insert_subcmd,
3782 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3783 		.args = ARGS(ARGS_ENTRY(struct buffer,
3784 					args.vc.table_id)),
3785 		.call = parse_qo,
3786 	},
3787 	[QUEUE_PATTERN_TEMPLATE] = {
3788 		.name = "pattern_template",
3789 		.help = "specify pattern template index",
3790 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3791 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3792 		.args = ARGS(ARGS_ENTRY(struct buffer,
3793 					args.vc.pat_templ_id)),
3794 		.call = parse_qo,
3795 	},
3796 	[QUEUE_ACTIONS_TEMPLATE] = {
3797 		.name = "actions_template",
3798 		.help = "specify actions template index",
3799 		.next = NEXT(NEXT_ENTRY(QUEUE_CREATE_POSTPONE),
3800 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3801 		.args = ARGS(ARGS_ENTRY(struct buffer,
3802 					args.vc.act_templ_id)),
3803 		.call = parse_qo,
3804 	},
3805 	[QUEUE_RULE_ID] = {
3806 		.name = "rule_index",
3807 		.help = "specify flow rule index",
3808 		.next = NEXT(next_async_pattern_subcmd,
3809 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3810 		.args = ARGS(ARGS_ENTRY(struct buffer,
3811 					args.vc.rule_id)),
3812 		.call = parse_qo,
3813 	},
3814 	[QUEUE_CREATE_POSTPONE] = {
3815 		.name = "postpone",
3816 		.help = "postpone create operation",
3817 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
3818 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3819 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3820 		.call = parse_qo,
3821 	},
3822 	[QUEUE_DESTROY_POSTPONE] = {
3823 		.name = "postpone",
3824 		.help = "postpone destroy operation",
3825 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3826 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3827 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3828 		.call = parse_qo_destroy,
3829 	},
3830 	[QUEUE_DESTROY_ID] = {
3831 		.name = "rule",
3832 		.help = "specify rule id to destroy",
3833 		.next = NEXT(next_queue_destroy_attr,
3834 			NEXT_ENTRY(COMMON_UNSIGNED)),
3835 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3836 					    args.destroy.rule)),
3837 		.call = parse_qo_destroy,
3838 	},
3839 	[QUEUE_UPDATE_ID] = {
3840 		.name = "rule",
3841 		.help = "specify rule id to update",
3842 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3843 			NEXT_ENTRY(COMMON_UNSIGNED)),
3844 		.args = ARGS(ARGS_ENTRY(struct buffer,
3845 				     args.vc.rule_id)),
3846 		.call = parse_qo,
3847 	},
3848 	/* Queue indirect action arguments */
3849 	[QUEUE_INDIRECT_ACTION_CREATE] = {
3850 		.name = "create",
3851 		.help = "create indirect action",
3852 		.next = NEXT(next_qia_create_attr),
3853 		.call = parse_qia,
3854 	},
3855 	[QUEUE_INDIRECT_ACTION_UPDATE] = {
3856 		.name = "update",
3857 		.help = "update indirect action",
3858 		.next = NEXT(next_qia_update_attr,
3859 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3860 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3861 		.call = parse_qia,
3862 	},
3863 	[QUEUE_INDIRECT_ACTION_DESTROY] = {
3864 		.name = "destroy",
3865 		.help = "destroy indirect action",
3866 		.next = NEXT(next_qia_destroy_attr),
3867 		.call = parse_qia_destroy,
3868 	},
3869 	[QUEUE_INDIRECT_ACTION_QUERY] = {
3870 		.name = "query",
3871 		.help = "query indirect action",
3872 		.next = NEXT(next_qia_query_attr,
3873 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3874 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3875 		.call = parse_qia,
3876 	},
3877 	/* Indirect action destroy arguments. */
3878 	[QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE] = {
3879 		.name = "postpone",
3880 		.help = "postpone destroy operation",
3881 		.next = NEXT(next_qia_destroy_attr,
3882 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3883 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3884 	},
3885 	[QUEUE_INDIRECT_ACTION_DESTROY_ID] = {
3886 		.name = "action_id",
3887 		.help = "specify a indirect action id to destroy",
3888 		.next = NEXT(next_qia_destroy_attr,
3889 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3890 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3891 					    args.ia_destroy.action_id)),
3892 		.call = parse_qia_destroy,
3893 	},
3894 	[QUEUE_INDIRECT_ACTION_QUERY_UPDATE] = {
3895 		.name = "query_update",
3896 		.help = "indirect query [and|or] update action",
3897 		.next = NEXT(next_qia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3898 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3899 		.call = parse_qia
3900 	},
3901 	[QUEUE_INDIRECT_ACTION_QU_MODE] = {
3902 		.name = "mode",
3903 		.help = "indirect query [and|or] update action",
3904 		.next = NEXT(next_qia_qu_attr,
3905 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
3906 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
3907 		.call = parse_qia
3908 	},
3909 	/* Indirect action update arguments. */
3910 	[QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE] = {
3911 		.name = "postpone",
3912 		.help = "postpone update operation",
3913 		.next = NEXT(next_qia_update_attr,
3914 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3915 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3916 	},
3917 	/* Indirect action update arguments. */
3918 	[QUEUE_INDIRECT_ACTION_QUERY_POSTPONE] = {
3919 		.name = "postpone",
3920 		.help = "postpone query operation",
3921 		.next = NEXT(next_qia_query_attr,
3922 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3923 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3924 	},
3925 	/* Indirect action create arguments. */
3926 	[QUEUE_INDIRECT_ACTION_CREATE_ID] = {
3927 		.name = "action_id",
3928 		.help = "specify a indirect action id to create",
3929 		.next = NEXT(next_qia_create_attr,
3930 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3931 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3932 	},
3933 	[QUEUE_INDIRECT_ACTION_INGRESS] = {
3934 		.name = "ingress",
3935 		.help = "affect rule to ingress",
3936 		.next = NEXT(next_qia_create_attr),
3937 		.call = parse_qia,
3938 	},
3939 	[QUEUE_INDIRECT_ACTION_EGRESS] = {
3940 		.name = "egress",
3941 		.help = "affect rule to egress",
3942 		.next = NEXT(next_qia_create_attr),
3943 		.call = parse_qia,
3944 	},
3945 	[QUEUE_INDIRECT_ACTION_TRANSFER] = {
3946 		.name = "transfer",
3947 		.help = "affect rule to transfer",
3948 		.next = NEXT(next_qia_create_attr),
3949 		.call = parse_qia,
3950 	},
3951 	[QUEUE_INDIRECT_ACTION_CREATE_POSTPONE] = {
3952 		.name = "postpone",
3953 		.help = "postpone create operation",
3954 		.next = NEXT(next_qia_create_attr,
3955 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3956 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3957 	},
3958 	[QUEUE_INDIRECT_ACTION_SPEC] = {
3959 		.name = "action",
3960 		.help = "specify action to create indirect handle",
3961 		.next = NEXT(next_action),
3962 	},
3963 	[QUEUE_INDIRECT_ACTION_LIST] = {
3964 		.name = "list",
3965 		.help = "specify actions for indirect handle list",
3966 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
3967 		.call = parse_qia,
3968 	},
3969 	/* Top-level command. */
3970 	[PUSH] = {
3971 		.name = "push",
3972 		.help = "push enqueued operations",
3973 		.next = NEXT(NEXT_ENTRY(PUSH_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3974 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3975 		.call = parse_push,
3976 	},
3977 	/* Sub-level commands. */
3978 	[PUSH_QUEUE] = {
3979 		.name = "queue",
3980 		.help = "specify queue id",
3981 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3982 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3983 	},
3984 	/* Top-level command. */
3985 	[PULL] = {
3986 		.name = "pull",
3987 		.help = "pull flow operations results",
3988 		.next = NEXT(NEXT_ENTRY(PULL_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3989 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3990 		.call = parse_pull,
3991 	},
3992 	/* Sub-level commands. */
3993 	[PULL_QUEUE] = {
3994 		.name = "queue",
3995 		.help = "specify queue id",
3996 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3997 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3998 	},
3999 	/* Top-level command. */
4000 	[HASH] = {
4001 		.name = "hash",
4002 		.help = "calculate hash for a given pattern in a given template table",
4003 		.next = NEXT(next_hash_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
4004 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4005 		.call = parse_hash,
4006 	},
4007 	/* Sub-level commands. */
4008 	[HASH_CALC_TABLE] = {
4009 		.name = "template_table",
4010 		.help = "specify table id",
4011 		.next = NEXT(NEXT_ENTRY(HASH_CALC_PATTERN_INDEX),
4012 			     NEXT_ENTRY(COMMON_TABLE_ID)),
4013 		.args = ARGS(ARGS_ENTRY(struct buffer,
4014 					args.vc.table_id)),
4015 		.call = parse_hash,
4016 	},
4017 	[HASH_CALC_ENCAP] = {
4018 		.name = "encap",
4019 		.help = "calculates encap hash",
4020 		.next = NEXT(next_hash_encap_dest_subcmd),
4021 		.call = parse_hash,
4022 	},
4023 	[HASH_CALC_PATTERN_INDEX] = {
4024 		.name = "pattern_template",
4025 		.help = "specify pattern template id",
4026 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
4027 			     NEXT_ENTRY(COMMON_UNSIGNED)),
4028 		.args = ARGS(ARGS_ENTRY(struct buffer,
4029 					args.vc.pat_templ_id)),
4030 		.call = parse_hash,
4031 	},
4032 	[ENCAP_HASH_FIELD_SRC_PORT] = {
4033 		.name = "hash_field_sport",
4034 		.help = "the encap hash field is src port",
4035 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
4036 		.call = parse_hash,
4037 	},
4038 	[ENCAP_HASH_FIELD_GRE_FLOW_ID] = {
4039 		.name = "hash_field_flow_id",
4040 		.help = "the encap hash field is NVGRE flow id",
4041 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
4042 		.call = parse_hash,
4043 	},
4044 	/* Top-level command. */
4045 	[INDIRECT_ACTION] = {
4046 		.name = "indirect_action",
4047 		.type = "{command} {port_id} [{arg} [...]]",
4048 		.help = "manage indirect actions",
4049 		.next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
4050 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4051 		.call = parse_ia,
4052 	},
4053 	/* Sub-level commands. */
4054 	[INDIRECT_ACTION_CREATE] = {
4055 		.name = "create",
4056 		.help = "create indirect action",
4057 		.next = NEXT(next_ia_create_attr),
4058 		.call = parse_ia,
4059 	},
4060 	[INDIRECT_ACTION_UPDATE] = {
4061 		.name = "update",
4062 		.help = "update indirect action",
4063 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
4064 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4065 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
4066 		.call = parse_ia,
4067 	},
4068 	[INDIRECT_ACTION_DESTROY] = {
4069 		.name = "destroy",
4070 		.help = "destroy indirect action",
4071 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
4072 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4073 		.call = parse_ia_destroy,
4074 	},
4075 	[INDIRECT_ACTION_QUERY] = {
4076 		.name = "query",
4077 		.help = "query indirect action",
4078 		.next = NEXT(NEXT_ENTRY(END),
4079 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4080 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
4081 		.call = parse_ia,
4082 	},
4083 	[INDIRECT_ACTION_QUERY_UPDATE] = {
4084 		.name = "query_update",
4085 		.help = "query [and|or] update",
4086 		.next = NEXT(next_ia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4087 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
4088 		.call = parse_ia
4089 	},
4090 	[INDIRECT_ACTION_QU_MODE] = {
4091 		.name = "mode",
4092 		.help = "query_update mode",
4093 		.next = NEXT(next_ia_qu_attr,
4094 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
4095 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
4096 		.call = parse_ia,
4097 	},
4098 	[INDIRECT_ACTION_QU_MODE_NAME] = {
4099 		.name = "mode_name",
4100 		.help = "query-update mode name",
4101 		.call = parse_qu_mode_name,
4102 		.comp = comp_qu_mode_name,
4103 	},
4104 	[VALIDATE] = {
4105 		.name = "validate",
4106 		.help = "check whether a flow rule can be created",
4107 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4108 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4109 		.call = parse_vc,
4110 	},
4111 	[CREATE] = {
4112 		.name = "create",
4113 		.help = "create a flow rule",
4114 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4115 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4116 		.call = parse_vc,
4117 	},
4118 	[DESTROY] = {
4119 		.name = "destroy",
4120 		.help = "destroy specific flow rules",
4121 		.next = NEXT(next_destroy_attr,
4122 			     NEXT_ENTRY(COMMON_PORT_ID)),
4123 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4124 		.call = parse_destroy,
4125 	},
4126 	[UPDATE] = {
4127 		.name = "update",
4128 		.help = "update a flow rule with new actions",
4129 		.next = NEXT(NEXT_ENTRY(VC_IS_USER_ID, END),
4130 			     NEXT_ENTRY(ACTIONS),
4131 			     NEXT_ENTRY(COMMON_RULE_ID),
4132 			     NEXT_ENTRY(COMMON_PORT_ID)),
4133 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.rule_id),
4134 			     ARGS_ENTRY(struct buffer, port)),
4135 		.call = parse_vc,
4136 	},
4137 	[FLUSH] = {
4138 		.name = "flush",
4139 		.help = "destroy all flow rules",
4140 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4141 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4142 		.call = parse_flush,
4143 	},
4144 	[DUMP] = {
4145 		.name = "dump",
4146 		.help = "dump single/all flow rules to file",
4147 		.next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
4148 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4149 		.call = parse_dump,
4150 	},
4151 	[QUERY] = {
4152 		.name = "query",
4153 		.help = "query an existing flow rule",
4154 		.next = NEXT(next_query_attr, NEXT_ENTRY(QUERY_ACTION),
4155 			     NEXT_ENTRY(COMMON_RULE_ID),
4156 			     NEXT_ENTRY(COMMON_PORT_ID)),
4157 		.args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
4158 			     ARGS_ENTRY(struct buffer, args.query.rule),
4159 			     ARGS_ENTRY(struct buffer, port)),
4160 		.call = parse_query,
4161 	},
4162 	[LIST] = {
4163 		.name = "list",
4164 		.help = "list existing flow rules",
4165 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4166 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4167 		.call = parse_list,
4168 	},
4169 	[AGED] = {
4170 		.name = "aged",
4171 		.help = "list and destroy aged flows",
4172 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4173 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4174 		.call = parse_aged,
4175 	},
4176 	[ISOLATE] = {
4177 		.name = "isolate",
4178 		.help = "restrict ingress traffic to the defined flow rules",
4179 		.next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
4180 			     NEXT_ENTRY(COMMON_PORT_ID)),
4181 		.args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
4182 			     ARGS_ENTRY(struct buffer, port)),
4183 		.call = parse_isolate,
4184 	},
4185 	[FLEX] = {
4186 		.name = "flex_item",
4187 		.help = "flex item API",
4188 		.next = NEXT(next_flex_item),
4189 		.call = parse_flex,
4190 	},
4191 	[FLEX_ITEM_INIT] = {
4192 		.name = "init",
4193 		.help = "flex item init",
4194 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
4195 			     ARGS_ENTRY(struct buffer, port)),
4196 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
4197 			     NEXT_ENTRY(COMMON_PORT_ID)),
4198 		.call = parse_flex
4199 	},
4200 	[FLEX_ITEM_CREATE] = {
4201 		.name = "create",
4202 		.help = "flex item create",
4203 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename),
4204 			     ARGS_ENTRY(struct buffer, args.flex.token),
4205 			     ARGS_ENTRY(struct buffer, port)),
4206 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH),
4207 			     NEXT_ENTRY(COMMON_FLEX_TOKEN),
4208 			     NEXT_ENTRY(COMMON_PORT_ID)),
4209 		.call = parse_flex
4210 	},
4211 	[FLEX_ITEM_DESTROY] = {
4212 		.name = "destroy",
4213 		.help = "flex item destroy",
4214 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
4215 			     ARGS_ENTRY(struct buffer, port)),
4216 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
4217 			     NEXT_ENTRY(COMMON_PORT_ID)),
4218 		.call = parse_flex
4219 	},
4220 	[TUNNEL] = {
4221 		.name = "tunnel",
4222 		.help = "new tunnel API",
4223 		.next = NEXT(NEXT_ENTRY
4224 			     (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
4225 		.call = parse_tunnel,
4226 	},
4227 	/* Tunnel arguments. */
4228 	[TUNNEL_CREATE] = {
4229 		.name = "create",
4230 		.help = "create new tunnel object",
4231 		.next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
4232 			     NEXT_ENTRY(COMMON_PORT_ID)),
4233 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4234 		.call = parse_tunnel,
4235 	},
4236 	[TUNNEL_CREATE_TYPE] = {
4237 		.name = "type",
4238 		.help = "create new tunnel",
4239 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
4240 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
4241 		.call = parse_tunnel,
4242 	},
4243 	[TUNNEL_DESTROY] = {
4244 		.name = "destroy",
4245 		.help = "destroy tunnel",
4246 		.next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
4247 			     NEXT_ENTRY(COMMON_PORT_ID)),
4248 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4249 		.call = parse_tunnel,
4250 	},
4251 	[TUNNEL_DESTROY_ID] = {
4252 		.name = "id",
4253 		.help = "tunnel identifier to destroy",
4254 		.next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
4255 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4256 		.call = parse_tunnel,
4257 	},
4258 	[TUNNEL_LIST] = {
4259 		.name = "list",
4260 		.help = "list existing tunnels",
4261 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4262 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4263 		.call = parse_tunnel,
4264 	},
4265 	/* Destroy arguments. */
4266 	[DESTROY_RULE] = {
4267 		.name = "rule",
4268 		.help = "specify a rule identifier",
4269 		.next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4270 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
4271 		.call = parse_destroy,
4272 	},
4273 	[DESTROY_IS_USER_ID] = {
4274 		.name = "user_id",
4275 		.help = "rule identifier is user-id",
4276 		.next = NEXT(next_destroy_attr),
4277 		.call = parse_destroy,
4278 	},
4279 	/* Dump arguments. */
4280 	[DUMP_ALL] = {
4281 		.name = "all",
4282 		.help = "dump all",
4283 		.next = NEXT(next_dump_attr),
4284 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
4285 		.call = parse_dump,
4286 	},
4287 	[DUMP_ONE] = {
4288 		.name = "rule",
4289 		.help = "dump one rule",
4290 		.next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4291 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
4292 				ARGS_ENTRY(struct buffer, args.dump.rule)),
4293 		.call = parse_dump,
4294 	},
4295 	[DUMP_IS_USER_ID] = {
4296 		.name = "user_id",
4297 		.help = "rule identifier is user-id",
4298 		.next = NEXT(next_dump_subcmd),
4299 		.call = parse_dump,
4300 	},
4301 	/* Query arguments. */
4302 	[QUERY_ACTION] = {
4303 		.name = "{action}",
4304 		.type = "ACTION",
4305 		.help = "action to query, must be part of the rule",
4306 		.call = parse_action,
4307 		.comp = comp_action,
4308 	},
4309 	[QUERY_IS_USER_ID] = {
4310 		.name = "user_id",
4311 		.help = "rule identifier is user-id",
4312 		.next = NEXT(next_query_attr),
4313 		.call = parse_query,
4314 	},
4315 	/* List arguments. */
4316 	[LIST_GROUP] = {
4317 		.name = "group",
4318 		.help = "specify a group",
4319 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4320 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
4321 		.call = parse_list,
4322 	},
4323 	[AGED_DESTROY] = {
4324 		.name = "destroy",
4325 		.help = "specify aged flows need be destroyed",
4326 		.call = parse_aged,
4327 		.comp = comp_none,
4328 	},
4329 	/* Validate/create attributes. */
4330 	[VC_GROUP] = {
4331 		.name = "group",
4332 		.help = "specify a group",
4333 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4334 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
4335 		.call = parse_vc,
4336 	},
4337 	[VC_PRIORITY] = {
4338 		.name = "priority",
4339 		.help = "specify a priority level",
4340 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
4341 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
4342 		.call = parse_vc,
4343 	},
4344 	[VC_INGRESS] = {
4345 		.name = "ingress",
4346 		.help = "affect rule to ingress",
4347 		.next = NEXT(next_vc_attr),
4348 		.call = parse_vc,
4349 	},
4350 	[VC_EGRESS] = {
4351 		.name = "egress",
4352 		.help = "affect rule to egress",
4353 		.next = NEXT(next_vc_attr),
4354 		.call = parse_vc,
4355 	},
4356 	[VC_TRANSFER] = {
4357 		.name = "transfer",
4358 		.help = "apply rule directly to endpoints found in pattern",
4359 		.next = NEXT(next_vc_attr),
4360 		.call = parse_vc,
4361 	},
4362 	[VC_TUNNEL_SET] = {
4363 		.name = "tunnel_set",
4364 		.help = "tunnel steer rule",
4365 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4366 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4367 		.call = parse_vc,
4368 	},
4369 	[VC_TUNNEL_MATCH] = {
4370 		.name = "tunnel_match",
4371 		.help = "tunnel match rule",
4372 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4373 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4374 		.call = parse_vc,
4375 	},
4376 	[VC_USER_ID] = {
4377 		.name = "user_id",
4378 		.help = "specify a user id to create",
4379 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4380 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.user_id)),
4381 		.call = parse_vc,
4382 	},
4383 	[VC_IS_USER_ID] = {
4384 		.name = "user_id",
4385 		.help = "rule identifier is user-id",
4386 		.call = parse_vc,
4387 	},
4388 	/* Validate/create pattern. */
4389 	[ITEM_PATTERN] = {
4390 		.name = "pattern",
4391 		.help = "submit a list of pattern items",
4392 		.next = NEXT(next_item),
4393 		.call = parse_vc,
4394 	},
4395 	[ITEM_PARAM_IS] = {
4396 		.name = "is",
4397 		.help = "match value perfectly (with full bit-mask)",
4398 		.call = parse_vc_spec,
4399 	},
4400 	[ITEM_PARAM_SPEC] = {
4401 		.name = "spec",
4402 		.help = "match value according to configured bit-mask",
4403 		.call = parse_vc_spec,
4404 	},
4405 	[ITEM_PARAM_LAST] = {
4406 		.name = "last",
4407 		.help = "specify upper bound to establish a range",
4408 		.call = parse_vc_spec,
4409 	},
4410 	[ITEM_PARAM_MASK] = {
4411 		.name = "mask",
4412 		.help = "specify bit-mask with relevant bits set to one",
4413 		.call = parse_vc_spec,
4414 	},
4415 	[ITEM_PARAM_PREFIX] = {
4416 		.name = "prefix",
4417 		.help = "generate bit-mask from a prefix length",
4418 		.call = parse_vc_spec,
4419 	},
4420 	[ITEM_NEXT] = {
4421 		.name = "/",
4422 		.help = "specify next pattern item",
4423 		.next = NEXT(next_item),
4424 	},
4425 	[ITEM_END] = {
4426 		.name = "end",
4427 		.help = "end list of pattern items",
4428 		.priv = PRIV_ITEM(END, 0),
4429 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
4430 		.call = parse_vc,
4431 	},
4432 	[ITEM_VOID] = {
4433 		.name = "void",
4434 		.help = "no-op pattern item",
4435 		.priv = PRIV_ITEM(VOID, 0),
4436 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4437 		.call = parse_vc,
4438 	},
4439 	[ITEM_INVERT] = {
4440 		.name = "invert",
4441 		.help = "perform actions when pattern does not match",
4442 		.priv = PRIV_ITEM(INVERT, 0),
4443 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4444 		.call = parse_vc,
4445 	},
4446 	[ITEM_ANY] = {
4447 		.name = "any",
4448 		.help = "match any protocol for the current layer",
4449 		.priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
4450 		.next = NEXT(item_any),
4451 		.call = parse_vc,
4452 	},
4453 	[ITEM_ANY_NUM] = {
4454 		.name = "num",
4455 		.help = "number of layers covered",
4456 		.next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4457 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
4458 	},
4459 	[ITEM_PORT_ID] = {
4460 		.name = "port_id",
4461 		.help = "match traffic from/to a given DPDK port ID",
4462 		.priv = PRIV_ITEM(PORT_ID,
4463 				  sizeof(struct rte_flow_item_port_id)),
4464 		.next = NEXT(item_port_id),
4465 		.call = parse_vc,
4466 	},
4467 	[ITEM_PORT_ID_ID] = {
4468 		.name = "id",
4469 		.help = "DPDK port ID",
4470 		.next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
4471 			     item_param),
4472 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
4473 	},
4474 	[ITEM_MARK] = {
4475 		.name = "mark",
4476 		.help = "match traffic against value set in previously matched rule",
4477 		.priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
4478 		.next = NEXT(item_mark),
4479 		.call = parse_vc,
4480 	},
4481 	[ITEM_MARK_ID] = {
4482 		.name = "id",
4483 		.help = "Integer value to match against",
4484 		.next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
4485 			     item_param),
4486 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
4487 	},
4488 	[ITEM_RAW] = {
4489 		.name = "raw",
4490 		.help = "match an arbitrary byte string",
4491 		.priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
4492 		.next = NEXT(item_raw),
4493 		.call = parse_vc,
4494 	},
4495 	[ITEM_RAW_RELATIVE] = {
4496 		.name = "relative",
4497 		.help = "look for pattern after the previous item",
4498 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4499 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4500 					   relative, 1)),
4501 	},
4502 	[ITEM_RAW_SEARCH] = {
4503 		.name = "search",
4504 		.help = "search pattern from offset (see also limit)",
4505 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4506 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4507 					   search, 1)),
4508 	},
4509 	[ITEM_RAW_OFFSET] = {
4510 		.name = "offset",
4511 		.help = "absolute or relative offset for pattern",
4512 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
4513 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
4514 	},
4515 	[ITEM_RAW_LIMIT] = {
4516 		.name = "limit",
4517 		.help = "search area limit for start of pattern",
4518 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4519 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
4520 	},
4521 	[ITEM_RAW_PATTERN] = {
4522 		.name = "pattern",
4523 		.help = "byte string to look for",
4524 		.next = NEXT(item_raw,
4525 			     NEXT_ENTRY(COMMON_STRING),
4526 			     NEXT_ENTRY(ITEM_PARAM_IS,
4527 					ITEM_PARAM_SPEC,
4528 					ITEM_PARAM_MASK)),
4529 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4530 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4531 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4532 					    ITEM_RAW_PATTERN_SIZE)),
4533 	},
4534 	[ITEM_RAW_PATTERN_HEX] = {
4535 		.name = "pattern_hex",
4536 		.help = "hex string to look for",
4537 		.next = NEXT(item_raw,
4538 			     NEXT_ENTRY(COMMON_HEX),
4539 			     NEXT_ENTRY(ITEM_PARAM_IS,
4540 					ITEM_PARAM_SPEC,
4541 					ITEM_PARAM_MASK)),
4542 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4543 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4544 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4545 					    ITEM_RAW_PATTERN_SIZE)),
4546 	},
4547 	[ITEM_ETH] = {
4548 		.name = "eth",
4549 		.help = "match Ethernet header",
4550 		.priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
4551 		.next = NEXT(item_eth),
4552 		.call = parse_vc,
4553 	},
4554 	[ITEM_ETH_DST] = {
4555 		.name = "dst",
4556 		.help = "destination MAC",
4557 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4558 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.dst_addr)),
4559 	},
4560 	[ITEM_ETH_SRC] = {
4561 		.name = "src",
4562 		.help = "source MAC",
4563 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4564 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.src_addr)),
4565 	},
4566 	[ITEM_ETH_TYPE] = {
4567 		.name = "type",
4568 		.help = "EtherType",
4569 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4570 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.ether_type)),
4571 	},
4572 	[ITEM_ETH_HAS_VLAN] = {
4573 		.name = "has_vlan",
4574 		.help = "packet header contains VLAN",
4575 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4576 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
4577 					   has_vlan, 1)),
4578 	},
4579 	[ITEM_VLAN] = {
4580 		.name = "vlan",
4581 		.help = "match 802.1Q/ad VLAN tag",
4582 		.priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
4583 		.next = NEXT(item_vlan),
4584 		.call = parse_vc,
4585 	},
4586 	[ITEM_VLAN_TCI] = {
4587 		.name = "tci",
4588 		.help = "tag control information",
4589 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4590 			     item_param),
4591 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, hdr.vlan_tci)),
4592 	},
4593 	[ITEM_VLAN_PCP] = {
4594 		.name = "pcp",
4595 		.help = "priority code point",
4596 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4597 			     item_param),
4598 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4599 						  hdr.vlan_tci, "\xe0\x00")),
4600 	},
4601 	[ITEM_VLAN_DEI] = {
4602 		.name = "dei",
4603 		.help = "drop eligible indicator",
4604 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4605 			     item_param),
4606 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4607 						  hdr.vlan_tci, "\x10\x00")),
4608 	},
4609 	[ITEM_VLAN_VID] = {
4610 		.name = "vid",
4611 		.help = "VLAN identifier",
4612 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4613 			     item_param),
4614 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4615 						  hdr.vlan_tci, "\x0f\xff")),
4616 	},
4617 	[ITEM_VLAN_INNER_TYPE] = {
4618 		.name = "inner_type",
4619 		.help = "inner EtherType",
4620 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4621 			     item_param),
4622 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
4623 					     hdr.eth_proto)),
4624 	},
4625 	[ITEM_VLAN_HAS_MORE_VLAN] = {
4626 		.name = "has_more_vlan",
4627 		.help = "packet header contains another VLAN",
4628 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4629 			     item_param),
4630 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
4631 					   has_more_vlan, 1)),
4632 	},
4633 	[ITEM_IPV4] = {
4634 		.name = "ipv4",
4635 		.help = "match IPv4 header",
4636 		.priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
4637 		.next = NEXT(item_ipv4),
4638 		.call = parse_vc,
4639 	},
4640 	[ITEM_IPV4_VER_IHL] = {
4641 		.name = "version_ihl",
4642 		.help = "match header length",
4643 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4644 			     item_param),
4645 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
4646 				     hdr.version_ihl)),
4647 	},
4648 	[ITEM_IPV4_TOS] = {
4649 		.name = "tos",
4650 		.help = "type of service",
4651 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4652 			     item_param),
4653 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4654 					     hdr.type_of_service)),
4655 	},
4656 	[ITEM_IPV4_LENGTH] = {
4657 		.name = "length",
4658 		.help = "total length",
4659 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4660 			     item_param),
4661 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4662 					     hdr.total_length)),
4663 	},
4664 	[ITEM_IPV4_ID] = {
4665 		.name = "packet_id",
4666 		.help = "fragment packet id",
4667 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4668 			     item_param),
4669 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4670 					     hdr.packet_id)),
4671 	},
4672 	[ITEM_IPV4_FRAGMENT_OFFSET] = {
4673 		.name = "fragment_offset",
4674 		.help = "fragmentation flags and fragment offset",
4675 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4676 			     item_param),
4677 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4678 					     hdr.fragment_offset)),
4679 	},
4680 	[ITEM_IPV4_TTL] = {
4681 		.name = "ttl",
4682 		.help = "time to live",
4683 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4684 			     item_param),
4685 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4686 					     hdr.time_to_live)),
4687 	},
4688 	[ITEM_IPV4_PROTO] = {
4689 		.name = "proto",
4690 		.help = "next protocol ID",
4691 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4692 			     item_param),
4693 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4694 					     hdr.next_proto_id)),
4695 	},
4696 	[ITEM_IPV4_SRC] = {
4697 		.name = "src",
4698 		.help = "source address",
4699 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4700 			     item_param),
4701 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4702 					     hdr.src_addr)),
4703 	},
4704 	[ITEM_IPV4_DST] = {
4705 		.name = "dst",
4706 		.help = "destination address",
4707 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4708 			     item_param),
4709 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4710 					     hdr.dst_addr)),
4711 	},
4712 	[ITEM_IPV6] = {
4713 		.name = "ipv6",
4714 		.help = "match IPv6 header",
4715 		.priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
4716 		.next = NEXT(item_ipv6),
4717 		.call = parse_vc,
4718 	},
4719 	[ITEM_IPV6_TC] = {
4720 		.name = "tc",
4721 		.help = "traffic class",
4722 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4723 			     item_param),
4724 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4725 						  hdr.vtc_flow,
4726 						  "\x0f\xf0\x00\x00")),
4727 	},
4728 	[ITEM_IPV6_FLOW] = {
4729 		.name = "flow",
4730 		.help = "flow label",
4731 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4732 			     item_param),
4733 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4734 						  hdr.vtc_flow,
4735 						  "\x00\x0f\xff\xff")),
4736 	},
4737 	[ITEM_IPV6_LEN] = {
4738 		.name = "length",
4739 		.help = "payload length",
4740 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4741 			     item_param),
4742 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4743 					     hdr.payload_len)),
4744 	},
4745 	[ITEM_IPV6_PROTO] = {
4746 		.name = "proto",
4747 		.help = "protocol (next header)",
4748 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4749 			     item_param),
4750 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4751 					     hdr.proto)),
4752 	},
4753 	[ITEM_IPV6_HOP] = {
4754 		.name = "hop",
4755 		.help = "hop limit",
4756 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4757 			     item_param),
4758 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4759 					     hdr.hop_limits)),
4760 	},
4761 	[ITEM_IPV6_SRC] = {
4762 		.name = "src",
4763 		.help = "source address",
4764 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4765 			     item_param),
4766 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4767 					     hdr.src_addr)),
4768 	},
4769 	[ITEM_IPV6_DST] = {
4770 		.name = "dst",
4771 		.help = "destination address",
4772 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4773 			     item_param),
4774 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4775 					     hdr.dst_addr)),
4776 	},
4777 	[ITEM_IPV6_HAS_FRAG_EXT] = {
4778 		.name = "has_frag_ext",
4779 		.help = "fragment packet attribute",
4780 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4781 			     item_param),
4782 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
4783 					   has_frag_ext, 1)),
4784 	},
4785 	[ITEM_IPV6_ROUTING_EXT] = {
4786 		.name = "ipv6_routing_ext",
4787 		.help = "match IPv6 routing extension header",
4788 		.priv = PRIV_ITEM(IPV6_ROUTING_EXT,
4789 				  sizeof(struct rte_flow_item_ipv6_routing_ext)),
4790 		.next = NEXT(item_ipv6_routing_ext),
4791 		.call = parse_vc,
4792 	},
4793 	[ITEM_IPV6_ROUTING_EXT_TYPE] = {
4794 		.name = "ext_type",
4795 		.help = "match IPv6 routing extension header type",
4796 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4797 			     item_param),
4798 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4799 					     hdr.type)),
4800 	},
4801 	[ITEM_IPV6_ROUTING_EXT_NEXT_HDR] = {
4802 		.name = "ext_next_hdr",
4803 		.help = "match IPv6 routing extension header next header type",
4804 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4805 			     item_param),
4806 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4807 					     hdr.next_hdr)),
4808 	},
4809 	[ITEM_IPV6_ROUTING_EXT_SEG_LEFT] = {
4810 		.name = "ext_seg_left",
4811 		.help = "match IPv6 routing extension header segment left",
4812 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4813 			     item_param),
4814 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4815 					     hdr.segments_left)),
4816 	},
4817 	[ITEM_ICMP] = {
4818 		.name = "icmp",
4819 		.help = "match ICMP header",
4820 		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
4821 		.next = NEXT(item_icmp),
4822 		.call = parse_vc,
4823 	},
4824 	[ITEM_ICMP_TYPE] = {
4825 		.name = "type",
4826 		.help = "ICMP packet type",
4827 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4828 			     item_param),
4829 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4830 					     hdr.icmp_type)),
4831 	},
4832 	[ITEM_ICMP_CODE] = {
4833 		.name = "code",
4834 		.help = "ICMP packet code",
4835 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4836 			     item_param),
4837 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4838 					     hdr.icmp_code)),
4839 	},
4840 	[ITEM_ICMP_IDENT] = {
4841 		.name = "ident",
4842 		.help = "ICMP packet identifier",
4843 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4844 			     item_param),
4845 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4846 					     hdr.icmp_ident)),
4847 	},
4848 	[ITEM_ICMP_SEQ] = {
4849 		.name = "seq",
4850 		.help = "ICMP packet sequence number",
4851 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4852 			     item_param),
4853 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4854 					     hdr.icmp_seq_nb)),
4855 	},
4856 	[ITEM_UDP] = {
4857 		.name = "udp",
4858 		.help = "match UDP header",
4859 		.priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
4860 		.next = NEXT(item_udp),
4861 		.call = parse_vc,
4862 	},
4863 	[ITEM_UDP_SRC] = {
4864 		.name = "src",
4865 		.help = "UDP source port",
4866 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
4867 			     item_param),
4868 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4869 					     hdr.src_port)),
4870 	},
4871 	[ITEM_UDP_DST] = {
4872 		.name = "dst",
4873 		.help = "UDP destination port",
4874 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4875 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4876 					     hdr.dst_port)),
4877 	},
4878 	[ITEM_TCP] = {
4879 		.name = "tcp",
4880 		.help = "match TCP header",
4881 		.priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
4882 		.next = NEXT(item_tcp),
4883 		.call = parse_vc,
4884 	},
4885 	[ITEM_TCP_SRC] = {
4886 		.name = "src",
4887 		.help = "TCP source port",
4888 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4889 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4890 					     hdr.src_port)),
4891 	},
4892 	[ITEM_TCP_DST] = {
4893 		.name = "dst",
4894 		.help = "TCP destination port",
4895 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4896 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4897 					     hdr.dst_port)),
4898 	},
4899 	[ITEM_TCP_FLAGS] = {
4900 		.name = "flags",
4901 		.help = "TCP flags",
4902 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4903 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4904 					     hdr.tcp_flags)),
4905 	},
4906 	[ITEM_SCTP] = {
4907 		.name = "sctp",
4908 		.help = "match SCTP header",
4909 		.priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
4910 		.next = NEXT(item_sctp),
4911 		.call = parse_vc,
4912 	},
4913 	[ITEM_SCTP_SRC] = {
4914 		.name = "src",
4915 		.help = "SCTP source port",
4916 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4917 			     item_param),
4918 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4919 					     hdr.src_port)),
4920 	},
4921 	[ITEM_SCTP_DST] = {
4922 		.name = "dst",
4923 		.help = "SCTP destination port",
4924 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4925 			     item_param),
4926 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4927 					     hdr.dst_port)),
4928 	},
4929 	[ITEM_SCTP_TAG] = {
4930 		.name = "tag",
4931 		.help = "validation tag",
4932 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4933 			     item_param),
4934 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4935 					     hdr.tag)),
4936 	},
4937 	[ITEM_SCTP_CKSUM] = {
4938 		.name = "cksum",
4939 		.help = "checksum",
4940 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4941 			     item_param),
4942 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4943 					     hdr.cksum)),
4944 	},
4945 	[ITEM_VXLAN] = {
4946 		.name = "vxlan",
4947 		.help = "match VXLAN header",
4948 		.priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
4949 		.next = NEXT(item_vxlan),
4950 		.call = parse_vc,
4951 	},
4952 	[ITEM_VXLAN_VNI] = {
4953 		.name = "vni",
4954 		.help = "VXLAN identifier",
4955 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4956 			     item_param),
4957 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, hdr.vni)),
4958 	},
4959 	[ITEM_VXLAN_FLAG_G] = {
4960 		.name = "flag_g",
4961 		.help = "VXLAN GBP bit",
4962 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4963 			     item_param),
4964 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4965 					   hdr.flag_g, 1)),
4966 	},
4967 	[ITEM_VXLAN_FLAG_VER] = {
4968 		.name = "flag_ver",
4969 		.help = "VXLAN GPE version",
4970 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4971 			     item_param),
4972 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4973 					   hdr.flag_ver, 2)),
4974 	},
4975 	[ITEM_VXLAN_FLAG_I] = {
4976 		.name = "flag_i",
4977 		.help = "VXLAN Instance bit",
4978 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4979 			     item_param),
4980 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4981 					   hdr.flag_i, 1)),
4982 	},
4983 	[ITEM_VXLAN_FLAG_P] = {
4984 		.name = "flag_p",
4985 		.help = "VXLAN GPE Next Protocol bit",
4986 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4987 			     item_param),
4988 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4989 					   hdr.flag_p, 1)),
4990 	},
4991 	[ITEM_VXLAN_FLAG_B] = {
4992 		.name = "flag_b",
4993 		.help = "VXLAN GPE Ingress-Replicated BUM",
4994 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4995 			     item_param),
4996 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4997 					   hdr.flag_b, 1)),
4998 	},
4999 	[ITEM_VXLAN_FLAG_O] = {
5000 		.name = "flag_o",
5001 		.help = "VXLAN GPE OAM Packet bit",
5002 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5003 			     item_param),
5004 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
5005 					   hdr.flag_o, 1)),
5006 	},
5007 	[ITEM_VXLAN_FLAG_D] = {
5008 		.name = "flag_d",
5009 		.help = "VXLAN GBP Don't Learn bit",
5010 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5011 			     item_param),
5012 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
5013 					   hdr.flag_d, 1)),
5014 	},
5015 	[ITEM_VXLAN_FLAG_A] = {
5016 		.name = "flag_a",
5017 		.help = "VXLAN GBP Applied bit",
5018 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5019 			     item_param),
5020 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
5021 					   hdr.flag_a, 1)),
5022 	},
5023 	[ITEM_VXLAN_GBP_ID] = {
5024 		.name = "group_policy_id",
5025 		.help = "VXLAN GBP ID",
5026 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5027 			     item_param),
5028 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5029 					     hdr.policy_id)),
5030 	},
5031 	[ITEM_VXLAN_GPE_PROTO] = {
5032 		.name = "protocol",
5033 		.help = "VXLAN GPE next protocol",
5034 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5035 			     item_param),
5036 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5037 					     hdr.proto)),
5038 	},
5039 	[ITEM_VXLAN_FIRST_RSVD] = {
5040 		.name = "first_rsvd",
5041 		.help = "VXLAN rsvd0 first byte",
5042 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5043 			     item_param),
5044 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5045 					     hdr.rsvd0[0])),
5046 	},
5047 	[ITEM_VXLAN_SECND_RSVD] = {
5048 		.name = "second_rsvd",
5049 		.help = "VXLAN rsvd0 second byte",
5050 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5051 			     item_param),
5052 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5053 					     hdr.rsvd0[1])),
5054 	},
5055 	[ITEM_VXLAN_THIRD_RSVD] = {
5056 		.name = "third_rsvd",
5057 		.help = "VXLAN rsvd0 third byte",
5058 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5059 			     item_param),
5060 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5061 					     hdr.rsvd0[2])),
5062 	},
5063 	[ITEM_VXLAN_LAST_RSVD] = {
5064 		.name = "last_rsvd",
5065 		.help = "VXLAN last reserved byte",
5066 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5067 			     item_param),
5068 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5069 					     hdr.last_rsvd)),
5070 	},
5071 	[ITEM_E_TAG] = {
5072 		.name = "e_tag",
5073 		.help = "match E-Tag header",
5074 		.priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
5075 		.next = NEXT(item_e_tag),
5076 		.call = parse_vc,
5077 	},
5078 	[ITEM_E_TAG_GRP_ECID_B] = {
5079 		.name = "grp_ecid_b",
5080 		.help = "GRP and E-CID base",
5081 		.next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
5082 			     item_param),
5083 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
5084 						  rsvd_grp_ecid_b,
5085 						  "\x3f\xff")),
5086 	},
5087 	[ITEM_NVGRE] = {
5088 		.name = "nvgre",
5089 		.help = "match NVGRE header",
5090 		.priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
5091 		.next = NEXT(item_nvgre),
5092 		.call = parse_vc,
5093 	},
5094 	[ITEM_NVGRE_TNI] = {
5095 		.name = "tni",
5096 		.help = "virtual subnet ID",
5097 		.next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
5098 			     item_param),
5099 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
5100 	},
5101 	[ITEM_MPLS] = {
5102 		.name = "mpls",
5103 		.help = "match MPLS header",
5104 		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
5105 		.next = NEXT(item_mpls),
5106 		.call = parse_vc,
5107 	},
5108 	[ITEM_MPLS_LABEL] = {
5109 		.name = "label",
5110 		.help = "MPLS label",
5111 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
5112 			     item_param),
5113 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
5114 						  label_tc_s,
5115 						  "\xff\xff\xf0")),
5116 	},
5117 	[ITEM_MPLS_TC] = {
5118 		.name = "tc",
5119 		.help = "MPLS Traffic Class",
5120 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
5121 			     item_param),
5122 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
5123 						  label_tc_s,
5124 						  "\x00\x00\x0e")),
5125 	},
5126 	[ITEM_MPLS_S] = {
5127 		.name = "s",
5128 		.help = "MPLS Bottom-of-Stack",
5129 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
5130 			     item_param),
5131 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
5132 						  label_tc_s,
5133 						  "\x00\x00\x01")),
5134 	},
5135 	[ITEM_MPLS_TTL] = {
5136 		.name = "ttl",
5137 		.help = "MPLS Time-to-Live",
5138 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
5139 			     item_param),
5140 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_mpls, ttl)),
5141 	},
5142 	[ITEM_GRE] = {
5143 		.name = "gre",
5144 		.help = "match GRE header",
5145 		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
5146 		.next = NEXT(item_gre),
5147 		.call = parse_vc,
5148 	},
5149 	[ITEM_GRE_PROTO] = {
5150 		.name = "protocol",
5151 		.help = "GRE protocol type",
5152 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
5153 			     item_param),
5154 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
5155 					     protocol)),
5156 	},
5157 	[ITEM_GRE_C_RSVD0_VER] = {
5158 		.name = "c_rsvd0_ver",
5159 		.help =
5160 			"checksum (1b), undefined (1b), key bit (1b),"
5161 			" sequence number (1b), reserved 0 (9b),"
5162 			" version (3b)",
5163 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
5164 			     item_param),
5165 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
5166 					     c_rsvd0_ver)),
5167 	},
5168 	[ITEM_GRE_C_BIT] = {
5169 		.name = "c_bit",
5170 		.help = "checksum bit (C)",
5171 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
5172 			     item_param),
5173 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5174 						  c_rsvd0_ver,
5175 						  "\x80\x00\x00\x00")),
5176 	},
5177 	[ITEM_GRE_S_BIT] = {
5178 		.name = "s_bit",
5179 		.help = "sequence number bit (S)",
5180 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
5181 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5182 						  c_rsvd0_ver,
5183 						  "\x10\x00\x00\x00")),
5184 	},
5185 	[ITEM_GRE_K_BIT] = {
5186 		.name = "k_bit",
5187 		.help = "key bit (K)",
5188 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
5189 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5190 						  c_rsvd0_ver,
5191 						  "\x20\x00\x00\x00")),
5192 	},
5193 	[ITEM_FUZZY] = {
5194 		.name = "fuzzy",
5195 		.help = "fuzzy pattern match, expect faster than default",
5196 		.priv = PRIV_ITEM(FUZZY,
5197 				sizeof(struct rte_flow_item_fuzzy)),
5198 		.next = NEXT(item_fuzzy),
5199 		.call = parse_vc,
5200 	},
5201 	[ITEM_FUZZY_THRESH] = {
5202 		.name = "thresh",
5203 		.help = "match accuracy threshold",
5204 		.next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
5205 			     item_param),
5206 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
5207 					thresh)),
5208 	},
5209 	[ITEM_GTP] = {
5210 		.name = "gtp",
5211 		.help = "match GTP header",
5212 		.priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
5213 		.next = NEXT(item_gtp),
5214 		.call = parse_vc,
5215 	},
5216 	[ITEM_GTP_FLAGS] = {
5217 		.name = "v_pt_rsv_flags",
5218 		.help = "GTP flags",
5219 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5220 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
5221 					hdr.gtp_hdr_info)),
5222 	},
5223 	[ITEM_GTP_MSG_TYPE] = {
5224 		.name = "msg_type",
5225 		.help = "GTP message type",
5226 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5227 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, hdr.msg_type)),
5228 	},
5229 	[ITEM_GTP_TEID] = {
5230 		.name = "teid",
5231 		.help = "tunnel endpoint identifier",
5232 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5233 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, hdr.teid)),
5234 	},
5235 	[ITEM_GTPC] = {
5236 		.name = "gtpc",
5237 		.help = "match GTP header",
5238 		.priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
5239 		.next = NEXT(item_gtp),
5240 		.call = parse_vc,
5241 	},
5242 	[ITEM_GTPU] = {
5243 		.name = "gtpu",
5244 		.help = "match GTP header",
5245 		.priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
5246 		.next = NEXT(item_gtp),
5247 		.call = parse_vc,
5248 	},
5249 	[ITEM_GENEVE] = {
5250 		.name = "geneve",
5251 		.help = "match GENEVE header",
5252 		.priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
5253 		.next = NEXT(item_geneve),
5254 		.call = parse_vc,
5255 	},
5256 	[ITEM_GENEVE_VNI] = {
5257 		.name = "vni",
5258 		.help = "virtual network identifier",
5259 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5260 			     item_param),
5261 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
5262 	},
5263 	[ITEM_GENEVE_PROTO] = {
5264 		.name = "protocol",
5265 		.help = "GENEVE protocol type",
5266 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5267 			     item_param),
5268 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
5269 					     protocol)),
5270 	},
5271 	[ITEM_GENEVE_OPTLEN] = {
5272 		.name = "optlen",
5273 		.help = "GENEVE options length in dwords",
5274 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5275 			     item_param),
5276 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
5277 						  ver_opt_len_o_c_rsvd0,
5278 						  "\x3f\x00")),
5279 	},
5280 	[ITEM_VXLAN_GPE] = {
5281 		.name = "vxlan-gpe",
5282 		.help = "match VXLAN-GPE header",
5283 		.priv = PRIV_ITEM(VXLAN_GPE,
5284 				  sizeof(struct rte_flow_item_vxlan_gpe)),
5285 		.next = NEXT(item_vxlan_gpe),
5286 		.call = parse_vc,
5287 	},
5288 	[ITEM_VXLAN_GPE_VNI] = {
5289 		.name = "vni",
5290 		.help = "VXLAN-GPE identifier",
5291 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5292 			     item_param),
5293 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5294 					     hdr.vni)),
5295 	},
5296 	[ITEM_VXLAN_GPE_PROTO_IN_DEPRECATED_VXLAN_GPE_HDR] = {
5297 		.name = "protocol",
5298 		.help = "VXLAN-GPE next protocol",
5299 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5300 			     item_param),
5301 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5302 					     protocol)),
5303 	},
5304 	[ITEM_VXLAN_GPE_FLAGS] = {
5305 		.name = "flags",
5306 		.help = "VXLAN-GPE flags",
5307 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5308 			     item_param),
5309 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5310 					     flags)),
5311 	},
5312 	[ITEM_VXLAN_GPE_RSVD0] = {
5313 		.name = "rsvd0",
5314 		.help = "VXLAN-GPE rsvd0",
5315 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5316 			     item_param),
5317 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5318 					     rsvd0)),
5319 	},
5320 	[ITEM_VXLAN_GPE_RSVD1] = {
5321 		.name = "rsvd1",
5322 		.help = "VXLAN-GPE rsvd1",
5323 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5324 			     item_param),
5325 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5326 					     rsvd1)),
5327 	},
5328 	[ITEM_ARP_ETH_IPV4] = {
5329 		.name = "arp_eth_ipv4",
5330 		.help = "match ARP header for Ethernet/IPv4",
5331 		.priv = PRIV_ITEM(ARP_ETH_IPV4,
5332 				  sizeof(struct rte_flow_item_arp_eth_ipv4)),
5333 		.next = NEXT(item_arp_eth_ipv4),
5334 		.call = parse_vc,
5335 	},
5336 	[ITEM_ARP_ETH_IPV4_SHA] = {
5337 		.name = "sha",
5338 		.help = "sender hardware address",
5339 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5340 			     item_param),
5341 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5342 					     hdr.arp_data.arp_sha)),
5343 	},
5344 	[ITEM_ARP_ETH_IPV4_SPA] = {
5345 		.name = "spa",
5346 		.help = "sender IPv4 address",
5347 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5348 			     item_param),
5349 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5350 					     hdr.arp_data.arp_sip)),
5351 	},
5352 	[ITEM_ARP_ETH_IPV4_THA] = {
5353 		.name = "tha",
5354 		.help = "target hardware address",
5355 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5356 			     item_param),
5357 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5358 					     hdr.arp_data.arp_tha)),
5359 	},
5360 	[ITEM_ARP_ETH_IPV4_TPA] = {
5361 		.name = "tpa",
5362 		.help = "target IPv4 address",
5363 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5364 			     item_param),
5365 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5366 					     hdr.arp_data.arp_tip)),
5367 	},
5368 	[ITEM_IPV6_EXT] = {
5369 		.name = "ipv6_ext",
5370 		.help = "match presence of any IPv6 extension header",
5371 		.priv = PRIV_ITEM(IPV6_EXT,
5372 				  sizeof(struct rte_flow_item_ipv6_ext)),
5373 		.next = NEXT(item_ipv6_ext),
5374 		.call = parse_vc,
5375 	},
5376 	[ITEM_IPV6_EXT_NEXT_HDR] = {
5377 		.name = "next_hdr",
5378 		.help = "next header",
5379 		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5380 			     item_param),
5381 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
5382 					     next_hdr)),
5383 	},
5384 	[ITEM_IPV6_FRAG_EXT] = {
5385 		.name = "ipv6_frag_ext",
5386 		.help = "match presence of IPv6 fragment extension header",
5387 		.priv = PRIV_ITEM(IPV6_FRAG_EXT,
5388 				sizeof(struct rte_flow_item_ipv6_frag_ext)),
5389 		.next = NEXT(item_ipv6_frag_ext),
5390 		.call = parse_vc,
5391 	},
5392 	[ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
5393 		.name = "next_hdr",
5394 		.help = "next header",
5395 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5396 			     item_param),
5397 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
5398 					hdr.next_header)),
5399 	},
5400 	[ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
5401 		.name = "frag_data",
5402 		.help = "fragment flags and offset",
5403 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5404 			     item_param),
5405 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5406 					     hdr.frag_data)),
5407 	},
5408 	[ITEM_IPV6_FRAG_EXT_ID] = {
5409 		.name = "packet_id",
5410 		.help = "fragment packet id",
5411 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5412 			     item_param),
5413 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5414 					     hdr.id)),
5415 	},
5416 	[ITEM_ICMP6] = {
5417 		.name = "icmp6",
5418 		.help = "match any ICMPv6 header",
5419 		.priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
5420 		.next = NEXT(item_icmp6),
5421 		.call = parse_vc,
5422 	},
5423 	[ITEM_ICMP6_TYPE] = {
5424 		.name = "type",
5425 		.help = "ICMPv6 type",
5426 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5427 			     item_param),
5428 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5429 					     type)),
5430 	},
5431 	[ITEM_ICMP6_CODE] = {
5432 		.name = "code",
5433 		.help = "ICMPv6 code",
5434 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5435 			     item_param),
5436 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5437 					     code)),
5438 	},
5439 	[ITEM_ICMP6_ECHO_REQUEST] = {
5440 		.name = "icmp6_echo_request",
5441 		.help = "match ICMPv6 echo request",
5442 		.priv = PRIV_ITEM(ICMP6_ECHO_REQUEST,
5443 				  sizeof(struct rte_flow_item_icmp6_echo)),
5444 		.next = NEXT(item_icmp6_echo_request),
5445 		.call = parse_vc,
5446 	},
5447 	[ITEM_ICMP6_ECHO_REQUEST_ID] = {
5448 		.name = "ident",
5449 		.help = "ICMPv6 echo request identifier",
5450 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5451 			     item_param),
5452 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5453 					     hdr.identifier)),
5454 	},
5455 	[ITEM_ICMP6_ECHO_REQUEST_SEQ] = {
5456 		.name = "seq",
5457 		.help = "ICMPv6 echo request sequence",
5458 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5459 			     item_param),
5460 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5461 					     hdr.sequence)),
5462 	},
5463 	[ITEM_ICMP6_ECHO_REPLY] = {
5464 		.name = "icmp6_echo_reply",
5465 		.help = "match ICMPv6 echo reply",
5466 		.priv = PRIV_ITEM(ICMP6_ECHO_REPLY,
5467 				  sizeof(struct rte_flow_item_icmp6_echo)),
5468 		.next = NEXT(item_icmp6_echo_reply),
5469 		.call = parse_vc,
5470 	},
5471 	[ITEM_ICMP6_ECHO_REPLY_ID] = {
5472 		.name = "ident",
5473 		.help = "ICMPv6 echo reply identifier",
5474 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5475 			     item_param),
5476 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5477 					     hdr.identifier)),
5478 	},
5479 	[ITEM_ICMP6_ECHO_REPLY_SEQ] = {
5480 		.name = "seq",
5481 		.help = "ICMPv6 echo reply sequence",
5482 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5483 			     item_param),
5484 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5485 					     hdr.sequence)),
5486 	},
5487 	[ITEM_ICMP6_ND_NS] = {
5488 		.name = "icmp6_nd_ns",
5489 		.help = "match ICMPv6 neighbor discovery solicitation",
5490 		.priv = PRIV_ITEM(ICMP6_ND_NS,
5491 				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
5492 		.next = NEXT(item_icmp6_nd_ns),
5493 		.call = parse_vc,
5494 	},
5495 	[ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
5496 		.name = "target_addr",
5497 		.help = "target address",
5498 		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
5499 			     item_param),
5500 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
5501 					     target_addr)),
5502 	},
5503 	[ITEM_ICMP6_ND_NA] = {
5504 		.name = "icmp6_nd_na",
5505 		.help = "match ICMPv6 neighbor discovery advertisement",
5506 		.priv = PRIV_ITEM(ICMP6_ND_NA,
5507 				  sizeof(struct rte_flow_item_icmp6_nd_na)),
5508 		.next = NEXT(item_icmp6_nd_na),
5509 		.call = parse_vc,
5510 	},
5511 	[ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
5512 		.name = "target_addr",
5513 		.help = "target address",
5514 		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
5515 			     item_param),
5516 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
5517 					     target_addr)),
5518 	},
5519 	[ITEM_ICMP6_ND_OPT] = {
5520 		.name = "icmp6_nd_opt",
5521 		.help = "match presence of any ICMPv6 neighbor discovery"
5522 			" option",
5523 		.priv = PRIV_ITEM(ICMP6_ND_OPT,
5524 				  sizeof(struct rte_flow_item_icmp6_nd_opt)),
5525 		.next = NEXT(item_icmp6_nd_opt),
5526 		.call = parse_vc,
5527 	},
5528 	[ITEM_ICMP6_ND_OPT_TYPE] = {
5529 		.name = "type",
5530 		.help = "ND option type",
5531 		.next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5532 			     item_param),
5533 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
5534 					     type)),
5535 	},
5536 	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
5537 		.name = "icmp6_nd_opt_sla_eth",
5538 		.help = "match ICMPv6 neighbor discovery source Ethernet"
5539 			" link-layer address option",
5540 		.priv = PRIV_ITEM
5541 			(ICMP6_ND_OPT_SLA_ETH,
5542 			 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
5543 		.next = NEXT(item_icmp6_nd_opt_sla_eth),
5544 		.call = parse_vc,
5545 	},
5546 	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
5547 		.name = "sla",
5548 		.help = "source Ethernet LLA",
5549 		.next = NEXT(item_icmp6_nd_opt_sla_eth,
5550 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5551 		.args = ARGS(ARGS_ENTRY_HTON
5552 			     (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
5553 	},
5554 	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
5555 		.name = "icmp6_nd_opt_tla_eth",
5556 		.help = "match ICMPv6 neighbor discovery target Ethernet"
5557 			" link-layer address option",
5558 		.priv = PRIV_ITEM
5559 			(ICMP6_ND_OPT_TLA_ETH,
5560 			 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
5561 		.next = NEXT(item_icmp6_nd_opt_tla_eth),
5562 		.call = parse_vc,
5563 	},
5564 	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
5565 		.name = "tla",
5566 		.help = "target Ethernet LLA",
5567 		.next = NEXT(item_icmp6_nd_opt_tla_eth,
5568 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5569 		.args = ARGS(ARGS_ENTRY_HTON
5570 			     (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
5571 	},
5572 	[ITEM_META] = {
5573 		.name = "meta",
5574 		.help = "match metadata header",
5575 		.priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
5576 		.next = NEXT(item_meta),
5577 		.call = parse_vc,
5578 	},
5579 	[ITEM_META_DATA] = {
5580 		.name = "data",
5581 		.help = "metadata value",
5582 		.next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
5583 			     item_param),
5584 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
5585 					     data, "\xff\xff\xff\xff")),
5586 	},
5587 	[ITEM_RANDOM] = {
5588 		.name = "random",
5589 		.help = "match random value",
5590 		.priv = PRIV_ITEM(RANDOM, sizeof(struct rte_flow_item_random)),
5591 		.next = NEXT(item_random),
5592 		.call = parse_vc,
5593 	},
5594 	[ITEM_RANDOM_VALUE] = {
5595 		.name = "value",
5596 		.help = "random value",
5597 		.next = NEXT(item_random, NEXT_ENTRY(COMMON_UNSIGNED),
5598 			     item_param),
5599 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_random,
5600 					     value, "\xff\xff")),
5601 	},
5602 	[ITEM_GRE_KEY] = {
5603 		.name = "gre_key",
5604 		.help = "match GRE key",
5605 		.priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
5606 		.next = NEXT(item_gre_key),
5607 		.call = parse_vc,
5608 	},
5609 	[ITEM_GRE_KEY_VALUE] = {
5610 		.name = "value",
5611 		.help = "key value",
5612 		.next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
5613 			     item_param),
5614 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5615 	},
5616 	[ITEM_GRE_OPTION] = {
5617 		.name = "gre_option",
5618 		.help = "match GRE optional fields",
5619 		.priv = PRIV_ITEM(GRE_OPTION,
5620 				  sizeof(struct rte_flow_item_gre_opt)),
5621 		.next = NEXT(item_gre_option),
5622 		.call = parse_vc,
5623 	},
5624 	[ITEM_GRE_OPTION_CHECKSUM] = {
5625 		.name = "checksum",
5626 		.help = "match GRE checksum",
5627 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5628 			     item_param),
5629 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5630 					     checksum_rsvd.checksum)),
5631 	},
5632 	[ITEM_GRE_OPTION_KEY] = {
5633 		.name = "key",
5634 		.help = "match GRE key",
5635 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5636 			     item_param),
5637 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5638 					     key.key)),
5639 	},
5640 	[ITEM_GRE_OPTION_SEQUENCE] = {
5641 		.name = "sequence",
5642 		.help = "match GRE sequence",
5643 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5644 			     item_param),
5645 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5646 					     sequence.sequence)),
5647 	},
5648 	[ITEM_GTP_PSC] = {
5649 		.name = "gtp_psc",
5650 		.help = "match GTP extension header with type 0x85",
5651 		.priv = PRIV_ITEM(GTP_PSC,
5652 				sizeof(struct rte_flow_item_gtp_psc)),
5653 		.next = NEXT(item_gtp_psc),
5654 		.call = parse_vc,
5655 	},
5656 	[ITEM_GTP_PSC_QFI] = {
5657 		.name = "qfi",
5658 		.help = "QoS flow identifier",
5659 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5660 			     item_param),
5661 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5662 					hdr.qfi, 6)),
5663 	},
5664 	[ITEM_GTP_PSC_PDU_T] = {
5665 		.name = "pdu_t",
5666 		.help = "PDU type",
5667 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5668 			     item_param),
5669 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5670 					hdr.type, 4)),
5671 	},
5672 	[ITEM_PPPOES] = {
5673 		.name = "pppoes",
5674 		.help = "match PPPoE session header",
5675 		.priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
5676 		.next = NEXT(item_pppoes),
5677 		.call = parse_vc,
5678 	},
5679 	[ITEM_PPPOED] = {
5680 		.name = "pppoed",
5681 		.help = "match PPPoE discovery header",
5682 		.priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
5683 		.next = NEXT(item_pppoed),
5684 		.call = parse_vc,
5685 	},
5686 	[ITEM_PPPOE_SEID] = {
5687 		.name = "seid",
5688 		.help = "session identifier",
5689 		.next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
5690 			     item_param),
5691 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
5692 					session_id)),
5693 	},
5694 	[ITEM_PPPOE_PROTO_ID] = {
5695 		.name = "pppoe_proto_id",
5696 		.help = "match PPPoE session protocol identifier",
5697 		.priv = PRIV_ITEM(PPPOE_PROTO_ID,
5698 				sizeof(struct rte_flow_item_pppoe_proto_id)),
5699 		.next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
5700 			     item_param),
5701 		.args = ARGS(ARGS_ENTRY_HTON
5702 			     (struct rte_flow_item_pppoe_proto_id, proto_id)),
5703 		.call = parse_vc,
5704 	},
5705 	[ITEM_HIGIG2] = {
5706 		.name = "higig2",
5707 		.help = "matches higig2 header",
5708 		.priv = PRIV_ITEM(HIGIG2,
5709 				sizeof(struct rte_flow_item_higig2_hdr)),
5710 		.next = NEXT(item_higig2),
5711 		.call = parse_vc,
5712 	},
5713 	[ITEM_HIGIG2_CLASSIFICATION] = {
5714 		.name = "classification",
5715 		.help = "matches classification of higig2 header",
5716 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5717 			     item_param),
5718 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5719 					hdr.ppt1.classification)),
5720 	},
5721 	[ITEM_HIGIG2_VID] = {
5722 		.name = "vid",
5723 		.help = "matches vid of higig2 header",
5724 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5725 			     item_param),
5726 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5727 					hdr.ppt1.vid)),
5728 	},
5729 	[ITEM_TAG] = {
5730 		.name = "tag",
5731 		.help = "match tag value",
5732 		.priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
5733 		.next = NEXT(item_tag),
5734 		.call = parse_vc,
5735 	},
5736 	[ITEM_TAG_DATA] = {
5737 		.name = "data",
5738 		.help = "tag value to match",
5739 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5740 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
5741 	},
5742 	[ITEM_TAG_INDEX] = {
5743 		.name = "index",
5744 		.help = "index of tag array to match",
5745 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
5746 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5747 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
5748 	},
5749 	[ITEM_L2TPV3OIP] = {
5750 		.name = "l2tpv3oip",
5751 		.help = "match L2TPv3 over IP header",
5752 		.priv = PRIV_ITEM(L2TPV3OIP,
5753 				  sizeof(struct rte_flow_item_l2tpv3oip)),
5754 		.next = NEXT(item_l2tpv3oip),
5755 		.call = parse_vc,
5756 	},
5757 	[ITEM_L2TPV3OIP_SESSION_ID] = {
5758 		.name = "session_id",
5759 		.help = "session identifier",
5760 		.next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
5761 			     item_param),
5762 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
5763 					     session_id)),
5764 	},
5765 	[ITEM_ESP] = {
5766 		.name = "esp",
5767 		.help = "match ESP header",
5768 		.priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
5769 		.next = NEXT(item_esp),
5770 		.call = parse_vc,
5771 	},
5772 	[ITEM_ESP_SPI] = {
5773 		.name = "spi",
5774 		.help = "security policy index",
5775 		.next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5776 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
5777 				hdr.spi)),
5778 	},
5779 	[ITEM_AH] = {
5780 		.name = "ah",
5781 		.help = "match AH header",
5782 		.priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
5783 		.next = NEXT(item_ah),
5784 		.call = parse_vc,
5785 	},
5786 	[ITEM_AH_SPI] = {
5787 		.name = "spi",
5788 		.help = "security parameters index",
5789 		.next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5790 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
5791 	},
5792 	[ITEM_PFCP] = {
5793 		.name = "pfcp",
5794 		.help = "match pfcp header",
5795 		.priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
5796 		.next = NEXT(item_pfcp),
5797 		.call = parse_vc,
5798 	},
5799 	[ITEM_PFCP_S_FIELD] = {
5800 		.name = "s_field",
5801 		.help = "S field",
5802 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5803 			     item_param),
5804 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
5805 				s_field)),
5806 	},
5807 	[ITEM_PFCP_SEID] = {
5808 		.name = "seid",
5809 		.help = "session endpoint identifier",
5810 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5811 			     item_param),
5812 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
5813 	},
5814 	[ITEM_ECPRI] = {
5815 		.name = "ecpri",
5816 		.help = "match eCPRI header",
5817 		.priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
5818 		.next = NEXT(item_ecpri),
5819 		.call = parse_vc,
5820 	},
5821 	[ITEM_ECPRI_COMMON] = {
5822 		.name = "common",
5823 		.help = "eCPRI common header",
5824 		.next = NEXT(item_ecpri_common),
5825 	},
5826 	[ITEM_ECPRI_COMMON_TYPE] = {
5827 		.name = "type",
5828 		.help = "type of common header",
5829 		.next = NEXT(item_ecpri_common_type),
5830 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
5831 	},
5832 	[ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
5833 		.name = "iq_data",
5834 		.help = "Type #0: IQ Data",
5835 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5836 					ITEM_NEXT)),
5837 		.call = parse_vc_item_ecpri_type,
5838 	},
5839 	[ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
5840 		.name = "pc_id",
5841 		.help = "Physical Channel ID",
5842 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5843 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5844 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5845 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5846 				hdr.type0.pc_id)),
5847 	},
5848 	[ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
5849 		.name = "rtc_ctrl",
5850 		.help = "Type #2: Real-Time Control Data",
5851 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5852 					ITEM_NEXT)),
5853 		.call = parse_vc_item_ecpri_type,
5854 	},
5855 	[ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
5856 		.name = "rtc_id",
5857 		.help = "Real-Time Control Data ID",
5858 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5859 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5860 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5861 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5862 				hdr.type2.rtc_id)),
5863 	},
5864 	[ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
5865 		.name = "delay_measure",
5866 		.help = "Type #5: One-Way Delay Measurement",
5867 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5868 					ITEM_NEXT)),
5869 		.call = parse_vc_item_ecpri_type,
5870 	},
5871 	[ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
5872 		.name = "msr_id",
5873 		.help = "Measurement ID",
5874 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5875 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5876 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5877 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5878 				hdr.type5.msr_id)),
5879 	},
5880 	[ITEM_GENEVE_OPT] = {
5881 		.name = "geneve-opt",
5882 		.help = "GENEVE header option",
5883 		.priv = PRIV_ITEM(GENEVE_OPT,
5884 				  sizeof(struct rte_flow_item_geneve_opt) +
5885 				  ITEM_GENEVE_OPT_DATA_SIZE),
5886 		.next = NEXT(item_geneve_opt),
5887 		.call = parse_vc,
5888 	},
5889 	[ITEM_GENEVE_OPT_CLASS]	= {
5890 		.name = "class",
5891 		.help = "GENEVE option class",
5892 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5893 			     item_param),
5894 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
5895 					     option_class)),
5896 	},
5897 	[ITEM_GENEVE_OPT_TYPE] = {
5898 		.name = "type",
5899 		.help = "GENEVE option type",
5900 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5901 			     item_param),
5902 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
5903 					option_type)),
5904 	},
5905 	[ITEM_GENEVE_OPT_LENGTH] = {
5906 		.name = "length",
5907 		.help = "GENEVE option data length (in 32b words)",
5908 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5909 			     item_param),
5910 		.args = ARGS(ARGS_ENTRY_BOUNDED(
5911 				struct rte_flow_item_geneve_opt, option_len,
5912 				0, 31)),
5913 	},
5914 	[ITEM_GENEVE_OPT_DATA] = {
5915 		.name = "data",
5916 		.help = "GENEVE option data pattern",
5917 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
5918 			     item_param),
5919 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
5920 			     ARGS_ENTRY_ARB(0, 0),
5921 			     ARGS_ENTRY_ARB
5922 				(sizeof(struct rte_flow_item_geneve_opt),
5923 				ITEM_GENEVE_OPT_DATA_SIZE)),
5924 	},
5925 	[ITEM_INTEGRITY] = {
5926 		.name = "integrity",
5927 		.help = "match packet integrity",
5928 		.priv = PRIV_ITEM(INTEGRITY,
5929 				  sizeof(struct rte_flow_item_integrity)),
5930 		.next = NEXT(item_integrity),
5931 		.call = parse_vc,
5932 	},
5933 	[ITEM_INTEGRITY_LEVEL] = {
5934 		.name = "level",
5935 		.help = "integrity level",
5936 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5937 			     item_param),
5938 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
5939 	},
5940 	[ITEM_INTEGRITY_VALUE] = {
5941 		.name = "value",
5942 		.help = "integrity value",
5943 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5944 			     item_param),
5945 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
5946 	},
5947 	[ITEM_CONNTRACK] = {
5948 		.name = "conntrack",
5949 		.help = "conntrack state",
5950 		.priv = PRIV_ITEM(CONNTRACK,
5951 				  sizeof(struct rte_flow_item_conntrack)),
5952 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
5953 			     item_param),
5954 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
5955 		.call = parse_vc,
5956 	},
5957 	[ITEM_PORT_REPRESENTOR] = {
5958 		.name = "port_representor",
5959 		.help = "match traffic entering the embedded switch from the given ethdev",
5960 		.priv = PRIV_ITEM(PORT_REPRESENTOR,
5961 				  sizeof(struct rte_flow_item_ethdev)),
5962 		.next = NEXT(item_port_representor),
5963 		.call = parse_vc,
5964 	},
5965 	[ITEM_PORT_REPRESENTOR_PORT_ID] = {
5966 		.name = "port_id",
5967 		.help = "ethdev port ID",
5968 		.next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
5969 			     item_param),
5970 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5971 	},
5972 	[ITEM_REPRESENTED_PORT] = {
5973 		.name = "represented_port",
5974 		.help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
5975 		.priv = PRIV_ITEM(REPRESENTED_PORT,
5976 				  sizeof(struct rte_flow_item_ethdev)),
5977 		.next = NEXT(item_represented_port),
5978 		.call = parse_vc,
5979 	},
5980 	[ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
5981 		.name = "ethdev_port_id",
5982 		.help = "ethdev port ID",
5983 		.next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
5984 			     item_param),
5985 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5986 	},
5987 	[ITEM_FLEX] = {
5988 		.name = "flex",
5989 		.help = "match flex header",
5990 		.priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
5991 		.next = NEXT(item_flex),
5992 		.call = parse_vc,
5993 	},
5994 	[ITEM_FLEX_ITEM_HANDLE] = {
5995 		.name = "item",
5996 		.help = "flex item handle",
5997 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5998 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5999 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
6000 	},
6001 	[ITEM_FLEX_PATTERN_HANDLE] = {
6002 		.name = "pattern",
6003 		.help = "flex pattern handle",
6004 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
6005 			     NEXT_ENTRY(ITEM_PARAM_IS)),
6006 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
6007 	},
6008 	[ITEM_L2TPV2] = {
6009 		.name = "l2tpv2",
6010 		.help = "match L2TPv2 header",
6011 		.priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
6012 		.next = NEXT(item_l2tpv2),
6013 		.call = parse_vc,
6014 	},
6015 	[ITEM_L2TPV2_TYPE] = {
6016 		.name = "type",
6017 		.help = "type of l2tpv2",
6018 		.next = NEXT(item_l2tpv2_type),
6019 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
6020 	},
6021 	[ITEM_L2TPV2_TYPE_DATA] = {
6022 		.name = "data",
6023 		.help = "Type #7: data message without any options",
6024 		.next = NEXT(item_l2tpv2_type_data),
6025 		.call = parse_vc_item_l2tpv2_type,
6026 	},
6027 	[ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
6028 		.name = "tunnel_id",
6029 		.help = "tunnel identifier",
6030 		.next = NEXT(item_l2tpv2_type_data,
6031 			     NEXT_ENTRY(COMMON_UNSIGNED),
6032 			     item_param),
6033 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6034 					     hdr.type7.tunnel_id)),
6035 	},
6036 	[ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
6037 		.name = "session_id",
6038 		.help = "session identifier",
6039 		.next = NEXT(item_l2tpv2_type_data,
6040 			     NEXT_ENTRY(COMMON_UNSIGNED),
6041 			     item_param),
6042 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6043 					     hdr.type7.session_id)),
6044 	},
6045 	[ITEM_L2TPV2_TYPE_DATA_L] = {
6046 		.name = "data_l",
6047 		.help = "Type #6: data message with length option",
6048 		.next = NEXT(item_l2tpv2_type_data_l),
6049 		.call = parse_vc_item_l2tpv2_type,
6050 	},
6051 	[ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
6052 		.name = "length",
6053 		.help = "message length",
6054 		.next = NEXT(item_l2tpv2_type_data_l,
6055 			     NEXT_ENTRY(COMMON_UNSIGNED),
6056 			     item_param),
6057 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6058 					     hdr.type6.length)),
6059 	},
6060 	[ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
6061 		.name = "tunnel_id",
6062 		.help = "tunnel identifier",
6063 		.next = NEXT(item_l2tpv2_type_data_l,
6064 			     NEXT_ENTRY(COMMON_UNSIGNED),
6065 			     item_param),
6066 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6067 					     hdr.type6.tunnel_id)),
6068 	},
6069 	[ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
6070 		.name = "session_id",
6071 		.help = "session identifier",
6072 		.next = NEXT(item_l2tpv2_type_data_l,
6073 			     NEXT_ENTRY(COMMON_UNSIGNED),
6074 			     item_param),
6075 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6076 					     hdr.type6.session_id)),
6077 	},
6078 	[ITEM_L2TPV2_TYPE_DATA_S] = {
6079 		.name = "data_s",
6080 		.help = "Type #5: data message with ns, nr option",
6081 		.next = NEXT(item_l2tpv2_type_data_s),
6082 		.call = parse_vc_item_l2tpv2_type,
6083 	},
6084 	[ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
6085 		.name = "tunnel_id",
6086 		.help = "tunnel identifier",
6087 		.next = NEXT(item_l2tpv2_type_data_s,
6088 			     NEXT_ENTRY(COMMON_UNSIGNED),
6089 			     item_param),
6090 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6091 					     hdr.type5.tunnel_id)),
6092 	},
6093 	[ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
6094 		.name = "session_id",
6095 		.help = "session identifier",
6096 		.next = NEXT(item_l2tpv2_type_data_s,
6097 			     NEXT_ENTRY(COMMON_UNSIGNED),
6098 			     item_param),
6099 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6100 					     hdr.type5.session_id)),
6101 	},
6102 	[ITEM_L2TPV2_MSG_DATA_S_NS] = {
6103 		.name = "ns",
6104 		.help = "sequence number for message",
6105 		.next = NEXT(item_l2tpv2_type_data_s,
6106 			     NEXT_ENTRY(COMMON_UNSIGNED),
6107 			     item_param),
6108 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6109 					     hdr.type5.ns)),
6110 	},
6111 	[ITEM_L2TPV2_MSG_DATA_S_NR] = {
6112 		.name = "nr",
6113 		.help = "sequence number for next receive message",
6114 		.next = NEXT(item_l2tpv2_type_data_s,
6115 			     NEXT_ENTRY(COMMON_UNSIGNED),
6116 			     item_param),
6117 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6118 					     hdr.type5.nr)),
6119 	},
6120 	[ITEM_L2TPV2_TYPE_DATA_O] = {
6121 		.name = "data_o",
6122 		.help = "Type #4: data message with offset option",
6123 		.next = NEXT(item_l2tpv2_type_data_o),
6124 		.call = parse_vc_item_l2tpv2_type,
6125 	},
6126 	[ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
6127 		.name = "tunnel_id",
6128 		.help = "tunnel identifier",
6129 		.next = NEXT(item_l2tpv2_type_data_o,
6130 			     NEXT_ENTRY(COMMON_UNSIGNED),
6131 			     item_param),
6132 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6133 					     hdr.type4.tunnel_id)),
6134 	},
6135 	[ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
6136 		.name = "session_id",
6137 		.help = "session identifier",
6138 		.next = NEXT(item_l2tpv2_type_data_o,
6139 			     NEXT_ENTRY(COMMON_UNSIGNED),
6140 			     item_param),
6141 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6142 					     hdr.type5.session_id)),
6143 	},
6144 	[ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
6145 		.name = "offset_size",
6146 		.help = "the size of offset padding",
6147 		.next = NEXT(item_l2tpv2_type_data_o,
6148 			     NEXT_ENTRY(COMMON_UNSIGNED),
6149 			     item_param),
6150 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6151 					     hdr.type4.offset_size)),
6152 	},
6153 	[ITEM_L2TPV2_TYPE_DATA_L_S] = {
6154 		.name = "data_l_s",
6155 		.help = "Type #3: data message contains length, ns, nr "
6156 			"options",
6157 		.next = NEXT(item_l2tpv2_type_data_l_s),
6158 		.call = parse_vc_item_l2tpv2_type,
6159 	},
6160 	[ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
6161 		.name = "length",
6162 		.help = "message length",
6163 		.next = NEXT(item_l2tpv2_type_data_l_s,
6164 			     NEXT_ENTRY(COMMON_UNSIGNED),
6165 			     item_param),
6166 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6167 					     hdr.type3.length)),
6168 	},
6169 	[ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
6170 		.name = "tunnel_id",
6171 		.help = "tunnel identifier",
6172 		.next = NEXT(item_l2tpv2_type_data_l_s,
6173 			     NEXT_ENTRY(COMMON_UNSIGNED),
6174 			     item_param),
6175 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6176 					     hdr.type3.tunnel_id)),
6177 	},
6178 	[ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
6179 		.name = "session_id",
6180 		.help = "session identifier",
6181 		.next = NEXT(item_l2tpv2_type_data_l_s,
6182 			     NEXT_ENTRY(COMMON_UNSIGNED),
6183 			     item_param),
6184 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6185 					     hdr.type3.session_id)),
6186 	},
6187 	[ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
6188 		.name = "ns",
6189 		.help = "sequence number for message",
6190 		.next = NEXT(item_l2tpv2_type_data_l_s,
6191 			     NEXT_ENTRY(COMMON_UNSIGNED),
6192 			     item_param),
6193 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6194 					     hdr.type3.ns)),
6195 	},
6196 	[ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
6197 		.name = "nr",
6198 		.help = "sequence number for next receive message",
6199 		.next = NEXT(item_l2tpv2_type_data_l_s,
6200 			     NEXT_ENTRY(COMMON_UNSIGNED),
6201 			     item_param),
6202 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6203 					     hdr.type3.nr)),
6204 	},
6205 	[ITEM_L2TPV2_TYPE_CTRL] = {
6206 		.name = "control",
6207 		.help = "Type #3: conrtol message contains length, ns, nr "
6208 			"options",
6209 		.next = NEXT(item_l2tpv2_type_ctrl),
6210 		.call = parse_vc_item_l2tpv2_type,
6211 	},
6212 	[ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
6213 		.name = "length",
6214 		.help = "message length",
6215 		.next = NEXT(item_l2tpv2_type_ctrl,
6216 			     NEXT_ENTRY(COMMON_UNSIGNED),
6217 			     item_param),
6218 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6219 					     hdr.type3.length)),
6220 	},
6221 	[ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
6222 		.name = "tunnel_id",
6223 		.help = "tunnel identifier",
6224 		.next = NEXT(item_l2tpv2_type_ctrl,
6225 			     NEXT_ENTRY(COMMON_UNSIGNED),
6226 			     item_param),
6227 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6228 					     hdr.type3.tunnel_id)),
6229 	},
6230 	[ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
6231 		.name = "session_id",
6232 		.help = "session identifier",
6233 		.next = NEXT(item_l2tpv2_type_ctrl,
6234 			     NEXT_ENTRY(COMMON_UNSIGNED),
6235 			     item_param),
6236 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6237 					     hdr.type3.session_id)),
6238 	},
6239 	[ITEM_L2TPV2_MSG_CTRL_NS] = {
6240 		.name = "ns",
6241 		.help = "sequence number for message",
6242 		.next = NEXT(item_l2tpv2_type_ctrl,
6243 			     NEXT_ENTRY(COMMON_UNSIGNED),
6244 			     item_param),
6245 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6246 					     hdr.type3.ns)),
6247 	},
6248 	[ITEM_L2TPV2_MSG_CTRL_NR] = {
6249 		.name = "nr",
6250 		.help = "sequence number for next receive message",
6251 		.next = NEXT(item_l2tpv2_type_ctrl,
6252 			     NEXT_ENTRY(COMMON_UNSIGNED),
6253 			     item_param),
6254 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6255 					     hdr.type3.nr)),
6256 	},
6257 	[ITEM_PPP] = {
6258 		.name = "ppp",
6259 		.help = "match PPP header",
6260 		.priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
6261 		.next = NEXT(item_ppp),
6262 		.call = parse_vc,
6263 	},
6264 	[ITEM_PPP_ADDR] = {
6265 		.name = "addr",
6266 		.help = "PPP address",
6267 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6268 			     item_param),
6269 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
6270 	},
6271 	[ITEM_PPP_CTRL] = {
6272 		.name = "ctrl",
6273 		.help = "PPP control",
6274 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6275 			     item_param),
6276 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
6277 	},
6278 	[ITEM_PPP_PROTO_ID] = {
6279 		.name = "proto_id",
6280 		.help = "PPP protocol identifier",
6281 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6282 			     item_param),
6283 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
6284 					hdr.proto_id)),
6285 	},
6286 	[ITEM_METER] = {
6287 		.name = "meter",
6288 		.help = "match meter color",
6289 		.priv = PRIV_ITEM(METER_COLOR,
6290 				  sizeof(struct rte_flow_item_meter_color)),
6291 		.next = NEXT(item_meter),
6292 		.call = parse_vc,
6293 	},
6294 	[ITEM_METER_COLOR] = {
6295 		.name = "color",
6296 		.help = "meter color",
6297 		.next = NEXT(item_meter,
6298 			     NEXT_ENTRY(ITEM_METER_COLOR_NAME),
6299 			     item_param),
6300 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_meter_color,
6301 					color)),
6302 	},
6303 	[ITEM_METER_COLOR_NAME] = {
6304 		.name = "color_name",
6305 		.help = "meter color name",
6306 		.call = parse_meter_color,
6307 		.comp = comp_meter_color,
6308 	},
6309 	[ITEM_QUOTA] = {
6310 		.name = "quota",
6311 		.help = "match quota",
6312 		.priv = PRIV_ITEM(QUOTA, sizeof(struct rte_flow_item_quota)),
6313 		.next = NEXT(item_quota),
6314 		.call = parse_vc
6315 	},
6316 	[ITEM_QUOTA_STATE] = {
6317 		.name = "quota_state",
6318 		.help = "quota state",
6319 		.next = NEXT(item_quota, NEXT_ENTRY(ITEM_QUOTA_STATE_NAME),
6320 			     NEXT_ENTRY(ITEM_PARAM_SPEC, ITEM_PARAM_MASK)),
6321 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_quota, state))
6322 	},
6323 	[ITEM_QUOTA_STATE_NAME] = {
6324 		.name = "state_name",
6325 		.help = "quota state name",
6326 		.call = parse_quota_state_name,
6327 		.comp = comp_quota_state_name
6328 	},
6329 	[ITEM_IB_BTH] = {
6330 		.name = "ib_bth",
6331 		.help = "match ib bth fields",
6332 		.priv = PRIV_ITEM(IB_BTH,
6333 				  sizeof(struct rte_flow_item_ib_bth)),
6334 		.next = NEXT(item_ib_bth),
6335 		.call = parse_vc,
6336 	},
6337 	[ITEM_IB_BTH_OPCODE] = {
6338 		.name = "opcode",
6339 		.help = "match ib bth opcode",
6340 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6341 				 item_param),
6342 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6343 						 hdr.opcode)),
6344 	},
6345 	[ITEM_IB_BTH_PKEY] = {
6346 		.name = "pkey",
6347 		.help = "partition key",
6348 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6349 				 item_param),
6350 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6351 						 hdr.pkey)),
6352 	},
6353 	[ITEM_IB_BTH_DST_QPN] = {
6354 		.name = "dst_qp",
6355 		.help = "destination qp",
6356 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6357 				 item_param),
6358 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6359 						 hdr.dst_qp)),
6360 	},
6361 	[ITEM_IB_BTH_PSN] = {
6362 		.name = "psn",
6363 		.help = "packet sequence number",
6364 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6365 				 item_param),
6366 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6367 						 hdr.psn)),
6368 	},
6369 	[ITEM_PTYPE] = {
6370 		.name = "ptype",
6371 		.help = "match L2/L3/L4 and tunnel information",
6372 		.priv = PRIV_ITEM(PTYPE,
6373 				  sizeof(struct rte_flow_item_ptype)),
6374 		.next = NEXT(item_ptype),
6375 		.call = parse_vc,
6376 	},
6377 	[ITEM_PTYPE_VALUE] = {
6378 		.name = "packet_type",
6379 		.help = "packet type as defined in rte_mbuf_ptype",
6380 		.next = NEXT(item_ptype, NEXT_ENTRY(COMMON_UNSIGNED),
6381 			     item_param),
6382 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ptype, packet_type)),
6383 	},
6384 	[ITEM_NSH] = {
6385 		.name = "nsh",
6386 		.help = "match NSH header",
6387 		.priv = PRIV_ITEM(NSH,
6388 				  sizeof(struct rte_flow_item_nsh)),
6389 		.next = NEXT(item_nsh),
6390 		.call = parse_vc,
6391 	},
6392 	[ITEM_COMPARE] = {
6393 		.name = "compare",
6394 		.help = "match with the comparison result",
6395 		.priv = PRIV_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
6396 		.next = NEXT(NEXT_ENTRY(ITEM_COMPARE_OP)),
6397 		.call = parse_vc,
6398 	},
6399 	[ITEM_COMPARE_OP] = {
6400 		.name = "op",
6401 		.help = "operation type",
6402 		.next = NEXT(item_compare_field,
6403 			NEXT_ENTRY(ITEM_COMPARE_OP_VALUE), item_param),
6404 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, operation)),
6405 	},
6406 	[ITEM_COMPARE_OP_VALUE] = {
6407 		.name = "{operation}",
6408 		.help = "operation type value",
6409 		.call = parse_vc_compare_op,
6410 		.comp = comp_set_compare_op,
6411 	},
6412 	[ITEM_COMPARE_FIELD_A_TYPE] = {
6413 		.name = "a_type",
6414 		.help = "compared field type",
6415 		.next = NEXT(compare_field_a,
6416 			NEXT_ENTRY(ITEM_COMPARE_FIELD_A_TYPE_VALUE), item_param),
6417 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.field)),
6418 	},
6419 	[ITEM_COMPARE_FIELD_A_TYPE_VALUE] = {
6420 		.name = "{a_type}",
6421 		.help = "compared field type value",
6422 		.call = parse_vc_compare_field_id,
6423 		.comp = comp_set_compare_field_id,
6424 	},
6425 	[ITEM_COMPARE_FIELD_A_LEVEL] = {
6426 		.name = "a_level",
6427 		.help = "compared field level",
6428 		.next = NEXT(compare_field_a,
6429 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_A_LEVEL_VALUE), item_param),
6430 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.level)),
6431 	},
6432 	[ITEM_COMPARE_FIELD_A_LEVEL_VALUE] = {
6433 		.name = "{a_level}",
6434 		.help = "compared field level value",
6435 		.call = parse_vc_compare_field_level,
6436 		.comp = comp_none,
6437 	},
6438 	[ITEM_COMPARE_FIELD_A_TAG_INDEX] = {
6439 		.name = "a_tag_index",
6440 		.help = "compared field tag array",
6441 		.next = NEXT(compare_field_a,
6442 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6443 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6444 					a.tag_index)),
6445 	},
6446 	[ITEM_COMPARE_FIELD_A_TYPE_ID] = {
6447 		.name = "a_type_id",
6448 		.help = "compared field type ID",
6449 		.next = NEXT(compare_field_a,
6450 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6451 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6452 					a.type)),
6453 	},
6454 	[ITEM_COMPARE_FIELD_A_CLASS_ID] = {
6455 		.name = "a_class",
6456 		.help = "compared field class ID",
6457 		.next = NEXT(compare_field_a,
6458 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6459 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6460 					     a.class_id)),
6461 	},
6462 	[ITEM_COMPARE_FIELD_A_OFFSET] = {
6463 		.name = "a_offset",
6464 		.help = "compared field bit offset",
6465 		.next = NEXT(compare_field_a,
6466 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6467 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6468 					a.offset)),
6469 	},
6470 	[ITEM_COMPARE_FIELD_B_TYPE] = {
6471 		.name = "b_type",
6472 		.help = "comparator field type",
6473 		.next = NEXT(compare_field_b,
6474 			NEXT_ENTRY(ITEM_COMPARE_FIELD_B_TYPE_VALUE), item_param),
6475 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6476 					b.field)),
6477 	},
6478 	[ITEM_COMPARE_FIELD_B_TYPE_VALUE] = {
6479 		.name = "{b_type}",
6480 		.help = "comparator field type value",
6481 		.call = parse_vc_compare_field_id,
6482 		.comp = comp_set_compare_field_id,
6483 	},
6484 	[ITEM_COMPARE_FIELD_B_LEVEL] = {
6485 		.name = "b_level",
6486 		.help = "comparator field level",
6487 		.next = NEXT(compare_field_b,
6488 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_B_LEVEL_VALUE), item_param),
6489 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6490 					b.level)),
6491 	},
6492 	[ITEM_COMPARE_FIELD_B_LEVEL_VALUE] = {
6493 		.name = "{b_level}",
6494 		.help = "comparator field level value",
6495 		.call = parse_vc_compare_field_level,
6496 		.comp = comp_none,
6497 	},
6498 	[ITEM_COMPARE_FIELD_B_TAG_INDEX] = {
6499 		.name = "b_tag_index",
6500 		.help = "comparator field tag array",
6501 		.next = NEXT(compare_field_b,
6502 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6503 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6504 					b.tag_index)),
6505 	},
6506 	[ITEM_COMPARE_FIELD_B_TYPE_ID] = {
6507 		.name = "b_type_id",
6508 		.help = "comparator field type ID",
6509 		.next = NEXT(compare_field_b,
6510 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6511 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6512 					b.type)),
6513 	},
6514 	[ITEM_COMPARE_FIELD_B_CLASS_ID] = {
6515 		.name = "b_class",
6516 		.help = "comparator field class ID",
6517 		.next = NEXT(compare_field_b,
6518 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6519 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6520 					     b.class_id)),
6521 	},
6522 	[ITEM_COMPARE_FIELD_B_OFFSET] = {
6523 		.name = "b_offset",
6524 		.help = "comparator field bit offset",
6525 		.next = NEXT(compare_field_b,
6526 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6527 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6528 					b.offset)),
6529 	},
6530 	[ITEM_COMPARE_FIELD_B_VALUE] = {
6531 		.name = "b_value",
6532 		.help = "comparator immediate value",
6533 		.next = NEXT(compare_field_b,
6534 			     NEXT_ENTRY(COMMON_HEX), item_param),
6535 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
6536 			     ARGS_ENTRY_ARB(0, 0),
6537 			     ARGS_ENTRY(struct rte_flow_item_compare,
6538 					b.value)),
6539 	},
6540 	[ITEM_COMPARE_FIELD_B_POINTER] = {
6541 		.name = "b_ptr",
6542 		.help = "pointer to comparator immediate value",
6543 		.next = NEXT(compare_field_b,
6544 			     NEXT_ENTRY(COMMON_HEX), item_param),
6545 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6546 					b.pvalue),
6547 			     ARGS_ENTRY_ARB(0, 0),
6548 			     ARGS_ENTRY_ARB
6549 				(sizeof(struct rte_flow_item_compare),
6550 				 FLOW_FIELD_PATTERN_SIZE)),
6551 	},
6552 	[ITEM_COMPARE_FIELD_WIDTH] = {
6553 		.name = "width",
6554 		.help = "number of bits to compare",
6555 		.next = NEXT(item_compare_field,
6556 			NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6557 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6558 					width)),
6559 	},
6560 
6561 	/* Validate/create actions. */
6562 	[ACTIONS] = {
6563 		.name = "actions",
6564 		.help = "submit a list of associated actions",
6565 		.next = NEXT(next_action),
6566 		.call = parse_vc,
6567 	},
6568 	[ACTION_NEXT] = {
6569 		.name = "/",
6570 		.help = "specify next action",
6571 		.next = NEXT(next_action),
6572 	},
6573 	[ACTION_END] = {
6574 		.name = "end",
6575 		.help = "end list of actions",
6576 		.priv = PRIV_ACTION(END, 0),
6577 		.call = parse_vc,
6578 	},
6579 	[ACTION_VOID] = {
6580 		.name = "void",
6581 		.help = "no-op action",
6582 		.priv = PRIV_ACTION(VOID, 0),
6583 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6584 		.call = parse_vc,
6585 	},
6586 	[ACTION_PASSTHRU] = {
6587 		.name = "passthru",
6588 		.help = "let subsequent rule process matched packets",
6589 		.priv = PRIV_ACTION(PASSTHRU, 0),
6590 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6591 		.call = parse_vc,
6592 	},
6593 	[ACTION_SKIP_CMAN] = {
6594 		.name = "skip_cman",
6595 		.help = "bypass cman on received packets",
6596 		.priv = PRIV_ACTION(SKIP_CMAN, 0),
6597 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6598 		.call = parse_vc,
6599 	},
6600 	[ACTION_JUMP] = {
6601 		.name = "jump",
6602 		.help = "redirect traffic to a given group",
6603 		.priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
6604 		.next = NEXT(action_jump),
6605 		.call = parse_vc,
6606 	},
6607 	[ACTION_JUMP_GROUP] = {
6608 		.name = "group",
6609 		.help = "group to redirect traffic to",
6610 		.next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
6611 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
6612 		.call = parse_vc_conf,
6613 	},
6614 	[ACTION_MARK] = {
6615 		.name = "mark",
6616 		.help = "attach 32 bit value to packets",
6617 		.priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
6618 		.next = NEXT(action_mark),
6619 		.call = parse_vc,
6620 	},
6621 	[ACTION_MARK_ID] = {
6622 		.name = "id",
6623 		.help = "32 bit value to return with packets",
6624 		.next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6625 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
6626 		.call = parse_vc_conf,
6627 	},
6628 	[ACTION_FLAG] = {
6629 		.name = "flag",
6630 		.help = "flag packets",
6631 		.priv = PRIV_ACTION(FLAG, 0),
6632 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6633 		.call = parse_vc,
6634 	},
6635 	[ACTION_QUEUE] = {
6636 		.name = "queue",
6637 		.help = "assign packets to a given queue index",
6638 		.priv = PRIV_ACTION(QUEUE,
6639 				    sizeof(struct rte_flow_action_queue)),
6640 		.next = NEXT(action_queue),
6641 		.call = parse_vc,
6642 	},
6643 	[ACTION_QUEUE_INDEX] = {
6644 		.name = "index",
6645 		.help = "queue index to use",
6646 		.next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
6647 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
6648 		.call = parse_vc_conf,
6649 	},
6650 	[ACTION_DROP] = {
6651 		.name = "drop",
6652 		.help = "drop packets (note: passthru has priority)",
6653 		.priv = PRIV_ACTION(DROP, 0),
6654 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6655 		.call = parse_vc,
6656 	},
6657 	[ACTION_COUNT] = {
6658 		.name = "count",
6659 		.help = "enable counters for this rule",
6660 		.priv = PRIV_ACTION(COUNT,
6661 				    sizeof(struct rte_flow_action_count)),
6662 		.next = NEXT(action_count),
6663 		.call = parse_vc,
6664 	},
6665 	[ACTION_COUNT_ID] = {
6666 		.name = "identifier",
6667 		.help = "counter identifier to use",
6668 		.next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
6669 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
6670 		.call = parse_vc_conf,
6671 	},
6672 	[ACTION_RSS] = {
6673 		.name = "rss",
6674 		.help = "spread packets among several queues",
6675 		.priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
6676 		.next = NEXT(action_rss),
6677 		.call = parse_vc_action_rss,
6678 	},
6679 	[ACTION_RSS_FUNC] = {
6680 		.name = "func",
6681 		.help = "RSS hash function to apply",
6682 		.next = NEXT(action_rss,
6683 			     NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
6684 					ACTION_RSS_FUNC_TOEPLITZ,
6685 					ACTION_RSS_FUNC_SIMPLE_XOR,
6686 					ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
6687 	},
6688 	[ACTION_RSS_FUNC_DEFAULT] = {
6689 		.name = "default",
6690 		.help = "default hash function",
6691 		.call = parse_vc_action_rss_func,
6692 	},
6693 	[ACTION_RSS_FUNC_TOEPLITZ] = {
6694 		.name = "toeplitz",
6695 		.help = "Toeplitz hash function",
6696 		.call = parse_vc_action_rss_func,
6697 	},
6698 	[ACTION_RSS_FUNC_SIMPLE_XOR] = {
6699 		.name = "simple_xor",
6700 		.help = "simple XOR hash function",
6701 		.call = parse_vc_action_rss_func,
6702 	},
6703 	[ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
6704 		.name = "symmetric_toeplitz",
6705 		.help = "Symmetric Toeplitz hash function",
6706 		.call = parse_vc_action_rss_func,
6707 	},
6708 	[ACTION_RSS_LEVEL] = {
6709 		.name = "level",
6710 		.help = "encapsulation level for \"types\"",
6711 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6712 		.args = ARGS(ARGS_ENTRY_ARB
6713 			     (offsetof(struct action_rss_data, conf) +
6714 			      offsetof(struct rte_flow_action_rss, level),
6715 			      sizeof(((struct rte_flow_action_rss *)0)->
6716 				     level))),
6717 	},
6718 	[ACTION_RSS_TYPES] = {
6719 		.name = "types",
6720 		.help = "specific RSS hash types",
6721 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
6722 	},
6723 	[ACTION_RSS_TYPE] = {
6724 		.name = "{type}",
6725 		.help = "RSS hash type",
6726 		.call = parse_vc_action_rss_type,
6727 		.comp = comp_vc_action_rss_type,
6728 	},
6729 	[ACTION_RSS_KEY] = {
6730 		.name = "key",
6731 		.help = "RSS hash key",
6732 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
6733 		.args = ARGS(ARGS_ENTRY_ARB
6734 			     (offsetof(struct action_rss_data, conf) +
6735 			      offsetof(struct rte_flow_action_rss, key),
6736 			      sizeof(((struct rte_flow_action_rss *)0)->key)),
6737 			     ARGS_ENTRY_ARB
6738 			     (offsetof(struct action_rss_data, conf) +
6739 			      offsetof(struct rte_flow_action_rss, key_len),
6740 			      sizeof(((struct rte_flow_action_rss *)0)->
6741 				     key_len)),
6742 			     ARGS_ENTRY(struct action_rss_data, key)),
6743 	},
6744 	[ACTION_RSS_KEY_LEN] = {
6745 		.name = "key_len",
6746 		.help = "RSS hash key length in bytes",
6747 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6748 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
6749 			     (offsetof(struct action_rss_data, conf) +
6750 			      offsetof(struct rte_flow_action_rss, key_len),
6751 			      sizeof(((struct rte_flow_action_rss *)0)->
6752 				     key_len),
6753 			      0,
6754 			      RSS_HASH_KEY_LENGTH)),
6755 	},
6756 	[ACTION_RSS_QUEUES] = {
6757 		.name = "queues",
6758 		.help = "queue indices to use",
6759 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
6760 		.call = parse_vc_conf,
6761 	},
6762 	[ACTION_RSS_QUEUE] = {
6763 		.name = "{queue}",
6764 		.help = "queue index",
6765 		.call = parse_vc_action_rss_queue,
6766 		.comp = comp_vc_action_rss_queue,
6767 	},
6768 	[ACTION_PF] = {
6769 		.name = "pf",
6770 		.help = "direct traffic to physical function",
6771 		.priv = PRIV_ACTION(PF, 0),
6772 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6773 		.call = parse_vc,
6774 	},
6775 	[ACTION_VF] = {
6776 		.name = "vf",
6777 		.help = "direct traffic to a virtual function ID",
6778 		.priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
6779 		.next = NEXT(action_vf),
6780 		.call = parse_vc,
6781 	},
6782 	[ACTION_VF_ORIGINAL] = {
6783 		.name = "original",
6784 		.help = "use original VF ID if possible",
6785 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
6786 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
6787 					   original, 1)),
6788 		.call = parse_vc_conf,
6789 	},
6790 	[ACTION_VF_ID] = {
6791 		.name = "id",
6792 		.help = "VF ID",
6793 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
6794 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
6795 		.call = parse_vc_conf,
6796 	},
6797 	[ACTION_PORT_ID] = {
6798 		.name = "port_id",
6799 		.help = "direct matching traffic to a given DPDK port ID",
6800 		.priv = PRIV_ACTION(PORT_ID,
6801 				    sizeof(struct rte_flow_action_port_id)),
6802 		.next = NEXT(action_port_id),
6803 		.call = parse_vc,
6804 	},
6805 	[ACTION_PORT_ID_ORIGINAL] = {
6806 		.name = "original",
6807 		.help = "use original DPDK port ID if possible",
6808 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
6809 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
6810 					   original, 1)),
6811 		.call = parse_vc_conf,
6812 	},
6813 	[ACTION_PORT_ID_ID] = {
6814 		.name = "id",
6815 		.help = "DPDK port ID",
6816 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
6817 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
6818 		.call = parse_vc_conf,
6819 	},
6820 	[ACTION_METER] = {
6821 		.name = "meter",
6822 		.help = "meter the directed packets at given id",
6823 		.priv = PRIV_ACTION(METER,
6824 				    sizeof(struct rte_flow_action_meter)),
6825 		.next = NEXT(action_meter),
6826 		.call = parse_vc,
6827 	},
6828 	[ACTION_METER_COLOR] = {
6829 		.name = "color",
6830 		.help = "meter color for the packets",
6831 		.priv = PRIV_ACTION(METER_COLOR,
6832 				sizeof(struct rte_flow_action_meter_color)),
6833 		.next = NEXT(action_meter_color),
6834 		.call = parse_vc,
6835 	},
6836 	[ACTION_METER_COLOR_TYPE] = {
6837 		.name = "type",
6838 		.help = "specific meter color",
6839 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
6840 				NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
6841 					ACTION_METER_COLOR_YELLOW,
6842 					ACTION_METER_COLOR_RED)),
6843 	},
6844 	[ACTION_METER_COLOR_GREEN] = {
6845 		.name = "green",
6846 		.help = "meter color green",
6847 		.call = parse_vc_action_meter_color_type,
6848 	},
6849 	[ACTION_METER_COLOR_YELLOW] = {
6850 		.name = "yellow",
6851 		.help = "meter color yellow",
6852 		.call = parse_vc_action_meter_color_type,
6853 	},
6854 	[ACTION_METER_COLOR_RED] = {
6855 		.name = "red",
6856 		.help = "meter color red",
6857 		.call = parse_vc_action_meter_color_type,
6858 	},
6859 	[ACTION_METER_ID] = {
6860 		.name = "mtr_id",
6861 		.help = "meter id to use",
6862 		.next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
6863 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
6864 		.call = parse_vc_conf,
6865 	},
6866 	[ACTION_METER_MARK] = {
6867 		.name = "meter_mark",
6868 		.help = "meter the directed packets using profile and policy",
6869 		.priv = PRIV_ACTION(METER_MARK,
6870 				    sizeof(struct rte_flow_action_meter_mark)),
6871 		.next = NEXT(action_meter_mark),
6872 		.call = parse_vc,
6873 	},
6874 	[ACTION_METER_PROFILE] = {
6875 		.name = "mtr_profile",
6876 		.help = "meter profile id to use",
6877 		.next = NEXT(NEXT_ENTRY(ACTION_METER_PROFILE_ID2PTR)),
6878 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6879 	},
6880 	[ACTION_METER_PROFILE_ID2PTR] = {
6881 		.name = "{mtr_profile_id}",
6882 		.type = "PROFILE_ID",
6883 		.help = "meter profile id",
6884 		.next = NEXT(action_meter_mark),
6885 		.call = parse_meter_profile_id2ptr,
6886 		.comp = comp_none,
6887 	},
6888 	[ACTION_METER_POLICY] = {
6889 		.name = "mtr_policy",
6890 		.help = "meter policy id to use",
6891 		.next = NEXT(NEXT_ENTRY(ACTION_METER_POLICY_ID2PTR)),
6892 		ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6893 	},
6894 	[ACTION_METER_POLICY_ID2PTR] = {
6895 		.name = "{mtr_policy_id}",
6896 		.type = "POLICY_ID",
6897 		.help = "meter policy id",
6898 		.next = NEXT(action_meter_mark),
6899 		.call = parse_meter_policy_id2ptr,
6900 		.comp = comp_none,
6901 	},
6902 	[ACTION_METER_COLOR_MODE] = {
6903 		.name = "mtr_color_mode",
6904 		.help = "meter color awareness mode",
6905 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6906 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, color_mode)),
6907 		.call = parse_vc_conf,
6908 	},
6909 	[ACTION_METER_STATE] = {
6910 		.name = "mtr_state",
6911 		.help = "meter state",
6912 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6913 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, state)),
6914 		.call = parse_vc_conf,
6915 	},
6916 	[ACTION_OF_DEC_NW_TTL] = {
6917 		.name = "of_dec_nw_ttl",
6918 		.help = "OpenFlow's OFPAT_DEC_NW_TTL",
6919 		.priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
6920 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6921 		.call = parse_vc,
6922 	},
6923 	[ACTION_OF_POP_VLAN] = {
6924 		.name = "of_pop_vlan",
6925 		.help = "OpenFlow's OFPAT_POP_VLAN",
6926 		.priv = PRIV_ACTION(OF_POP_VLAN, 0),
6927 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6928 		.call = parse_vc,
6929 	},
6930 	[ACTION_OF_PUSH_VLAN] = {
6931 		.name = "of_push_vlan",
6932 		.help = "OpenFlow's OFPAT_PUSH_VLAN",
6933 		.priv = PRIV_ACTION
6934 			(OF_PUSH_VLAN,
6935 			 sizeof(struct rte_flow_action_of_push_vlan)),
6936 		.next = NEXT(action_of_push_vlan),
6937 		.call = parse_vc,
6938 	},
6939 	[ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
6940 		.name = "ethertype",
6941 		.help = "EtherType",
6942 		.next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
6943 		.args = ARGS(ARGS_ENTRY_HTON
6944 			     (struct rte_flow_action_of_push_vlan,
6945 			      ethertype)),
6946 		.call = parse_vc_conf,
6947 	},
6948 	[ACTION_OF_SET_VLAN_VID] = {
6949 		.name = "of_set_vlan_vid",
6950 		.help = "OpenFlow's OFPAT_SET_VLAN_VID",
6951 		.priv = PRIV_ACTION
6952 			(OF_SET_VLAN_VID,
6953 			 sizeof(struct rte_flow_action_of_set_vlan_vid)),
6954 		.next = NEXT(action_of_set_vlan_vid),
6955 		.call = parse_vc,
6956 	},
6957 	[ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
6958 		.name = "vlan_vid",
6959 		.help = "VLAN id",
6960 		.next = NEXT(action_of_set_vlan_vid,
6961 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6962 		.args = ARGS(ARGS_ENTRY_HTON
6963 			     (struct rte_flow_action_of_set_vlan_vid,
6964 			      vlan_vid)),
6965 		.call = parse_vc_conf,
6966 	},
6967 	[ACTION_OF_SET_VLAN_PCP] = {
6968 		.name = "of_set_vlan_pcp",
6969 		.help = "OpenFlow's OFPAT_SET_VLAN_PCP",
6970 		.priv = PRIV_ACTION
6971 			(OF_SET_VLAN_PCP,
6972 			 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
6973 		.next = NEXT(action_of_set_vlan_pcp),
6974 		.call = parse_vc,
6975 	},
6976 	[ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
6977 		.name = "vlan_pcp",
6978 		.help = "VLAN priority",
6979 		.next = NEXT(action_of_set_vlan_pcp,
6980 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6981 		.args = ARGS(ARGS_ENTRY_HTON
6982 			     (struct rte_flow_action_of_set_vlan_pcp,
6983 			      vlan_pcp)),
6984 		.call = parse_vc_conf,
6985 	},
6986 	[ACTION_OF_POP_MPLS] = {
6987 		.name = "of_pop_mpls",
6988 		.help = "OpenFlow's OFPAT_POP_MPLS",
6989 		.priv = PRIV_ACTION(OF_POP_MPLS,
6990 				    sizeof(struct rte_flow_action_of_pop_mpls)),
6991 		.next = NEXT(action_of_pop_mpls),
6992 		.call = parse_vc,
6993 	},
6994 	[ACTION_OF_POP_MPLS_ETHERTYPE] = {
6995 		.name = "ethertype",
6996 		.help = "EtherType",
6997 		.next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6998 		.args = ARGS(ARGS_ENTRY_HTON
6999 			     (struct rte_flow_action_of_pop_mpls,
7000 			      ethertype)),
7001 		.call = parse_vc_conf,
7002 	},
7003 	[ACTION_OF_PUSH_MPLS] = {
7004 		.name = "of_push_mpls",
7005 		.help = "OpenFlow's OFPAT_PUSH_MPLS",
7006 		.priv = PRIV_ACTION
7007 			(OF_PUSH_MPLS,
7008 			 sizeof(struct rte_flow_action_of_push_mpls)),
7009 		.next = NEXT(action_of_push_mpls),
7010 		.call = parse_vc,
7011 	},
7012 	[ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
7013 		.name = "ethertype",
7014 		.help = "EtherType",
7015 		.next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
7016 		.args = ARGS(ARGS_ENTRY_HTON
7017 			     (struct rte_flow_action_of_push_mpls,
7018 			      ethertype)),
7019 		.call = parse_vc_conf,
7020 	},
7021 	[ACTION_VXLAN_ENCAP] = {
7022 		.name = "vxlan_encap",
7023 		.help = "VXLAN encapsulation, uses configuration set by \"set"
7024 			" vxlan\"",
7025 		.priv = PRIV_ACTION(VXLAN_ENCAP,
7026 				    sizeof(struct action_vxlan_encap_data)),
7027 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7028 		.call = parse_vc_action_vxlan_encap,
7029 	},
7030 	[ACTION_VXLAN_DECAP] = {
7031 		.name = "vxlan_decap",
7032 		.help = "Performs a decapsulation action by stripping all"
7033 			" headers of the VXLAN tunnel network overlay from the"
7034 			" matched flow.",
7035 		.priv = PRIV_ACTION(VXLAN_DECAP, 0),
7036 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7037 		.call = parse_vc,
7038 	},
7039 	[ACTION_NVGRE_ENCAP] = {
7040 		.name = "nvgre_encap",
7041 		.help = "NVGRE encapsulation, uses configuration set by \"set"
7042 			" nvgre\"",
7043 		.priv = PRIV_ACTION(NVGRE_ENCAP,
7044 				    sizeof(struct action_nvgre_encap_data)),
7045 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7046 		.call = parse_vc_action_nvgre_encap,
7047 	},
7048 	[ACTION_NVGRE_DECAP] = {
7049 		.name = "nvgre_decap",
7050 		.help = "Performs a decapsulation action by stripping all"
7051 			" headers of the NVGRE tunnel network overlay from the"
7052 			" matched flow.",
7053 		.priv = PRIV_ACTION(NVGRE_DECAP, 0),
7054 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7055 		.call = parse_vc,
7056 	},
7057 	[ACTION_L2_ENCAP] = {
7058 		.name = "l2_encap",
7059 		.help = "l2 encap, uses configuration set by"
7060 			" \"set l2_encap\"",
7061 		.priv = PRIV_ACTION(RAW_ENCAP,
7062 				    sizeof(struct action_raw_encap_data)),
7063 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7064 		.call = parse_vc_action_l2_encap,
7065 	},
7066 	[ACTION_L2_DECAP] = {
7067 		.name = "l2_decap",
7068 		.help = "l2 decap, uses configuration set by"
7069 			" \"set l2_decap\"",
7070 		.priv = PRIV_ACTION(RAW_DECAP,
7071 				    sizeof(struct action_raw_decap_data)),
7072 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7073 		.call = parse_vc_action_l2_decap,
7074 	},
7075 	[ACTION_MPLSOGRE_ENCAP] = {
7076 		.name = "mplsogre_encap",
7077 		.help = "mplsogre encapsulation, uses configuration set by"
7078 			" \"set mplsogre_encap\"",
7079 		.priv = PRIV_ACTION(RAW_ENCAP,
7080 				    sizeof(struct action_raw_encap_data)),
7081 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7082 		.call = parse_vc_action_mplsogre_encap,
7083 	},
7084 	[ACTION_MPLSOGRE_DECAP] = {
7085 		.name = "mplsogre_decap",
7086 		.help = "mplsogre decapsulation, uses configuration set by"
7087 			" \"set mplsogre_decap\"",
7088 		.priv = PRIV_ACTION(RAW_DECAP,
7089 				    sizeof(struct action_raw_decap_data)),
7090 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7091 		.call = parse_vc_action_mplsogre_decap,
7092 	},
7093 	[ACTION_MPLSOUDP_ENCAP] = {
7094 		.name = "mplsoudp_encap",
7095 		.help = "mplsoudp encapsulation, uses configuration set by"
7096 			" \"set mplsoudp_encap\"",
7097 		.priv = PRIV_ACTION(RAW_ENCAP,
7098 				    sizeof(struct action_raw_encap_data)),
7099 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7100 		.call = parse_vc_action_mplsoudp_encap,
7101 	},
7102 	[ACTION_MPLSOUDP_DECAP] = {
7103 		.name = "mplsoudp_decap",
7104 		.help = "mplsoudp decapsulation, uses configuration set by"
7105 			" \"set mplsoudp_decap\"",
7106 		.priv = PRIV_ACTION(RAW_DECAP,
7107 				    sizeof(struct action_raw_decap_data)),
7108 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7109 		.call = parse_vc_action_mplsoudp_decap,
7110 	},
7111 	[ACTION_SET_IPV4_SRC] = {
7112 		.name = "set_ipv4_src",
7113 		.help = "Set a new IPv4 source address in the outermost"
7114 			" IPv4 header",
7115 		.priv = PRIV_ACTION(SET_IPV4_SRC,
7116 			sizeof(struct rte_flow_action_set_ipv4)),
7117 		.next = NEXT(action_set_ipv4_src),
7118 		.call = parse_vc,
7119 	},
7120 	[ACTION_SET_IPV4_SRC_IPV4_SRC] = {
7121 		.name = "ipv4_addr",
7122 		.help = "new IPv4 source address to set",
7123 		.next = NEXT(action_set_ipv4_src, 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_IPV4_DST] = {
7129 		.name = "set_ipv4_dst",
7130 		.help = "Set a new IPv4 destination address in the outermost"
7131 			" IPv4 header",
7132 		.priv = PRIV_ACTION(SET_IPV4_DST,
7133 			sizeof(struct rte_flow_action_set_ipv4)),
7134 		.next = NEXT(action_set_ipv4_dst),
7135 		.call = parse_vc,
7136 	},
7137 	[ACTION_SET_IPV4_DST_IPV4_DST] = {
7138 		.name = "ipv4_addr",
7139 		.help = "new IPv4 destination address to set",
7140 		.next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
7141 		.args = ARGS(ARGS_ENTRY_HTON
7142 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
7143 		.call = parse_vc_conf,
7144 	},
7145 	[ACTION_SET_IPV6_SRC] = {
7146 		.name = "set_ipv6_src",
7147 		.help = "Set a new IPv6 source address in the outermost"
7148 			" IPv6 header",
7149 		.priv = PRIV_ACTION(SET_IPV6_SRC,
7150 			sizeof(struct rte_flow_action_set_ipv6)),
7151 		.next = NEXT(action_set_ipv6_src),
7152 		.call = parse_vc,
7153 	},
7154 	[ACTION_SET_IPV6_SRC_IPV6_SRC] = {
7155 		.name = "ipv6_addr",
7156 		.help = "new IPv6 source address to set",
7157 		.next = NEXT(action_set_ipv6_src, 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_IPV6_DST] = {
7163 		.name = "set_ipv6_dst",
7164 		.help = "Set a new IPv6 destination address in the outermost"
7165 			" IPv6 header",
7166 		.priv = PRIV_ACTION(SET_IPV6_DST,
7167 			sizeof(struct rte_flow_action_set_ipv6)),
7168 		.next = NEXT(action_set_ipv6_dst),
7169 		.call = parse_vc,
7170 	},
7171 	[ACTION_SET_IPV6_DST_IPV6_DST] = {
7172 		.name = "ipv6_addr",
7173 		.help = "new IPv6 destination address to set",
7174 		.next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
7175 		.args = ARGS(ARGS_ENTRY_HTON
7176 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
7177 		.call = parse_vc_conf,
7178 	},
7179 	[ACTION_SET_TP_SRC] = {
7180 		.name = "set_tp_src",
7181 		.help = "set a new source port number in the outermost"
7182 			" TCP/UDP header",
7183 		.priv = PRIV_ACTION(SET_TP_SRC,
7184 			sizeof(struct rte_flow_action_set_tp)),
7185 		.next = NEXT(action_set_tp_src),
7186 		.call = parse_vc,
7187 	},
7188 	[ACTION_SET_TP_SRC_TP_SRC] = {
7189 		.name = "port",
7190 		.help = "new source port number to set",
7191 		.next = NEXT(action_set_tp_src, 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_SET_TP_DST] = {
7197 		.name = "set_tp_dst",
7198 		.help = "set a new destination port number in the outermost"
7199 			" TCP/UDP header",
7200 		.priv = PRIV_ACTION(SET_TP_DST,
7201 			sizeof(struct rte_flow_action_set_tp)),
7202 		.next = NEXT(action_set_tp_dst),
7203 		.call = parse_vc,
7204 	},
7205 	[ACTION_SET_TP_DST_TP_DST] = {
7206 		.name = "port",
7207 		.help = "new destination port number to set",
7208 		.next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
7209 		.args = ARGS(ARGS_ENTRY_HTON
7210 			     (struct rte_flow_action_set_tp, port)),
7211 		.call = parse_vc_conf,
7212 	},
7213 	[ACTION_MAC_SWAP] = {
7214 		.name = "mac_swap",
7215 		.help = "Swap the source and destination MAC addresses"
7216 			" in the outermost Ethernet header",
7217 		.priv = PRIV_ACTION(MAC_SWAP, 0),
7218 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7219 		.call = parse_vc,
7220 	},
7221 	[ACTION_DEC_TTL] = {
7222 		.name = "dec_ttl",
7223 		.help = "decrease network TTL if available",
7224 		.priv = PRIV_ACTION(DEC_TTL, 0),
7225 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7226 		.call = parse_vc,
7227 	},
7228 	[ACTION_SET_TTL] = {
7229 		.name = "set_ttl",
7230 		.help = "set ttl value",
7231 		.priv = PRIV_ACTION(SET_TTL,
7232 			sizeof(struct rte_flow_action_set_ttl)),
7233 		.next = NEXT(action_set_ttl),
7234 		.call = parse_vc,
7235 	},
7236 	[ACTION_SET_TTL_TTL] = {
7237 		.name = "ttl_value",
7238 		.help = "new ttl value to set",
7239 		.next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
7240 		.args = ARGS(ARGS_ENTRY_HTON
7241 			     (struct rte_flow_action_set_ttl, ttl_value)),
7242 		.call = parse_vc_conf,
7243 	},
7244 	[ACTION_SET_MAC_SRC] = {
7245 		.name = "set_mac_src",
7246 		.help = "set source mac address",
7247 		.priv = PRIV_ACTION(SET_MAC_SRC,
7248 			sizeof(struct rte_flow_action_set_mac)),
7249 		.next = NEXT(action_set_mac_src),
7250 		.call = parse_vc,
7251 	},
7252 	[ACTION_SET_MAC_SRC_MAC_SRC] = {
7253 		.name = "mac_addr",
7254 		.help = "new source mac address",
7255 		.next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
7256 		.args = ARGS(ARGS_ENTRY_HTON
7257 			     (struct rte_flow_action_set_mac, mac_addr)),
7258 		.call = parse_vc_conf,
7259 	},
7260 	[ACTION_SET_MAC_DST] = {
7261 		.name = "set_mac_dst",
7262 		.help = "set destination mac address",
7263 		.priv = PRIV_ACTION(SET_MAC_DST,
7264 			sizeof(struct rte_flow_action_set_mac)),
7265 		.next = NEXT(action_set_mac_dst),
7266 		.call = parse_vc,
7267 	},
7268 	[ACTION_SET_MAC_DST_MAC_DST] = {
7269 		.name = "mac_addr",
7270 		.help = "new destination mac address to set",
7271 		.next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
7272 		.args = ARGS(ARGS_ENTRY_HTON
7273 			     (struct rte_flow_action_set_mac, mac_addr)),
7274 		.call = parse_vc_conf,
7275 	},
7276 	[ACTION_INC_TCP_SEQ] = {
7277 		.name = "inc_tcp_seq",
7278 		.help = "increase TCP sequence number",
7279 		.priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
7280 		.next = NEXT(action_inc_tcp_seq),
7281 		.call = parse_vc,
7282 	},
7283 	[ACTION_INC_TCP_SEQ_VALUE] = {
7284 		.name = "value",
7285 		.help = "the value to increase TCP sequence number by",
7286 		.next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7287 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7288 		.call = parse_vc_conf,
7289 	},
7290 	[ACTION_DEC_TCP_SEQ] = {
7291 		.name = "dec_tcp_seq",
7292 		.help = "decrease TCP sequence number",
7293 		.priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
7294 		.next = NEXT(action_dec_tcp_seq),
7295 		.call = parse_vc,
7296 	},
7297 	[ACTION_DEC_TCP_SEQ_VALUE] = {
7298 		.name = "value",
7299 		.help = "the value to decrease TCP sequence number by",
7300 		.next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7301 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7302 		.call = parse_vc_conf,
7303 	},
7304 	[ACTION_INC_TCP_ACK] = {
7305 		.name = "inc_tcp_ack",
7306 		.help = "increase TCP acknowledgment number",
7307 		.priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
7308 		.next = NEXT(action_inc_tcp_ack),
7309 		.call = parse_vc,
7310 	},
7311 	[ACTION_INC_TCP_ACK_VALUE] = {
7312 		.name = "value",
7313 		.help = "the value to increase TCP acknowledgment number by",
7314 		.next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7315 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7316 		.call = parse_vc_conf,
7317 	},
7318 	[ACTION_DEC_TCP_ACK] = {
7319 		.name = "dec_tcp_ack",
7320 		.help = "decrease TCP acknowledgment number",
7321 		.priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
7322 		.next = NEXT(action_dec_tcp_ack),
7323 		.call = parse_vc,
7324 	},
7325 	[ACTION_DEC_TCP_ACK_VALUE] = {
7326 		.name = "value",
7327 		.help = "the value to decrease TCP acknowledgment number by",
7328 		.next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7329 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7330 		.call = parse_vc_conf,
7331 	},
7332 	[ACTION_RAW_ENCAP] = {
7333 		.name = "raw_encap",
7334 		.help = "encapsulation data, defined by set raw_encap",
7335 		.priv = PRIV_ACTION(RAW_ENCAP,
7336 			sizeof(struct action_raw_encap_data)),
7337 		.next = NEXT(action_raw_encap),
7338 		.call = parse_vc_action_raw_encap,
7339 	},
7340 	[ACTION_RAW_ENCAP_SIZE] = {
7341 		.name = "size",
7342 		.help = "raw encap size",
7343 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7344 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7345 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_raw_encap, size)),
7346 		.call = parse_vc_conf,
7347 	},
7348 	[ACTION_RAW_ENCAP_INDEX] = {
7349 		.name = "index",
7350 		.help = "the index of raw_encap_confs",
7351 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
7352 	},
7353 	[ACTION_RAW_ENCAP_INDEX_VALUE] = {
7354 		.name = "{index}",
7355 		.type = "UNSIGNED",
7356 		.help = "unsigned integer value",
7357 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7358 		.call = parse_vc_action_raw_encap_index,
7359 		.comp = comp_set_raw_index,
7360 	},
7361 	[ACTION_RAW_DECAP] = {
7362 		.name = "raw_decap",
7363 		.help = "decapsulation data, defined by set raw_encap",
7364 		.priv = PRIV_ACTION(RAW_DECAP,
7365 			sizeof(struct action_raw_decap_data)),
7366 		.next = NEXT(action_raw_decap),
7367 		.call = parse_vc_action_raw_decap,
7368 	},
7369 	[ACTION_RAW_DECAP_INDEX] = {
7370 		.name = "index",
7371 		.help = "the index of raw_encap_confs",
7372 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
7373 	},
7374 	[ACTION_RAW_DECAP_INDEX_VALUE] = {
7375 		.name = "{index}",
7376 		.type = "UNSIGNED",
7377 		.help = "unsigned integer value",
7378 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7379 		.call = parse_vc_action_raw_decap_index,
7380 		.comp = comp_set_raw_index,
7381 	},
7382 	[ACTION_MODIFY_FIELD] = {
7383 		.name = "modify_field",
7384 		.help = "modify destination field with data from source field",
7385 		.priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
7386 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
7387 		.call = parse_vc,
7388 	},
7389 	[ACTION_MODIFY_FIELD_OP] = {
7390 		.name = "op",
7391 		.help = "operation type",
7392 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
7393 			NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
7394 		.call = parse_vc_conf,
7395 	},
7396 	[ACTION_MODIFY_FIELD_OP_VALUE] = {
7397 		.name = "{operation}",
7398 		.help = "operation type value",
7399 		.call = parse_vc_modify_field_op,
7400 		.comp = comp_set_modify_field_op,
7401 	},
7402 	[ACTION_MODIFY_FIELD_DST_TYPE] = {
7403 		.name = "dst_type",
7404 		.help = "destination field type",
7405 		.next = NEXT(action_modify_field_dst,
7406 			NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
7407 		.call = parse_vc_conf,
7408 	},
7409 	[ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
7410 		.name = "{dst_type}",
7411 		.help = "destination field type value",
7412 		.call = parse_vc_modify_field_id,
7413 		.comp = comp_set_modify_field_id,
7414 	},
7415 	[ACTION_MODIFY_FIELD_DST_LEVEL] = {
7416 		.name = "dst_level",
7417 		.help = "destination field level",
7418 		.next = NEXT(action_modify_field_dst,
7419 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)),
7420 		.call = parse_vc_conf,
7421 	},
7422 	[ACTION_MODIFY_FIELD_DST_LEVEL_VALUE] = {
7423 		.name = "{dst_level}",
7424 		.help = "destination field level value",
7425 		.call = parse_vc_modify_field_level,
7426 		.comp = comp_none,
7427 	},
7428 	[ACTION_MODIFY_FIELD_DST_TAG_INDEX] = {
7429 		.name = "dst_tag_index",
7430 		.help = "destination field tag array",
7431 		.next = NEXT(action_modify_field_dst,
7432 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7433 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7434 					dst.tag_index)),
7435 		.call = parse_vc_conf,
7436 	},
7437 	[ACTION_MODIFY_FIELD_DST_TYPE_ID] = {
7438 		.name = "dst_type_id",
7439 		.help = "destination field type ID",
7440 		.next = NEXT(action_modify_field_dst,
7441 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7442 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7443 					dst.type)),
7444 		.call = parse_vc_conf,
7445 	},
7446 	[ACTION_MODIFY_FIELD_DST_CLASS_ID] = {
7447 		.name = "dst_class",
7448 		.help = "destination field class ID",
7449 		.next = NEXT(action_modify_field_dst,
7450 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7451 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7452 					     dst.class_id)),
7453 		.call = parse_vc_conf,
7454 	},
7455 	[ACTION_MODIFY_FIELD_DST_OFFSET] = {
7456 		.name = "dst_offset",
7457 		.help = "destination field bit offset",
7458 		.next = NEXT(action_modify_field_dst,
7459 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7460 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7461 					dst.offset)),
7462 		.call = parse_vc_conf,
7463 	},
7464 	[ACTION_MODIFY_FIELD_SRC_TYPE] = {
7465 		.name = "src_type",
7466 		.help = "source field type",
7467 		.next = NEXT(action_modify_field_src,
7468 			NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
7469 		.call = parse_vc_conf,
7470 	},
7471 	[ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
7472 		.name = "{src_type}",
7473 		.help = "source field type value",
7474 		.call = parse_vc_modify_field_id,
7475 		.comp = comp_set_modify_field_id,
7476 	},
7477 	[ACTION_MODIFY_FIELD_SRC_LEVEL] = {
7478 		.name = "src_level",
7479 		.help = "source field level",
7480 		.next = NEXT(action_modify_field_src,
7481 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)),
7482 		.call = parse_vc_conf,
7483 	},
7484 	[ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE] = {
7485 		.name = "{src_level}",
7486 		.help = "source field level value",
7487 		.call = parse_vc_modify_field_level,
7488 		.comp = comp_none,
7489 	},
7490 	[ACTION_MODIFY_FIELD_SRC_TAG_INDEX] = {
7491 		.name = "src_tag_index",
7492 		.help = "source field tag array",
7493 		.next = NEXT(action_modify_field_src,
7494 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7495 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7496 					src.tag_index)),
7497 		.call = parse_vc_conf,
7498 	},
7499 	[ACTION_MODIFY_FIELD_SRC_TYPE_ID] = {
7500 		.name = "src_type_id",
7501 		.help = "source field type ID",
7502 		.next = NEXT(action_modify_field_src,
7503 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7504 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7505 					src.type)),
7506 		.call = parse_vc_conf,
7507 	},
7508 	[ACTION_MODIFY_FIELD_SRC_CLASS_ID] = {
7509 		.name = "src_class",
7510 		.help = "source field class ID",
7511 		.next = NEXT(action_modify_field_src,
7512 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7513 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7514 					     src.class_id)),
7515 		.call = parse_vc_conf,
7516 	},
7517 	[ACTION_MODIFY_FIELD_SRC_OFFSET] = {
7518 		.name = "src_offset",
7519 		.help = "source field bit offset",
7520 		.next = NEXT(action_modify_field_src,
7521 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7522 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7523 					src.offset)),
7524 		.call = parse_vc_conf,
7525 	},
7526 	[ACTION_MODIFY_FIELD_SRC_VALUE] = {
7527 		.name = "src_value",
7528 		.help = "source immediate value",
7529 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7530 			     NEXT_ENTRY(COMMON_HEX)),
7531 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
7532 			     ARGS_ENTRY_ARB(0, 0),
7533 			     ARGS_ENTRY(struct rte_flow_action_modify_field,
7534 					src.value)),
7535 		.call = parse_vc_conf,
7536 	},
7537 	[ACTION_MODIFY_FIELD_SRC_POINTER] = {
7538 		.name = "src_ptr",
7539 		.help = "pointer to source immediate value",
7540 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7541 			     NEXT_ENTRY(COMMON_HEX)),
7542 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7543 					src.pvalue),
7544 			     ARGS_ENTRY_ARB(0, 0),
7545 			     ARGS_ENTRY_ARB
7546 				(sizeof(struct rte_flow_action_modify_field),
7547 				 FLOW_FIELD_PATTERN_SIZE)),
7548 		.call = parse_vc_conf,
7549 	},
7550 	[ACTION_MODIFY_FIELD_WIDTH] = {
7551 		.name = "width",
7552 		.help = "number of bits to copy",
7553 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7554 			NEXT_ENTRY(COMMON_UNSIGNED)),
7555 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7556 					width)),
7557 		.call = parse_vc_conf,
7558 	},
7559 	[ACTION_SEND_TO_KERNEL] = {
7560 		.name = "send_to_kernel",
7561 		.help = "send packets to kernel",
7562 		.priv = PRIV_ACTION(SEND_TO_KERNEL, 0),
7563 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7564 		.call = parse_vc,
7565 	},
7566 	[ACTION_IPV6_EXT_REMOVE] = {
7567 		.name = "ipv6_ext_remove",
7568 		.help = "IPv6 extension type, defined by set ipv6_ext_remove",
7569 		.priv = PRIV_ACTION(IPV6_EXT_REMOVE,
7570 			sizeof(struct action_ipv6_ext_remove_data)),
7571 		.next = NEXT(action_ipv6_ext_remove),
7572 		.call = parse_vc_action_ipv6_ext_remove,
7573 	},
7574 	[ACTION_IPV6_EXT_REMOVE_INDEX] = {
7575 		.name = "index",
7576 		.help = "the index of ipv6_ext_remove",
7577 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_REMOVE_INDEX_VALUE)),
7578 	},
7579 	[ACTION_IPV6_EXT_REMOVE_INDEX_VALUE] = {
7580 		.name = "{index}",
7581 		.type = "UNSIGNED",
7582 		.help = "unsigned integer value",
7583 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7584 		.call = parse_vc_action_ipv6_ext_remove_index,
7585 		.comp = comp_set_ipv6_ext_index,
7586 	},
7587 	[ACTION_IPV6_EXT_PUSH] = {
7588 		.name = "ipv6_ext_push",
7589 		.help = "IPv6 extension data, defined by set ipv6_ext_push",
7590 		.priv = PRIV_ACTION(IPV6_EXT_PUSH,
7591 			sizeof(struct action_ipv6_ext_push_data)),
7592 		.next = NEXT(action_ipv6_ext_push),
7593 		.call = parse_vc_action_ipv6_ext_push,
7594 	},
7595 	[ACTION_IPV6_EXT_PUSH_INDEX] = {
7596 		.name = "index",
7597 		.help = "the index of ipv6_ext_push",
7598 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_PUSH_INDEX_VALUE)),
7599 	},
7600 	[ACTION_IPV6_EXT_PUSH_INDEX_VALUE] = {
7601 		.name = "{index}",
7602 		.type = "UNSIGNED",
7603 		.help = "unsigned integer value",
7604 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7605 		.call = parse_vc_action_ipv6_ext_push_index,
7606 		.comp = comp_set_ipv6_ext_index,
7607 	},
7608 	[ACTION_NAT64] = {
7609 		.name = "nat64",
7610 		.help = "NAT64 IP headers translation",
7611 		.priv = PRIV_ACTION(NAT64, sizeof(struct rte_flow_action_nat64)),
7612 		.next = NEXT(action_nat64),
7613 		.call = parse_vc,
7614 	},
7615 	[ACTION_NAT64_MODE] = {
7616 		.name = "type",
7617 		.help = "NAT64 translation type",
7618 		.next = NEXT(action_nat64, NEXT_ENTRY(COMMON_UNSIGNED)),
7619 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_nat64, type)),
7620 		.call = parse_vc_conf,
7621 	},
7622 	[ACTION_JUMP_TO_TABLE_INDEX] = {
7623 		.name = "jump_to_table_index",
7624 		.help = "Jump to table index",
7625 		.priv = PRIV_ACTION(JUMP_TO_TABLE_INDEX,
7626 				    sizeof(struct rte_flow_action_jump_to_table_index)),
7627 		.next = NEXT(action_jump_to_table_index),
7628 		.call = parse_vc,
7629 	},
7630 	[ACTION_JUMP_TO_TABLE_INDEX_TABLE] = {
7631 		.name = "table",
7632 		.help = "table to redirect traffic to",
7633 		.next = NEXT(action_jump_to_table_index, NEXT_ENTRY(COMMON_UNSIGNED)),
7634 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump_to_table_index, table)),
7635 		.call = parse_vc_conf,
7636 	},
7637 	[ACTION_JUMP_TO_TABLE_INDEX_INDEX] = {
7638 		.name = "index",
7639 		.help = "rule index to redirect traffic to",
7640 		.next = NEXT(action_jump_to_table_index, NEXT_ENTRY(COMMON_UNSIGNED)),
7641 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump_to_table_index, index)),
7642 		.call = parse_vc_conf,
7643 	},
7644 
7645 	/* Top level command. */
7646 	[SET] = {
7647 		.name = "set",
7648 		.help = "set raw encap/decap/sample data",
7649 		.type = "set raw_encap|raw_decap <index> <pattern>"
7650 				" or set sample_actions <index> <action>",
7651 		.next = NEXT(NEXT_ENTRY
7652 			     (SET_RAW_ENCAP,
7653 			      SET_RAW_DECAP,
7654 			      SET_SAMPLE_ACTIONS,
7655 			      SET_IPV6_EXT_REMOVE,
7656 			      SET_IPV6_EXT_PUSH)),
7657 		.call = parse_set_init,
7658 	},
7659 	/* Sub-level commands. */
7660 	[SET_RAW_ENCAP] = {
7661 		.name = "raw_encap",
7662 		.help = "set raw encap data",
7663 		.next = NEXT(next_set_raw),
7664 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7665 				(offsetof(struct buffer, port),
7666 				 sizeof(((struct buffer *)0)->port),
7667 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7668 		.call = parse_set_raw_encap_decap,
7669 	},
7670 	[SET_RAW_DECAP] = {
7671 		.name = "raw_decap",
7672 		.help = "set raw decap data",
7673 		.next = NEXT(next_set_raw),
7674 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7675 				(offsetof(struct buffer, port),
7676 				 sizeof(((struct buffer *)0)->port),
7677 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7678 		.call = parse_set_raw_encap_decap,
7679 	},
7680 	[SET_RAW_INDEX] = {
7681 		.name = "{index}",
7682 		.type = "COMMON_UNSIGNED",
7683 		.help = "index of raw_encap/raw_decap data",
7684 		.next = NEXT(next_item),
7685 		.call = parse_port,
7686 	},
7687 	[SET_SAMPLE_INDEX] = {
7688 		.name = "{index}",
7689 		.type = "UNSIGNED",
7690 		.help = "index of sample actions",
7691 		.next = NEXT(next_action_sample),
7692 		.call = parse_port,
7693 	},
7694 	[SET_SAMPLE_ACTIONS] = {
7695 		.name = "sample_actions",
7696 		.help = "set sample actions list",
7697 		.next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
7698 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7699 				(offsetof(struct buffer, port),
7700 				 sizeof(((struct buffer *)0)->port),
7701 				 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
7702 		.call = parse_set_sample_action,
7703 	},
7704 	[SET_IPV6_EXT_PUSH] = {
7705 		.name = "ipv6_ext_push",
7706 		.help = "set IPv6 extension header",
7707 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7708 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7709 				(offsetof(struct buffer, port),
7710 				 sizeof(((struct buffer *)0)->port),
7711 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7712 		.call = parse_set_ipv6_ext_action,
7713 	},
7714 	[SET_IPV6_EXT_REMOVE] = {
7715 		.name = "ipv6_ext_remove",
7716 		.help = "set IPv6 extension header",
7717 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7718 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7719 				(offsetof(struct buffer, port),
7720 				 sizeof(((struct buffer *)0)->port),
7721 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7722 		.call = parse_set_ipv6_ext_action,
7723 	},
7724 	[SET_IPV6_EXT_INDEX] = {
7725 		.name = "{index}",
7726 		.type = "UNSIGNED",
7727 		.help = "index of ipv6 extension push/remove actions",
7728 		.next = NEXT(item_ipv6_push_ext),
7729 		.call = parse_port,
7730 	},
7731 	[ITEM_IPV6_PUSH_REMOVE_EXT] = {
7732 		.name = "ipv6_ext",
7733 		.help = "set IPv6 extension header",
7734 		.priv = PRIV_ITEM(IPV6_EXT,
7735 				  sizeof(struct rte_flow_item_ipv6_ext)),
7736 		.next = NEXT(item_ipv6_push_ext_type),
7737 		.call = parse_vc,
7738 	},
7739 	[ITEM_IPV6_PUSH_REMOVE_EXT_TYPE] = {
7740 		.name = "type",
7741 		.help = "set IPv6 extension type",
7742 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
7743 					     next_hdr)),
7744 		.next = NEXT(item_ipv6_push_ext_header, NEXT_ENTRY(COMMON_UNSIGNED),
7745 			     item_param),
7746 	},
7747 	[ACTION_SET_TAG] = {
7748 		.name = "set_tag",
7749 		.help = "set tag",
7750 		.priv = PRIV_ACTION(SET_TAG,
7751 			sizeof(struct rte_flow_action_set_tag)),
7752 		.next = NEXT(action_set_tag),
7753 		.call = parse_vc,
7754 	},
7755 	[ACTION_SET_TAG_INDEX] = {
7756 		.name = "index",
7757 		.help = "index of tag array",
7758 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7759 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
7760 		.call = parse_vc_conf,
7761 	},
7762 	[ACTION_SET_TAG_DATA] = {
7763 		.name = "data",
7764 		.help = "tag value",
7765 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7766 		.args = ARGS(ARGS_ENTRY
7767 			     (struct rte_flow_action_set_tag, data)),
7768 		.call = parse_vc_conf,
7769 	},
7770 	[ACTION_SET_TAG_MASK] = {
7771 		.name = "mask",
7772 		.help = "mask for tag value",
7773 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7774 		.args = ARGS(ARGS_ENTRY
7775 			     (struct rte_flow_action_set_tag, mask)),
7776 		.call = parse_vc_conf,
7777 	},
7778 	[ACTION_SET_META] = {
7779 		.name = "set_meta",
7780 		.help = "set metadata",
7781 		.priv = PRIV_ACTION(SET_META,
7782 			sizeof(struct rte_flow_action_set_meta)),
7783 		.next = NEXT(action_set_meta),
7784 		.call = parse_vc_action_set_meta,
7785 	},
7786 	[ACTION_SET_META_DATA] = {
7787 		.name = "data",
7788 		.help = "metadata value",
7789 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7790 		.args = ARGS(ARGS_ENTRY
7791 			     (struct rte_flow_action_set_meta, data)),
7792 		.call = parse_vc_conf,
7793 	},
7794 	[ACTION_SET_META_MASK] = {
7795 		.name = "mask",
7796 		.help = "mask for metadata value",
7797 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7798 		.args = ARGS(ARGS_ENTRY
7799 			     (struct rte_flow_action_set_meta, mask)),
7800 		.call = parse_vc_conf,
7801 	},
7802 	[ACTION_SET_IPV4_DSCP] = {
7803 		.name = "set_ipv4_dscp",
7804 		.help = "set DSCP value",
7805 		.priv = PRIV_ACTION(SET_IPV4_DSCP,
7806 			sizeof(struct rte_flow_action_set_dscp)),
7807 		.next = NEXT(action_set_ipv4_dscp),
7808 		.call = parse_vc,
7809 	},
7810 	[ACTION_SET_IPV4_DSCP_VALUE] = {
7811 		.name = "dscp_value",
7812 		.help = "new IPv4 DSCP value to set",
7813 		.next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7814 		.args = ARGS(ARGS_ENTRY
7815 			     (struct rte_flow_action_set_dscp, dscp)),
7816 		.call = parse_vc_conf,
7817 	},
7818 	[ACTION_SET_IPV6_DSCP] = {
7819 		.name = "set_ipv6_dscp",
7820 		.help = "set DSCP value",
7821 		.priv = PRIV_ACTION(SET_IPV6_DSCP,
7822 			sizeof(struct rte_flow_action_set_dscp)),
7823 		.next = NEXT(action_set_ipv6_dscp),
7824 		.call = parse_vc,
7825 	},
7826 	[ACTION_SET_IPV6_DSCP_VALUE] = {
7827 		.name = "dscp_value",
7828 		.help = "new IPv6 DSCP value to set",
7829 		.next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7830 		.args = ARGS(ARGS_ENTRY
7831 			     (struct rte_flow_action_set_dscp, dscp)),
7832 		.call = parse_vc_conf,
7833 	},
7834 	[ACTION_AGE] = {
7835 		.name = "age",
7836 		.help = "set a specific metadata header",
7837 		.next = NEXT(action_age),
7838 		.priv = PRIV_ACTION(AGE,
7839 			sizeof(struct rte_flow_action_age)),
7840 		.call = parse_vc,
7841 	},
7842 	[ACTION_AGE_TIMEOUT] = {
7843 		.name = "timeout",
7844 		.help = "flow age timeout value",
7845 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
7846 					   timeout, 24)),
7847 		.next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
7848 		.call = parse_vc_conf,
7849 	},
7850 	[ACTION_AGE_UPDATE] = {
7851 		.name = "age_update",
7852 		.help = "update aging parameter",
7853 		.next = NEXT(action_age_update),
7854 		.priv = PRIV_ACTION(AGE,
7855 				    sizeof(struct rte_flow_update_age)),
7856 		.call = parse_vc,
7857 	},
7858 	[ACTION_AGE_UPDATE_TIMEOUT] = {
7859 		.name = "timeout",
7860 		.help = "age timeout update value",
7861 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7862 					   timeout, 24)),
7863 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_UNSIGNED)),
7864 		.call = parse_vc_conf_timeout,
7865 	},
7866 	[ACTION_AGE_UPDATE_TOUCH] = {
7867 		.name = "touch",
7868 		.help = "this flow is touched",
7869 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_BOOLEAN)),
7870 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7871 					   touch, 1)),
7872 		.call = parse_vc_conf,
7873 	},
7874 	[ACTION_SAMPLE] = {
7875 		.name = "sample",
7876 		.help = "set a sample action",
7877 		.next = NEXT(action_sample),
7878 		.priv = PRIV_ACTION(SAMPLE,
7879 			sizeof(struct action_sample_data)),
7880 		.call = parse_vc_action_sample,
7881 	},
7882 	[ACTION_SAMPLE_RATIO] = {
7883 		.name = "ratio",
7884 		.help = "flow sample ratio value",
7885 		.next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
7886 		.args = ARGS(ARGS_ENTRY_ARB
7887 			     (offsetof(struct action_sample_data, conf) +
7888 			      offsetof(struct rte_flow_action_sample, ratio),
7889 			      sizeof(((struct rte_flow_action_sample *)0)->
7890 				     ratio))),
7891 	},
7892 	[ACTION_SAMPLE_INDEX] = {
7893 		.name = "index",
7894 		.help = "the index of sample actions list",
7895 		.next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
7896 	},
7897 	[ACTION_SAMPLE_INDEX_VALUE] = {
7898 		.name = "{index}",
7899 		.type = "COMMON_UNSIGNED",
7900 		.help = "unsigned integer value",
7901 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7902 		.call = parse_vc_action_sample_index,
7903 		.comp = comp_set_sample_index,
7904 	},
7905 	[ACTION_CONNTRACK] = {
7906 		.name = "conntrack",
7907 		.help = "create a conntrack object",
7908 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7909 		.priv = PRIV_ACTION(CONNTRACK,
7910 				    sizeof(struct rte_flow_action_conntrack)),
7911 		.call = parse_vc,
7912 	},
7913 	[ACTION_CONNTRACK_UPDATE] = {
7914 		.name = "conntrack_update",
7915 		.help = "update a conntrack object",
7916 		.next = NEXT(action_update_conntrack),
7917 		.priv = PRIV_ACTION(CONNTRACK,
7918 				    sizeof(struct rte_flow_modify_conntrack)),
7919 		.call = parse_vc,
7920 	},
7921 	[ACTION_CONNTRACK_UPDATE_DIR] = {
7922 		.name = "dir",
7923 		.help = "update a conntrack object direction",
7924 		.next = NEXT(action_update_conntrack),
7925 		.call = parse_vc_action_conntrack_update,
7926 	},
7927 	[ACTION_CONNTRACK_UPDATE_CTX] = {
7928 		.name = "ctx",
7929 		.help = "update a conntrack object context",
7930 		.next = NEXT(action_update_conntrack),
7931 		.call = parse_vc_action_conntrack_update,
7932 	},
7933 	[ACTION_PORT_REPRESENTOR] = {
7934 		.name = "port_representor",
7935 		.help = "at embedded switch level, send matching traffic to the given ethdev",
7936 		.priv = PRIV_ACTION(PORT_REPRESENTOR,
7937 				    sizeof(struct rte_flow_action_ethdev)),
7938 		.next = NEXT(action_port_representor),
7939 		.call = parse_vc,
7940 	},
7941 	[ACTION_PORT_REPRESENTOR_PORT_ID] = {
7942 		.name = "port_id",
7943 		.help = "ethdev port ID",
7944 		.next = NEXT(action_port_representor,
7945 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7946 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7947 					port_id)),
7948 		.call = parse_vc_conf,
7949 	},
7950 	[ACTION_REPRESENTED_PORT] = {
7951 		.name = "represented_port",
7952 		.help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
7953 		.priv = PRIV_ACTION(REPRESENTED_PORT,
7954 				sizeof(struct rte_flow_action_ethdev)),
7955 		.next = NEXT(action_represented_port),
7956 		.call = parse_vc,
7957 	},
7958 	[ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
7959 		.name = "ethdev_port_id",
7960 		.help = "ethdev port ID",
7961 		.next = NEXT(action_represented_port,
7962 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7963 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7964 					port_id)),
7965 		.call = parse_vc_conf,
7966 	},
7967 	/* Indirect action destroy arguments. */
7968 	[INDIRECT_ACTION_DESTROY_ID] = {
7969 		.name = "action_id",
7970 		.help = "specify a indirect action id to destroy",
7971 		.next = NEXT(next_ia_destroy_attr,
7972 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7973 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
7974 					    args.ia_destroy.action_id)),
7975 		.call = parse_ia_destroy,
7976 	},
7977 	/* Indirect action create arguments. */
7978 	[INDIRECT_ACTION_CREATE_ID] = {
7979 		.name = "action_id",
7980 		.help = "specify a indirect action id to create",
7981 		.next = NEXT(next_ia_create_attr,
7982 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7983 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
7984 	},
7985 	[ACTION_INDIRECT] = {
7986 		.name = "indirect",
7987 		.help = "apply indirect action by id",
7988 		.priv = PRIV_ACTION(INDIRECT, 0),
7989 		.next = NEXT(next_ia),
7990 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7991 		.call = parse_vc,
7992 	},
7993 	[ACTION_INDIRECT_LIST] = {
7994 		.name = "indirect_list",
7995 		.help = "apply indirect list action by id",
7996 		.priv = PRIV_ACTION(INDIRECT_LIST,
7997 				    sizeof(struct
7998 					   rte_flow_action_indirect_list)),
7999 		.next = NEXT(next_ial),
8000 		.call = parse_vc,
8001 	},
8002 	[ACTION_INDIRECT_LIST_HANDLE] = {
8003 		.name = "handle",
8004 		.help = "indirect list handle",
8005 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_HANDLE)),
8006 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
8007 	},
8008 	[ACTION_INDIRECT_LIST_CONF] = {
8009 		.name = "conf",
8010 		.help = "indirect list configuration",
8011 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_CONF)),
8012 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
8013 	},
8014 	[INDIRECT_LIST_ACTION_ID2PTR_HANDLE] = {
8015 		.type = "UNSIGNED",
8016 		.help = "unsigned integer value",
8017 		.call = parse_indlst_id2ptr,
8018 		.comp = comp_none,
8019 	},
8020 	[INDIRECT_LIST_ACTION_ID2PTR_CONF] = {
8021 		.type = "UNSIGNED",
8022 		.help = "unsigned integer value",
8023 		.call = parse_indlst_id2ptr,
8024 		.comp = comp_none,
8025 	},
8026 	[ACTION_SHARED_INDIRECT] = {
8027 		.name = "shared_indirect",
8028 		.help = "apply indirect action by id and port",
8029 		.priv = PRIV_ACTION(INDIRECT, 0),
8030 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_PORT)),
8031 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t)),
8032 			     ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
8033 		.call = parse_vc,
8034 	},
8035 	[INDIRECT_ACTION_PORT] = {
8036 		.name = "{indirect_action_port}",
8037 		.type = "INDIRECT_ACTION_PORT",
8038 		.help = "indirect action port",
8039 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
8040 		.call = parse_ia_port,
8041 		.comp = comp_none,
8042 	},
8043 	[INDIRECT_ACTION_ID2PTR] = {
8044 		.name = "{action_id}",
8045 		.type = "INDIRECT_ACTION_ID",
8046 		.help = "indirect action id",
8047 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
8048 		.call = parse_ia_id2ptr,
8049 		.comp = comp_none,
8050 	},
8051 	[INDIRECT_ACTION_INGRESS] = {
8052 		.name = "ingress",
8053 		.help = "affect rule to ingress",
8054 		.next = NEXT(next_ia_create_attr),
8055 		.call = parse_ia,
8056 	},
8057 	[INDIRECT_ACTION_EGRESS] = {
8058 		.name = "egress",
8059 		.help = "affect rule to egress",
8060 		.next = NEXT(next_ia_create_attr),
8061 		.call = parse_ia,
8062 	},
8063 	[INDIRECT_ACTION_TRANSFER] = {
8064 		.name = "transfer",
8065 		.help = "affect rule to transfer",
8066 		.next = NEXT(next_ia_create_attr),
8067 		.call = parse_ia,
8068 	},
8069 	[INDIRECT_ACTION_SPEC] = {
8070 		.name = "action",
8071 		.help = "specify action to create indirect handle",
8072 		.next = NEXT(next_action),
8073 	},
8074 	[INDIRECT_ACTION_LIST] = {
8075 		.name = "list",
8076 		.help = "specify actions for indirect handle list",
8077 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
8078 		.call = parse_ia,
8079 	},
8080 	[INDIRECT_ACTION_FLOW_CONF] = {
8081 		.name = "flow_conf",
8082 		.help = "specify actions configuration for indirect handle list",
8083 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
8084 		.call = parse_ia,
8085 	},
8086 	[ACTION_POL_G] = {
8087 		.name = "g_actions",
8088 		.help = "submit a list of associated actions for green",
8089 		.next = NEXT(next_action),
8090 		.call = parse_mp,
8091 	},
8092 	[ACTION_POL_Y] = {
8093 		.name = "y_actions",
8094 		.help = "submit a list of associated actions for yellow",
8095 		.next = NEXT(next_action),
8096 	},
8097 	[ACTION_POL_R] = {
8098 		.name = "r_actions",
8099 		.help = "submit a list of associated actions for red",
8100 		.next = NEXT(next_action),
8101 	},
8102 	[ACTION_QUOTA_CREATE] = {
8103 		.name = "quota_create",
8104 		.help = "create quota action",
8105 		.priv = PRIV_ACTION(QUOTA,
8106 				    sizeof(struct rte_flow_action_quota)),
8107 		.next = NEXT(action_quota_create),
8108 		.call = parse_vc
8109 	},
8110 	[ACTION_QUOTA_CREATE_LIMIT] = {
8111 		.name = "limit",
8112 		.help = "quota limit",
8113 		.next = NEXT(action_quota_create, NEXT_ENTRY(COMMON_UNSIGNED)),
8114 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, quota)),
8115 		.call = parse_vc_conf
8116 	},
8117 	[ACTION_QUOTA_CREATE_MODE] = {
8118 		.name = "mode",
8119 		.help = "quota mode",
8120 		.next = NEXT(action_quota_create,
8121 			     NEXT_ENTRY(ACTION_QUOTA_CREATE_MODE_NAME)),
8122 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, mode)),
8123 		.call = parse_vc_conf
8124 	},
8125 	[ACTION_QUOTA_CREATE_MODE_NAME] = {
8126 		.name = "mode_name",
8127 		.help = "quota mode name",
8128 		.call = parse_quota_mode_name,
8129 		.comp = comp_quota_mode_name
8130 	},
8131 	[ACTION_QUOTA_QU] = {
8132 		.name = "quota_update",
8133 		.help = "update quota action",
8134 		.priv = PRIV_ACTION(QUOTA,
8135 				    sizeof(struct rte_flow_update_quota)),
8136 		.next = NEXT(action_quota_update),
8137 		.call = parse_vc
8138 	},
8139 	[ACTION_QUOTA_QU_LIMIT] = {
8140 		.name = "limit",
8141 		.help = "quota limit",
8142 		.next = NEXT(action_quota_update, NEXT_ENTRY(COMMON_UNSIGNED)),
8143 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, quota)),
8144 		.call = parse_vc_conf
8145 	},
8146 	[ACTION_QUOTA_QU_UPDATE_OP] = {
8147 		.name = "update_op",
8148 		.help = "query update op SET|ADD",
8149 		.next = NEXT(action_quota_update,
8150 			     NEXT_ENTRY(ACTION_QUOTA_QU_UPDATE_OP_NAME)),
8151 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, op)),
8152 		.call = parse_vc_conf
8153 	},
8154 	[ACTION_QUOTA_QU_UPDATE_OP_NAME] = {
8155 		.name = "update_op_name",
8156 		.help = "quota update op name",
8157 		.call = parse_quota_update_name,
8158 		.comp = comp_quota_update_name
8159 	},
8160 
8161 	/* Top-level command. */
8162 	[ADD] = {
8163 		.name = "add",
8164 		.type = "port meter policy {port_id} {arg}",
8165 		.help = "add port meter policy",
8166 		.next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
8167 		.call = parse_init,
8168 	},
8169 	/* Sub-level commands. */
8170 	[ITEM_POL_PORT] = {
8171 		.name = "port",
8172 		.help = "add port meter policy",
8173 		.next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
8174 	},
8175 	[ITEM_POL_METER] = {
8176 		.name = "meter",
8177 		.help = "add port meter policy",
8178 		.next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
8179 	},
8180 	[ITEM_POL_POLICY] = {
8181 		.name = "policy",
8182 		.help = "add port meter policy",
8183 		.next = NEXT(NEXT_ENTRY(ACTION_POL_R),
8184 				NEXT_ENTRY(ACTION_POL_Y),
8185 				NEXT_ENTRY(ACTION_POL_G),
8186 				NEXT_ENTRY(COMMON_POLICY_ID),
8187 				NEXT_ENTRY(COMMON_PORT_ID)),
8188 		.args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
8189 				ARGS_ENTRY(struct buffer, port)),
8190 		.call = parse_mp,
8191 	},
8192 	[ITEM_AGGR_AFFINITY] = {
8193 		.name = "aggr_affinity",
8194 		.help = "match on the aggregated port receiving the packets",
8195 		.priv = PRIV_ITEM(AGGR_AFFINITY,
8196 				  sizeof(struct rte_flow_item_aggr_affinity)),
8197 		.next = NEXT(item_aggr_affinity),
8198 		.call = parse_vc,
8199 	},
8200 	[ITEM_AGGR_AFFINITY_VALUE] = {
8201 		.name = "affinity",
8202 		.help = "aggregated affinity value",
8203 		.next = NEXT(item_aggr_affinity, NEXT_ENTRY(COMMON_UNSIGNED),
8204 			     item_param),
8205 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_aggr_affinity,
8206 					affinity)),
8207 	},
8208 	[ITEM_TX_QUEUE] = {
8209 		.name = "tx_queue",
8210 		.help = "match on the tx queue of send packet",
8211 		.priv = PRIV_ITEM(TX_QUEUE,
8212 				  sizeof(struct rte_flow_item_tx_queue)),
8213 		.next = NEXT(item_tx_queue),
8214 		.call = parse_vc,
8215 	},
8216 	[ITEM_TX_QUEUE_VALUE] = {
8217 		.name = "tx_queue_value",
8218 		.help = "tx queue value",
8219 		.next = NEXT(item_tx_queue, NEXT_ENTRY(COMMON_UNSIGNED),
8220 			     item_param),
8221 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tx_queue,
8222 					tx_queue)),
8223 	},
8224 };
8225 
8226 /** Remove and return last entry from argument stack. */
8227 static const struct arg *
8228 pop_args(struct context *ctx)
8229 {
8230 	return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
8231 }
8232 
8233 /** Add entry on top of the argument stack. */
8234 static int
8235 push_args(struct context *ctx, const struct arg *arg)
8236 {
8237 	if (ctx->args_num == CTX_STACK_SIZE)
8238 		return -1;
8239 	ctx->args[ctx->args_num++] = arg;
8240 	return 0;
8241 }
8242 
8243 /** Spread value into buffer according to bit-mask. */
8244 static size_t
8245 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
8246 {
8247 	uint32_t i = arg->size;
8248 	uint32_t end = 0;
8249 	int sub = 1;
8250 	int add = 0;
8251 	size_t len = 0;
8252 
8253 	if (!arg->mask)
8254 		return 0;
8255 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8256 	if (!arg->hton) {
8257 		i = 0;
8258 		end = arg->size;
8259 		sub = 0;
8260 		add = 1;
8261 	}
8262 #endif
8263 	while (i != end) {
8264 		unsigned int shift = 0;
8265 		uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
8266 
8267 		for (shift = 0; arg->mask[i] >> shift; ++shift) {
8268 			if (!(arg->mask[i] & (1 << shift)))
8269 				continue;
8270 			++len;
8271 			if (!dst)
8272 				continue;
8273 			*buf &= ~(1 << shift);
8274 			*buf |= (val & 1) << shift;
8275 			val >>= 1;
8276 		}
8277 		i += add;
8278 	}
8279 	return len;
8280 }
8281 
8282 /** Compare a string with a partial one of a given length. */
8283 static int
8284 strcmp_partial(const char *full, const char *partial, size_t partial_len)
8285 {
8286 	int r = strncmp(full, partial, partial_len);
8287 
8288 	if (r)
8289 		return r;
8290 	if (strlen(full) <= partial_len)
8291 		return 0;
8292 	return full[partial_len];
8293 }
8294 
8295 /**
8296  * Parse a prefix length and generate a bit-mask.
8297  *
8298  * Last argument (ctx->args) is retrieved to determine mask size, storage
8299  * location and whether the result must use network byte ordering.
8300  */
8301 static int
8302 parse_prefix(struct context *ctx, const struct token *token,
8303 	     const char *str, unsigned int len,
8304 	     void *buf, unsigned int size)
8305 {
8306 	const struct arg *arg = pop_args(ctx);
8307 	static const uint8_t conv[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0,
8308 					0xf8, 0xfc, 0xfe, 0xff };
8309 	char *end;
8310 	uintmax_t u;
8311 	unsigned int bytes;
8312 	unsigned int extra;
8313 
8314 	(void)token;
8315 	/* Argument is expected. */
8316 	if (!arg)
8317 		return -1;
8318 	errno = 0;
8319 	u = strtoumax(str, &end, 0);
8320 	if (errno || (size_t)(end - str) != len)
8321 		goto error;
8322 	if (arg->mask) {
8323 		uintmax_t v = 0;
8324 
8325 		extra = arg_entry_bf_fill(NULL, 0, arg);
8326 		if (u > extra)
8327 			goto error;
8328 		if (!ctx->object)
8329 			return len;
8330 		extra -= u;
8331 		while (u--)
8332 			(v <<= 1, v |= 1);
8333 		v <<= extra;
8334 		if (!arg_entry_bf_fill(ctx->object, v, arg) ||
8335 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
8336 			goto error;
8337 		return len;
8338 	}
8339 	bytes = u / 8;
8340 	extra = u % 8;
8341 	size = arg->size;
8342 	if (bytes > size || bytes + !!extra > size)
8343 		goto error;
8344 	if (!ctx->object)
8345 		return len;
8346 	buf = (uint8_t *)ctx->object + arg->offset;
8347 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8348 	if (!arg->hton) {
8349 		memset((uint8_t *)buf + size - bytes, 0xff, bytes);
8350 		memset(buf, 0x00, size - bytes);
8351 		if (extra)
8352 			((uint8_t *)buf)[size - bytes - 1] = conv[extra];
8353 	} else
8354 #endif
8355 	{
8356 		memset(buf, 0xff, bytes);
8357 		memset((uint8_t *)buf + bytes, 0x00, size - bytes);
8358 		if (extra)
8359 			((uint8_t *)buf)[bytes] = conv[extra];
8360 	}
8361 	if (ctx->objmask)
8362 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8363 	return len;
8364 error:
8365 	push_args(ctx, arg);
8366 	return -1;
8367 }
8368 
8369 /** Default parsing function for token name matching. */
8370 static int
8371 parse_default(struct context *ctx, const struct token *token,
8372 	      const char *str, unsigned int len,
8373 	      void *buf, unsigned int size)
8374 {
8375 	(void)ctx;
8376 	(void)buf;
8377 	(void)size;
8378 	if (strcmp_partial(token->name, str, len))
8379 		return -1;
8380 	return len;
8381 }
8382 
8383 /** Parse flow command, initialize output buffer for subsequent tokens. */
8384 static int
8385 parse_init(struct context *ctx, const struct token *token,
8386 	   const char *str, unsigned int len,
8387 	   void *buf, unsigned int size)
8388 {
8389 	struct buffer *out = buf;
8390 
8391 	/* Token name must match. */
8392 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8393 		return -1;
8394 	/* Nothing else to do if there is no buffer. */
8395 	if (!out)
8396 		return len;
8397 	/* Make sure buffer is large enough. */
8398 	if (size < sizeof(*out))
8399 		return -1;
8400 	/* Initialize buffer. */
8401 	memset(out, 0x00, sizeof(*out));
8402 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
8403 	ctx->objdata = 0;
8404 	ctx->object = out;
8405 	ctx->objmask = NULL;
8406 	return len;
8407 }
8408 
8409 /** Parse tokens for indirect action commands. */
8410 static int
8411 parse_ia(struct context *ctx, const struct token *token,
8412 	 const char *str, unsigned int len,
8413 	 void *buf, unsigned int size)
8414 {
8415 	struct buffer *out = buf;
8416 
8417 	/* Token name must match. */
8418 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8419 		return -1;
8420 	/* Nothing else to do if there is no buffer. */
8421 	if (!out)
8422 		return len;
8423 	if (!out->command) {
8424 		if (ctx->curr != INDIRECT_ACTION)
8425 			return -1;
8426 		if (sizeof(*out) > size)
8427 			return -1;
8428 		out->command = ctx->curr;
8429 		ctx->objdata = 0;
8430 		ctx->object = out;
8431 		ctx->objmask = NULL;
8432 		out->args.vc.data = (uint8_t *)out + size;
8433 		return len;
8434 	}
8435 	switch (ctx->curr) {
8436 	case INDIRECT_ACTION_CREATE:
8437 	case INDIRECT_ACTION_UPDATE:
8438 	case INDIRECT_ACTION_QUERY_UPDATE:
8439 		out->args.vc.actions =
8440 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8441 					       sizeof(double));
8442 		out->args.vc.attr.group = UINT32_MAX;
8443 		/* fallthrough */
8444 	case INDIRECT_ACTION_QUERY:
8445 		out->command = ctx->curr;
8446 		ctx->objdata = 0;
8447 		ctx->object = out;
8448 		ctx->objmask = NULL;
8449 		return len;
8450 	case INDIRECT_ACTION_EGRESS:
8451 		out->args.vc.attr.egress = 1;
8452 		return len;
8453 	case INDIRECT_ACTION_INGRESS:
8454 		out->args.vc.attr.ingress = 1;
8455 		return len;
8456 	case INDIRECT_ACTION_TRANSFER:
8457 		out->args.vc.attr.transfer = 1;
8458 		return len;
8459 	case INDIRECT_ACTION_QU_MODE:
8460 		return len;
8461 	case INDIRECT_ACTION_LIST:
8462 		out->command = INDIRECT_ACTION_LIST_CREATE;
8463 		return len;
8464 	case INDIRECT_ACTION_FLOW_CONF:
8465 		out->command = INDIRECT_ACTION_FLOW_CONF_CREATE;
8466 		return len;
8467 	default:
8468 		return -1;
8469 	}
8470 }
8471 
8472 
8473 /** Parse tokens for indirect action destroy command. */
8474 static int
8475 parse_ia_destroy(struct context *ctx, const struct token *token,
8476 		 const char *str, unsigned int len,
8477 		 void *buf, unsigned int size)
8478 {
8479 	struct buffer *out = buf;
8480 	uint32_t *action_id;
8481 
8482 	/* Token name must match. */
8483 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8484 		return -1;
8485 	/* Nothing else to do if there is no buffer. */
8486 	if (!out)
8487 		return len;
8488 	if (!out->command || out->command == INDIRECT_ACTION) {
8489 		if (ctx->curr != INDIRECT_ACTION_DESTROY)
8490 			return -1;
8491 		if (sizeof(*out) > size)
8492 			return -1;
8493 		out->command = ctx->curr;
8494 		ctx->objdata = 0;
8495 		ctx->object = out;
8496 		ctx->objmask = NULL;
8497 		out->args.ia_destroy.action_id =
8498 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8499 					       sizeof(double));
8500 		return len;
8501 	}
8502 	action_id = out->args.ia_destroy.action_id
8503 		    + out->args.ia_destroy.action_id_n++;
8504 	if ((uint8_t *)action_id > (uint8_t *)out + size)
8505 		return -1;
8506 	ctx->objdata = 0;
8507 	ctx->object = action_id;
8508 	ctx->objmask = NULL;
8509 	return len;
8510 }
8511 
8512 /** Parse tokens for indirect action commands. */
8513 static int
8514 parse_qia(struct context *ctx, const struct token *token,
8515 	  const char *str, unsigned int len,
8516 	  void *buf, unsigned int size)
8517 {
8518 	struct buffer *out = buf;
8519 
8520 	/* Token name must match. */
8521 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8522 		return -1;
8523 	/* Nothing else to do if there is no buffer. */
8524 	if (!out)
8525 		return len;
8526 	if (!out->command) {
8527 		if (ctx->curr != QUEUE)
8528 			return -1;
8529 		if (sizeof(*out) > size)
8530 			return -1;
8531 		out->args.vc.data = (uint8_t *)out + size;
8532 		return len;
8533 	}
8534 	switch (ctx->curr) {
8535 	case QUEUE_INDIRECT_ACTION:
8536 		return len;
8537 	case QUEUE_INDIRECT_ACTION_CREATE:
8538 	case QUEUE_INDIRECT_ACTION_UPDATE:
8539 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
8540 		out->args.vc.actions =
8541 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8542 					       sizeof(double));
8543 		out->args.vc.attr.group = UINT32_MAX;
8544 		/* fallthrough */
8545 	case QUEUE_INDIRECT_ACTION_QUERY:
8546 		out->command = ctx->curr;
8547 		ctx->objdata = 0;
8548 		ctx->object = out;
8549 		ctx->objmask = NULL;
8550 		return len;
8551 	case QUEUE_INDIRECT_ACTION_EGRESS:
8552 		out->args.vc.attr.egress = 1;
8553 		return len;
8554 	case QUEUE_INDIRECT_ACTION_INGRESS:
8555 		out->args.vc.attr.ingress = 1;
8556 		return len;
8557 	case QUEUE_INDIRECT_ACTION_TRANSFER:
8558 		out->args.vc.attr.transfer = 1;
8559 		return len;
8560 	case QUEUE_INDIRECT_ACTION_CREATE_POSTPONE:
8561 		return len;
8562 	case QUEUE_INDIRECT_ACTION_QU_MODE:
8563 		return len;
8564 	case QUEUE_INDIRECT_ACTION_LIST:
8565 		out->command = QUEUE_INDIRECT_ACTION_LIST_CREATE;
8566 		return len;
8567 	default:
8568 		return -1;
8569 	}
8570 }
8571 
8572 /** Parse tokens for indirect action destroy command. */
8573 static int
8574 parse_qia_destroy(struct context *ctx, const struct token *token,
8575 		  const char *str, unsigned int len,
8576 		  void *buf, unsigned int size)
8577 {
8578 	struct buffer *out = buf;
8579 	uint32_t *action_id;
8580 
8581 	/* Token name must match. */
8582 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8583 		return -1;
8584 	/* Nothing else to do if there is no buffer. */
8585 	if (!out)
8586 		return len;
8587 	if (!out->command || out->command == QUEUE) {
8588 		if (ctx->curr != QUEUE_INDIRECT_ACTION_DESTROY)
8589 			return -1;
8590 		if (sizeof(*out) > size)
8591 			return -1;
8592 		out->command = ctx->curr;
8593 		ctx->objdata = 0;
8594 		ctx->object = out;
8595 		ctx->objmask = NULL;
8596 		out->args.ia_destroy.action_id =
8597 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8598 					       sizeof(double));
8599 		return len;
8600 	}
8601 	switch (ctx->curr) {
8602 	case QUEUE_INDIRECT_ACTION:
8603 		out->command = ctx->curr;
8604 		ctx->objdata = 0;
8605 		ctx->object = out;
8606 		ctx->objmask = NULL;
8607 		return len;
8608 	case QUEUE_INDIRECT_ACTION_DESTROY_ID:
8609 		action_id = out->args.ia_destroy.action_id
8610 				+ out->args.ia_destroy.action_id_n++;
8611 		if ((uint8_t *)action_id > (uint8_t *)out + size)
8612 			return -1;
8613 		ctx->objdata = 0;
8614 		ctx->object = action_id;
8615 		ctx->objmask = NULL;
8616 		return len;
8617 	case QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE:
8618 		return len;
8619 	default:
8620 		return -1;
8621 	}
8622 }
8623 
8624 /** Parse tokens for meter policy action commands. */
8625 static int
8626 parse_mp(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 
8632 	/* Token name must match. */
8633 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8634 		return -1;
8635 	/* Nothing else to do if there is no buffer. */
8636 	if (!out)
8637 		return len;
8638 	if (!out->command) {
8639 		if (ctx->curr != ITEM_POL_POLICY)
8640 			return -1;
8641 		if (sizeof(*out) > size)
8642 			return -1;
8643 		out->command = ctx->curr;
8644 		ctx->objdata = 0;
8645 		ctx->object = out;
8646 		ctx->objmask = NULL;
8647 		out->args.vc.data = (uint8_t *)out + size;
8648 		return len;
8649 	}
8650 	switch (ctx->curr) {
8651 	case ACTION_POL_G:
8652 		out->args.vc.actions =
8653 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8654 					sizeof(double));
8655 		out->command = ctx->curr;
8656 		ctx->objdata = 0;
8657 		ctx->object = out;
8658 		ctx->objmask = NULL;
8659 		return len;
8660 	default:
8661 		return -1;
8662 	}
8663 }
8664 
8665 /** Parse tokens for validate/create commands. */
8666 static int
8667 parse_vc(struct context *ctx, const struct token *token,
8668 	 const char *str, unsigned int len,
8669 	 void *buf, unsigned int size)
8670 {
8671 	struct buffer *out = buf;
8672 	uint8_t *data;
8673 	uint32_t data_size;
8674 
8675 	/* Token name must match. */
8676 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8677 		return -1;
8678 	/* Nothing else to do if there is no buffer. */
8679 	if (!out)
8680 		return len;
8681 	if (!out->command) {
8682 		if (ctx->curr != VALIDATE && ctx->curr != CREATE &&
8683 		    ctx->curr != PATTERN_TEMPLATE_CREATE &&
8684 		    ctx->curr != ACTIONS_TEMPLATE_CREATE &&
8685 		    ctx->curr != UPDATE)
8686 			return -1;
8687 		if (ctx->curr == UPDATE)
8688 			out->args.vc.pattern =
8689 				(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8690 						       sizeof(double));
8691 		if (sizeof(*out) > size)
8692 			return -1;
8693 		out->command = ctx->curr;
8694 		ctx->objdata = 0;
8695 		ctx->object = out;
8696 		ctx->objmask = NULL;
8697 		out->args.vc.data = (uint8_t *)out + size;
8698 		return len;
8699 	}
8700 	ctx->objdata = 0;
8701 	switch (ctx->curr) {
8702 	default:
8703 		ctx->object = &out->args.vc.attr;
8704 		break;
8705 	case VC_TUNNEL_SET:
8706 	case VC_TUNNEL_MATCH:
8707 		ctx->object = &out->args.vc.tunnel_ops;
8708 		break;
8709 	case VC_USER_ID:
8710 		ctx->object = out;
8711 		break;
8712 	}
8713 	ctx->objmask = NULL;
8714 	switch (ctx->curr) {
8715 	case VC_GROUP:
8716 	case VC_PRIORITY:
8717 	case VC_USER_ID:
8718 		return len;
8719 	case VC_TUNNEL_SET:
8720 		out->args.vc.tunnel_ops.enabled = 1;
8721 		out->args.vc.tunnel_ops.actions = 1;
8722 		return len;
8723 	case VC_TUNNEL_MATCH:
8724 		out->args.vc.tunnel_ops.enabled = 1;
8725 		out->args.vc.tunnel_ops.items = 1;
8726 		return len;
8727 	case VC_INGRESS:
8728 		out->args.vc.attr.ingress = 1;
8729 		return len;
8730 	case VC_EGRESS:
8731 		out->args.vc.attr.egress = 1;
8732 		return len;
8733 	case VC_TRANSFER:
8734 		out->args.vc.attr.transfer = 1;
8735 		return len;
8736 	case ITEM_PATTERN:
8737 		out->args.vc.pattern =
8738 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8739 					       sizeof(double));
8740 		ctx->object = out->args.vc.pattern;
8741 		ctx->objmask = NULL;
8742 		return len;
8743 	case ITEM_END:
8744 		if ((out->command == VALIDATE || out->command == CREATE) &&
8745 		    ctx->last)
8746 			return -1;
8747 		if (out->command == PATTERN_TEMPLATE_CREATE &&
8748 		    !ctx->last)
8749 			return -1;
8750 		break;
8751 	case ACTIONS:
8752 		out->args.vc.actions = out->args.vc.pattern ?
8753 			(void *)RTE_ALIGN_CEIL((uintptr_t)
8754 					       (out->args.vc.pattern +
8755 						out->args.vc.pattern_n),
8756 					       sizeof(double)) :
8757 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8758 					       sizeof(double));
8759 		ctx->object = out->args.vc.actions;
8760 		ctx->objmask = NULL;
8761 		return len;
8762 	case VC_IS_USER_ID:
8763 		out->args.vc.user_id = true;
8764 		return len;
8765 	default:
8766 		if (!token->priv)
8767 			return -1;
8768 		break;
8769 	}
8770 	if (!out->args.vc.actions) {
8771 		const struct parse_item_priv *priv = token->priv;
8772 		struct rte_flow_item *item =
8773 			out->args.vc.pattern + out->args.vc.pattern_n;
8774 
8775 		data_size = priv->size * 3; /* spec, last, mask */
8776 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8777 					       (out->args.vc.data - data_size),
8778 					       sizeof(double));
8779 		if ((uint8_t *)item + sizeof(*item) > data)
8780 			return -1;
8781 		*item = (struct rte_flow_item){
8782 			.type = priv->type,
8783 		};
8784 		++out->args.vc.pattern_n;
8785 		ctx->object = item;
8786 		ctx->objmask = NULL;
8787 	} else {
8788 		const struct parse_action_priv *priv = token->priv;
8789 		struct rte_flow_action *action =
8790 			out->args.vc.actions + out->args.vc.actions_n;
8791 
8792 		data_size = priv->size; /* configuration */
8793 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8794 					       (out->args.vc.data - data_size),
8795 					       sizeof(double));
8796 		if ((uint8_t *)action + sizeof(*action) > data)
8797 			return -1;
8798 		*action = (struct rte_flow_action){
8799 			.type = priv->type,
8800 			.conf = data_size ? data : NULL,
8801 		};
8802 		++out->args.vc.actions_n;
8803 		ctx->object = action;
8804 		ctx->objmask = NULL;
8805 	}
8806 	memset(data, 0, data_size);
8807 	out->args.vc.data = data;
8808 	ctx->objdata = data_size;
8809 	return len;
8810 }
8811 
8812 /** Parse pattern item parameter type. */
8813 static int
8814 parse_vc_spec(struct context *ctx, const struct token *token,
8815 	      const char *str, unsigned int len,
8816 	      void *buf, unsigned int size)
8817 {
8818 	struct buffer *out = buf;
8819 	struct rte_flow_item *item;
8820 	uint32_t data_size;
8821 	int index;
8822 	int objmask = 0;
8823 
8824 	(void)size;
8825 	/* Token name must match. */
8826 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8827 		return -1;
8828 	/* Parse parameter types. */
8829 	switch (ctx->curr) {
8830 		static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
8831 
8832 	case ITEM_PARAM_IS:
8833 		index = 0;
8834 		objmask = 1;
8835 		break;
8836 	case ITEM_PARAM_SPEC:
8837 		index = 0;
8838 		break;
8839 	case ITEM_PARAM_LAST:
8840 		index = 1;
8841 		break;
8842 	case ITEM_PARAM_PREFIX:
8843 		/* Modify next token to expect a prefix. */
8844 		if (ctx->next_num < 2)
8845 			return -1;
8846 		ctx->next[ctx->next_num - 2] = prefix;
8847 		/* Fall through. */
8848 	case ITEM_PARAM_MASK:
8849 		index = 2;
8850 		break;
8851 	default:
8852 		return -1;
8853 	}
8854 	/* Nothing else to do if there is no buffer. */
8855 	if (!out)
8856 		return len;
8857 	if (!out->args.vc.pattern_n)
8858 		return -1;
8859 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8860 	data_size = ctx->objdata / 3; /* spec, last, mask */
8861 	/* Point to selected object. */
8862 	ctx->object = out->args.vc.data + (data_size * index);
8863 	if (objmask) {
8864 		ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
8865 		item->mask = ctx->objmask;
8866 	} else
8867 		ctx->objmask = NULL;
8868 	/* Update relevant item pointer. */
8869 	*((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
8870 		ctx->object;
8871 	return len;
8872 }
8873 
8874 /** Parse action configuration field. */
8875 static int
8876 parse_vc_conf(struct context *ctx, const struct token *token,
8877 	      const char *str, unsigned int len,
8878 	      void *buf, unsigned int size)
8879 {
8880 	struct buffer *out = buf;
8881 
8882 	(void)size;
8883 	/* Token name must match. */
8884 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8885 		return -1;
8886 	/* Nothing else to do if there is no buffer. */
8887 	if (!out)
8888 		return len;
8889 	/* Point to selected object. */
8890 	ctx->object = out->args.vc.data;
8891 	ctx->objmask = NULL;
8892 	return len;
8893 }
8894 
8895 /** Parse action configuration field. */
8896 static int
8897 parse_vc_conf_timeout(struct context *ctx, const struct token *token,
8898 		      const char *str, unsigned int len,
8899 		      void *buf, unsigned int size)
8900 {
8901 	struct buffer *out = buf;
8902 	struct rte_flow_update_age *update;
8903 
8904 	(void)size;
8905 	if (ctx->curr != ACTION_AGE_UPDATE_TIMEOUT)
8906 		return -1;
8907 	/* Token name must match. */
8908 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8909 		return -1;
8910 	/* Nothing else to do if there is no buffer. */
8911 	if (!out)
8912 		return len;
8913 	/* Point to selected object. */
8914 	ctx->object = out->args.vc.data;
8915 	ctx->objmask = NULL;
8916 	/* Update the timeout is valid. */
8917 	update = (struct rte_flow_update_age *)out->args.vc.data;
8918 	update->timeout_valid = 1;
8919 	return len;
8920 }
8921 
8922 /** Parse eCPRI common header type field. */
8923 static int
8924 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
8925 			 const char *str, unsigned int len,
8926 			 void *buf, unsigned int size)
8927 {
8928 	struct rte_flow_item_ecpri *ecpri;
8929 	struct rte_flow_item_ecpri *ecpri_mask;
8930 	struct rte_flow_item *item;
8931 	uint32_t data_size;
8932 	uint8_t msg_type;
8933 	struct buffer *out = buf;
8934 	const struct arg *arg;
8935 
8936 	(void)size;
8937 	/* Token name must match. */
8938 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8939 		return -1;
8940 	switch (ctx->curr) {
8941 	case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
8942 		msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
8943 		break;
8944 	case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
8945 		msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
8946 		break;
8947 	case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
8948 		msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
8949 		break;
8950 	default:
8951 		return -1;
8952 	}
8953 	if (!ctx->object)
8954 		return len;
8955 	arg = pop_args(ctx);
8956 	if (!arg)
8957 		return -1;
8958 	ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
8959 	ecpri->hdr.common.type = msg_type;
8960 	data_size = ctx->objdata / 3; /* spec, last, mask */
8961 	ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
8962 						    (data_size * 2));
8963 	ecpri_mask->hdr.common.type = 0xFF;
8964 	if (arg->hton) {
8965 		ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
8966 		ecpri_mask->hdr.common.u32 =
8967 				rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
8968 	}
8969 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8970 	item->spec = ecpri;
8971 	item->mask = ecpri_mask;
8972 	return len;
8973 }
8974 
8975 /** Parse L2TPv2 common header type field. */
8976 static int
8977 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
8978 			 const char *str, unsigned int len,
8979 			 void *buf, unsigned int size)
8980 {
8981 	struct rte_flow_item_l2tpv2 *l2tpv2;
8982 	struct rte_flow_item_l2tpv2 *l2tpv2_mask;
8983 	struct rte_flow_item *item;
8984 	uint32_t data_size;
8985 	uint16_t msg_type = 0;
8986 	struct buffer *out = buf;
8987 	const struct arg *arg;
8988 
8989 	(void)size;
8990 	/* Token name must match. */
8991 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8992 		return -1;
8993 	switch (ctx->curr) {
8994 	case ITEM_L2TPV2_TYPE_DATA:
8995 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
8996 		break;
8997 	case ITEM_L2TPV2_TYPE_DATA_L:
8998 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
8999 		break;
9000 	case ITEM_L2TPV2_TYPE_DATA_S:
9001 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
9002 		break;
9003 	case ITEM_L2TPV2_TYPE_DATA_O:
9004 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
9005 		break;
9006 	case ITEM_L2TPV2_TYPE_DATA_L_S:
9007 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
9008 		break;
9009 	case ITEM_L2TPV2_TYPE_CTRL:
9010 		msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
9011 		break;
9012 	default:
9013 		return -1;
9014 	}
9015 	if (!ctx->object)
9016 		return len;
9017 	arg = pop_args(ctx);
9018 	if (!arg)
9019 		return -1;
9020 	l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
9021 	l2tpv2->hdr.common.flags_version |= msg_type;
9022 	data_size = ctx->objdata / 3; /* spec, last, mask */
9023 	l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
9024 						    (data_size * 2));
9025 	l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
9026 	if (arg->hton) {
9027 		l2tpv2->hdr.common.flags_version =
9028 			rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
9029 		l2tpv2_mask->hdr.common.flags_version =
9030 		    rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
9031 	}
9032 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
9033 	item->spec = l2tpv2;
9034 	item->mask = l2tpv2_mask;
9035 	return len;
9036 }
9037 
9038 /** Parse operation for compare match item. */
9039 static int
9040 parse_vc_compare_op(struct context *ctx, const struct token *token,
9041 			 const char *str, unsigned int len, void *buf,
9042 			 unsigned int size)
9043 {
9044 	struct rte_flow_item_compare *compare_item;
9045 	unsigned int i;
9046 
9047 	(void)token;
9048 	(void)buf;
9049 	(void)size;
9050 	if (ctx->curr != ITEM_COMPARE_OP_VALUE)
9051 		return -1;
9052 	for (i = 0; compare_ops[i]; ++i)
9053 		if (!strcmp_partial(compare_ops[i], str, len))
9054 			break;
9055 	if (!compare_ops[i])
9056 		return -1;
9057 	if (!ctx->object)
9058 		return len;
9059 	compare_item = ctx->object;
9060 	compare_item->operation = (enum rte_flow_item_compare_op)i;
9061 	return len;
9062 }
9063 
9064 /** Parse id for compare match item. */
9065 static int
9066 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
9067 			  const char *str, unsigned int len, void *buf,
9068 			  unsigned int size)
9069 {
9070 	struct rte_flow_item_compare *compare_item;
9071 	unsigned int i;
9072 
9073 	(void)token;
9074 	(void)buf;
9075 	(void)size;
9076 	if (ctx->curr != ITEM_COMPARE_FIELD_A_TYPE_VALUE &&
9077 		ctx->curr != ITEM_COMPARE_FIELD_B_TYPE_VALUE)
9078 		return -1;
9079 	for (i = 0; flow_field_ids[i]; ++i)
9080 		if (!strcmp_partial(flow_field_ids[i], str, len))
9081 			break;
9082 	if (!flow_field_ids[i])
9083 		return -1;
9084 	if (!ctx->object)
9085 		return len;
9086 	compare_item = ctx->object;
9087 	if (ctx->curr == ITEM_COMPARE_FIELD_A_TYPE_VALUE)
9088 		compare_item->a.field = (enum rte_flow_field_id)i;
9089 	else
9090 		compare_item->b.field = (enum rte_flow_field_id)i;
9091 	return len;
9092 }
9093 
9094 /** Parse level for compare match item. */
9095 static int
9096 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
9097 			     const char *str, unsigned int len, void *buf,
9098 			     unsigned int size)
9099 {
9100 	struct rte_flow_item_compare *compare_item;
9101 	struct flex_item *fp = NULL;
9102 	uint32_t val;
9103 	struct buffer *out = buf;
9104 	char *end;
9105 
9106 	(void)token;
9107 	(void)size;
9108 	if (ctx->curr != ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
9109 		ctx->curr != ITEM_COMPARE_FIELD_B_LEVEL_VALUE)
9110 		return -1;
9111 	if (!ctx->object)
9112 		return len;
9113 	compare_item = ctx->object;
9114 	errno = 0;
9115 	val = strtoumax(str, &end, 0);
9116 	if (errno || (size_t)(end - str) != len)
9117 		return -1;
9118 	/* No need to validate action template mask value */
9119 	if (out->args.vc.masks) {
9120 		if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE)
9121 			compare_item->a.level = val;
9122 		else
9123 			compare_item->b.level = val;
9124 		return len;
9125 	}
9126 	if ((ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
9127 		compare_item->a.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
9128 		(ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE &&
9129 		compare_item->b.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
9130 		if (val >= FLEX_MAX_PARSERS_NUM) {
9131 			printf("Bad flex item handle\n");
9132 			return -1;
9133 		}
9134 		fp = flex_items[ctx->port][val];
9135 		if (!fp) {
9136 			printf("Bad flex item handle\n");
9137 			return -1;
9138 		}
9139 	}
9140 	if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE) {
9141 		if (compare_item->a.field != RTE_FLOW_FIELD_FLEX_ITEM)
9142 			compare_item->a.level = val;
9143 		else
9144 			compare_item->a.flex_handle = fp->flex_handle;
9145 	} else if (ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE) {
9146 		if (compare_item->b.field != RTE_FLOW_FIELD_FLEX_ITEM)
9147 			compare_item->b.level = val;
9148 		else
9149 			compare_item->b.flex_handle = fp->flex_handle;
9150 	}
9151 	return len;
9152 }
9153 
9154 /** Parse meter color action type. */
9155 static int
9156 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
9157 				const char *str, unsigned int len,
9158 				void *buf, unsigned int size)
9159 {
9160 	struct rte_flow_action *action_data;
9161 	struct rte_flow_action_meter_color *conf;
9162 	enum rte_color color;
9163 
9164 	(void)buf;
9165 	(void)size;
9166 	/* Token name must match. */
9167 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9168 		return -1;
9169 	switch (ctx->curr) {
9170 	case ACTION_METER_COLOR_GREEN:
9171 		color = RTE_COLOR_GREEN;
9172 	break;
9173 	case ACTION_METER_COLOR_YELLOW:
9174 		color = RTE_COLOR_YELLOW;
9175 	break;
9176 	case ACTION_METER_COLOR_RED:
9177 		color = RTE_COLOR_RED;
9178 	break;
9179 	default:
9180 		return -1;
9181 	}
9182 
9183 	if (!ctx->object)
9184 		return len;
9185 	action_data = ctx->object;
9186 	conf = (struct rte_flow_action_meter_color *)
9187 					(uintptr_t)(action_data->conf);
9188 	conf->color = color;
9189 	return len;
9190 }
9191 
9192 /** Parse RSS action. */
9193 static int
9194 parse_vc_action_rss(struct context *ctx, const struct token *token,
9195 		    const char *str, unsigned int len,
9196 		    void *buf, unsigned int size)
9197 {
9198 	struct buffer *out = buf;
9199 	struct rte_flow_action *action;
9200 	struct action_rss_data *action_rss_data;
9201 	unsigned int i;
9202 	int ret;
9203 
9204 	ret = parse_vc(ctx, token, str, len, buf, size);
9205 	if (ret < 0)
9206 		return ret;
9207 	/* Nothing else to do if there is no buffer. */
9208 	if (!out)
9209 		return ret;
9210 	if (!out->args.vc.actions_n)
9211 		return -1;
9212 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9213 	/* Point to selected object. */
9214 	ctx->object = out->args.vc.data;
9215 	ctx->objmask = NULL;
9216 	/* Set up default configuration. */
9217 	action_rss_data = ctx->object;
9218 	*action_rss_data = (struct action_rss_data){
9219 		.conf = (struct rte_flow_action_rss){
9220 			.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
9221 			.level = 0,
9222 			.types = rss_hf,
9223 			.key_len = 0,
9224 			.queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
9225 			.key = NULL,
9226 			.queue = action_rss_data->queue,
9227 		},
9228 		.queue = { 0 },
9229 	};
9230 	for (i = 0; i < action_rss_data->conf.queue_num; ++i)
9231 		action_rss_data->queue[i] = i;
9232 	action->conf = &action_rss_data->conf;
9233 	return ret;
9234 }
9235 
9236 /**
9237  * Parse func field for RSS action.
9238  *
9239  * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
9240  * ACTION_RSS_FUNC_* index that called this function.
9241  */
9242 static int
9243 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
9244 			 const char *str, unsigned int len,
9245 			 void *buf, unsigned int size)
9246 {
9247 	struct action_rss_data *action_rss_data;
9248 	enum rte_eth_hash_function func;
9249 
9250 	(void)buf;
9251 	(void)size;
9252 	/* Token name must match. */
9253 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9254 		return -1;
9255 	switch (ctx->curr) {
9256 	case ACTION_RSS_FUNC_DEFAULT:
9257 		func = RTE_ETH_HASH_FUNCTION_DEFAULT;
9258 		break;
9259 	case ACTION_RSS_FUNC_TOEPLITZ:
9260 		func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
9261 		break;
9262 	case ACTION_RSS_FUNC_SIMPLE_XOR:
9263 		func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
9264 		break;
9265 	case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
9266 		func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
9267 		break;
9268 	default:
9269 		return -1;
9270 	}
9271 	if (!ctx->object)
9272 		return len;
9273 	action_rss_data = ctx->object;
9274 	action_rss_data->conf.func = func;
9275 	return len;
9276 }
9277 
9278 /**
9279  * Parse type field for RSS action.
9280  *
9281  * Valid tokens are type field names and the "end" token.
9282  */
9283 static int
9284 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
9285 			  const char *str, unsigned int len,
9286 			  void *buf, unsigned int size)
9287 {
9288 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
9289 	struct action_rss_data *action_rss_data;
9290 	unsigned int i;
9291 
9292 	(void)token;
9293 	(void)buf;
9294 	(void)size;
9295 	if (ctx->curr != ACTION_RSS_TYPE)
9296 		return -1;
9297 	if (!(ctx->objdata >> 16) && ctx->object) {
9298 		action_rss_data = ctx->object;
9299 		action_rss_data->conf.types = 0;
9300 	}
9301 	if (!strcmp_partial("end", str, len)) {
9302 		ctx->objdata &= 0xffff;
9303 		return len;
9304 	}
9305 	for (i = 0; rss_type_table[i].str; ++i)
9306 		if (!strcmp_partial(rss_type_table[i].str, str, len))
9307 			break;
9308 	if (!rss_type_table[i].str)
9309 		return -1;
9310 	ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
9311 	/* Repeat token. */
9312 	if (ctx->next_num == RTE_DIM(ctx->next))
9313 		return -1;
9314 	ctx->next[ctx->next_num++] = next;
9315 	if (!ctx->object)
9316 		return len;
9317 	action_rss_data = ctx->object;
9318 	action_rss_data->conf.types |= rss_type_table[i].rss_type;
9319 	return len;
9320 }
9321 
9322 /**
9323  * Parse queue field for RSS action.
9324  *
9325  * Valid tokens are queue indices and the "end" token.
9326  */
9327 static int
9328 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
9329 			  const char *str, unsigned int len,
9330 			  void *buf, unsigned int size)
9331 {
9332 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
9333 	struct action_rss_data *action_rss_data;
9334 	const struct arg *arg;
9335 	int ret;
9336 	int i;
9337 
9338 	(void)token;
9339 	(void)buf;
9340 	(void)size;
9341 	if (ctx->curr != ACTION_RSS_QUEUE)
9342 		return -1;
9343 	i = ctx->objdata >> 16;
9344 	if (!strcmp_partial("end", str, len)) {
9345 		ctx->objdata &= 0xffff;
9346 		goto end;
9347 	}
9348 	if (i >= ACTION_RSS_QUEUE_NUM)
9349 		return -1;
9350 	arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
9351 			     i * sizeof(action_rss_data->queue[i]),
9352 			     sizeof(action_rss_data->queue[i]));
9353 	if (push_args(ctx, arg))
9354 		return -1;
9355 	ret = parse_int(ctx, token, str, len, NULL, 0);
9356 	if (ret < 0) {
9357 		pop_args(ctx);
9358 		return -1;
9359 	}
9360 	++i;
9361 	ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
9362 	/* Repeat token. */
9363 	if (ctx->next_num == RTE_DIM(ctx->next))
9364 		return -1;
9365 	ctx->next[ctx->next_num++] = next;
9366 end:
9367 	if (!ctx->object)
9368 		return len;
9369 	action_rss_data = ctx->object;
9370 	action_rss_data->conf.queue_num = i;
9371 	action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
9372 	return len;
9373 }
9374 
9375 /** Setup VXLAN encap configuration. */
9376 static int
9377 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
9378 {
9379 	/* Set up default configuration. */
9380 	*action_vxlan_encap_data = (struct action_vxlan_encap_data){
9381 		.conf = (struct rte_flow_action_vxlan_encap){
9382 			.definition = action_vxlan_encap_data->items,
9383 		},
9384 		.items = {
9385 			{
9386 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9387 				.spec = &action_vxlan_encap_data->item_eth,
9388 				.mask = &rte_flow_item_eth_mask,
9389 			},
9390 			{
9391 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9392 				.spec = &action_vxlan_encap_data->item_vlan,
9393 				.mask = &rte_flow_item_vlan_mask,
9394 			},
9395 			{
9396 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9397 				.spec = &action_vxlan_encap_data->item_ipv4,
9398 				.mask = &rte_flow_item_ipv4_mask,
9399 			},
9400 			{
9401 				.type = RTE_FLOW_ITEM_TYPE_UDP,
9402 				.spec = &action_vxlan_encap_data->item_udp,
9403 				.mask = &rte_flow_item_udp_mask,
9404 			},
9405 			{
9406 				.type = RTE_FLOW_ITEM_TYPE_VXLAN,
9407 				.spec = &action_vxlan_encap_data->item_vxlan,
9408 				.mask = &rte_flow_item_vxlan_mask,
9409 			},
9410 			{
9411 				.type = RTE_FLOW_ITEM_TYPE_END,
9412 			},
9413 		},
9414 		.item_eth.hdr.ether_type = 0,
9415 		.item_vlan = {
9416 			.hdr.vlan_tci = vxlan_encap_conf.vlan_tci,
9417 			.hdr.eth_proto = 0,
9418 		},
9419 		.item_ipv4.hdr = {
9420 			.src_addr = vxlan_encap_conf.ipv4_src,
9421 			.dst_addr = vxlan_encap_conf.ipv4_dst,
9422 		},
9423 		.item_udp.hdr = {
9424 			.src_port = vxlan_encap_conf.udp_src,
9425 			.dst_port = vxlan_encap_conf.udp_dst,
9426 		},
9427 		.item_vxlan.hdr.flags = 0,
9428 	};
9429 	memcpy(action_vxlan_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9430 	       vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9431 	memcpy(action_vxlan_encap_data->item_eth.hdr.src_addr.addr_bytes,
9432 	       vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9433 	if (!vxlan_encap_conf.select_ipv4) {
9434 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
9435 		       &vxlan_encap_conf.ipv6_src,
9436 		       sizeof(vxlan_encap_conf.ipv6_src));
9437 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
9438 		       &vxlan_encap_conf.ipv6_dst,
9439 		       sizeof(vxlan_encap_conf.ipv6_dst));
9440 		action_vxlan_encap_data->items[2] = (struct rte_flow_item){
9441 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9442 			.spec = &action_vxlan_encap_data->item_ipv6,
9443 			.mask = &rte_flow_item_ipv6_mask,
9444 		};
9445 	}
9446 	if (!vxlan_encap_conf.select_vlan)
9447 		action_vxlan_encap_data->items[1].type =
9448 			RTE_FLOW_ITEM_TYPE_VOID;
9449 	if (vxlan_encap_conf.select_tos_ttl) {
9450 		if (vxlan_encap_conf.select_ipv4) {
9451 			static struct rte_flow_item_ipv4 ipv4_mask_tos;
9452 
9453 			memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
9454 			       sizeof(ipv4_mask_tos));
9455 			ipv4_mask_tos.hdr.type_of_service = 0xff;
9456 			ipv4_mask_tos.hdr.time_to_live = 0xff;
9457 			action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
9458 					vxlan_encap_conf.ip_tos;
9459 			action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
9460 					vxlan_encap_conf.ip_ttl;
9461 			action_vxlan_encap_data->items[2].mask =
9462 							&ipv4_mask_tos;
9463 		} else {
9464 			static struct rte_flow_item_ipv6 ipv6_mask_tos;
9465 
9466 			memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
9467 			       sizeof(ipv6_mask_tos));
9468 			ipv6_mask_tos.hdr.vtc_flow |=
9469 				RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
9470 			ipv6_mask_tos.hdr.hop_limits = 0xff;
9471 			action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
9472 				rte_cpu_to_be_32
9473 					((uint32_t)vxlan_encap_conf.ip_tos <<
9474 					 RTE_IPV6_HDR_TC_SHIFT);
9475 			action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
9476 					vxlan_encap_conf.ip_ttl;
9477 			action_vxlan_encap_data->items[2].mask =
9478 							&ipv6_mask_tos;
9479 		}
9480 	}
9481 	memcpy(action_vxlan_encap_data->item_vxlan.hdr.vni, vxlan_encap_conf.vni,
9482 	       RTE_DIM(vxlan_encap_conf.vni));
9483 	return 0;
9484 }
9485 
9486 /** Parse VXLAN encap action. */
9487 static int
9488 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
9489 			    const char *str, unsigned int len,
9490 			    void *buf, unsigned int size)
9491 {
9492 	struct buffer *out = buf;
9493 	struct rte_flow_action *action;
9494 	struct action_vxlan_encap_data *action_vxlan_encap_data;
9495 	int ret;
9496 
9497 	ret = parse_vc(ctx, token, str, len, buf, size);
9498 	if (ret < 0)
9499 		return ret;
9500 	/* Nothing else to do if there is no buffer. */
9501 	if (!out)
9502 		return ret;
9503 	if (!out->args.vc.actions_n)
9504 		return -1;
9505 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9506 	/* Point to selected object. */
9507 	ctx->object = out->args.vc.data;
9508 	ctx->objmask = NULL;
9509 	action_vxlan_encap_data = ctx->object;
9510 	parse_setup_vxlan_encap_data(action_vxlan_encap_data);
9511 	action->conf = &action_vxlan_encap_data->conf;
9512 	return ret;
9513 }
9514 
9515 /** Setup NVGRE encap configuration. */
9516 static int
9517 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
9518 {
9519 	/* Set up default configuration. */
9520 	*action_nvgre_encap_data = (struct action_nvgre_encap_data){
9521 		.conf = (struct rte_flow_action_nvgre_encap){
9522 			.definition = action_nvgre_encap_data->items,
9523 		},
9524 		.items = {
9525 			{
9526 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9527 				.spec = &action_nvgre_encap_data->item_eth,
9528 				.mask = &rte_flow_item_eth_mask,
9529 			},
9530 			{
9531 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9532 				.spec = &action_nvgre_encap_data->item_vlan,
9533 				.mask = &rte_flow_item_vlan_mask,
9534 			},
9535 			{
9536 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9537 				.spec = &action_nvgre_encap_data->item_ipv4,
9538 				.mask = &rte_flow_item_ipv4_mask,
9539 			},
9540 			{
9541 				.type = RTE_FLOW_ITEM_TYPE_NVGRE,
9542 				.spec = &action_nvgre_encap_data->item_nvgre,
9543 				.mask = &rte_flow_item_nvgre_mask,
9544 			},
9545 			{
9546 				.type = RTE_FLOW_ITEM_TYPE_END,
9547 			},
9548 		},
9549 		.item_eth.hdr.ether_type = 0,
9550 		.item_vlan = {
9551 			.hdr.vlan_tci = nvgre_encap_conf.vlan_tci,
9552 			.hdr.eth_proto = 0,
9553 		},
9554 		.item_ipv4.hdr = {
9555 		       .src_addr = nvgre_encap_conf.ipv4_src,
9556 		       .dst_addr = nvgre_encap_conf.ipv4_dst,
9557 		},
9558 		.item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
9559 		.item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
9560 		.item_nvgre.flow_id = 0,
9561 	};
9562 	memcpy(action_nvgre_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9563 	       nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9564 	memcpy(action_nvgre_encap_data->item_eth.hdr.src_addr.addr_bytes,
9565 	       nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9566 	if (!nvgre_encap_conf.select_ipv4) {
9567 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
9568 		       &nvgre_encap_conf.ipv6_src,
9569 		       sizeof(nvgre_encap_conf.ipv6_src));
9570 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
9571 		       &nvgre_encap_conf.ipv6_dst,
9572 		       sizeof(nvgre_encap_conf.ipv6_dst));
9573 		action_nvgre_encap_data->items[2] = (struct rte_flow_item){
9574 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9575 			.spec = &action_nvgre_encap_data->item_ipv6,
9576 			.mask = &rte_flow_item_ipv6_mask,
9577 		};
9578 	}
9579 	if (!nvgre_encap_conf.select_vlan)
9580 		action_nvgre_encap_data->items[1].type =
9581 			RTE_FLOW_ITEM_TYPE_VOID;
9582 	memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
9583 	       RTE_DIM(nvgre_encap_conf.tni));
9584 	return 0;
9585 }
9586 
9587 /** Parse NVGRE encap action. */
9588 static int
9589 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
9590 			    const char *str, unsigned int len,
9591 			    void *buf, unsigned int size)
9592 {
9593 	struct buffer *out = buf;
9594 	struct rte_flow_action *action;
9595 	struct action_nvgre_encap_data *action_nvgre_encap_data;
9596 	int ret;
9597 
9598 	ret = parse_vc(ctx, token, str, len, buf, size);
9599 	if (ret < 0)
9600 		return ret;
9601 	/* Nothing else to do if there is no buffer. */
9602 	if (!out)
9603 		return ret;
9604 	if (!out->args.vc.actions_n)
9605 		return -1;
9606 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9607 	/* Point to selected object. */
9608 	ctx->object = out->args.vc.data;
9609 	ctx->objmask = NULL;
9610 	action_nvgre_encap_data = ctx->object;
9611 	parse_setup_nvgre_encap_data(action_nvgre_encap_data);
9612 	action->conf = &action_nvgre_encap_data->conf;
9613 	return ret;
9614 }
9615 
9616 /** Parse l2 encap action. */
9617 static int
9618 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
9619 			 const char *str, unsigned int len,
9620 			 void *buf, unsigned int size)
9621 {
9622 	struct buffer *out = buf;
9623 	struct rte_flow_action *action;
9624 	struct action_raw_encap_data *action_encap_data;
9625 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9626 	struct rte_flow_item_vlan vlan = {
9627 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9628 		.hdr.eth_proto = 0,
9629 	};
9630 	uint8_t *header;
9631 	int ret;
9632 
9633 	ret = parse_vc(ctx, token, str, len, buf, size);
9634 	if (ret < 0)
9635 		return ret;
9636 	/* Nothing else to do if there is no buffer. */
9637 	if (!out)
9638 		return ret;
9639 	if (!out->args.vc.actions_n)
9640 		return -1;
9641 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9642 	/* Point to selected object. */
9643 	ctx->object = out->args.vc.data;
9644 	ctx->objmask = NULL;
9645 	/* Copy the headers to the buffer. */
9646 	action_encap_data = ctx->object;
9647 	*action_encap_data = (struct action_raw_encap_data) {
9648 		.conf = (struct rte_flow_action_raw_encap){
9649 			.data = action_encap_data->data,
9650 		},
9651 		.data = {},
9652 	};
9653 	header = action_encap_data->data;
9654 	if (l2_encap_conf.select_vlan)
9655 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9656 	else if (l2_encap_conf.select_ipv4)
9657 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9658 	else
9659 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9660 	memcpy(eth.hdr.dst_addr.addr_bytes,
9661 	       l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9662 	memcpy(eth.hdr.src_addr.addr_bytes,
9663 	       l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9664 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9665 	header += sizeof(struct rte_ether_hdr);
9666 	if (l2_encap_conf.select_vlan) {
9667 		if (l2_encap_conf.select_ipv4)
9668 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9669 		else
9670 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9671 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9672 		header += sizeof(struct rte_vlan_hdr);
9673 	}
9674 	action_encap_data->conf.size = header -
9675 		action_encap_data->data;
9676 	action->conf = &action_encap_data->conf;
9677 	return ret;
9678 }
9679 
9680 /** Parse l2 decap action. */
9681 static int
9682 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
9683 			 const char *str, unsigned int len,
9684 			 void *buf, unsigned int size)
9685 {
9686 	struct buffer *out = buf;
9687 	struct rte_flow_action *action;
9688 	struct action_raw_decap_data *action_decap_data;
9689 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9690 	struct rte_flow_item_vlan vlan = {
9691 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9692 		.hdr.eth_proto = 0,
9693 	};
9694 	uint8_t *header;
9695 	int ret;
9696 
9697 	ret = parse_vc(ctx, token, str, len, buf, size);
9698 	if (ret < 0)
9699 		return ret;
9700 	/* Nothing else to do if there is no buffer. */
9701 	if (!out)
9702 		return ret;
9703 	if (!out->args.vc.actions_n)
9704 		return -1;
9705 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9706 	/* Point to selected object. */
9707 	ctx->object = out->args.vc.data;
9708 	ctx->objmask = NULL;
9709 	/* Copy the headers to the buffer. */
9710 	action_decap_data = ctx->object;
9711 	*action_decap_data = (struct action_raw_decap_data) {
9712 		.conf = (struct rte_flow_action_raw_decap){
9713 			.data = action_decap_data->data,
9714 		},
9715 		.data = {},
9716 	};
9717 	header = action_decap_data->data;
9718 	if (l2_decap_conf.select_vlan)
9719 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9720 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9721 	header += sizeof(struct rte_ether_hdr);
9722 	if (l2_decap_conf.select_vlan) {
9723 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9724 		header += sizeof(struct rte_vlan_hdr);
9725 	}
9726 	action_decap_data->conf.size = header -
9727 		action_decap_data->data;
9728 	action->conf = &action_decap_data->conf;
9729 	return ret;
9730 }
9731 
9732 #define ETHER_TYPE_MPLS_UNICAST 0x8847
9733 
9734 /** Parse MPLSOGRE encap action. */
9735 static int
9736 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
9737 			       const char *str, unsigned int len,
9738 			       void *buf, unsigned int size)
9739 {
9740 	struct buffer *out = buf;
9741 	struct rte_flow_action *action;
9742 	struct action_raw_encap_data *action_encap_data;
9743 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9744 	struct rte_flow_item_vlan vlan = {
9745 		.hdr.vlan_tci = mplsogre_encap_conf.vlan_tci,
9746 		.hdr.eth_proto = 0,
9747 	};
9748 	struct rte_flow_item_ipv4 ipv4 = {
9749 		.hdr =  {
9750 			.src_addr = mplsogre_encap_conf.ipv4_src,
9751 			.dst_addr = mplsogre_encap_conf.ipv4_dst,
9752 			.next_proto_id = IPPROTO_GRE,
9753 			.version_ihl = RTE_IPV4_VHL_DEF,
9754 			.time_to_live = IPDEFTTL,
9755 		},
9756 	};
9757 	struct rte_flow_item_ipv6 ipv6 = {
9758 		.hdr =  {
9759 			.proto = IPPROTO_GRE,
9760 			.hop_limits = IPDEFTTL,
9761 		},
9762 	};
9763 	struct rte_flow_item_gre gre = {
9764 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9765 	};
9766 	struct rte_flow_item_mpls mpls = {
9767 		.ttl = 0,
9768 	};
9769 	uint8_t *header;
9770 	int ret;
9771 
9772 	ret = parse_vc(ctx, token, str, len, buf, size);
9773 	if (ret < 0)
9774 		return ret;
9775 	/* Nothing else to do if there is no buffer. */
9776 	if (!out)
9777 		return ret;
9778 	if (!out->args.vc.actions_n)
9779 		return -1;
9780 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9781 	/* Point to selected object. */
9782 	ctx->object = out->args.vc.data;
9783 	ctx->objmask = NULL;
9784 	/* Copy the headers to the buffer. */
9785 	action_encap_data = ctx->object;
9786 	*action_encap_data = (struct action_raw_encap_data) {
9787 		.conf = (struct rte_flow_action_raw_encap){
9788 			.data = action_encap_data->data,
9789 		},
9790 		.data = {},
9791 		.preserve = {},
9792 	};
9793 	header = action_encap_data->data;
9794 	if (mplsogre_encap_conf.select_vlan)
9795 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9796 	else if (mplsogre_encap_conf.select_ipv4)
9797 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9798 	else
9799 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9800 	memcpy(eth.hdr.dst_addr.addr_bytes,
9801 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9802 	memcpy(eth.hdr.src_addr.addr_bytes,
9803 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9804 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9805 	header += sizeof(struct rte_ether_hdr);
9806 	if (mplsogre_encap_conf.select_vlan) {
9807 		if (mplsogre_encap_conf.select_ipv4)
9808 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9809 		else
9810 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9811 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9812 		header += sizeof(struct rte_vlan_hdr);
9813 	}
9814 	if (mplsogre_encap_conf.select_ipv4) {
9815 		memcpy(header, &ipv4, sizeof(ipv4));
9816 		header += sizeof(ipv4);
9817 	} else {
9818 		memcpy(&ipv6.hdr.src_addr,
9819 		       &mplsogre_encap_conf.ipv6_src,
9820 		       sizeof(mplsogre_encap_conf.ipv6_src));
9821 		memcpy(&ipv6.hdr.dst_addr,
9822 		       &mplsogre_encap_conf.ipv6_dst,
9823 		       sizeof(mplsogre_encap_conf.ipv6_dst));
9824 		memcpy(header, &ipv6, sizeof(ipv6));
9825 		header += sizeof(ipv6);
9826 	}
9827 	memcpy(header, &gre, sizeof(gre));
9828 	header += sizeof(gre);
9829 	memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
9830 	       RTE_DIM(mplsogre_encap_conf.label));
9831 	mpls.label_tc_s[2] |= 0x1;
9832 	memcpy(header, &mpls, sizeof(mpls));
9833 	header += sizeof(mpls);
9834 	action_encap_data->conf.size = header -
9835 		action_encap_data->data;
9836 	action->conf = &action_encap_data->conf;
9837 	return ret;
9838 }
9839 
9840 /** Parse MPLSOGRE decap action. */
9841 static int
9842 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
9843 			       const char *str, unsigned int len,
9844 			       void *buf, unsigned int size)
9845 {
9846 	struct buffer *out = buf;
9847 	struct rte_flow_action *action;
9848 	struct action_raw_decap_data *action_decap_data;
9849 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9850 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
9851 	struct rte_flow_item_ipv4 ipv4 = {
9852 		.hdr =  {
9853 			.next_proto_id = IPPROTO_GRE,
9854 		},
9855 	};
9856 	struct rte_flow_item_ipv6 ipv6 = {
9857 		.hdr =  {
9858 			.proto = IPPROTO_GRE,
9859 		},
9860 	};
9861 	struct rte_flow_item_gre gre = {
9862 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9863 	};
9864 	struct rte_flow_item_mpls mpls;
9865 	uint8_t *header;
9866 	int ret;
9867 
9868 	ret = parse_vc(ctx, token, str, len, buf, size);
9869 	if (ret < 0)
9870 		return ret;
9871 	/* Nothing else to do if there is no buffer. */
9872 	if (!out)
9873 		return ret;
9874 	if (!out->args.vc.actions_n)
9875 		return -1;
9876 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9877 	/* Point to selected object. */
9878 	ctx->object = out->args.vc.data;
9879 	ctx->objmask = NULL;
9880 	/* Copy the headers to the buffer. */
9881 	action_decap_data = ctx->object;
9882 	*action_decap_data = (struct action_raw_decap_data) {
9883 		.conf = (struct rte_flow_action_raw_decap){
9884 			.data = action_decap_data->data,
9885 		},
9886 		.data = {},
9887 	};
9888 	header = action_decap_data->data;
9889 	if (mplsogre_decap_conf.select_vlan)
9890 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9891 	else if (mplsogre_encap_conf.select_ipv4)
9892 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9893 	else
9894 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9895 	memcpy(eth.hdr.dst_addr.addr_bytes,
9896 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9897 	memcpy(eth.hdr.src_addr.addr_bytes,
9898 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9899 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9900 	header += sizeof(struct rte_ether_hdr);
9901 	if (mplsogre_encap_conf.select_vlan) {
9902 		if (mplsogre_encap_conf.select_ipv4)
9903 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9904 		else
9905 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9906 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9907 		header += sizeof(struct rte_vlan_hdr);
9908 	}
9909 	if (mplsogre_encap_conf.select_ipv4) {
9910 		memcpy(header, &ipv4, sizeof(ipv4));
9911 		header += sizeof(ipv4);
9912 	} else {
9913 		memcpy(header, &ipv6, sizeof(ipv6));
9914 		header += sizeof(ipv6);
9915 	}
9916 	memcpy(header, &gre, sizeof(gre));
9917 	header += sizeof(gre);
9918 	memset(&mpls, 0, sizeof(mpls));
9919 	memcpy(header, &mpls, sizeof(mpls));
9920 	header += sizeof(mpls);
9921 	action_decap_data->conf.size = header -
9922 		action_decap_data->data;
9923 	action->conf = &action_decap_data->conf;
9924 	return ret;
9925 }
9926 
9927 /** Parse MPLSOUDP encap action. */
9928 static int
9929 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
9930 			       const char *str, unsigned int len,
9931 			       void *buf, unsigned int size)
9932 {
9933 	struct buffer *out = buf;
9934 	struct rte_flow_action *action;
9935 	struct action_raw_encap_data *action_encap_data;
9936 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9937 	struct rte_flow_item_vlan vlan = {
9938 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9939 		.hdr.eth_proto = 0,
9940 	};
9941 	struct rte_flow_item_ipv4 ipv4 = {
9942 		.hdr =  {
9943 			.src_addr = mplsoudp_encap_conf.ipv4_src,
9944 			.dst_addr = mplsoudp_encap_conf.ipv4_dst,
9945 			.next_proto_id = IPPROTO_UDP,
9946 			.version_ihl = RTE_IPV4_VHL_DEF,
9947 			.time_to_live = IPDEFTTL,
9948 		},
9949 	};
9950 	struct rte_flow_item_ipv6 ipv6 = {
9951 		.hdr =  {
9952 			.proto = IPPROTO_UDP,
9953 			.hop_limits = IPDEFTTL,
9954 		},
9955 	};
9956 	struct rte_flow_item_udp udp = {
9957 		.hdr = {
9958 			.src_port = mplsoudp_encap_conf.udp_src,
9959 			.dst_port = mplsoudp_encap_conf.udp_dst,
9960 		},
9961 	};
9962 	struct rte_flow_item_mpls mpls;
9963 	uint8_t *header;
9964 	int ret;
9965 
9966 	ret = parse_vc(ctx, token, str, len, buf, size);
9967 	if (ret < 0)
9968 		return ret;
9969 	/* Nothing else to do if there is no buffer. */
9970 	if (!out)
9971 		return ret;
9972 	if (!out->args.vc.actions_n)
9973 		return -1;
9974 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9975 	/* Point to selected object. */
9976 	ctx->object = out->args.vc.data;
9977 	ctx->objmask = NULL;
9978 	/* Copy the headers to the buffer. */
9979 	action_encap_data = ctx->object;
9980 	*action_encap_data = (struct action_raw_encap_data) {
9981 		.conf = (struct rte_flow_action_raw_encap){
9982 			.data = action_encap_data->data,
9983 		},
9984 		.data = {},
9985 		.preserve = {},
9986 	};
9987 	header = action_encap_data->data;
9988 	if (mplsoudp_encap_conf.select_vlan)
9989 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9990 	else if (mplsoudp_encap_conf.select_ipv4)
9991 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9992 	else
9993 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9994 	memcpy(eth.hdr.dst_addr.addr_bytes,
9995 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9996 	memcpy(eth.hdr.src_addr.addr_bytes,
9997 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9998 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9999 	header += sizeof(struct rte_ether_hdr);
10000 	if (mplsoudp_encap_conf.select_vlan) {
10001 		if (mplsoudp_encap_conf.select_ipv4)
10002 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
10003 		else
10004 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
10005 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
10006 		header += sizeof(struct rte_vlan_hdr);
10007 	}
10008 	if (mplsoudp_encap_conf.select_ipv4) {
10009 		memcpy(header, &ipv4, sizeof(ipv4));
10010 		header += sizeof(ipv4);
10011 	} else {
10012 		memcpy(&ipv6.hdr.src_addr,
10013 		       &mplsoudp_encap_conf.ipv6_src,
10014 		       sizeof(mplsoudp_encap_conf.ipv6_src));
10015 		memcpy(&ipv6.hdr.dst_addr,
10016 		       &mplsoudp_encap_conf.ipv6_dst,
10017 		       sizeof(mplsoudp_encap_conf.ipv6_dst));
10018 		memcpy(header, &ipv6, sizeof(ipv6));
10019 		header += sizeof(ipv6);
10020 	}
10021 	memcpy(header, &udp, sizeof(udp));
10022 	header += sizeof(udp);
10023 	memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
10024 	       RTE_DIM(mplsoudp_encap_conf.label));
10025 	mpls.label_tc_s[2] |= 0x1;
10026 	memcpy(header, &mpls, sizeof(mpls));
10027 	header += sizeof(mpls);
10028 	action_encap_data->conf.size = header -
10029 		action_encap_data->data;
10030 	action->conf = &action_encap_data->conf;
10031 	return ret;
10032 }
10033 
10034 /** Parse MPLSOUDP decap action. */
10035 static int
10036 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
10037 			       const char *str, unsigned int len,
10038 			       void *buf, unsigned int size)
10039 {
10040 	struct buffer *out = buf;
10041 	struct rte_flow_action *action;
10042 	struct action_raw_decap_data *action_decap_data;
10043 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
10044 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
10045 	struct rte_flow_item_ipv4 ipv4 = {
10046 		.hdr =  {
10047 			.next_proto_id = IPPROTO_UDP,
10048 		},
10049 	};
10050 	struct rte_flow_item_ipv6 ipv6 = {
10051 		.hdr =  {
10052 			.proto = IPPROTO_UDP,
10053 		},
10054 	};
10055 	struct rte_flow_item_udp udp = {
10056 		.hdr = {
10057 			.dst_port = rte_cpu_to_be_16(6635),
10058 		},
10059 	};
10060 	struct rte_flow_item_mpls mpls;
10061 	uint8_t *header;
10062 	int ret;
10063 
10064 	ret = parse_vc(ctx, token, str, len, buf, size);
10065 	if (ret < 0)
10066 		return ret;
10067 	/* Nothing else to do if there is no buffer. */
10068 	if (!out)
10069 		return ret;
10070 	if (!out->args.vc.actions_n)
10071 		return -1;
10072 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10073 	/* Point to selected object. */
10074 	ctx->object = out->args.vc.data;
10075 	ctx->objmask = NULL;
10076 	/* Copy the headers to the buffer. */
10077 	action_decap_data = ctx->object;
10078 	*action_decap_data = (struct action_raw_decap_data) {
10079 		.conf = (struct rte_flow_action_raw_decap){
10080 			.data = action_decap_data->data,
10081 		},
10082 		.data = {},
10083 	};
10084 	header = action_decap_data->data;
10085 	if (mplsoudp_decap_conf.select_vlan)
10086 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
10087 	else if (mplsoudp_encap_conf.select_ipv4)
10088 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
10089 	else
10090 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
10091 	memcpy(eth.hdr.dst_addr.addr_bytes,
10092 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
10093 	memcpy(eth.hdr.src_addr.addr_bytes,
10094 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
10095 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
10096 	header += sizeof(struct rte_ether_hdr);
10097 	if (mplsoudp_encap_conf.select_vlan) {
10098 		if (mplsoudp_encap_conf.select_ipv4)
10099 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
10100 		else
10101 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
10102 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
10103 		header += sizeof(struct rte_vlan_hdr);
10104 	}
10105 	if (mplsoudp_encap_conf.select_ipv4) {
10106 		memcpy(header, &ipv4, sizeof(ipv4));
10107 		header += sizeof(ipv4);
10108 	} else {
10109 		memcpy(header, &ipv6, sizeof(ipv6));
10110 		header += sizeof(ipv6);
10111 	}
10112 	memcpy(header, &udp, sizeof(udp));
10113 	header += sizeof(udp);
10114 	memset(&mpls, 0, sizeof(mpls));
10115 	memcpy(header, &mpls, sizeof(mpls));
10116 	header += sizeof(mpls);
10117 	action_decap_data->conf.size = header -
10118 		action_decap_data->data;
10119 	action->conf = &action_decap_data->conf;
10120 	return ret;
10121 }
10122 
10123 static int
10124 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
10125 				const char *str, unsigned int len, void *buf,
10126 				unsigned int size)
10127 {
10128 	struct action_raw_decap_data *action_raw_decap_data;
10129 	struct rte_flow_action *action;
10130 	const struct arg *arg;
10131 	struct buffer *out = buf;
10132 	int ret;
10133 	uint16_t idx;
10134 
10135 	RTE_SET_USED(token);
10136 	RTE_SET_USED(buf);
10137 	RTE_SET_USED(size);
10138 	arg = ARGS_ENTRY_ARB_BOUNDED
10139 		(offsetof(struct action_raw_decap_data, idx),
10140 		 sizeof(((struct action_raw_decap_data *)0)->idx),
10141 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
10142 	if (push_args(ctx, arg))
10143 		return -1;
10144 	ret = parse_int(ctx, token, str, len, NULL, 0);
10145 	if (ret < 0) {
10146 		pop_args(ctx);
10147 		return -1;
10148 	}
10149 	if (!ctx->object)
10150 		return len;
10151 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10152 	action_raw_decap_data = ctx->object;
10153 	idx = action_raw_decap_data->idx;
10154 	action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
10155 	action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
10156 	action->conf = &action_raw_decap_data->conf;
10157 	return len;
10158 }
10159 
10160 
10161 static int
10162 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
10163 				const char *str, unsigned int len, void *buf,
10164 				unsigned int size)
10165 {
10166 	struct action_raw_encap_data *action_raw_encap_data;
10167 	struct rte_flow_action *action;
10168 	const struct arg *arg;
10169 	struct buffer *out = buf;
10170 	int ret;
10171 	uint16_t idx;
10172 
10173 	RTE_SET_USED(token);
10174 	RTE_SET_USED(buf);
10175 	RTE_SET_USED(size);
10176 	if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
10177 		return -1;
10178 	arg = ARGS_ENTRY_ARB_BOUNDED
10179 		(offsetof(struct action_raw_encap_data, idx),
10180 		 sizeof(((struct action_raw_encap_data *)0)->idx),
10181 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
10182 	if (push_args(ctx, arg))
10183 		return -1;
10184 	ret = parse_int(ctx, token, str, len, NULL, 0);
10185 	if (ret < 0) {
10186 		pop_args(ctx);
10187 		return -1;
10188 	}
10189 	if (!ctx->object)
10190 		return len;
10191 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10192 	action_raw_encap_data = ctx->object;
10193 	idx = action_raw_encap_data->idx;
10194 	action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
10195 	action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
10196 	action_raw_encap_data->conf.preserve = NULL;
10197 	action->conf = &action_raw_encap_data->conf;
10198 	return len;
10199 }
10200 
10201 static int
10202 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
10203 			  const char *str, unsigned int len, void *buf,
10204 			  unsigned int size)
10205 {
10206 	struct buffer *out = buf;
10207 	int ret;
10208 
10209 	ret = parse_vc(ctx, token, str, len, buf, size);
10210 	if (ret < 0)
10211 		return ret;
10212 	/* Nothing else to do if there is no buffer. */
10213 	if (!out)
10214 		return ret;
10215 	if (!out->args.vc.actions_n)
10216 		return -1;
10217 	/* Point to selected object. */
10218 	ctx->object = out->args.vc.data;
10219 	ctx->objmask = NULL;
10220 	return ret;
10221 }
10222 
10223 static int
10224 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
10225 			  const char *str, unsigned int len, void *buf,
10226 			  unsigned int size)
10227 {
10228 	struct buffer *out = buf;
10229 	struct rte_flow_action *action;
10230 	struct action_raw_decap_data *action_raw_decap_data = NULL;
10231 	int ret;
10232 
10233 	ret = parse_vc(ctx, token, str, len, buf, size);
10234 	if (ret < 0)
10235 		return ret;
10236 	/* Nothing else to do if there is no buffer. */
10237 	if (!out)
10238 		return ret;
10239 	if (!out->args.vc.actions_n)
10240 		return -1;
10241 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10242 	/* Point to selected object. */
10243 	ctx->object = out->args.vc.data;
10244 	ctx->objmask = NULL;
10245 	/* Copy the headers to the buffer. */
10246 	action_raw_decap_data = ctx->object;
10247 	action_raw_decap_data->conf.data = raw_decap_confs[0].data;
10248 	action_raw_decap_data->conf.size = raw_decap_confs[0].size;
10249 	action->conf = &action_raw_decap_data->conf;
10250 	return ret;
10251 }
10252 
10253 static int
10254 parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
10255 				const char *str, unsigned int len, void *buf,
10256 				unsigned int size)
10257 {
10258 	struct buffer *out = buf;
10259 	struct rte_flow_action *action;
10260 	struct action_ipv6_ext_remove_data *ipv6_ext_remove_data = NULL;
10261 	int ret;
10262 
10263 	ret = parse_vc(ctx, token, str, len, buf, size);
10264 	if (ret < 0)
10265 		return ret;
10266 	/* Nothing else to do if there is no buffer. */
10267 	if (!out)
10268 		return ret;
10269 	if (!out->args.vc.actions_n)
10270 		return -1;
10271 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10272 	/* Point to selected object. */
10273 	ctx->object = out->args.vc.data;
10274 	ctx->objmask = NULL;
10275 	/* Copy the headers to the buffer. */
10276 	ipv6_ext_remove_data = ctx->object;
10277 	ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[0].type;
10278 	action->conf = &ipv6_ext_remove_data->conf;
10279 	return ret;
10280 }
10281 
10282 static int
10283 parse_vc_action_ipv6_ext_remove_index(struct context *ctx, const struct token *token,
10284 				      const char *str, unsigned int len, void *buf,
10285 				      unsigned int size)
10286 {
10287 	struct action_ipv6_ext_remove_data *action_ipv6_ext_remove_data;
10288 	struct rte_flow_action *action;
10289 	const struct arg *arg;
10290 	struct buffer *out = buf;
10291 	int ret;
10292 	uint16_t idx;
10293 
10294 	RTE_SET_USED(token);
10295 	RTE_SET_USED(buf);
10296 	RTE_SET_USED(size);
10297 	arg = ARGS_ENTRY_ARB_BOUNDED
10298 		(offsetof(struct action_ipv6_ext_remove_data, idx),
10299 		 sizeof(((struct action_ipv6_ext_remove_data *)0)->idx),
10300 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10301 	if (push_args(ctx, arg))
10302 		return -1;
10303 	ret = parse_int(ctx, token, str, len, NULL, 0);
10304 	if (ret < 0) {
10305 		pop_args(ctx);
10306 		return -1;
10307 	}
10308 	if (!ctx->object)
10309 		return len;
10310 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10311 	action_ipv6_ext_remove_data = ctx->object;
10312 	idx = action_ipv6_ext_remove_data->idx;
10313 	action_ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[idx].type;
10314 	action->conf = &action_ipv6_ext_remove_data->conf;
10315 	return len;
10316 }
10317 
10318 static int
10319 parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
10320 			      const char *str, unsigned int len, void *buf,
10321 			      unsigned int size)
10322 {
10323 	struct buffer *out = buf;
10324 	struct rte_flow_action *action;
10325 	struct action_ipv6_ext_push_data *ipv6_ext_push_data = NULL;
10326 	int ret;
10327 
10328 	ret = parse_vc(ctx, token, str, len, buf, size);
10329 	if (ret < 0)
10330 		return ret;
10331 	/* Nothing else to do if there is no buffer. */
10332 	if (!out)
10333 		return ret;
10334 	if (!out->args.vc.actions_n)
10335 		return -1;
10336 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10337 	/* Point to selected object. */
10338 	ctx->object = out->args.vc.data;
10339 	ctx->objmask = NULL;
10340 	/* Copy the headers to the buffer. */
10341 	ipv6_ext_push_data = ctx->object;
10342 	ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[0].type;
10343 	ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[0].data;
10344 	ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[0].size;
10345 	action->conf = &ipv6_ext_push_data->conf;
10346 	return ret;
10347 }
10348 
10349 static int
10350 parse_vc_action_ipv6_ext_push_index(struct context *ctx, const struct token *token,
10351 				    const char *str, unsigned int len, void *buf,
10352 				    unsigned int size)
10353 {
10354 	struct action_ipv6_ext_push_data *action_ipv6_ext_push_data;
10355 	struct rte_flow_action *action;
10356 	const struct arg *arg;
10357 	struct buffer *out = buf;
10358 	int ret;
10359 	uint16_t idx;
10360 
10361 	RTE_SET_USED(token);
10362 	RTE_SET_USED(buf);
10363 	RTE_SET_USED(size);
10364 	arg = ARGS_ENTRY_ARB_BOUNDED
10365 		(offsetof(struct action_ipv6_ext_push_data, idx),
10366 		 sizeof(((struct action_ipv6_ext_push_data *)0)->idx),
10367 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10368 	if (push_args(ctx, arg))
10369 		return -1;
10370 	ret = parse_int(ctx, token, str, len, NULL, 0);
10371 	if (ret < 0) {
10372 		pop_args(ctx);
10373 		return -1;
10374 	}
10375 	if (!ctx->object)
10376 		return len;
10377 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10378 	action_ipv6_ext_push_data = ctx->object;
10379 	idx = action_ipv6_ext_push_data->idx;
10380 	action_ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[idx].type;
10381 	action_ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[idx].size;
10382 	action_ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[idx].data;
10383 	action->conf = &action_ipv6_ext_push_data->conf;
10384 	return len;
10385 }
10386 
10387 static int
10388 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
10389 			 const char *str, unsigned int len, void *buf,
10390 			 unsigned int size)
10391 {
10392 	int ret;
10393 
10394 	ret = parse_vc(ctx, token, str, len, buf, size);
10395 	if (ret < 0)
10396 		return ret;
10397 	ret = rte_flow_dynf_metadata_register();
10398 	if (ret < 0)
10399 		return -1;
10400 	return len;
10401 }
10402 
10403 static int
10404 parse_vc_action_sample(struct context *ctx, const struct token *token,
10405 			 const char *str, unsigned int len, void *buf,
10406 			 unsigned int size)
10407 {
10408 	struct buffer *out = buf;
10409 	struct rte_flow_action *action;
10410 	struct action_sample_data *action_sample_data = NULL;
10411 	static struct rte_flow_action end_action = {
10412 		RTE_FLOW_ACTION_TYPE_END, 0
10413 	};
10414 	int ret;
10415 
10416 	ret = parse_vc(ctx, token, str, len, buf, size);
10417 	if (ret < 0)
10418 		return ret;
10419 	/* Nothing else to do if there is no buffer. */
10420 	if (!out)
10421 		return ret;
10422 	if (!out->args.vc.actions_n)
10423 		return -1;
10424 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10425 	/* Point to selected object. */
10426 	ctx->object = out->args.vc.data;
10427 	ctx->objmask = NULL;
10428 	/* Copy the headers to the buffer. */
10429 	action_sample_data = ctx->object;
10430 	action_sample_data->conf.actions = &end_action;
10431 	action->conf = &action_sample_data->conf;
10432 	return ret;
10433 }
10434 
10435 static int
10436 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
10437 				const char *str, unsigned int len, void *buf,
10438 				unsigned int size)
10439 {
10440 	struct action_sample_data *action_sample_data;
10441 	struct rte_flow_action *action;
10442 	const struct arg *arg;
10443 	struct buffer *out = buf;
10444 	int ret;
10445 	uint16_t idx;
10446 
10447 	RTE_SET_USED(token);
10448 	RTE_SET_USED(buf);
10449 	RTE_SET_USED(size);
10450 	if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
10451 		return -1;
10452 	arg = ARGS_ENTRY_ARB_BOUNDED
10453 		(offsetof(struct action_sample_data, idx),
10454 		 sizeof(((struct action_sample_data *)0)->idx),
10455 		 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
10456 	if (push_args(ctx, arg))
10457 		return -1;
10458 	ret = parse_int(ctx, token, str, len, NULL, 0);
10459 	if (ret < 0) {
10460 		pop_args(ctx);
10461 		return -1;
10462 	}
10463 	if (!ctx->object)
10464 		return len;
10465 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10466 	action_sample_data = ctx->object;
10467 	idx = action_sample_data->idx;
10468 	action_sample_data->conf.actions = raw_sample_confs[idx].data;
10469 	action->conf = &action_sample_data->conf;
10470 	return len;
10471 }
10472 
10473 /** Parse operation for modify_field command. */
10474 static int
10475 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
10476 			 const char *str, unsigned int len, void *buf,
10477 			 unsigned int size)
10478 {
10479 	struct rte_flow_action_modify_field *action_modify_field;
10480 	unsigned int i;
10481 
10482 	(void)token;
10483 	(void)buf;
10484 	(void)size;
10485 	if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
10486 		return -1;
10487 	for (i = 0; modify_field_ops[i]; ++i)
10488 		if (!strcmp_partial(modify_field_ops[i], str, len))
10489 			break;
10490 	if (!modify_field_ops[i])
10491 		return -1;
10492 	if (!ctx->object)
10493 		return len;
10494 	action_modify_field = ctx->object;
10495 	action_modify_field->operation = (enum rte_flow_modify_op)i;
10496 	return len;
10497 }
10498 
10499 /** Parse id for modify_field command. */
10500 static int
10501 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
10502 			 const char *str, unsigned int len, void *buf,
10503 			 unsigned int size)
10504 {
10505 	struct rte_flow_action_modify_field *action_modify_field;
10506 	unsigned int i;
10507 
10508 	(void)token;
10509 	(void)buf;
10510 	(void)size;
10511 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
10512 		ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
10513 		return -1;
10514 	for (i = 0; flow_field_ids[i]; ++i)
10515 		if (!strcmp_partial(flow_field_ids[i], str, len))
10516 			break;
10517 	if (!flow_field_ids[i])
10518 		return -1;
10519 	if (!ctx->object)
10520 		return len;
10521 	action_modify_field = ctx->object;
10522 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
10523 		action_modify_field->dst.field = (enum rte_flow_field_id)i;
10524 	else
10525 		action_modify_field->src.field = (enum rte_flow_field_id)i;
10526 	return len;
10527 }
10528 
10529 /** Parse level for modify_field command. */
10530 static int
10531 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
10532 			 const char *str, unsigned int len, void *buf,
10533 			 unsigned int size)
10534 {
10535 	struct rte_flow_action_modify_field *action;
10536 	struct flex_item *fp = NULL;
10537 	uint32_t val;
10538 	struct buffer *out = buf;
10539 	char *end;
10540 
10541 	(void)token;
10542 	(void)size;
10543 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10544 		ctx->curr != ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)
10545 		return -1;
10546 	if (!ctx->object)
10547 		return len;
10548 	action = ctx->object;
10549 	errno = 0;
10550 	val = strtoumax(str, &end, 0);
10551 	if (errno || (size_t)(end - str) != len)
10552 		return -1;
10553 	/* No need to validate action template mask value */
10554 	if (out->args.vc.masks) {
10555 		if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)
10556 			action->dst.level = val;
10557 		else
10558 			action->src.level = val;
10559 		return len;
10560 	}
10561 	if ((ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10562 		action->dst.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
10563 		(ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE &&
10564 		action->src.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
10565 		if (val >= FLEX_MAX_PARSERS_NUM) {
10566 			printf("Bad flex item handle\n");
10567 			return -1;
10568 		}
10569 		fp = flex_items[ctx->port][val];
10570 		if (!fp) {
10571 			printf("Bad flex item handle\n");
10572 			return -1;
10573 		}
10574 	}
10575 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE) {
10576 		if (action->dst.field != RTE_FLOW_FIELD_FLEX_ITEM)
10577 			action->dst.level = val;
10578 		else
10579 			action->dst.flex_handle = fp->flex_handle;
10580 	} else if (ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE) {
10581 		if (action->src.field != RTE_FLOW_FIELD_FLEX_ITEM)
10582 			action->src.level = val;
10583 		else
10584 			action->src.flex_handle = fp->flex_handle;
10585 	}
10586 	return len;
10587 }
10588 
10589 /** Parse the conntrack update, not a rte_flow_action. */
10590 static int
10591 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
10592 			 const char *str, unsigned int len, void *buf,
10593 			 unsigned int size)
10594 {
10595 	struct buffer *out = buf;
10596 	struct rte_flow_modify_conntrack *ct_modify = NULL;
10597 
10598 	(void)size;
10599 	if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
10600 	    ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
10601 		return -1;
10602 	/* Token name must match. */
10603 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10604 		return -1;
10605 	/* Nothing else to do if there is no buffer. */
10606 	if (!out)
10607 		return len;
10608 	ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
10609 	if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
10610 		ct_modify->new_ct.is_original_dir =
10611 				conntrack_context.is_original_dir;
10612 		ct_modify->direction = 1;
10613 	} else {
10614 		uint32_t old_dir;
10615 
10616 		old_dir = ct_modify->new_ct.is_original_dir;
10617 		memcpy(&ct_modify->new_ct, &conntrack_context,
10618 		       sizeof(conntrack_context));
10619 		ct_modify->new_ct.is_original_dir = old_dir;
10620 		ct_modify->state = 1;
10621 	}
10622 	return len;
10623 }
10624 
10625 /** Parse tokens for destroy command. */
10626 static int
10627 parse_destroy(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 != DESTROY)
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 		out->args.destroy.rule =
10649 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10650 					       sizeof(double));
10651 		return len;
10652 	}
10653 	if (ctx->curr == DESTROY_IS_USER_ID) {
10654 		out->args.destroy.is_user_id = true;
10655 		return len;
10656 	}
10657 	if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
10658 	     sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
10659 		return -1;
10660 	ctx->objdata = 0;
10661 	ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
10662 	ctx->objmask = NULL;
10663 	return len;
10664 }
10665 
10666 /** Parse tokens for flush command. */
10667 static int
10668 parse_flush(struct context *ctx, const struct token *token,
10669 	    const char *str, unsigned int len,
10670 	    void *buf, unsigned int size)
10671 {
10672 	struct buffer *out = buf;
10673 
10674 	/* Token name must match. */
10675 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10676 		return -1;
10677 	/* Nothing else to do if there is no buffer. */
10678 	if (!out)
10679 		return len;
10680 	if (!out->command) {
10681 		if (ctx->curr != FLUSH)
10682 			return -1;
10683 		if (sizeof(*out) > size)
10684 			return -1;
10685 		out->command = ctx->curr;
10686 		ctx->objdata = 0;
10687 		ctx->object = out;
10688 		ctx->objmask = NULL;
10689 	}
10690 	return len;
10691 }
10692 
10693 /** Parse tokens for dump command. */
10694 static int
10695 parse_dump(struct context *ctx, const struct token *token,
10696 	    const char *str, unsigned int len,
10697 	    void *buf, unsigned int size)
10698 {
10699 	struct buffer *out = buf;
10700 
10701 	/* Token name must match. */
10702 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10703 		return -1;
10704 	/* Nothing else to do if there is no buffer. */
10705 	if (!out)
10706 		return len;
10707 	if (!out->command) {
10708 		if (ctx->curr != DUMP)
10709 			return -1;
10710 		if (sizeof(*out) > size)
10711 			return -1;
10712 		out->command = ctx->curr;
10713 		ctx->objdata = 0;
10714 		ctx->object = out;
10715 		ctx->objmask = NULL;
10716 		return len;
10717 	}
10718 	switch (ctx->curr) {
10719 	case DUMP_ALL:
10720 	case DUMP_ONE:
10721 		out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
10722 		out->command = ctx->curr;
10723 		ctx->objdata = 0;
10724 		ctx->object = out;
10725 		ctx->objmask = NULL;
10726 		return len;
10727 	case DUMP_IS_USER_ID:
10728 		out->args.dump.is_user_id = true;
10729 		return len;
10730 	default:
10731 		return -1;
10732 	}
10733 }
10734 
10735 /** Parse tokens for query command. */
10736 static int
10737 parse_query(struct context *ctx, const struct token *token,
10738 	    const char *str, unsigned int len,
10739 	    void *buf, unsigned int size)
10740 {
10741 	struct buffer *out = buf;
10742 
10743 	/* Token name must match. */
10744 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10745 		return -1;
10746 	/* Nothing else to do if there is no buffer. */
10747 	if (!out)
10748 		return len;
10749 	if (!out->command) {
10750 		if (ctx->curr != QUERY)
10751 			return -1;
10752 		if (sizeof(*out) > size)
10753 			return -1;
10754 		out->command = ctx->curr;
10755 		ctx->objdata = 0;
10756 		ctx->object = out;
10757 		ctx->objmask = NULL;
10758 	}
10759 	if (ctx->curr == QUERY_IS_USER_ID) {
10760 		out->args.query.is_user_id = true;
10761 		return len;
10762 	}
10763 	return len;
10764 }
10765 
10766 /** Parse action names. */
10767 static int
10768 parse_action(struct context *ctx, const struct token *token,
10769 	     const char *str, unsigned int len,
10770 	     void *buf, unsigned int size)
10771 {
10772 	struct buffer *out = buf;
10773 	const struct arg *arg = pop_args(ctx);
10774 	unsigned int i;
10775 
10776 	(void)size;
10777 	/* Argument is expected. */
10778 	if (!arg)
10779 		return -1;
10780 	/* Parse action name. */
10781 	for (i = 0; next_action[i]; ++i) {
10782 		const struct parse_action_priv *priv;
10783 
10784 		token = &token_list[next_action[i]];
10785 		if (strcmp_partial(token->name, str, len))
10786 			continue;
10787 		priv = token->priv;
10788 		if (!priv)
10789 			goto error;
10790 		if (out)
10791 			memcpy((uint8_t *)ctx->object + arg->offset,
10792 			       &priv->type,
10793 			       arg->size);
10794 		return len;
10795 	}
10796 error:
10797 	push_args(ctx, arg);
10798 	return -1;
10799 }
10800 
10801 /** Parse tokens for list command. */
10802 static int
10803 parse_list(struct context *ctx, const struct token *token,
10804 	   const char *str, unsigned int len,
10805 	   void *buf, unsigned int size)
10806 {
10807 	struct buffer *out = buf;
10808 
10809 	/* Token name must match. */
10810 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10811 		return -1;
10812 	/* Nothing else to do if there is no buffer. */
10813 	if (!out)
10814 		return len;
10815 	if (!out->command) {
10816 		if (ctx->curr != LIST)
10817 			return -1;
10818 		if (sizeof(*out) > size)
10819 			return -1;
10820 		out->command = ctx->curr;
10821 		ctx->objdata = 0;
10822 		ctx->object = out;
10823 		ctx->objmask = NULL;
10824 		out->args.list.group =
10825 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10826 					       sizeof(double));
10827 		return len;
10828 	}
10829 	if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
10830 	     sizeof(*out->args.list.group)) > (uint8_t *)out + size)
10831 		return -1;
10832 	ctx->objdata = 0;
10833 	ctx->object = out->args.list.group + out->args.list.group_n++;
10834 	ctx->objmask = NULL;
10835 	return len;
10836 }
10837 
10838 /** Parse tokens for list all aged flows command. */
10839 static int
10840 parse_aged(struct context *ctx, const struct token *token,
10841 	   const char *str, unsigned int len,
10842 	   void *buf, unsigned int size)
10843 {
10844 	struct buffer *out = buf;
10845 
10846 	/* Token name must match. */
10847 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10848 		return -1;
10849 	/* Nothing else to do if there is no buffer. */
10850 	if (!out)
10851 		return len;
10852 	if (!out->command || out->command == QUEUE) {
10853 		if (ctx->curr != AGED && ctx->curr != QUEUE_AGED)
10854 			return -1;
10855 		if (sizeof(*out) > size)
10856 			return -1;
10857 		out->command = ctx->curr;
10858 		ctx->objdata = 0;
10859 		ctx->object = out;
10860 		ctx->objmask = NULL;
10861 	}
10862 	if (ctx->curr == AGED_DESTROY)
10863 		out->args.aged.destroy = 1;
10864 	return len;
10865 }
10866 
10867 /** Parse tokens for isolate command. */
10868 static int
10869 parse_isolate(struct context *ctx, const struct token *token,
10870 	      const char *str, unsigned int len,
10871 	      void *buf, unsigned int size)
10872 {
10873 	struct buffer *out = buf;
10874 
10875 	/* Token name must match. */
10876 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10877 		return -1;
10878 	/* Nothing else to do if there is no buffer. */
10879 	if (!out)
10880 		return len;
10881 	if (!out->command) {
10882 		if (ctx->curr != ISOLATE)
10883 			return -1;
10884 		if (sizeof(*out) > size)
10885 			return -1;
10886 		out->command = ctx->curr;
10887 		ctx->objdata = 0;
10888 		ctx->object = out;
10889 		ctx->objmask = NULL;
10890 	}
10891 	return len;
10892 }
10893 
10894 /** Parse tokens for info/configure command. */
10895 static int
10896 parse_configure(struct context *ctx, const struct token *token,
10897 		const char *str, unsigned int len,
10898 		void *buf, unsigned int size)
10899 {
10900 	struct buffer *out = buf;
10901 
10902 	/* Token name must match. */
10903 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10904 		return -1;
10905 	/* Nothing else to do if there is no buffer. */
10906 	if (!out)
10907 		return len;
10908 	if (!out->command) {
10909 		if (ctx->curr != INFO && ctx->curr != CONFIGURE)
10910 			return -1;
10911 		if (sizeof(*out) > size)
10912 			return -1;
10913 		out->command = ctx->curr;
10914 		ctx->objdata = 0;
10915 		ctx->object = out;
10916 		ctx->objmask = NULL;
10917 	}
10918 	return len;
10919 }
10920 
10921 /** Parse tokens for template create command. */
10922 static int
10923 parse_template(struct context *ctx, const struct token *token,
10924 	       const char *str, unsigned int len,
10925 	       void *buf, unsigned int size)
10926 {
10927 	struct buffer *out = buf;
10928 
10929 	/* Token name must match. */
10930 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10931 		return -1;
10932 	/* Nothing else to do if there is no buffer. */
10933 	if (!out)
10934 		return len;
10935 	if (!out->command) {
10936 		if (ctx->curr != PATTERN_TEMPLATE &&
10937 		    ctx->curr != ACTIONS_TEMPLATE)
10938 			return -1;
10939 		if (sizeof(*out) > size)
10940 			return -1;
10941 		out->command = ctx->curr;
10942 		ctx->objdata = 0;
10943 		ctx->object = out;
10944 		ctx->objmask = NULL;
10945 		out->args.vc.data = (uint8_t *)out + size;
10946 		return len;
10947 	}
10948 	switch (ctx->curr) {
10949 	case PATTERN_TEMPLATE_CREATE:
10950 		out->args.vc.pattern =
10951 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10952 					       sizeof(double));
10953 		out->args.vc.pat_templ_id = UINT32_MAX;
10954 		out->command = ctx->curr;
10955 		ctx->objdata = 0;
10956 		ctx->object = out;
10957 		ctx->objmask = NULL;
10958 		return len;
10959 	case PATTERN_TEMPLATE_EGRESS:
10960 		out->args.vc.attr.egress = 1;
10961 		return len;
10962 	case PATTERN_TEMPLATE_INGRESS:
10963 		out->args.vc.attr.ingress = 1;
10964 		return len;
10965 	case PATTERN_TEMPLATE_TRANSFER:
10966 		out->args.vc.attr.transfer = 1;
10967 		return len;
10968 	case ACTIONS_TEMPLATE_CREATE:
10969 		out->args.vc.act_templ_id = UINT32_MAX;
10970 		out->command = ctx->curr;
10971 		ctx->objdata = 0;
10972 		ctx->object = out;
10973 		ctx->objmask = NULL;
10974 		return len;
10975 	case ACTIONS_TEMPLATE_SPEC:
10976 		out->args.vc.actions =
10977 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10978 					       sizeof(double));
10979 		ctx->object = out->args.vc.actions;
10980 		ctx->objmask = NULL;
10981 		return len;
10982 	case ACTIONS_TEMPLATE_MASK:
10983 		out->args.vc.masks =
10984 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10985 					       (out->args.vc.actions +
10986 						out->args.vc.actions_n),
10987 					       sizeof(double));
10988 		ctx->object = out->args.vc.masks;
10989 		ctx->objmask = NULL;
10990 		return len;
10991 	case ACTIONS_TEMPLATE_EGRESS:
10992 		out->args.vc.attr.egress = 1;
10993 		return len;
10994 	case ACTIONS_TEMPLATE_INGRESS:
10995 		out->args.vc.attr.ingress = 1;
10996 		return len;
10997 	case ACTIONS_TEMPLATE_TRANSFER:
10998 		out->args.vc.attr.transfer = 1;
10999 		return len;
11000 	default:
11001 		return -1;
11002 	}
11003 }
11004 
11005 /** Parse tokens for template destroy command. */
11006 static int
11007 parse_template_destroy(struct context *ctx, const struct token *token,
11008 		       const char *str, unsigned int len,
11009 		       void *buf, unsigned int size)
11010 {
11011 	struct buffer *out = buf;
11012 	uint32_t *template_id;
11013 
11014 	/* Token name must match. */
11015 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11016 		return -1;
11017 	/* Nothing else to do if there is no buffer. */
11018 	if (!out)
11019 		return len;
11020 	if (!out->command ||
11021 		out->command == PATTERN_TEMPLATE ||
11022 		out->command == ACTIONS_TEMPLATE) {
11023 		if (ctx->curr != PATTERN_TEMPLATE_DESTROY &&
11024 			ctx->curr != ACTIONS_TEMPLATE_DESTROY)
11025 			return -1;
11026 		if (sizeof(*out) > size)
11027 			return -1;
11028 		out->command = ctx->curr;
11029 		ctx->objdata = 0;
11030 		ctx->object = out;
11031 		ctx->objmask = NULL;
11032 		out->args.templ_destroy.template_id =
11033 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11034 					       sizeof(double));
11035 		return len;
11036 	}
11037 	template_id = out->args.templ_destroy.template_id
11038 		    + out->args.templ_destroy.template_id_n++;
11039 	if ((uint8_t *)template_id > (uint8_t *)out + size)
11040 		return -1;
11041 	ctx->objdata = 0;
11042 	ctx->object = template_id;
11043 	ctx->objmask = NULL;
11044 	return len;
11045 }
11046 
11047 /** Parse tokens for table create command. */
11048 static int
11049 parse_table(struct context *ctx, const struct token *token,
11050 	    const char *str, unsigned int len,
11051 	    void *buf, unsigned int size)
11052 {
11053 	struct buffer *out = buf;
11054 	uint32_t *template_id;
11055 
11056 	/* Token name must match. */
11057 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11058 		return -1;
11059 	/* Nothing else to do if there is no buffer. */
11060 	if (!out)
11061 		return len;
11062 	if (!out->command) {
11063 		if (ctx->curr != TABLE)
11064 			return -1;
11065 		if (sizeof(*out) > size)
11066 			return -1;
11067 		out->command = ctx->curr;
11068 		ctx->objdata = 0;
11069 		ctx->object = out;
11070 		ctx->objmask = NULL;
11071 		return len;
11072 	}
11073 	switch (ctx->curr) {
11074 	case TABLE_CREATE:
11075 	case TABLE_RESIZE:
11076 		out->command = ctx->curr;
11077 		ctx->objdata = 0;
11078 		ctx->object = out;
11079 		ctx->objmask = NULL;
11080 		out->args.table.id = UINT32_MAX;
11081 		return len;
11082 	case TABLE_PATTERN_TEMPLATE:
11083 		out->args.table.pat_templ_id =
11084 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11085 					       sizeof(double));
11086 		template_id = out->args.table.pat_templ_id
11087 				+ out->args.table.pat_templ_id_n++;
11088 		if ((uint8_t *)template_id > (uint8_t *)out + size)
11089 			return -1;
11090 		ctx->objdata = 0;
11091 		ctx->object = template_id;
11092 		ctx->objmask = NULL;
11093 		return len;
11094 	case TABLE_ACTIONS_TEMPLATE:
11095 		out->args.table.act_templ_id =
11096 			(void *)RTE_ALIGN_CEIL((uintptr_t)
11097 					       (out->args.table.pat_templ_id +
11098 						out->args.table.pat_templ_id_n),
11099 					       sizeof(double));
11100 		template_id = out->args.table.act_templ_id
11101 				+ out->args.table.act_templ_id_n++;
11102 		if ((uint8_t *)template_id > (uint8_t *)out + size)
11103 			return -1;
11104 		ctx->objdata = 0;
11105 		ctx->object = template_id;
11106 		ctx->objmask = NULL;
11107 		return len;
11108 	case TABLE_INGRESS:
11109 		out->args.table.attr.flow_attr.ingress = 1;
11110 		return len;
11111 	case TABLE_EGRESS:
11112 		out->args.table.attr.flow_attr.egress = 1;
11113 		return len;
11114 	case TABLE_TRANSFER:
11115 		out->args.table.attr.flow_attr.transfer = 1;
11116 		return len;
11117 	case TABLE_TRANSFER_WIRE_ORIG:
11118 		if (!out->args.table.attr.flow_attr.transfer)
11119 			return -1;
11120 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_WIRE_ORIG;
11121 		return len;
11122 	case TABLE_TRANSFER_VPORT_ORIG:
11123 		if (!out->args.table.attr.flow_attr.transfer)
11124 			return -1;
11125 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_VPORT_ORIG;
11126 		return len;
11127 	case TABLE_RESIZABLE:
11128 		out->args.table.attr.specialize |=
11129 			RTE_FLOW_TABLE_SPECIALIZE_RESIZABLE;
11130 		return len;
11131 	case TABLE_RULES_NUMBER:
11132 		ctx->objdata = 0;
11133 		ctx->object = out;
11134 		ctx->objmask = NULL;
11135 		return len;
11136 	case TABLE_RESIZE_ID:
11137 	case TABLE_RESIZE_RULES_NUMBER:
11138 		return len;
11139 	default:
11140 		return -1;
11141 	}
11142 }
11143 
11144 /** Parse tokens for table destroy command. */
11145 static int
11146 parse_table_destroy(struct context *ctx, const struct token *token,
11147 		    const char *str, unsigned int len,
11148 		    void *buf, unsigned int size)
11149 {
11150 	struct buffer *out = buf;
11151 	uint32_t *table_id;
11152 
11153 	/* Token name must match. */
11154 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11155 		return -1;
11156 	/* Nothing else to do if there is no buffer. */
11157 	if (!out)
11158 		return len;
11159 	if (!out->command || out->command == TABLE) {
11160 		if (ctx->curr != TABLE_DESTROY &&
11161 		    ctx->curr != TABLE_RESIZE_COMPLETE)
11162 			return -1;
11163 		if (sizeof(*out) > size)
11164 			return -1;
11165 		out->command = ctx->curr;
11166 		ctx->objdata = 0;
11167 		ctx->object = out;
11168 		ctx->objmask = NULL;
11169 		out->args.table_destroy.table_id =
11170 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11171 					       sizeof(double));
11172 		return len;
11173 	}
11174 	table_id = out->args.table_destroy.table_id
11175 		    + out->args.table_destroy.table_id_n++;
11176 	if ((uint8_t *)table_id > (uint8_t *)out + size)
11177 		return -1;
11178 	ctx->objdata = 0;
11179 	ctx->object = table_id;
11180 	ctx->objmask = NULL;
11181 	return len;
11182 }
11183 
11184 /** Parse tokens for queue create commands. */
11185 static int
11186 parse_qo(struct context *ctx, const struct token *token,
11187 	 const char *str, unsigned int len,
11188 	 void *buf, unsigned int size)
11189 {
11190 	struct buffer *out = buf;
11191 
11192 	/* Token name must match. */
11193 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11194 		return -1;
11195 	/* Nothing else to do if there is no buffer. */
11196 	if (!out)
11197 		return len;
11198 	if (!out->command) {
11199 		if (ctx->curr != QUEUE)
11200 			return -1;
11201 		if (sizeof(*out) > size)
11202 			return -1;
11203 		out->command = ctx->curr;
11204 		ctx->objdata = 0;
11205 		ctx->object = out;
11206 		ctx->objmask = NULL;
11207 		out->args.vc.data = (uint8_t *)out + size;
11208 		return len;
11209 	}
11210 	switch (ctx->curr) {
11211 	case QUEUE_CREATE:
11212 	case QUEUE_UPDATE:
11213 		out->command = ctx->curr;
11214 		ctx->objdata = 0;
11215 		ctx->object = out;
11216 		ctx->objmask = NULL;
11217 		out->args.vc.rule_id = UINT32_MAX;
11218 		return len;
11219 	case QUEUE_TEMPLATE_TABLE:
11220 	case QUEUE_PATTERN_TEMPLATE:
11221 	case QUEUE_ACTIONS_TEMPLATE:
11222 	case QUEUE_CREATE_POSTPONE:
11223 	case QUEUE_RULE_ID:
11224 	case QUEUE_UPDATE_ID:
11225 		return len;
11226 	case ITEM_PATTERN:
11227 		out->args.vc.pattern =
11228 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11229 					       sizeof(double));
11230 		ctx->object = out->args.vc.pattern;
11231 		ctx->objmask = NULL;
11232 		return len;
11233 	case ACTIONS:
11234 		out->args.vc.actions =
11235 			(void *)RTE_ALIGN_CEIL((uintptr_t)
11236 					       (out->args.vc.pattern +
11237 						out->args.vc.pattern_n),
11238 					       sizeof(double));
11239 		ctx->object = out->args.vc.actions;
11240 		ctx->objmask = NULL;
11241 		return len;
11242 	default:
11243 		return -1;
11244 	}
11245 }
11246 
11247 /** Parse tokens for queue destroy command. */
11248 static int
11249 parse_qo_destroy(struct context *ctx, const struct token *token,
11250 		 const char *str, unsigned int len,
11251 		 void *buf, unsigned int size)
11252 {
11253 	struct buffer *out = buf;
11254 	uint64_t *flow_id;
11255 
11256 	/* Token name must match. */
11257 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11258 		return -1;
11259 	/* Nothing else to do if there is no buffer. */
11260 	if (!out)
11261 		return len;
11262 	if (!out->command || out->command == QUEUE) {
11263 		if (ctx->curr != QUEUE_DESTROY &&
11264 		    ctx->curr != QUEUE_FLOW_UPDATE_RESIZED)
11265 			return -1;
11266 		if (sizeof(*out) > size)
11267 			return -1;
11268 		out->command = ctx->curr;
11269 		ctx->objdata = 0;
11270 		ctx->object = out;
11271 		ctx->objmask = NULL;
11272 		out->args.destroy.rule =
11273 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11274 					       sizeof(double));
11275 		return len;
11276 	}
11277 	switch (ctx->curr) {
11278 	case QUEUE_DESTROY_ID:
11279 		flow_id = out->args.destroy.rule
11280 				+ out->args.destroy.rule_n++;
11281 		if ((uint8_t *)flow_id > (uint8_t *)out + size)
11282 			return -1;
11283 		ctx->objdata = 0;
11284 		ctx->object = flow_id;
11285 		ctx->objmask = NULL;
11286 		return len;
11287 	case QUEUE_DESTROY_POSTPONE:
11288 		return len;
11289 	default:
11290 		return -1;
11291 	}
11292 }
11293 
11294 /** Parse tokens for push queue command. */
11295 static int
11296 parse_push(struct context *ctx, const struct token *token,
11297 	   const char *str, unsigned int len,
11298 	   void *buf, unsigned int size)
11299 {
11300 	struct buffer *out = buf;
11301 
11302 	/* Token name must match. */
11303 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11304 		return -1;
11305 	/* Nothing else to do if there is no buffer. */
11306 	if (!out)
11307 		return len;
11308 	if (!out->command) {
11309 		if (ctx->curr != PUSH)
11310 			return -1;
11311 		if (sizeof(*out) > size)
11312 			return -1;
11313 		out->command = ctx->curr;
11314 		ctx->objdata = 0;
11315 		ctx->object = out;
11316 		ctx->objmask = NULL;
11317 		out->args.vc.data = (uint8_t *)out + size;
11318 	}
11319 	return len;
11320 }
11321 
11322 /** Parse tokens for pull command. */
11323 static int
11324 parse_pull(struct context *ctx, const struct token *token,
11325 	   const char *str, unsigned int len,
11326 	   void *buf, unsigned int size)
11327 {
11328 	struct buffer *out = buf;
11329 
11330 	/* Token name must match. */
11331 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11332 		return -1;
11333 	/* Nothing else to do if there is no buffer. */
11334 	if (!out)
11335 		return len;
11336 	if (!out->command) {
11337 		if (ctx->curr != PULL)
11338 			return -1;
11339 		if (sizeof(*out) > size)
11340 			return -1;
11341 		out->command = ctx->curr;
11342 		ctx->objdata = 0;
11343 		ctx->object = out;
11344 		ctx->objmask = NULL;
11345 		out->args.vc.data = (uint8_t *)out + size;
11346 	}
11347 	return len;
11348 }
11349 
11350 /** Parse tokens for hash calculation commands. */
11351 static int
11352 parse_hash(struct context *ctx, const struct token *token,
11353 	 const char *str, unsigned int len,
11354 	 void *buf, unsigned int size)
11355 {
11356 	struct buffer *out = buf;
11357 
11358 	/* Token name must match. */
11359 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11360 		return -1;
11361 	/* Nothing else to do if there is no buffer. */
11362 	if (!out)
11363 		return len;
11364 	if (!out->command) {
11365 		if (ctx->curr != HASH)
11366 			return -1;
11367 		if (sizeof(*out) > size)
11368 			return -1;
11369 		out->command = ctx->curr;
11370 		ctx->objdata = 0;
11371 		ctx->object = out;
11372 		ctx->objmask = NULL;
11373 		out->args.vc.data = (uint8_t *)out + size;
11374 		return len;
11375 	}
11376 	switch (ctx->curr) {
11377 	case HASH_CALC_TABLE:
11378 	case HASH_CALC_PATTERN_INDEX:
11379 		return len;
11380 	case ITEM_PATTERN:
11381 		out->args.vc.pattern =
11382 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11383 					       sizeof(double));
11384 		ctx->object = out->args.vc.pattern;
11385 		ctx->objmask = NULL;
11386 		return len;
11387 	case HASH_CALC_ENCAP:
11388 		out->args.vc.encap_hash = 1;
11389 		return len;
11390 	case ENCAP_HASH_FIELD_SRC_PORT:
11391 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_SRC_PORT;
11392 		return len;
11393 	case ENCAP_HASH_FIELD_GRE_FLOW_ID:
11394 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_NVGRE_FLOW_ID;
11395 		return len;
11396 	default:
11397 		return -1;
11398 	}
11399 }
11400 
11401 static int
11402 parse_group(struct context *ctx, const struct token *token,
11403 	    const char *str, unsigned int len,
11404 	    void *buf, unsigned int size)
11405 {
11406 	struct buffer *out = buf;
11407 
11408 	/* Token name must match. */
11409 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11410 		return -1;
11411 	/* Nothing else to do if there is no buffer. */
11412 	if (!out)
11413 		return len;
11414 	if (!out->command) {
11415 		if (ctx->curr != FLOW_GROUP)
11416 			return -1;
11417 		if (sizeof(*out) > size)
11418 			return -1;
11419 		out->command = ctx->curr;
11420 		ctx->objdata = 0;
11421 		ctx->object = out;
11422 		ctx->objmask = NULL;
11423 		out->args.vc.data = (uint8_t *)out + size;
11424 		return len;
11425 	}
11426 	switch (ctx->curr) {
11427 	case GROUP_INGRESS:
11428 		out->args.vc.attr.ingress = 1;
11429 		return len;
11430 	case GROUP_EGRESS:
11431 		out->args.vc.attr.egress = 1;
11432 		return len;
11433 	case GROUP_TRANSFER:
11434 		out->args.vc.attr.transfer = 1;
11435 		return len;
11436 	case GROUP_SET_MISS_ACTIONS:
11437 		out->command = ctx->curr;
11438 		ctx->objdata = 0;
11439 		ctx->object = out;
11440 		ctx->objmask = NULL;
11441 		out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11442 							       sizeof(double));
11443 		return len;
11444 	default:
11445 		return -1;
11446 	}
11447 }
11448 
11449 static int
11450 parse_flex(struct context *ctx, const struct token *token,
11451 	     const char *str, unsigned int len,
11452 	     void *buf, unsigned int size)
11453 {
11454 	struct buffer *out = buf;
11455 
11456 	/* Token name must match. */
11457 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11458 		return -1;
11459 	/* Nothing else to do if there is no buffer. */
11460 	if (!out)
11461 		return len;
11462 	if (out->command == ZERO) {
11463 		if (ctx->curr != FLEX)
11464 			return -1;
11465 		if (sizeof(*out) > size)
11466 			return -1;
11467 		out->command = ctx->curr;
11468 		ctx->objdata = 0;
11469 		ctx->object = out;
11470 		ctx->objmask = NULL;
11471 	} else {
11472 		switch (ctx->curr) {
11473 		default:
11474 			break;
11475 		case FLEX_ITEM_INIT:
11476 		case FLEX_ITEM_CREATE:
11477 		case FLEX_ITEM_DESTROY:
11478 			out->command = ctx->curr;
11479 			break;
11480 		}
11481 	}
11482 
11483 	return len;
11484 }
11485 
11486 static int
11487 parse_tunnel(struct context *ctx, const struct token *token,
11488 	     const char *str, unsigned int len,
11489 	     void *buf, unsigned int size)
11490 {
11491 	struct buffer *out = buf;
11492 
11493 	/* Token name must match. */
11494 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11495 		return -1;
11496 	/* Nothing else to do if there is no buffer. */
11497 	if (!out)
11498 		return len;
11499 	if (!out->command) {
11500 		if (ctx->curr != TUNNEL)
11501 			return -1;
11502 		if (sizeof(*out) > size)
11503 			return -1;
11504 		out->command = ctx->curr;
11505 		ctx->objdata = 0;
11506 		ctx->object = out;
11507 		ctx->objmask = NULL;
11508 	} else {
11509 		switch (ctx->curr) {
11510 		default:
11511 			break;
11512 		case TUNNEL_CREATE:
11513 		case TUNNEL_DESTROY:
11514 		case TUNNEL_LIST:
11515 			out->command = ctx->curr;
11516 			break;
11517 		case TUNNEL_CREATE_TYPE:
11518 		case TUNNEL_DESTROY_ID:
11519 			ctx->object = &out->args.vc.tunnel_ops;
11520 			break;
11521 		}
11522 	}
11523 
11524 	return len;
11525 }
11526 
11527 /**
11528  * Parse signed/unsigned integers 8 to 64-bit long.
11529  *
11530  * Last argument (ctx->args) is retrieved to determine integer type and
11531  * storage location.
11532  */
11533 static int
11534 parse_int(struct context *ctx, const struct token *token,
11535 	  const char *str, unsigned int len,
11536 	  void *buf, unsigned int size)
11537 {
11538 	const struct arg *arg = pop_args(ctx);
11539 	uintmax_t u;
11540 	char *end;
11541 
11542 	(void)token;
11543 	/* Argument is expected. */
11544 	if (!arg)
11545 		return -1;
11546 	errno = 0;
11547 	u = arg->sign ?
11548 		(uintmax_t)strtoimax(str, &end, 0) :
11549 		strtoumax(str, &end, 0);
11550 	if (errno || (size_t)(end - str) != len)
11551 		goto error;
11552 	if (arg->bounded &&
11553 	    ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
11554 			    (intmax_t)u > (intmax_t)arg->max)) ||
11555 	     (!arg->sign && (u < arg->min || u > arg->max))))
11556 		goto error;
11557 	if (!ctx->object)
11558 		return len;
11559 	if (arg->mask) {
11560 		if (!arg_entry_bf_fill(ctx->object, u, arg) ||
11561 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
11562 			goto error;
11563 		return len;
11564 	}
11565 	buf = (uint8_t *)ctx->object + arg->offset;
11566 	size = arg->size;
11567 	if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
11568 		return -1;
11569 objmask:
11570 	switch (size) {
11571 	case sizeof(uint8_t):
11572 		*(uint8_t *)buf = u;
11573 		break;
11574 	case sizeof(uint16_t):
11575 		*(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
11576 		break;
11577 	case sizeof(uint8_t [3]):
11578 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
11579 		if (!arg->hton) {
11580 			((uint8_t *)buf)[0] = u;
11581 			((uint8_t *)buf)[1] = u >> 8;
11582 			((uint8_t *)buf)[2] = u >> 16;
11583 			break;
11584 		}
11585 #endif
11586 		((uint8_t *)buf)[0] = u >> 16;
11587 		((uint8_t *)buf)[1] = u >> 8;
11588 		((uint8_t *)buf)[2] = u;
11589 		break;
11590 	case sizeof(uint32_t):
11591 		*(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
11592 		break;
11593 	case sizeof(uint64_t):
11594 		*(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
11595 		break;
11596 	default:
11597 		goto error;
11598 	}
11599 	if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
11600 		u = -1;
11601 		buf = (uint8_t *)ctx->objmask + arg->offset;
11602 		goto objmask;
11603 	}
11604 	return len;
11605 error:
11606 	push_args(ctx, arg);
11607 	return -1;
11608 }
11609 
11610 /**
11611  * Parse a string.
11612  *
11613  * Three arguments (ctx->args) are retrieved from the stack to store data,
11614  * its actual length and address (in that order).
11615  */
11616 static int
11617 parse_string(struct context *ctx, const struct token *token,
11618 	     const char *str, unsigned int len,
11619 	     void *buf, unsigned int size)
11620 {
11621 	const struct arg *arg_data = pop_args(ctx);
11622 	const struct arg *arg_len = pop_args(ctx);
11623 	const struct arg *arg_addr = pop_args(ctx);
11624 	char tmp[16]; /* Ought to be enough. */
11625 	int ret;
11626 
11627 	/* Arguments are expected. */
11628 	if (!arg_data)
11629 		return -1;
11630 	if (!arg_len) {
11631 		push_args(ctx, arg_data);
11632 		return -1;
11633 	}
11634 	if (!arg_addr) {
11635 		push_args(ctx, arg_len);
11636 		push_args(ctx, arg_data);
11637 		return -1;
11638 	}
11639 	size = arg_data->size;
11640 	/* Bit-mask fill is not supported. */
11641 	if (arg_data->mask || size < len)
11642 		goto error;
11643 	if (!ctx->object)
11644 		return len;
11645 	/* Let parse_int() fill length information first. */
11646 	ret = snprintf(tmp, sizeof(tmp), "%u", len);
11647 	if (ret < 0)
11648 		goto error;
11649 	push_args(ctx, arg_len);
11650 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11651 	if (ret < 0) {
11652 		pop_args(ctx);
11653 		goto error;
11654 	}
11655 	buf = (uint8_t *)ctx->object + arg_data->offset;
11656 	/* Output buffer is not necessarily NUL-terminated. */
11657 	memcpy(buf, str, len);
11658 	memset((uint8_t *)buf + len, 0x00, size - len);
11659 	if (ctx->objmask)
11660 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11661 	/* Save address if requested. */
11662 	if (arg_addr->size) {
11663 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11664 		       (void *[]){
11665 			(uint8_t *)ctx->object + arg_data->offset
11666 		       },
11667 		       arg_addr->size);
11668 		if (ctx->objmask)
11669 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11670 			       (void *[]){
11671 				(uint8_t *)ctx->objmask + arg_data->offset
11672 			       },
11673 			       arg_addr->size);
11674 	}
11675 	return len;
11676 error:
11677 	push_args(ctx, arg_addr);
11678 	push_args(ctx, arg_len);
11679 	push_args(ctx, arg_data);
11680 	return -1;
11681 }
11682 
11683 static int
11684 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
11685 {
11686 	const uint8_t *head = dst;
11687 	uint32_t left;
11688 
11689 	if (*size == 0)
11690 		return -1;
11691 
11692 	left = *size;
11693 
11694 	/* Convert chars to bytes */
11695 	while (left) {
11696 		char tmp[3], *end = tmp;
11697 		uint32_t read_lim = left & 1 ? 1 : 2;
11698 
11699 		snprintf(tmp, read_lim + 1, "%s", src);
11700 		*dst = strtoul(tmp, &end, 16);
11701 		if (*end) {
11702 			*dst = 0;
11703 			*size = (uint32_t)(dst - head);
11704 			return -1;
11705 		}
11706 		left -= read_lim;
11707 		src += read_lim;
11708 		dst++;
11709 	}
11710 	*dst = 0;
11711 	*size = (uint32_t)(dst - head);
11712 	return 0;
11713 }
11714 
11715 static int
11716 parse_hex(struct context *ctx, const struct token *token,
11717 		const char *str, unsigned int len,
11718 		void *buf, unsigned int size)
11719 {
11720 	const struct arg *arg_data = pop_args(ctx);
11721 	const struct arg *arg_len = pop_args(ctx);
11722 	const struct arg *arg_addr = pop_args(ctx);
11723 	char tmp[16]; /* Ought to be enough. */
11724 	int ret;
11725 	unsigned int hexlen = len;
11726 	unsigned int length = 256;
11727 	uint8_t hex_tmp[length];
11728 
11729 	/* Arguments are expected. */
11730 	if (!arg_data)
11731 		return -1;
11732 	if (!arg_len) {
11733 		push_args(ctx, arg_data);
11734 		return -1;
11735 	}
11736 	if (!arg_addr) {
11737 		push_args(ctx, arg_len);
11738 		push_args(ctx, arg_data);
11739 		return -1;
11740 	}
11741 	size = arg_data->size;
11742 	/* Bit-mask fill is not supported. */
11743 	if (arg_data->mask)
11744 		goto error;
11745 	if (!ctx->object)
11746 		return len;
11747 
11748 	/* translate bytes string to array. */
11749 	if (str[0] == '0' && ((str[1] == 'x') ||
11750 			(str[1] == 'X'))) {
11751 		str += 2;
11752 		hexlen -= 2;
11753 	}
11754 	if (hexlen > length)
11755 		goto error;
11756 	ret = parse_hex_string(str, hex_tmp, &hexlen);
11757 	if (ret < 0)
11758 		goto error;
11759 	/* Check the converted binary fits into data buffer. */
11760 	if (hexlen > size)
11761 		goto error;
11762 	/* Let parse_int() fill length information first. */
11763 	ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
11764 	if (ret < 0)
11765 		goto error;
11766 	/* Save length if requested. */
11767 	if (arg_len->size) {
11768 		push_args(ctx, arg_len);
11769 		ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11770 		if (ret < 0) {
11771 			pop_args(ctx);
11772 			goto error;
11773 		}
11774 	}
11775 	buf = (uint8_t *)ctx->object + arg_data->offset;
11776 	/* Output buffer is not necessarily NUL-terminated. */
11777 	memcpy(buf, hex_tmp, hexlen);
11778 	memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
11779 	if (ctx->objmask)
11780 		memset((uint8_t *)ctx->objmask + arg_data->offset,
11781 					0xff, hexlen);
11782 	/* Save address if requested. */
11783 	if (arg_addr->size) {
11784 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11785 		       (void *[]){
11786 			(uint8_t *)ctx->object + arg_data->offset
11787 		       },
11788 		       arg_addr->size);
11789 		if (ctx->objmask)
11790 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11791 			       (void *[]){
11792 				(uint8_t *)ctx->objmask + arg_data->offset
11793 			       },
11794 			       arg_addr->size);
11795 	}
11796 	return len;
11797 error:
11798 	push_args(ctx, arg_addr);
11799 	push_args(ctx, arg_len);
11800 	push_args(ctx, arg_data);
11801 	return -1;
11802 
11803 }
11804 
11805 /**
11806  * Parse a zero-ended string.
11807  */
11808 static int
11809 parse_string0(struct context *ctx, const struct token *token __rte_unused,
11810 	     const char *str, unsigned int len,
11811 	     void *buf, unsigned int size)
11812 {
11813 	const struct arg *arg_data = pop_args(ctx);
11814 
11815 	/* Arguments are expected. */
11816 	if (!arg_data)
11817 		return -1;
11818 	size = arg_data->size;
11819 	/* Bit-mask fill is not supported. */
11820 	if (arg_data->mask || size < len + 1)
11821 		goto error;
11822 	if (!ctx->object)
11823 		return len;
11824 	buf = (uint8_t *)ctx->object + arg_data->offset;
11825 	strncpy(buf, str, len);
11826 	if (ctx->objmask)
11827 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11828 	return len;
11829 error:
11830 	push_args(ctx, arg_data);
11831 	return -1;
11832 }
11833 
11834 /**
11835  * Parse a MAC address.
11836  *
11837  * Last argument (ctx->args) is retrieved to determine storage size and
11838  * location.
11839  */
11840 static int
11841 parse_mac_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 	struct rte_ether_addr tmp;
11847 	int ret;
11848 
11849 	(void)token;
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 	ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
11861 	if (ret < 0 || (unsigned int)ret != len)
11862 		goto error;
11863 	if (!ctx->object)
11864 		return len;
11865 	buf = (uint8_t *)ctx->object + arg->offset;
11866 	memcpy(buf, &tmp, size);
11867 	if (ctx->objmask)
11868 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11869 	return len;
11870 error:
11871 	push_args(ctx, arg);
11872 	return -1;
11873 }
11874 
11875 /**
11876  * Parse an IPv4 address.
11877  *
11878  * Last argument (ctx->args) is retrieved to determine storage size and
11879  * location.
11880  */
11881 static int
11882 parse_ipv4_addr(struct context *ctx, const struct token *token,
11883 		const char *str, unsigned int len,
11884 		void *buf, unsigned int size)
11885 {
11886 	const struct arg *arg = pop_args(ctx);
11887 	char str2[len + 1];
11888 	struct in_addr tmp;
11889 	int ret;
11890 
11891 	/* Argument is expected. */
11892 	if (!arg)
11893 		return -1;
11894 	size = arg->size;
11895 	/* Bit-mask fill is not supported. */
11896 	if (arg->mask || size != sizeof(tmp))
11897 		goto error;
11898 	/* Only network endian is supported. */
11899 	if (!arg->hton)
11900 		goto error;
11901 	memcpy(str2, str, len);
11902 	str2[len] = '\0';
11903 	ret = inet_pton(AF_INET, str2, &tmp);
11904 	if (ret != 1) {
11905 		/* Attempt integer parsing. */
11906 		push_args(ctx, arg);
11907 		return parse_int(ctx, token, str, len, buf, size);
11908 	}
11909 	if (!ctx->object)
11910 		return len;
11911 	buf = (uint8_t *)ctx->object + arg->offset;
11912 	memcpy(buf, &tmp, size);
11913 	if (ctx->objmask)
11914 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11915 	return len;
11916 error:
11917 	push_args(ctx, arg);
11918 	return -1;
11919 }
11920 
11921 /**
11922  * Parse an IPv6 address.
11923  *
11924  * Last argument (ctx->args) is retrieved to determine storage size and
11925  * location.
11926  */
11927 static int
11928 parse_ipv6_addr(struct context *ctx, const struct token *token,
11929 		const char *str, unsigned int len,
11930 		void *buf, unsigned int size)
11931 {
11932 	const struct arg *arg = pop_args(ctx);
11933 	char str2[len + 1];
11934 	struct in6_addr tmp;
11935 	int ret;
11936 
11937 	(void)token;
11938 	/* Argument is expected. */
11939 	if (!arg)
11940 		return -1;
11941 	size = arg->size;
11942 	/* Bit-mask fill is not supported. */
11943 	if (arg->mask || size != sizeof(tmp))
11944 		goto error;
11945 	/* Only network endian is supported. */
11946 	if (!arg->hton)
11947 		goto error;
11948 	memcpy(str2, str, len);
11949 	str2[len] = '\0';
11950 	ret = inet_pton(AF_INET6, str2, &tmp);
11951 	if (ret != 1)
11952 		goto error;
11953 	if (!ctx->object)
11954 		return len;
11955 	buf = (uint8_t *)ctx->object + arg->offset;
11956 	memcpy(buf, &tmp, size);
11957 	if (ctx->objmask)
11958 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11959 	return len;
11960 error:
11961 	push_args(ctx, arg);
11962 	return -1;
11963 }
11964 
11965 /** Boolean values (even indices stand for false). */
11966 static const char *const boolean_name[] = {
11967 	"0", "1",
11968 	"false", "true",
11969 	"no", "yes",
11970 	"N", "Y",
11971 	"off", "on",
11972 	NULL,
11973 };
11974 
11975 /**
11976  * Parse a boolean value.
11977  *
11978  * Last argument (ctx->args) is retrieved to determine storage size and
11979  * location.
11980  */
11981 static int
11982 parse_boolean(struct context *ctx, const struct token *token,
11983 	      const char *str, unsigned int len,
11984 	      void *buf, unsigned int size)
11985 {
11986 	const struct arg *arg = pop_args(ctx);
11987 	unsigned int i;
11988 	int ret;
11989 
11990 	/* Argument is expected. */
11991 	if (!arg)
11992 		return -1;
11993 	for (i = 0; boolean_name[i]; ++i)
11994 		if (!strcmp_partial(boolean_name[i], str, len))
11995 			break;
11996 	/* Process token as integer. */
11997 	if (boolean_name[i])
11998 		str = i & 1 ? "1" : "0";
11999 	push_args(ctx, arg);
12000 	ret = parse_int(ctx, token, str, strlen(str), buf, size);
12001 	return ret > 0 ? (int)len : ret;
12002 }
12003 
12004 /** Parse port and update context. */
12005 static int
12006 parse_port(struct context *ctx, const struct token *token,
12007 	   const char *str, unsigned int len,
12008 	   void *buf, unsigned int size)
12009 {
12010 	struct buffer *out = &(struct buffer){ .port = 0 };
12011 	int ret;
12012 
12013 	if (buf)
12014 		out = buf;
12015 	else {
12016 		ctx->objdata = 0;
12017 		ctx->object = out;
12018 		ctx->objmask = NULL;
12019 		size = sizeof(*out);
12020 	}
12021 	ret = parse_int(ctx, token, str, len, out, size);
12022 	if (ret >= 0)
12023 		ctx->port = out->port;
12024 	if (!buf)
12025 		ctx->object = NULL;
12026 	return ret;
12027 }
12028 
12029 /** Parse tokens for shared indirect actions. */
12030 static int
12031 parse_ia_port(struct context *ctx, const struct token *token,
12032 	      const char *str, unsigned int len,
12033 	      void *buf, unsigned int size)
12034 {
12035 	struct rte_flow_action *action = ctx->object;
12036 	uint32_t id;
12037 	int ret;
12038 
12039 	(void)buf;
12040 	(void)size;
12041 	ctx->objdata = 0;
12042 	ctx->object = &id;
12043 	ctx->objmask = NULL;
12044 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12045 	ctx->object = action;
12046 	if (ret != (int)len)
12047 		return ret;
12048 	/* set indirect action */
12049 	if (action)
12050 		action->conf = (void *)(uintptr_t)id;
12051 	return ret;
12052 }
12053 
12054 static int
12055 parse_ia_id2ptr(struct context *ctx, const struct token *token,
12056 		const char *str, unsigned int len,
12057 		void *buf, unsigned int size)
12058 {
12059 	struct rte_flow_action *action = ctx->object;
12060 	uint32_t id;
12061 	int ret;
12062 
12063 	(void)buf;
12064 	(void)size;
12065 	ctx->objdata = 0;
12066 	ctx->object = &id;
12067 	ctx->objmask = NULL;
12068 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12069 	ctx->object = action;
12070 	if (ret != (int)len)
12071 		return ret;
12072 	/* set indirect action */
12073 	if (action) {
12074 		portid_t port_id = ctx->port;
12075 		if (ctx->prev == INDIRECT_ACTION_PORT)
12076 			port_id = (portid_t)(uintptr_t)action->conf;
12077 		action->conf = port_action_handle_get_by_id(port_id, id);
12078 		ret = (action->conf) ? ret : -1;
12079 	}
12080 	return ret;
12081 }
12082 
12083 static int
12084 parse_indlst_id2ptr(struct context *ctx, const struct token *token,
12085 		    const char *str, unsigned int len,
12086 		    __rte_unused void *buf, __rte_unused unsigned int size)
12087 {
12088 	struct rte_flow_action *action = ctx->object;
12089 	struct rte_flow_action_indirect_list *action_conf;
12090 	const struct indlst_conf *indlst_conf;
12091 	uint32_t id;
12092 	int ret;
12093 
12094 	ctx->objdata = 0;
12095 	ctx->object = &id;
12096 	ctx->objmask = NULL;
12097 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12098 	ctx->object = action;
12099 	if (ret != (int)len)
12100 		return ret;
12101 
12102 	/* set handle and conf */
12103 	if (action) {
12104 		action_conf = (void *)(uintptr_t)action->conf;
12105 		action_conf->conf = NULL;
12106 		switch (ctx->curr) {
12107 		case INDIRECT_LIST_ACTION_ID2PTR_HANDLE:
12108 		action_conf->handle = (typeof(action_conf->handle))
12109 					port_action_handle_get_by_id(ctx->port, id);
12110 			if (!action_conf->handle) {
12111 				printf("no indirect list handle for id %u\n", id);
12112 				return -1;
12113 			}
12114 			break;
12115 		case INDIRECT_LIST_ACTION_ID2PTR_CONF:
12116 			indlst_conf = indirect_action_list_conf_get(id);
12117 			if (!indlst_conf)
12118 				return -1;
12119 			action_conf->conf = (const void **)indlst_conf->conf;
12120 			break;
12121 		default:
12122 			break;
12123 		}
12124 	}
12125 	return ret;
12126 }
12127 
12128 static int
12129 parse_meter_profile_id2ptr(struct context *ctx, const struct token *token,
12130 		const char *str, unsigned int len,
12131 		void *buf, unsigned int size)
12132 {
12133 	struct rte_flow_action *action = ctx->object;
12134 	struct rte_flow_action_meter_mark *meter;
12135 	struct rte_flow_meter_profile *profile = NULL;
12136 	uint32_t id = 0;
12137 	int ret;
12138 
12139 	(void)buf;
12140 	(void)size;
12141 	ctx->objdata = 0;
12142 	ctx->object = &id;
12143 	ctx->objmask = NULL;
12144 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12145 	ctx->object = action;
12146 	if (ret != (int)len)
12147 		return ret;
12148 	/* set meter profile */
12149 	if (action) {
12150 		meter = (struct rte_flow_action_meter_mark *)
12151 			(uintptr_t)(action->conf);
12152 		profile = port_meter_profile_get_by_id(ctx->port, id);
12153 		meter->profile = profile;
12154 		ret = (profile) ? ret : -1;
12155 	}
12156 	return ret;
12157 }
12158 
12159 static int
12160 parse_meter_policy_id2ptr(struct context *ctx, const struct token *token,
12161 		const char *str, unsigned int len,
12162 		void *buf, unsigned int size)
12163 {
12164 	struct rte_flow_action *action = ctx->object;
12165 	struct rte_flow_action_meter_mark *meter;
12166 	struct rte_flow_meter_policy *policy = NULL;
12167 	uint32_t id = 0;
12168 	int ret;
12169 
12170 	(void)buf;
12171 	(void)size;
12172 	ctx->objdata = 0;
12173 	ctx->object = &id;
12174 	ctx->objmask = NULL;
12175 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12176 	ctx->object = action;
12177 	if (ret != (int)len)
12178 		return ret;
12179 	/* set meter policy */
12180 	if (action) {
12181 		meter = (struct rte_flow_action_meter_mark *)
12182 			(uintptr_t)(action->conf);
12183 		policy = port_meter_policy_get_by_id(ctx->port, id);
12184 		meter->policy = policy;
12185 		ret = (policy) ? ret : -1;
12186 	}
12187 	return ret;
12188 }
12189 
12190 /** Parse set command, initialize output buffer for subsequent tokens. */
12191 static int
12192 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
12193 			  const char *str, unsigned int len,
12194 			  void *buf, unsigned int size)
12195 {
12196 	struct buffer *out = buf;
12197 
12198 	/* Token name must match. */
12199 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12200 		return -1;
12201 	/* Nothing else to do if there is no buffer. */
12202 	if (!out)
12203 		return len;
12204 	/* Make sure buffer is large enough. */
12205 	if (size < sizeof(*out))
12206 		return -1;
12207 	ctx->objdata = 0;
12208 	ctx->objmask = NULL;
12209 	ctx->object = out;
12210 	if (!out->command)
12211 		return -1;
12212 	out->command = ctx->curr;
12213 	/* For encap/decap we need is pattern */
12214 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12215 						       sizeof(double));
12216 	return len;
12217 }
12218 
12219 /** Parse set command, initialize output buffer for subsequent tokens. */
12220 static int
12221 parse_set_sample_action(struct context *ctx, const struct token *token,
12222 			  const char *str, unsigned int len,
12223 			  void *buf, unsigned int size)
12224 {
12225 	struct buffer *out = buf;
12226 
12227 	/* Token name must match. */
12228 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12229 		return -1;
12230 	/* Nothing else to do if there is no buffer. */
12231 	if (!out)
12232 		return len;
12233 	/* Make sure buffer is large enough. */
12234 	if (size < sizeof(*out))
12235 		return -1;
12236 	ctx->objdata = 0;
12237 	ctx->objmask = NULL;
12238 	ctx->object = out;
12239 	if (!out->command)
12240 		return -1;
12241 	out->command = ctx->curr;
12242 	/* For sampler we need is actions */
12243 	out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12244 						       sizeof(double));
12245 	return len;
12246 }
12247 
12248 /** Parse set command, initialize output buffer for subsequent tokens. */
12249 static int
12250 parse_set_ipv6_ext_action(struct context *ctx, const struct token *token,
12251 			  const char *str, unsigned int len,
12252 			  void *buf, unsigned int size)
12253 {
12254 	struct buffer *out = buf;
12255 
12256 	/* Token name must match. */
12257 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12258 		return -1;
12259 	/* Nothing else to do if there is no buffer. */
12260 	if (!out)
12261 		return len;
12262 	/* Make sure buffer is large enough. */
12263 	if (size < sizeof(*out))
12264 		return -1;
12265 	ctx->objdata = 0;
12266 	ctx->objmask = NULL;
12267 	ctx->object = out;
12268 	if (!out->command)
12269 		return -1;
12270 	out->command = ctx->curr;
12271 	/* For ipv6_ext_push/remove we need is pattern */
12272 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12273 						       sizeof(double));
12274 	return len;
12275 }
12276 
12277 /**
12278  * Parse set raw_encap/raw_decap command,
12279  * initialize output buffer for subsequent tokens.
12280  */
12281 static int
12282 parse_set_init(struct context *ctx, const struct token *token,
12283 	       const char *str, unsigned int len,
12284 	       void *buf, unsigned int size)
12285 {
12286 	struct buffer *out = buf;
12287 
12288 	/* Token name must match. */
12289 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12290 		return -1;
12291 	/* Nothing else to do if there is no buffer. */
12292 	if (!out)
12293 		return len;
12294 	/* Make sure buffer is large enough. */
12295 	if (size < sizeof(*out))
12296 		return -1;
12297 	/* Initialize buffer. */
12298 	memset(out, 0x00, sizeof(*out));
12299 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
12300 	ctx->objdata = 0;
12301 	ctx->object = out;
12302 	ctx->objmask = NULL;
12303 	if (!out->command) {
12304 		if (ctx->curr != SET)
12305 			return -1;
12306 		if (sizeof(*out) > size)
12307 			return -1;
12308 		out->command = ctx->curr;
12309 		out->args.vc.data = (uint8_t *)out + size;
12310 		ctx->object  = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12311 						       sizeof(double));
12312 	}
12313 	return len;
12314 }
12315 
12316 /*
12317  * Replace testpmd handles in a flex flow item with real values.
12318  */
12319 static int
12320 parse_flex_handle(struct context *ctx, const struct token *token,
12321 		  const char *str, unsigned int len,
12322 		  void *buf, unsigned int size)
12323 {
12324 	struct rte_flow_item_flex *spec, *mask;
12325 	const struct rte_flow_item_flex *src_spec, *src_mask;
12326 	const struct arg *arg = pop_args(ctx);
12327 	uint32_t offset;
12328 	uint16_t handle;
12329 	int ret;
12330 
12331 	if (!arg) {
12332 		printf("Bad environment\n");
12333 		return -1;
12334 	}
12335 	offset = arg->offset;
12336 	push_args(ctx, arg);
12337 	ret = parse_int(ctx, token, str, len, buf, size);
12338 	if (ret <= 0 || !ctx->object)
12339 		return ret;
12340 	if (ctx->port >= RTE_MAX_ETHPORTS) {
12341 		printf("Bad port\n");
12342 		return -1;
12343 	}
12344 	if (offset == offsetof(struct rte_flow_item_flex, handle)) {
12345 		const struct flex_item *fp;
12346 		spec = ctx->object;
12347 		handle = (uint16_t)(uintptr_t)spec->handle;
12348 		if (handle >= FLEX_MAX_PARSERS_NUM) {
12349 			printf("Bad flex item handle\n");
12350 			return -1;
12351 		}
12352 		fp = flex_items[ctx->port][handle];
12353 		if (!fp) {
12354 			printf("Bad flex item handle\n");
12355 			return -1;
12356 		}
12357 		spec->handle = fp->flex_handle;
12358 		mask = spec + 2; /* spec, last, mask */
12359 		mask->handle = fp->flex_handle;
12360 	} else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
12361 		handle = (uint16_t)(uintptr_t)
12362 			((struct rte_flow_item_flex *)ctx->object)->pattern;
12363 		if (handle >= FLEX_MAX_PATTERNS_NUM) {
12364 			printf("Bad pattern handle\n");
12365 			return -1;
12366 		}
12367 		src_spec = &flex_patterns[handle].spec;
12368 		src_mask = &flex_patterns[handle].mask;
12369 		spec = ctx->object;
12370 		mask = spec + 2; /* spec, last, mask */
12371 		/* fill flow rule spec and mask parameters */
12372 		spec->length = src_spec->length;
12373 		spec->pattern = src_spec->pattern;
12374 		mask->length = src_mask->length;
12375 		mask->pattern = src_mask->pattern;
12376 	} else {
12377 		printf("Bad arguments - unknown flex item offset\n");
12378 		return -1;
12379 	}
12380 	return ret;
12381 }
12382 
12383 /** Parse Meter color name */
12384 static int
12385 parse_meter_color(struct context *ctx, const struct token *token,
12386 		  const char *str, unsigned int len, void *buf,
12387 		  unsigned int size)
12388 {
12389 	struct rte_flow_item_meter_color *meter_color;
12390 	unsigned int i;
12391 
12392 	(void)token;
12393 	(void)buf;
12394 	(void)size;
12395 	for (i = 0; meter_colors[i]; ++i)
12396 		if (!strcmp_partial(meter_colors[i], str, len))
12397 			break;
12398 	if (!meter_colors[i])
12399 		return -1;
12400 	if (!ctx->object)
12401 		return len;
12402 	meter_color = ctx->object;
12403 	meter_color->color = (enum rte_color)i;
12404 	return len;
12405 }
12406 
12407 /** Parse Insertion Table Type name */
12408 static int
12409 parse_insertion_table_type(struct context *ctx, const struct token *token,
12410 			   const char *str, unsigned int len, void *buf,
12411 			   unsigned int size)
12412 {
12413 	const struct arg *arg = pop_args(ctx);
12414 	unsigned int i;
12415 	char tmp[2];
12416 	int ret;
12417 
12418 	(void)size;
12419 	/* Argument is expected. */
12420 	if (!arg)
12421 		return -1;
12422 	for (i = 0; table_insertion_types[i]; ++i)
12423 		if (!strcmp_partial(table_insertion_types[i], str, len))
12424 			break;
12425 	if (!table_insertion_types[i])
12426 		return -1;
12427 	push_args(ctx, arg);
12428 	snprintf(tmp, sizeof(tmp), "%u", i);
12429 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12430 	return ret > 0 ? (int)len : ret;
12431 }
12432 
12433 /** Parse Hash Calculation Table Type name */
12434 static int
12435 parse_hash_table_type(struct context *ctx, const struct token *token,
12436 		      const char *str, unsigned int len, void *buf,
12437 		      unsigned int size)
12438 {
12439 	const struct arg *arg = pop_args(ctx);
12440 	unsigned int i;
12441 	char tmp[2];
12442 	int ret;
12443 
12444 	(void)size;
12445 	/* Argument is expected. */
12446 	if (!arg)
12447 		return -1;
12448 	for (i = 0; table_hash_funcs[i]; ++i)
12449 		if (!strcmp_partial(table_hash_funcs[i], str, len))
12450 			break;
12451 	if (!table_hash_funcs[i])
12452 		return -1;
12453 	push_args(ctx, arg);
12454 	snprintf(tmp, sizeof(tmp), "%u", i);
12455 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12456 	return ret > 0 ? (int)len : ret;
12457 }
12458 
12459 static int
12460 parse_name_to_index(struct context *ctx, const struct token *token,
12461 		    const char *str, unsigned int len, void *buf,
12462 		    unsigned int size,
12463 		    const char *const names[], size_t names_size, uint32_t *dst)
12464 {
12465 	int ret;
12466 	uint32_t i;
12467 
12468 	RTE_SET_USED(token);
12469 	RTE_SET_USED(buf);
12470 	RTE_SET_USED(size);
12471 	if (!ctx->object)
12472 		return len;
12473 	for (i = 0; i < names_size; i++) {
12474 		if (!names[i])
12475 			continue;
12476 		ret = strcmp_partial(names[i], str,
12477 				     RTE_MIN(len, strlen(names[i])));
12478 		if (!ret) {
12479 			*dst = i;
12480 			return len;
12481 		}
12482 	}
12483 	return -1;
12484 }
12485 
12486 static const char *const quota_mode_names[] = {
12487 	NULL,
12488 	[RTE_FLOW_QUOTA_MODE_PACKET] = "packet",
12489 	[RTE_FLOW_QUOTA_MODE_L2] = "l2",
12490 	[RTE_FLOW_QUOTA_MODE_L3] = "l3"
12491 };
12492 
12493 static const char *const quota_state_names[] = {
12494 	[RTE_FLOW_QUOTA_STATE_PASS] = "pass",
12495 	[RTE_FLOW_QUOTA_STATE_BLOCK] = "block"
12496 };
12497 
12498 static const char *const quota_update_names[] = {
12499 	[RTE_FLOW_UPDATE_QUOTA_SET] = "set",
12500 	[RTE_FLOW_UPDATE_QUOTA_ADD] = "add"
12501 };
12502 
12503 static const char *const query_update_mode_names[] = {
12504 	[RTE_FLOW_QU_QUERY_FIRST] = "query_first",
12505 	[RTE_FLOW_QU_UPDATE_FIRST] = "update_first"
12506 };
12507 
12508 static int
12509 parse_quota_state_name(struct context *ctx, const struct token *token,
12510 		       const char *str, unsigned int len, void *buf,
12511 		       unsigned int size)
12512 {
12513 	struct rte_flow_item_quota *quota = ctx->object;
12514 
12515 	return parse_name_to_index(ctx, token, str, len, buf, size,
12516 				   quota_state_names,
12517 				   RTE_DIM(quota_state_names),
12518 				   (uint32_t *)&quota->state);
12519 }
12520 
12521 static int
12522 parse_quota_mode_name(struct context *ctx, const struct token *token,
12523 		      const char *str, unsigned int len, void *buf,
12524 		      unsigned int size)
12525 {
12526 	struct rte_flow_action_quota *quota = ctx->object;
12527 
12528 	return parse_name_to_index(ctx, token, str, len, buf, size,
12529 				   quota_mode_names,
12530 				   RTE_DIM(quota_mode_names),
12531 				   (uint32_t *)&quota->mode);
12532 }
12533 
12534 static int
12535 parse_quota_update_name(struct context *ctx, const struct token *token,
12536 			const char *str, unsigned int len, void *buf,
12537 			unsigned int size)
12538 {
12539 	struct rte_flow_update_quota *update = ctx->object;
12540 
12541 	return parse_name_to_index(ctx, token, str, len, buf, size,
12542 				   quota_update_names,
12543 				   RTE_DIM(quota_update_names),
12544 				   (uint32_t *)&update->op);
12545 }
12546 
12547 static int
12548 parse_qu_mode_name(struct context *ctx, const struct token *token,
12549 		   const char *str, unsigned int len, void *buf,
12550 		   unsigned int size)
12551 {
12552 	struct buffer *out = ctx->object;
12553 
12554 	return parse_name_to_index(ctx, token, str, len, buf, size,
12555 				   query_update_mode_names,
12556 				   RTE_DIM(query_update_mode_names),
12557 				   (uint32_t *)&out->args.ia.qu_mode);
12558 }
12559 
12560 /** No completion. */
12561 static int
12562 comp_none(struct context *ctx, const struct token *token,
12563 	  unsigned int ent, char *buf, unsigned int size)
12564 {
12565 	(void)ctx;
12566 	(void)token;
12567 	(void)ent;
12568 	(void)buf;
12569 	(void)size;
12570 	return 0;
12571 }
12572 
12573 /** Complete boolean values. */
12574 static int
12575 comp_boolean(struct context *ctx, const struct token *token,
12576 	     unsigned int ent, char *buf, unsigned int size)
12577 {
12578 	unsigned int i;
12579 
12580 	(void)ctx;
12581 	(void)token;
12582 	for (i = 0; boolean_name[i]; ++i)
12583 		if (buf && i == ent)
12584 			return strlcpy(buf, boolean_name[i], size);
12585 	if (buf)
12586 		return -1;
12587 	return i;
12588 }
12589 
12590 /** Complete action names. */
12591 static int
12592 comp_action(struct context *ctx, const struct token *token,
12593 	    unsigned int ent, char *buf, unsigned int size)
12594 {
12595 	unsigned int i;
12596 
12597 	(void)ctx;
12598 	(void)token;
12599 	for (i = 0; next_action[i]; ++i)
12600 		if (buf && i == ent)
12601 			return strlcpy(buf, token_list[next_action[i]].name,
12602 				       size);
12603 	if (buf)
12604 		return -1;
12605 	return i;
12606 }
12607 
12608 /** Complete available ports. */
12609 static int
12610 comp_port(struct context *ctx, const struct token *token,
12611 	  unsigned int ent, char *buf, unsigned int size)
12612 {
12613 	unsigned int i = 0;
12614 	portid_t p;
12615 
12616 	(void)ctx;
12617 	(void)token;
12618 	RTE_ETH_FOREACH_DEV(p) {
12619 		if (buf && i == ent)
12620 			return snprintf(buf, size, "%u", p);
12621 		++i;
12622 	}
12623 	if (buf)
12624 		return -1;
12625 	return i;
12626 }
12627 
12628 /** Complete available rule IDs. */
12629 static int
12630 comp_rule_id(struct context *ctx, const struct token *token,
12631 	     unsigned int ent, char *buf, unsigned int size)
12632 {
12633 	unsigned int i = 0;
12634 	struct rte_port *port;
12635 	struct port_flow *pf;
12636 
12637 	(void)token;
12638 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12639 	    ctx->port == (portid_t)RTE_PORT_ALL)
12640 		return -1;
12641 	port = &ports[ctx->port];
12642 	for (pf = port->flow_list; pf != NULL; pf = pf->next) {
12643 		if (buf && i == ent)
12644 			return snprintf(buf, size, "%"PRIu64, pf->id);
12645 		++i;
12646 	}
12647 	if (buf)
12648 		return -1;
12649 	return i;
12650 }
12651 
12652 /** Complete operation for compare match item. */
12653 static int
12654 comp_set_compare_op(struct context *ctx, const struct token *token,
12655 		    unsigned int ent, char *buf, unsigned int size)
12656 {
12657 	RTE_SET_USED(ctx);
12658 	RTE_SET_USED(token);
12659 	if (!buf)
12660 		return RTE_DIM(compare_ops);
12661 	if (ent < RTE_DIM(compare_ops) - 1)
12662 		return strlcpy(buf, compare_ops[ent], size);
12663 	return -1;
12664 }
12665 
12666 /** Complete field id for compare match item. */
12667 static int
12668 comp_set_compare_field_id(struct context *ctx, const struct token *token,
12669 			  unsigned int ent, char *buf, unsigned int size)
12670 {
12671 	const char *name;
12672 
12673 	RTE_SET_USED(token);
12674 	if (!buf)
12675 		return RTE_DIM(flow_field_ids);
12676 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12677 		return -1;
12678 	name = flow_field_ids[ent];
12679 	if (ctx->curr == ITEM_COMPARE_FIELD_B_TYPE ||
12680 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12681 		return strlcpy(buf, name, size);
12682 	return -1;
12683 }
12684 
12685 /** Complete type field for RSS action. */
12686 static int
12687 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
12688 			unsigned int ent, char *buf, unsigned int size)
12689 {
12690 	unsigned int i;
12691 
12692 	(void)ctx;
12693 	(void)token;
12694 	for (i = 0; rss_type_table[i].str; ++i)
12695 		;
12696 	if (!buf)
12697 		return i + 1;
12698 	if (ent < i)
12699 		return strlcpy(buf, rss_type_table[ent].str, size);
12700 	if (ent == i)
12701 		return snprintf(buf, size, "end");
12702 	return -1;
12703 }
12704 
12705 /** Complete queue field for RSS action. */
12706 static int
12707 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
12708 			 unsigned int ent, char *buf, unsigned int size)
12709 {
12710 	(void)ctx;
12711 	(void)token;
12712 	if (!buf)
12713 		return nb_rxq + 1;
12714 	if (ent < nb_rxq)
12715 		return snprintf(buf, size, "%u", ent);
12716 	if (ent == nb_rxq)
12717 		return snprintf(buf, size, "end");
12718 	return -1;
12719 }
12720 
12721 /** Complete index number for set raw_encap/raw_decap commands. */
12722 static int
12723 comp_set_raw_index(struct context *ctx, const struct token *token,
12724 		   unsigned int ent, char *buf, unsigned int size)
12725 {
12726 	uint16_t idx = 0;
12727 	uint16_t nb = 0;
12728 
12729 	RTE_SET_USED(ctx);
12730 	RTE_SET_USED(token);
12731 	for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
12732 		if (buf && idx == ent)
12733 			return snprintf(buf, size, "%u", idx);
12734 		++nb;
12735 	}
12736 	return nb;
12737 }
12738 
12739 /** Complete index number for set raw_ipv6_ext_push/ipv6_ext_remove commands. */
12740 static int
12741 comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
12742 			unsigned int ent, char *buf, unsigned int size)
12743 {
12744 	uint16_t idx = 0;
12745 	uint16_t nb = 0;
12746 
12747 	RTE_SET_USED(ctx);
12748 	RTE_SET_USED(token);
12749 	for (idx = 0; idx < IPV6_EXT_PUSH_CONFS_MAX_NUM; ++idx) {
12750 		if (buf && idx == ent)
12751 			return snprintf(buf, size, "%u", idx);
12752 		++nb;
12753 	}
12754 	return nb;
12755 }
12756 
12757 /** Complete index number for set raw_encap/raw_decap commands. */
12758 static int
12759 comp_set_sample_index(struct context *ctx, const struct token *token,
12760 		   unsigned int ent, char *buf, unsigned int size)
12761 {
12762 	uint16_t idx = 0;
12763 	uint16_t nb = 0;
12764 
12765 	RTE_SET_USED(ctx);
12766 	RTE_SET_USED(token);
12767 	for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
12768 		if (buf && idx == ent)
12769 			return snprintf(buf, size, "%u", idx);
12770 		++nb;
12771 	}
12772 	return nb;
12773 }
12774 
12775 /** Complete operation for modify_field command. */
12776 static int
12777 comp_set_modify_field_op(struct context *ctx, const struct token *token,
12778 		   unsigned int ent, char *buf, unsigned int size)
12779 {
12780 	RTE_SET_USED(ctx);
12781 	RTE_SET_USED(token);
12782 	if (!buf)
12783 		return RTE_DIM(modify_field_ops);
12784 	if (ent < RTE_DIM(modify_field_ops) - 1)
12785 		return strlcpy(buf, modify_field_ops[ent], size);
12786 	return -1;
12787 }
12788 
12789 /** Complete field id for modify_field command. */
12790 static int
12791 comp_set_modify_field_id(struct context *ctx, const struct token *token,
12792 		   unsigned int ent, char *buf, unsigned int size)
12793 {
12794 	const char *name;
12795 
12796 	RTE_SET_USED(token);
12797 	if (!buf)
12798 		return RTE_DIM(flow_field_ids);
12799 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12800 		return -1;
12801 	name = flow_field_ids[ent];
12802 	if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
12803 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12804 		return strlcpy(buf, name, size);
12805 	return -1;
12806 }
12807 
12808 /** Complete available pattern template IDs. */
12809 static int
12810 comp_pattern_template_id(struct context *ctx, const struct token *token,
12811 			 unsigned int ent, char *buf, unsigned int size)
12812 {
12813 	unsigned int i = 0;
12814 	struct rte_port *port;
12815 	struct port_template *pt;
12816 
12817 	(void)token;
12818 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12819 	    ctx->port == (portid_t)RTE_PORT_ALL)
12820 		return -1;
12821 	port = &ports[ctx->port];
12822 	for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) {
12823 		if (buf && i == ent)
12824 			return snprintf(buf, size, "%u", pt->id);
12825 		++i;
12826 	}
12827 	if (buf)
12828 		return -1;
12829 	return i;
12830 }
12831 
12832 /** Complete available actions template IDs. */
12833 static int
12834 comp_actions_template_id(struct context *ctx, const struct token *token,
12835 			 unsigned int ent, char *buf, unsigned int size)
12836 {
12837 	unsigned int i = 0;
12838 	struct rte_port *port;
12839 	struct port_template *pt;
12840 
12841 	(void)token;
12842 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12843 	    ctx->port == (portid_t)RTE_PORT_ALL)
12844 		return -1;
12845 	port = &ports[ctx->port];
12846 	for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) {
12847 		if (buf && i == ent)
12848 			return snprintf(buf, size, "%u", pt->id);
12849 		++i;
12850 	}
12851 	if (buf)
12852 		return -1;
12853 	return i;
12854 }
12855 
12856 /** Complete available table IDs. */
12857 static int
12858 comp_table_id(struct context *ctx, const struct token *token,
12859 	      unsigned int ent, char *buf, unsigned int size)
12860 {
12861 	unsigned int i = 0;
12862 	struct rte_port *port;
12863 	struct port_table *pt;
12864 
12865 	(void)token;
12866 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12867 	    ctx->port == (portid_t)RTE_PORT_ALL)
12868 		return -1;
12869 	port = &ports[ctx->port];
12870 	for (pt = port->table_list; pt != NULL; pt = pt->next) {
12871 		if (buf && i == ent)
12872 			return snprintf(buf, size, "%u", pt->id);
12873 		++i;
12874 	}
12875 	if (buf)
12876 		return -1;
12877 	return i;
12878 }
12879 
12880 /** Complete available queue IDs. */
12881 static int
12882 comp_queue_id(struct context *ctx, const struct token *token,
12883 	      unsigned int ent, char *buf, unsigned int size)
12884 {
12885 	unsigned int i = 0;
12886 	struct rte_port *port;
12887 
12888 	(void)token;
12889 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12890 	    ctx->port == (portid_t)RTE_PORT_ALL)
12891 		return -1;
12892 	port = &ports[ctx->port];
12893 	for (i = 0; i < port->queue_nb; i++) {
12894 		if (buf && i == ent)
12895 			return snprintf(buf, size, "%u", i);
12896 	}
12897 	if (buf)
12898 		return -1;
12899 	return i;
12900 }
12901 
12902 static int
12903 comp_names_to_index(struct context *ctx, const struct token *token,
12904 		    unsigned int ent, char *buf, unsigned int size,
12905 		    const char *const names[], size_t names_size)
12906 {
12907 	RTE_SET_USED(ctx);
12908 	RTE_SET_USED(token);
12909 	if (!buf)
12910 		return names_size;
12911 	if (names[ent] && ent < names_size)
12912 		return rte_strscpy(buf, names[ent], size);
12913 	return -1;
12914 
12915 }
12916 
12917 /** Complete available Meter colors. */
12918 static int
12919 comp_meter_color(struct context *ctx, const struct token *token,
12920 		 unsigned int ent, char *buf, unsigned int size)
12921 {
12922 	RTE_SET_USED(ctx);
12923 	RTE_SET_USED(token);
12924 	if (!buf)
12925 		return RTE_DIM(meter_colors);
12926 	if (ent < RTE_DIM(meter_colors) - 1)
12927 		return strlcpy(buf, meter_colors[ent], size);
12928 	return -1;
12929 }
12930 
12931 /** Complete available Insertion Table types. */
12932 static int
12933 comp_insertion_table_type(struct context *ctx, const struct token *token,
12934 			  unsigned int ent, char *buf, unsigned int size)
12935 {
12936 	RTE_SET_USED(ctx);
12937 	RTE_SET_USED(token);
12938 	if (!buf)
12939 		return RTE_DIM(table_insertion_types);
12940 	if (ent < RTE_DIM(table_insertion_types) - 1)
12941 		return rte_strscpy(buf, table_insertion_types[ent], size);
12942 	return -1;
12943 }
12944 
12945 /** Complete available Hash Calculation Table types. */
12946 static int
12947 comp_hash_table_type(struct context *ctx, const struct token *token,
12948 		     unsigned int ent, char *buf, unsigned int size)
12949 {
12950 	RTE_SET_USED(ctx);
12951 	RTE_SET_USED(token);
12952 	if (!buf)
12953 		return RTE_DIM(table_hash_funcs);
12954 	if (ent < RTE_DIM(table_hash_funcs) - 1)
12955 		return rte_strscpy(buf, table_hash_funcs[ent], size);
12956 	return -1;
12957 }
12958 
12959 static int
12960 comp_quota_state_name(struct context *ctx, const struct token *token,
12961 		      unsigned int ent, char *buf, unsigned int size)
12962 {
12963 	return comp_names_to_index(ctx, token, ent, buf, size,
12964 				   quota_state_names,
12965 				   RTE_DIM(quota_state_names));
12966 }
12967 
12968 static int
12969 comp_quota_mode_name(struct context *ctx, const struct token *token,
12970 		     unsigned int ent, char *buf, unsigned int size)
12971 {
12972 	return comp_names_to_index(ctx, token, ent, buf, size,
12973 				   quota_mode_names,
12974 				   RTE_DIM(quota_mode_names));
12975 }
12976 
12977 static int
12978 comp_quota_update_name(struct context *ctx, const struct token *token,
12979 		       unsigned int ent, char *buf, unsigned int size)
12980 {
12981 	return comp_names_to_index(ctx, token, ent, buf, size,
12982 				   quota_update_names,
12983 				   RTE_DIM(quota_update_names));
12984 }
12985 
12986 static int
12987 comp_qu_mode_name(struct context *ctx, const struct token *token,
12988 		  unsigned int ent, char *buf, unsigned int size)
12989 {
12990 	return comp_names_to_index(ctx, token, ent, buf, size,
12991 				   query_update_mode_names,
12992 				   RTE_DIM(query_update_mode_names));
12993 }
12994 
12995 /** Internal context. */
12996 static struct context cmd_flow_context;
12997 
12998 /** Global parser instance (cmdline API). */
12999 cmdline_parse_inst_t cmd_flow;
13000 cmdline_parse_inst_t cmd_set_raw;
13001 
13002 /** Initialize context. */
13003 static void
13004 cmd_flow_context_init(struct context *ctx)
13005 {
13006 	/* A full memset() is not necessary. */
13007 	ctx->curr = ZERO;
13008 	ctx->prev = ZERO;
13009 	ctx->next_num = 0;
13010 	ctx->args_num = 0;
13011 	ctx->eol = 0;
13012 	ctx->last = 0;
13013 	ctx->port = 0;
13014 	ctx->objdata = 0;
13015 	ctx->object = NULL;
13016 	ctx->objmask = NULL;
13017 }
13018 
13019 /** Parse a token (cmdline API). */
13020 static int
13021 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
13022 	       unsigned int size)
13023 {
13024 	struct context *ctx = &cmd_flow_context;
13025 	const struct token *token;
13026 	const enum index *list;
13027 	int len;
13028 	int i;
13029 
13030 	(void)hdr;
13031 	token = &token_list[ctx->curr];
13032 	/* Check argument length. */
13033 	ctx->eol = 0;
13034 	ctx->last = 1;
13035 	for (len = 0; src[len]; ++len)
13036 		if (src[len] == '#' || isspace(src[len]))
13037 			break;
13038 	if (!len)
13039 		return -1;
13040 	/* Last argument and EOL detection. */
13041 	for (i = len; src[i]; ++i)
13042 		if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
13043 			break;
13044 		else if (!isspace(src[i])) {
13045 			ctx->last = 0;
13046 			break;
13047 		}
13048 	for (; src[i]; ++i)
13049 		if (src[i] == '\r' || src[i] == '\n') {
13050 			ctx->eol = 1;
13051 			break;
13052 		}
13053 	/* Initialize context if necessary. */
13054 	if (!ctx->next_num) {
13055 		if (!token->next)
13056 			return 0;
13057 		ctx->next[ctx->next_num++] = token->next[0];
13058 	}
13059 	/* Process argument through candidates. */
13060 	ctx->prev = ctx->curr;
13061 	list = ctx->next[ctx->next_num - 1];
13062 	for (i = 0; list[i]; ++i) {
13063 		const struct token *next = &token_list[list[i]];
13064 		int tmp;
13065 
13066 		ctx->curr = list[i];
13067 		if (next->call)
13068 			tmp = next->call(ctx, next, src, len, result, size);
13069 		else
13070 			tmp = parse_default(ctx, next, src, len, result, size);
13071 		if (tmp == -1 || tmp != len)
13072 			continue;
13073 		token = next;
13074 		break;
13075 	}
13076 	if (!list[i])
13077 		return -1;
13078 	--ctx->next_num;
13079 	/* Push subsequent tokens if any. */
13080 	if (token->next)
13081 		for (i = 0; token->next[i]; ++i) {
13082 			if (ctx->next_num == RTE_DIM(ctx->next))
13083 				return -1;
13084 			ctx->next[ctx->next_num++] = token->next[i];
13085 		}
13086 	/* Push arguments if any. */
13087 	if (token->args)
13088 		for (i = 0; token->args[i]; ++i) {
13089 			if (ctx->args_num == RTE_DIM(ctx->args))
13090 				return -1;
13091 			ctx->args[ctx->args_num++] = token->args[i];
13092 		}
13093 	return len;
13094 }
13095 
13096 int
13097 flow_parse(const char *src, void *result, unsigned int size,
13098 	   struct rte_flow_attr **attr,
13099 	   struct rte_flow_item **pattern, struct rte_flow_action **actions)
13100 {
13101 	int ret;
13102 	struct context saved_flow_ctx = cmd_flow_context;
13103 
13104 	cmd_flow_context_init(&cmd_flow_context);
13105 	do {
13106 		ret = cmd_flow_parse(NULL, src, result, size);
13107 		if (ret > 0) {
13108 			src += ret;
13109 			while (isspace(*src))
13110 				src++;
13111 		}
13112 	} while (ret > 0 && strlen(src));
13113 	cmd_flow_context = saved_flow_ctx;
13114 	*attr = &((struct buffer *)result)->args.vc.attr;
13115 	*pattern = ((struct buffer *)result)->args.vc.pattern;
13116 	*actions = ((struct buffer *)result)->args.vc.actions;
13117 	return (ret >= 0 && !strlen(src)) ? 0 : -1;
13118 }
13119 
13120 /** Return number of completion entries (cmdline API). */
13121 static int
13122 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
13123 {
13124 	struct context *ctx = &cmd_flow_context;
13125 	const struct token *token = &token_list[ctx->curr];
13126 	const enum index *list;
13127 	int i;
13128 
13129 	(void)hdr;
13130 	/* Count number of tokens in current list. */
13131 	if (ctx->next_num)
13132 		list = ctx->next[ctx->next_num - 1];
13133 	else
13134 		list = token->next[0];
13135 	for (i = 0; list[i]; ++i)
13136 		;
13137 	if (!i)
13138 		return 0;
13139 	/*
13140 	 * If there is a single token, use its completion callback, otherwise
13141 	 * return the number of entries.
13142 	 */
13143 	token = &token_list[list[0]];
13144 	if (i == 1 && token->comp) {
13145 		/* Save index for cmd_flow_get_help(). */
13146 		ctx->prev = list[0];
13147 		return token->comp(ctx, token, 0, NULL, 0);
13148 	}
13149 	return i;
13150 }
13151 
13152 /** Return a completion entry (cmdline API). */
13153 static int
13154 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
13155 			  char *dst, unsigned int size)
13156 {
13157 	struct context *ctx = &cmd_flow_context;
13158 	const struct token *token = &token_list[ctx->curr];
13159 	const enum index *list;
13160 	int i;
13161 
13162 	(void)hdr;
13163 	/* Count number of tokens in current list. */
13164 	if (ctx->next_num)
13165 		list = ctx->next[ctx->next_num - 1];
13166 	else
13167 		list = token->next[0];
13168 	for (i = 0; list[i]; ++i)
13169 		;
13170 	if (!i)
13171 		return -1;
13172 	/* If there is a single token, use its completion callback. */
13173 	token = &token_list[list[0]];
13174 	if (i == 1 && token->comp) {
13175 		/* Save index for cmd_flow_get_help(). */
13176 		ctx->prev = list[0];
13177 		return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
13178 	}
13179 	/* Otherwise make sure the index is valid and use defaults. */
13180 	if (index >= i)
13181 		return -1;
13182 	token = &token_list[list[index]];
13183 	strlcpy(dst, token->name, size);
13184 	/* Save index for cmd_flow_get_help(). */
13185 	ctx->prev = list[index];
13186 	return 0;
13187 }
13188 
13189 /** Populate help strings for current token (cmdline API). */
13190 static int
13191 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
13192 {
13193 	struct context *ctx = &cmd_flow_context;
13194 	const struct token *token = &token_list[ctx->prev];
13195 
13196 	(void)hdr;
13197 	if (!size)
13198 		return -1;
13199 	/* Set token type and update global help with details. */
13200 	strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
13201 	if (token->help)
13202 		cmd_flow.help_str = token->help;
13203 	else
13204 		cmd_flow.help_str = token->name;
13205 	return 0;
13206 }
13207 
13208 /** Token definition template (cmdline API). */
13209 static struct cmdline_token_hdr cmd_flow_token_hdr = {
13210 	.ops = &(struct cmdline_token_ops){
13211 		.parse = cmd_flow_parse,
13212 		.complete_get_nb = cmd_flow_complete_get_nb,
13213 		.complete_get_elt = cmd_flow_complete_get_elt,
13214 		.get_help = cmd_flow_get_help,
13215 	},
13216 	.offset = 0,
13217 };
13218 
13219 /** Populate the next dynamic token. */
13220 static void
13221 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
13222 	     cmdline_parse_token_hdr_t **hdr_inst)
13223 {
13224 	struct context *ctx = &cmd_flow_context;
13225 
13226 	/* Always reinitialize context before requesting the first token. */
13227 	if (!(hdr_inst - cmd_flow.tokens))
13228 		cmd_flow_context_init(ctx);
13229 	/* Return NULL when no more tokens are expected. */
13230 	if (!ctx->next_num && ctx->curr) {
13231 		*hdr = NULL;
13232 		return;
13233 	}
13234 	/* Determine if command should end here. */
13235 	if (ctx->eol && ctx->last && ctx->next_num) {
13236 		const enum index *list = ctx->next[ctx->next_num - 1];
13237 		int i;
13238 
13239 		for (i = 0; list[i]; ++i) {
13240 			if (list[i] != END)
13241 				continue;
13242 			*hdr = NULL;
13243 			return;
13244 		}
13245 	}
13246 	*hdr = &cmd_flow_token_hdr;
13247 }
13248 
13249 static SLIST_HEAD(, indlst_conf) indlst_conf_head =
13250 	SLIST_HEAD_INITIALIZER();
13251 
13252 static void
13253 indirect_action_flow_conf_create(const struct buffer *in)
13254 {
13255 	int len, ret;
13256 	uint32_t i;
13257 	struct indlst_conf *indlst_conf = NULL;
13258 	size_t base = RTE_ALIGN(sizeof(*indlst_conf), 8);
13259 	struct rte_flow_action *src = in->args.vc.actions;
13260 
13261 	if (!in->args.vc.actions_n)
13262 		goto end;
13263 	len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, src, NULL);
13264 	if (len <= 0)
13265 		goto end;
13266 	len = RTE_ALIGN(len, 16);
13267 
13268 	indlst_conf = calloc(1, base + len +
13269 			     in->args.vc.actions_n * sizeof(uintptr_t));
13270 	if (!indlst_conf)
13271 		goto end;
13272 	indlst_conf->id = in->args.vc.attr.group;
13273 	indlst_conf->conf_num = in->args.vc.actions_n - 1;
13274 	indlst_conf->actions = RTE_PTR_ADD(indlst_conf, base);
13275 	ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, indlst_conf->actions,
13276 			    len, src, NULL);
13277 	if (ret <= 0) {
13278 		free(indlst_conf);
13279 		indlst_conf = NULL;
13280 		goto end;
13281 	}
13282 	indlst_conf->conf = RTE_PTR_ADD(indlst_conf, base + len);
13283 	for (i = 0; i < indlst_conf->conf_num; i++)
13284 		indlst_conf->conf[i] = indlst_conf->actions[i].conf;
13285 	SLIST_INSERT_HEAD(&indlst_conf_head, indlst_conf, next);
13286 end:
13287 	if (indlst_conf)
13288 		printf("created indirect action list configuration %u\n",
13289 		       in->args.vc.attr.group);
13290 	else
13291 		printf("cannot create indirect action list configuration %u\n",
13292 		       in->args.vc.attr.group);
13293 }
13294 
13295 static const struct indlst_conf *
13296 indirect_action_list_conf_get(uint32_t conf_id)
13297 {
13298 	const struct indlst_conf *conf;
13299 
13300 	SLIST_FOREACH(conf, &indlst_conf_head, next) {
13301 		if (conf->id == conf_id)
13302 			return conf;
13303 	}
13304 	return NULL;
13305 }
13306 
13307 /** Dispatch parsed buffer to function calls. */
13308 static void
13309 cmd_flow_parsed(const struct buffer *in)
13310 {
13311 	switch (in->command) {
13312 	case INFO:
13313 		port_flow_get_info(in->port);
13314 		break;
13315 	case CONFIGURE:
13316 		port_flow_configure(in->port,
13317 				    &in->args.configure.port_attr,
13318 				    in->args.configure.nb_queue,
13319 				    &in->args.configure.queue_attr);
13320 		break;
13321 	case PATTERN_TEMPLATE_CREATE:
13322 		port_flow_pattern_template_create(in->port,
13323 				in->args.vc.pat_templ_id,
13324 				&((const struct rte_flow_pattern_template_attr) {
13325 					.relaxed_matching = in->args.vc.attr.reserved,
13326 					.ingress = in->args.vc.attr.ingress,
13327 					.egress = in->args.vc.attr.egress,
13328 					.transfer = in->args.vc.attr.transfer,
13329 				}),
13330 				in->args.vc.pattern);
13331 		break;
13332 	case PATTERN_TEMPLATE_DESTROY:
13333 		port_flow_pattern_template_destroy(in->port,
13334 				in->args.templ_destroy.template_id_n,
13335 				in->args.templ_destroy.template_id);
13336 		break;
13337 	case ACTIONS_TEMPLATE_CREATE:
13338 		port_flow_actions_template_create(in->port,
13339 				in->args.vc.act_templ_id,
13340 				&((const struct rte_flow_actions_template_attr) {
13341 					.ingress = in->args.vc.attr.ingress,
13342 					.egress = in->args.vc.attr.egress,
13343 					.transfer = in->args.vc.attr.transfer,
13344 				}),
13345 				in->args.vc.actions,
13346 				in->args.vc.masks);
13347 		break;
13348 	case ACTIONS_TEMPLATE_DESTROY:
13349 		port_flow_actions_template_destroy(in->port,
13350 				in->args.templ_destroy.template_id_n,
13351 				in->args.templ_destroy.template_id);
13352 		break;
13353 	case TABLE_CREATE:
13354 		port_flow_template_table_create(in->port, in->args.table.id,
13355 			&in->args.table.attr, in->args.table.pat_templ_id_n,
13356 			in->args.table.pat_templ_id, in->args.table.act_templ_id_n,
13357 			in->args.table.act_templ_id);
13358 		break;
13359 	case TABLE_DESTROY:
13360 		port_flow_template_table_destroy(in->port,
13361 					in->args.table_destroy.table_id_n,
13362 					in->args.table_destroy.table_id);
13363 		break;
13364 	case TABLE_RESIZE_COMPLETE:
13365 		port_flow_template_table_resize_complete
13366 			(in->port, in->args.table_destroy.table_id[0]);
13367 		break;
13368 	case GROUP_SET_MISS_ACTIONS:
13369 		port_queue_group_set_miss_actions(in->port, &in->args.vc.attr,
13370 						  in->args.vc.actions);
13371 		break;
13372 	case TABLE_RESIZE:
13373 		port_flow_template_table_resize(in->port, in->args.table.id,
13374 						in->args.table.attr.nb_flows);
13375 		break;
13376 	case QUEUE_CREATE:
13377 		port_queue_flow_create(in->port, in->queue, in->postpone,
13378 			in->args.vc.table_id, in->args.vc.rule_id,
13379 			in->args.vc.pat_templ_id, in->args.vc.act_templ_id,
13380 			in->args.vc.pattern, in->args.vc.actions);
13381 		break;
13382 	case QUEUE_DESTROY:
13383 		port_queue_flow_destroy(in->port, in->queue, in->postpone,
13384 					in->args.destroy.rule_n,
13385 					in->args.destroy.rule);
13386 		break;
13387 	case QUEUE_FLOW_UPDATE_RESIZED:
13388 		port_queue_flow_update_resized(in->port, in->queue,
13389 					       in->postpone,
13390 					       in->args.destroy.rule[0]);
13391 		break;
13392 	case QUEUE_UPDATE:
13393 		port_queue_flow_update(in->port, in->queue, in->postpone,
13394 				in->args.vc.rule_id, in->args.vc.act_templ_id,
13395 				in->args.vc.actions);
13396 		break;
13397 	case PUSH:
13398 		port_queue_flow_push(in->port, in->queue);
13399 		break;
13400 	case PULL:
13401 		port_queue_flow_pull(in->port, in->queue);
13402 		break;
13403 	case HASH:
13404 		if (!in->args.vc.encap_hash)
13405 			port_flow_hash_calc(in->port, in->args.vc.table_id,
13406 					    in->args.vc.pat_templ_id,
13407 					    in->args.vc.pattern);
13408 		else
13409 			port_flow_hash_calc_encap(in->port, in->args.vc.field,
13410 						  in->args.vc.pattern);
13411 		break;
13412 	case QUEUE_AGED:
13413 		port_queue_flow_aged(in->port, in->queue,
13414 				     in->args.aged.destroy);
13415 		break;
13416 	case QUEUE_INDIRECT_ACTION_CREATE:
13417 	case QUEUE_INDIRECT_ACTION_LIST_CREATE:
13418 		port_queue_action_handle_create(
13419 				in->port, in->queue, in->postpone,
13420 				in->args.vc.attr.group,
13421 				in->command == QUEUE_INDIRECT_ACTION_LIST_CREATE,
13422 				&((const struct rte_flow_indir_action_conf) {
13423 					.ingress = in->args.vc.attr.ingress,
13424 					.egress = in->args.vc.attr.egress,
13425 					.transfer = in->args.vc.attr.transfer,
13426 				}),
13427 				in->args.vc.actions);
13428 		break;
13429 	case QUEUE_INDIRECT_ACTION_DESTROY:
13430 		port_queue_action_handle_destroy(in->port,
13431 					   in->queue, in->postpone,
13432 					   in->args.ia_destroy.action_id_n,
13433 					   in->args.ia_destroy.action_id);
13434 		break;
13435 	case QUEUE_INDIRECT_ACTION_UPDATE:
13436 		port_queue_action_handle_update(in->port,
13437 						in->queue, in->postpone,
13438 						in->args.vc.attr.group,
13439 						in->args.vc.actions);
13440 		break;
13441 	case QUEUE_INDIRECT_ACTION_QUERY:
13442 		port_queue_action_handle_query(in->port,
13443 					       in->queue, in->postpone,
13444 					       in->args.ia.action_id);
13445 		break;
13446 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
13447 		port_queue_action_handle_query_update(in->port, in->queue,
13448 						      in->postpone,
13449 						      in->args.ia.action_id,
13450 						      in->args.ia.qu_mode,
13451 						      in->args.vc.actions);
13452 		break;
13453 	case INDIRECT_ACTION_CREATE:
13454 	case INDIRECT_ACTION_LIST_CREATE:
13455 		port_action_handle_create(
13456 				in->port, in->args.vc.attr.group,
13457 				in->command == INDIRECT_ACTION_LIST_CREATE,
13458 				&((const struct rte_flow_indir_action_conf) {
13459 					.ingress = in->args.vc.attr.ingress,
13460 					.egress = in->args.vc.attr.egress,
13461 					.transfer = in->args.vc.attr.transfer,
13462 				}),
13463 				in->args.vc.actions);
13464 		break;
13465 	case INDIRECT_ACTION_FLOW_CONF_CREATE:
13466 		indirect_action_flow_conf_create(in);
13467 		break;
13468 	case INDIRECT_ACTION_DESTROY:
13469 		port_action_handle_destroy(in->port,
13470 					   in->args.ia_destroy.action_id_n,
13471 					   in->args.ia_destroy.action_id);
13472 		break;
13473 	case INDIRECT_ACTION_UPDATE:
13474 		port_action_handle_update(in->port, in->args.vc.attr.group,
13475 					  in->args.vc.actions);
13476 		break;
13477 	case INDIRECT_ACTION_QUERY:
13478 		port_action_handle_query(in->port, in->args.ia.action_id);
13479 		break;
13480 	case INDIRECT_ACTION_QUERY_UPDATE:
13481 		port_action_handle_query_update(in->port,
13482 						in->args.ia.action_id,
13483 						in->args.ia.qu_mode,
13484 						in->args.vc.actions);
13485 		break;
13486 	case VALIDATE:
13487 		port_flow_validate(in->port, &in->args.vc.attr,
13488 				   in->args.vc.pattern, in->args.vc.actions,
13489 				   &in->args.vc.tunnel_ops);
13490 		break;
13491 	case CREATE:
13492 		port_flow_create(in->port, &in->args.vc.attr,
13493 				 in->args.vc.pattern, in->args.vc.actions,
13494 				 &in->args.vc.tunnel_ops, in->args.vc.user_id);
13495 		break;
13496 	case DESTROY:
13497 		port_flow_destroy(in->port, in->args.destroy.rule_n,
13498 				  in->args.destroy.rule,
13499 				  in->args.destroy.is_user_id);
13500 		break;
13501 	case UPDATE:
13502 		port_flow_update(in->port, in->args.vc.rule_id,
13503 				 in->args.vc.actions, in->args.vc.user_id);
13504 		break;
13505 	case FLUSH:
13506 		port_flow_flush(in->port);
13507 		break;
13508 	case DUMP_ONE:
13509 	case DUMP_ALL:
13510 		port_flow_dump(in->port, in->args.dump.mode,
13511 				in->args.dump.rule, in->args.dump.file,
13512 				in->args.dump.is_user_id);
13513 		break;
13514 	case QUERY:
13515 		port_flow_query(in->port, in->args.query.rule,
13516 				&in->args.query.action,
13517 				in->args.query.is_user_id);
13518 		break;
13519 	case LIST:
13520 		port_flow_list(in->port, in->args.list.group_n,
13521 			       in->args.list.group);
13522 		break;
13523 	case ISOLATE:
13524 		port_flow_isolate(in->port, in->args.isolate.set);
13525 		break;
13526 	case AGED:
13527 		port_flow_aged(in->port, in->args.aged.destroy);
13528 		break;
13529 	case TUNNEL_CREATE:
13530 		port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
13531 		break;
13532 	case TUNNEL_DESTROY:
13533 		port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
13534 		break;
13535 	case TUNNEL_LIST:
13536 		port_flow_tunnel_list(in->port);
13537 		break;
13538 	case ACTION_POL_G:
13539 		port_meter_policy_add(in->port, in->args.policy.policy_id,
13540 					in->args.vc.actions);
13541 		break;
13542 	case FLEX_ITEM_CREATE:
13543 		flex_item_create(in->port, in->args.flex.token,
13544 				 in->args.flex.filename);
13545 		break;
13546 	case FLEX_ITEM_DESTROY:
13547 		flex_item_destroy(in->port, in->args.flex.token);
13548 		break;
13549 	default:
13550 		break;
13551 	}
13552 	fflush(stdout);
13553 }
13554 
13555 /** Token generator and output processing callback (cmdline API). */
13556 static void
13557 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
13558 {
13559 	if (cl == NULL)
13560 		cmd_flow_tok(arg0, arg2);
13561 	else
13562 		cmd_flow_parsed(arg0);
13563 }
13564 
13565 /** Global parser instance (cmdline API). */
13566 cmdline_parse_inst_t cmd_flow = {
13567 	.f = cmd_flow_cb,
13568 	.data = NULL, /**< Unused. */
13569 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
13570 	.tokens = {
13571 		NULL,
13572 	}, /**< Tokens are returned by cmd_flow_tok(). */
13573 };
13574 
13575 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
13576 
13577 static void
13578 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
13579 {
13580 	struct rte_ipv4_hdr *ipv4;
13581 	struct rte_ether_hdr *eth;
13582 	struct rte_ipv6_hdr *ipv6;
13583 	struct rte_vxlan_hdr *vxlan;
13584 	struct rte_vxlan_gpe_hdr *gpe;
13585 	struct rte_flow_item_nvgre *nvgre;
13586 	uint32_t ipv6_vtc_flow;
13587 
13588 	switch (item->type) {
13589 	case RTE_FLOW_ITEM_TYPE_ETH:
13590 		eth = (struct rte_ether_hdr *)buf;
13591 		if (next_proto)
13592 			eth->ether_type = rte_cpu_to_be_16(next_proto);
13593 		break;
13594 	case RTE_FLOW_ITEM_TYPE_IPV4:
13595 		ipv4 = (struct rte_ipv4_hdr *)buf;
13596 		if (!ipv4->version_ihl)
13597 			ipv4->version_ihl = RTE_IPV4_VHL_DEF;
13598 		if (next_proto && ipv4->next_proto_id == 0)
13599 			ipv4->next_proto_id = (uint8_t)next_proto;
13600 		break;
13601 	case RTE_FLOW_ITEM_TYPE_IPV6:
13602 		ipv6 = (struct rte_ipv6_hdr *)buf;
13603 		if (next_proto && ipv6->proto == 0)
13604 			ipv6->proto = (uint8_t)next_proto;
13605 		ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
13606 		ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
13607 		ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
13608 		ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
13609 		break;
13610 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13611 		vxlan = (struct rte_vxlan_hdr *)buf;
13612 		vxlan->vx_flags = 0x08;
13613 		break;
13614 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13615 		gpe = (struct rte_vxlan_gpe_hdr *)buf;
13616 		gpe->vx_flags = 0x0C;
13617 		break;
13618 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13619 		nvgre = (struct rte_flow_item_nvgre *)buf;
13620 		nvgre->protocol = rte_cpu_to_be_16(0x6558);
13621 		nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
13622 		break;
13623 	default:
13624 		break;
13625 	}
13626 }
13627 
13628 /** Helper of get item's default mask. */
13629 static const void *
13630 flow_item_default_mask(const struct rte_flow_item *item)
13631 {
13632 	const void *mask = NULL;
13633 	static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
13634 	static struct rte_flow_item_ipv6_routing_ext ipv6_routing_ext_default_mask = {
13635 		.hdr = {
13636 			.next_hdr = 0xff,
13637 			.type = 0xff,
13638 			.segments_left = 0xff,
13639 		},
13640 	};
13641 
13642 	switch (item->type) {
13643 	case RTE_FLOW_ITEM_TYPE_ANY:
13644 		mask = &rte_flow_item_any_mask;
13645 		break;
13646 	case RTE_FLOW_ITEM_TYPE_PORT_ID:
13647 		mask = &rte_flow_item_port_id_mask;
13648 		break;
13649 	case RTE_FLOW_ITEM_TYPE_RAW:
13650 		mask = &rte_flow_item_raw_mask;
13651 		break;
13652 	case RTE_FLOW_ITEM_TYPE_ETH:
13653 		mask = &rte_flow_item_eth_mask;
13654 		break;
13655 	case RTE_FLOW_ITEM_TYPE_VLAN:
13656 		mask = &rte_flow_item_vlan_mask;
13657 		break;
13658 	case RTE_FLOW_ITEM_TYPE_IPV4:
13659 		mask = &rte_flow_item_ipv4_mask;
13660 		break;
13661 	case RTE_FLOW_ITEM_TYPE_IPV6:
13662 		mask = &rte_flow_item_ipv6_mask;
13663 		break;
13664 	case RTE_FLOW_ITEM_TYPE_ICMP:
13665 		mask = &rte_flow_item_icmp_mask;
13666 		break;
13667 	case RTE_FLOW_ITEM_TYPE_UDP:
13668 		mask = &rte_flow_item_udp_mask;
13669 		break;
13670 	case RTE_FLOW_ITEM_TYPE_TCP:
13671 		mask = &rte_flow_item_tcp_mask;
13672 		break;
13673 	case RTE_FLOW_ITEM_TYPE_SCTP:
13674 		mask = &rte_flow_item_sctp_mask;
13675 		break;
13676 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13677 		mask = &rte_flow_item_vxlan_mask;
13678 		break;
13679 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13680 		mask = &rte_flow_item_vxlan_gpe_mask;
13681 		break;
13682 	case RTE_FLOW_ITEM_TYPE_E_TAG:
13683 		mask = &rte_flow_item_e_tag_mask;
13684 		break;
13685 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13686 		mask = &rte_flow_item_nvgre_mask;
13687 		break;
13688 	case RTE_FLOW_ITEM_TYPE_MPLS:
13689 		mask = &rte_flow_item_mpls_mask;
13690 		break;
13691 	case RTE_FLOW_ITEM_TYPE_GRE:
13692 		mask = &rte_flow_item_gre_mask;
13693 		break;
13694 	case RTE_FLOW_ITEM_TYPE_GRE_KEY:
13695 		mask = &gre_key_default_mask;
13696 		break;
13697 	case RTE_FLOW_ITEM_TYPE_META:
13698 		mask = &rte_flow_item_meta_mask;
13699 		break;
13700 	case RTE_FLOW_ITEM_TYPE_RANDOM:
13701 		mask = &rte_flow_item_random_mask;
13702 		break;
13703 	case RTE_FLOW_ITEM_TYPE_FUZZY:
13704 		mask = &rte_flow_item_fuzzy_mask;
13705 		break;
13706 	case RTE_FLOW_ITEM_TYPE_GTP:
13707 		mask = &rte_flow_item_gtp_mask;
13708 		break;
13709 	case RTE_FLOW_ITEM_TYPE_GTP_PSC:
13710 		mask = &rte_flow_item_gtp_psc_mask;
13711 		break;
13712 	case RTE_FLOW_ITEM_TYPE_GENEVE:
13713 		mask = &rte_flow_item_geneve_mask;
13714 		break;
13715 	case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
13716 		mask = &rte_flow_item_geneve_opt_mask;
13717 		break;
13718 	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
13719 		mask = &rte_flow_item_pppoe_proto_id_mask;
13720 		break;
13721 	case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
13722 		mask = &rte_flow_item_l2tpv3oip_mask;
13723 		break;
13724 	case RTE_FLOW_ITEM_TYPE_ESP:
13725 		mask = &rte_flow_item_esp_mask;
13726 		break;
13727 	case RTE_FLOW_ITEM_TYPE_AH:
13728 		mask = &rte_flow_item_ah_mask;
13729 		break;
13730 	case RTE_FLOW_ITEM_TYPE_PFCP:
13731 		mask = &rte_flow_item_pfcp_mask;
13732 		break;
13733 	case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
13734 	case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
13735 		mask = &rte_flow_item_ethdev_mask;
13736 		break;
13737 	case RTE_FLOW_ITEM_TYPE_L2TPV2:
13738 		mask = &rte_flow_item_l2tpv2_mask;
13739 		break;
13740 	case RTE_FLOW_ITEM_TYPE_PPP:
13741 		mask = &rte_flow_item_ppp_mask;
13742 		break;
13743 	case RTE_FLOW_ITEM_TYPE_METER_COLOR:
13744 		mask = &rte_flow_item_meter_color_mask;
13745 		break;
13746 	case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13747 		mask = &ipv6_routing_ext_default_mask;
13748 		break;
13749 	case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
13750 		mask = &rte_flow_item_aggr_affinity_mask;
13751 		break;
13752 	case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
13753 		mask = &rte_flow_item_tx_queue_mask;
13754 		break;
13755 	case RTE_FLOW_ITEM_TYPE_IB_BTH:
13756 		mask = &rte_flow_item_ib_bth_mask;
13757 		break;
13758 	case RTE_FLOW_ITEM_TYPE_PTYPE:
13759 		mask = &rte_flow_item_ptype_mask;
13760 		break;
13761 	default:
13762 		break;
13763 	}
13764 	return mask;
13765 }
13766 
13767 /** Dispatch parsed buffer to function calls. */
13768 static void
13769 cmd_set_ipv6_ext_parsed(const struct buffer *in)
13770 {
13771 	uint32_t n = in->args.vc.pattern_n;
13772 	int i = 0;
13773 	struct rte_flow_item *item = NULL;
13774 	size_t size = 0;
13775 	uint8_t *data = NULL;
13776 	uint8_t *type = NULL;
13777 	size_t *total_size = NULL;
13778 	uint16_t idx = in->port; /* We borrow port field as index */
13779 	struct rte_flow_item_ipv6_routing_ext *ext;
13780 	const struct rte_flow_item_ipv6_ext *ipv6_ext;
13781 
13782 	RTE_ASSERT(in->command == SET_IPV6_EXT_PUSH ||
13783 		   in->command == SET_IPV6_EXT_REMOVE);
13784 
13785 	if (in->command == SET_IPV6_EXT_REMOVE) {
13786 		if (n != 1 || in->args.vc.pattern->type !=
13787 		    RTE_FLOW_ITEM_TYPE_IPV6_EXT) {
13788 			fprintf(stderr, "Error - Not supported item\n");
13789 			return;
13790 		}
13791 		type = (uint8_t *)&ipv6_ext_remove_confs[idx].type;
13792 		item = in->args.vc.pattern;
13793 		ipv6_ext = item->spec;
13794 		*type = ipv6_ext->next_hdr;
13795 		return;
13796 	}
13797 
13798 	total_size = &ipv6_ext_push_confs[idx].size;
13799 	data = (uint8_t *)&ipv6_ext_push_confs[idx].data;
13800 	type = (uint8_t *)&ipv6_ext_push_confs[idx].type;
13801 
13802 	*total_size = 0;
13803 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13804 	for (i = n - 1 ; i >= 0; --i) {
13805 		item = in->args.vc.pattern + i;
13806 		switch (item->type) {
13807 		case RTE_FLOW_ITEM_TYPE_IPV6_EXT:
13808 			ipv6_ext = item->spec;
13809 			*type = ipv6_ext->next_hdr;
13810 			break;
13811 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13812 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13813 			if (!ext->hdr.hdr_len) {
13814 				size = sizeof(struct rte_ipv6_routing_ext) +
13815 				(ext->hdr.segments_left << 4);
13816 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
13817 				/* Indicate no TLV once SRH. */
13818 				if (ext->hdr.type == 4)
13819 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
13820 			} else {
13821 				size = sizeof(struct rte_ipv6_routing_ext) +
13822 				(ext->hdr.hdr_len << 3);
13823 			}
13824 			*total_size += size;
13825 			memcpy(data, ext, size);
13826 			break;
13827 		default:
13828 			fprintf(stderr, "Error - Not supported item\n");
13829 			goto error;
13830 		}
13831 	}
13832 	RTE_ASSERT((*total_size) <= ACTION_IPV6_EXT_PUSH_MAX_DATA);
13833 	return;
13834 error:
13835 	*total_size = 0;
13836 	memset(data, 0x00, ACTION_IPV6_EXT_PUSH_MAX_DATA);
13837 }
13838 
13839 /** Dispatch parsed buffer to function calls. */
13840 static void
13841 cmd_set_raw_parsed_sample(const struct buffer *in)
13842 {
13843 	uint32_t n = in->args.vc.actions_n;
13844 	uint32_t i = 0;
13845 	struct rte_flow_action *action = NULL;
13846 	struct rte_flow_action *data = NULL;
13847 	const struct rte_flow_action_rss *rss = NULL;
13848 	size_t size = 0;
13849 	uint16_t idx = in->port; /* We borrow port field as index */
13850 	uint32_t max_size = sizeof(struct rte_flow_action) *
13851 						ACTION_SAMPLE_ACTIONS_NUM;
13852 
13853 	RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
13854 	data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
13855 	memset(data, 0x00, max_size);
13856 	for (; i <= n - 1; i++) {
13857 		action = in->args.vc.actions + i;
13858 		if (action->type == RTE_FLOW_ACTION_TYPE_END)
13859 			break;
13860 		switch (action->type) {
13861 		case RTE_FLOW_ACTION_TYPE_MARK:
13862 			size = sizeof(struct rte_flow_action_mark);
13863 			rte_memcpy(&sample_mark[idx],
13864 				(const void *)action->conf, size);
13865 			action->conf = &sample_mark[idx];
13866 			break;
13867 		case RTE_FLOW_ACTION_TYPE_COUNT:
13868 			size = sizeof(struct rte_flow_action_count);
13869 			rte_memcpy(&sample_count[idx],
13870 				(const void *)action->conf, size);
13871 			action->conf = &sample_count[idx];
13872 			break;
13873 		case RTE_FLOW_ACTION_TYPE_QUEUE:
13874 			size = sizeof(struct rte_flow_action_queue);
13875 			rte_memcpy(&sample_queue[idx],
13876 				(const void *)action->conf, size);
13877 			action->conf = &sample_queue[idx];
13878 			break;
13879 		case RTE_FLOW_ACTION_TYPE_RSS:
13880 			size = sizeof(struct rte_flow_action_rss);
13881 			rss = action->conf;
13882 			rte_memcpy(&sample_rss_data[idx].conf,
13883 				   (const void *)rss, size);
13884 			if (rss->key_len && rss->key) {
13885 				sample_rss_data[idx].conf.key =
13886 						sample_rss_data[idx].key;
13887 				rte_memcpy((void *)((uintptr_t)
13888 					   sample_rss_data[idx].conf.key),
13889 					   (const void *)rss->key,
13890 					   sizeof(uint8_t) * rss->key_len);
13891 			}
13892 			if (rss->queue_num && rss->queue) {
13893 				sample_rss_data[idx].conf.queue =
13894 						sample_rss_data[idx].queue;
13895 				rte_memcpy((void *)((uintptr_t)
13896 					   sample_rss_data[idx].conf.queue),
13897 					   (const void *)rss->queue,
13898 					   sizeof(uint16_t) * rss->queue_num);
13899 			}
13900 			action->conf = &sample_rss_data[idx].conf;
13901 			break;
13902 		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
13903 			size = sizeof(struct rte_flow_action_raw_encap);
13904 			rte_memcpy(&sample_encap[idx],
13905 				(const void *)action->conf, size);
13906 			action->conf = &sample_encap[idx];
13907 			break;
13908 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
13909 			size = sizeof(struct rte_flow_action_port_id);
13910 			rte_memcpy(&sample_port_id[idx],
13911 				(const void *)action->conf, size);
13912 			action->conf = &sample_port_id[idx];
13913 			break;
13914 		case RTE_FLOW_ACTION_TYPE_PF:
13915 			break;
13916 		case RTE_FLOW_ACTION_TYPE_VF:
13917 			size = sizeof(struct rte_flow_action_vf);
13918 			rte_memcpy(&sample_vf[idx],
13919 					(const void *)action->conf, size);
13920 			action->conf = &sample_vf[idx];
13921 			break;
13922 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
13923 			size = sizeof(struct rte_flow_action_vxlan_encap);
13924 			parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
13925 			action->conf = &sample_vxlan_encap[idx].conf;
13926 			break;
13927 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
13928 			size = sizeof(struct rte_flow_action_nvgre_encap);
13929 			parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
13930 			action->conf = &sample_nvgre_encap[idx];
13931 			break;
13932 		case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
13933 			size = sizeof(struct rte_flow_action_ethdev);
13934 			rte_memcpy(&sample_port_representor[idx],
13935 					(const void *)action->conf, size);
13936 			action->conf = &sample_port_representor[idx];
13937 			break;
13938 		case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
13939 			size = sizeof(struct rte_flow_action_ethdev);
13940 			rte_memcpy(&sample_represented_port[idx],
13941 					(const void *)action->conf, size);
13942 			action->conf = &sample_represented_port[idx];
13943 			break;
13944 		default:
13945 			fprintf(stderr, "Error - Not supported action\n");
13946 			return;
13947 		}
13948 		rte_memcpy(data, action, sizeof(struct rte_flow_action));
13949 		data++;
13950 	}
13951 }
13952 
13953 /** Dispatch parsed buffer to function calls. */
13954 static void
13955 cmd_set_raw_parsed(const struct buffer *in)
13956 {
13957 	uint32_t n = in->args.vc.pattern_n;
13958 	int i = 0;
13959 	struct rte_flow_item *item = NULL;
13960 	size_t size = 0;
13961 	uint8_t *data = NULL;
13962 	uint8_t *data_tail = NULL;
13963 	size_t *total_size = NULL;
13964 	uint16_t upper_layer = 0;
13965 	uint16_t proto = 0;
13966 	uint16_t idx = in->port; /* We borrow port field as index */
13967 	int gtp_psc = -1; /* GTP PSC option index. */
13968 	const void *src_spec;
13969 
13970 	if (in->command == SET_SAMPLE_ACTIONS)
13971 		return cmd_set_raw_parsed_sample(in);
13972 	else if (in->command == SET_IPV6_EXT_PUSH ||
13973 		 in->command == SET_IPV6_EXT_REMOVE)
13974 		return cmd_set_ipv6_ext_parsed(in);
13975 	RTE_ASSERT(in->command == SET_RAW_ENCAP ||
13976 		   in->command == SET_RAW_DECAP);
13977 	if (in->command == SET_RAW_ENCAP) {
13978 		total_size = &raw_encap_confs[idx].size;
13979 		data = (uint8_t *)&raw_encap_confs[idx].data;
13980 	} else {
13981 		total_size = &raw_decap_confs[idx].size;
13982 		data = (uint8_t *)&raw_decap_confs[idx].data;
13983 	}
13984 	*total_size = 0;
13985 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13986 	/* process hdr from upper layer to low layer (L3/L4 -> L2). */
13987 	data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
13988 	for (i = n - 1 ; i >= 0; --i) {
13989 		const struct rte_flow_item_gtp *gtp;
13990 		const struct rte_flow_item_geneve_opt *opt;
13991 		struct rte_flow_item_ipv6_routing_ext *ext;
13992 
13993 		item = in->args.vc.pattern + i;
13994 		if (item->spec == NULL)
13995 			item->spec = flow_item_default_mask(item);
13996 		src_spec = item->spec;
13997 		switch (item->type) {
13998 		case RTE_FLOW_ITEM_TYPE_ETH:
13999 			size = sizeof(struct rte_ether_hdr);
14000 			break;
14001 		case RTE_FLOW_ITEM_TYPE_VLAN:
14002 			size = sizeof(struct rte_vlan_hdr);
14003 			proto = RTE_ETHER_TYPE_VLAN;
14004 			break;
14005 		case RTE_FLOW_ITEM_TYPE_IPV4:
14006 			size = sizeof(struct rte_ipv4_hdr);
14007 			proto = RTE_ETHER_TYPE_IPV4;
14008 			break;
14009 		case RTE_FLOW_ITEM_TYPE_IPV6:
14010 			size = sizeof(struct rte_ipv6_hdr);
14011 			proto = RTE_ETHER_TYPE_IPV6;
14012 			break;
14013 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
14014 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
14015 			if (!ext->hdr.hdr_len) {
14016 				size = sizeof(struct rte_ipv6_routing_ext) +
14017 					(ext->hdr.segments_left << 4);
14018 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
14019 				/* SRv6 without TLV. */
14020 				if (ext->hdr.type == RTE_IPV6_SRCRT_TYPE_4)
14021 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
14022 			} else {
14023 				size = sizeof(struct rte_ipv6_routing_ext) +
14024 					(ext->hdr.hdr_len << 3);
14025 			}
14026 			proto = IPPROTO_ROUTING;
14027 			break;
14028 		case RTE_FLOW_ITEM_TYPE_UDP:
14029 			size = sizeof(struct rte_udp_hdr);
14030 			proto = 0x11;
14031 			break;
14032 		case RTE_FLOW_ITEM_TYPE_TCP:
14033 			size = sizeof(struct rte_tcp_hdr);
14034 			proto = 0x06;
14035 			break;
14036 		case RTE_FLOW_ITEM_TYPE_VXLAN:
14037 			size = sizeof(struct rte_vxlan_hdr);
14038 			break;
14039 		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
14040 			size = sizeof(struct rte_vxlan_gpe_hdr);
14041 			break;
14042 		case RTE_FLOW_ITEM_TYPE_GRE:
14043 			size = sizeof(struct rte_gre_hdr);
14044 			proto = 0x2F;
14045 			break;
14046 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
14047 			size = sizeof(rte_be32_t);
14048 			proto = 0x0;
14049 			break;
14050 		case RTE_FLOW_ITEM_TYPE_MPLS:
14051 			size = sizeof(struct rte_mpls_hdr);
14052 			proto = 0x0;
14053 			break;
14054 		case RTE_FLOW_ITEM_TYPE_NVGRE:
14055 			size = sizeof(struct rte_flow_item_nvgre);
14056 			proto = 0x2F;
14057 			break;
14058 		case RTE_FLOW_ITEM_TYPE_GENEVE:
14059 			size = sizeof(struct rte_geneve_hdr);
14060 			break;
14061 		case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
14062 			opt = (const struct rte_flow_item_geneve_opt *)
14063 								item->spec;
14064 			size = offsetof(struct rte_flow_item_geneve_opt,
14065 					option_len) + sizeof(uint8_t);
14066 			if (opt->option_len && opt->data) {
14067 				*total_size += opt->option_len *
14068 					       sizeof(uint32_t);
14069 				rte_memcpy(data_tail - (*total_size),
14070 					   opt->data,
14071 					   opt->option_len * sizeof(uint32_t));
14072 			}
14073 			break;
14074 		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
14075 			size = sizeof(rte_be32_t);
14076 			proto = 0x73;
14077 			break;
14078 		case RTE_FLOW_ITEM_TYPE_ESP:
14079 			size = sizeof(struct rte_esp_hdr);
14080 			proto = 0x32;
14081 			break;
14082 		case RTE_FLOW_ITEM_TYPE_AH:
14083 			size = sizeof(struct rte_flow_item_ah);
14084 			proto = 0x33;
14085 			break;
14086 		case RTE_FLOW_ITEM_TYPE_GTP:
14087 			if (gtp_psc < 0) {
14088 				size = sizeof(struct rte_gtp_hdr);
14089 				break;
14090 			}
14091 			if (gtp_psc != i + 1) {
14092 				fprintf(stderr,
14093 					"Error - GTP PSC does not follow GTP\n");
14094 				goto error;
14095 			}
14096 			gtp = item->spec;
14097 			if (gtp->hdr.s == 1 || gtp->hdr.pn == 1) {
14098 				/* Only E flag should be set. */
14099 				fprintf(stderr,
14100 					"Error - GTP unsupported flags\n");
14101 				goto error;
14102 			} else {
14103 				struct rte_gtp_hdr_ext_word ext_word = {
14104 					.next_ext = 0x85
14105 				};
14106 
14107 				/* We have to add GTP header extra word. */
14108 				*total_size += sizeof(ext_word);
14109 				rte_memcpy(data_tail - (*total_size),
14110 					   &ext_word, sizeof(ext_word));
14111 			}
14112 			size = sizeof(struct rte_gtp_hdr);
14113 			break;
14114 		case RTE_FLOW_ITEM_TYPE_GTP_PSC:
14115 			if (gtp_psc >= 0) {
14116 				fprintf(stderr,
14117 					"Error - Multiple GTP PSC items\n");
14118 				goto error;
14119 			} else {
14120 				const struct rte_flow_item_gtp_psc
14121 					*opt = item->spec;
14122 				struct rte_gtp_psc_generic_hdr *hdr;
14123 				size_t hdr_size = RTE_ALIGN(sizeof(*hdr),
14124 							 sizeof(int32_t));
14125 
14126 				*total_size += hdr_size;
14127 				hdr = (typeof(hdr))(data_tail - (*total_size));
14128 				memset(hdr, 0, hdr_size);
14129 				*hdr = opt->hdr;
14130 				hdr->ext_hdr_len = 1;
14131 				gtp_psc = i;
14132 				size = 0;
14133 			}
14134 			break;
14135 		case RTE_FLOW_ITEM_TYPE_PFCP:
14136 			size = sizeof(struct rte_flow_item_pfcp);
14137 			break;
14138 		case RTE_FLOW_ITEM_TYPE_FLEX:
14139 			if (item->spec != NULL) {
14140 				size = ((const struct rte_flow_item_flex *)item->spec)->length;
14141 				src_spec = ((const struct rte_flow_item_flex *)item->spec)->pattern;
14142 			} else {
14143 				size = 0;
14144 				src_spec = NULL;
14145 			}
14146 			break;
14147 		case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
14148 			size = 0;
14149 			if (item->spec) {
14150 				const struct rte_flow_item_gre_opt
14151 					*opt = item->spec;
14152 				if (opt->checksum_rsvd.checksum) {
14153 					*total_size +=
14154 						sizeof(opt->checksum_rsvd);
14155 					rte_memcpy(data_tail - (*total_size),
14156 						   &opt->checksum_rsvd,
14157 						   sizeof(opt->checksum_rsvd));
14158 				}
14159 				if (opt->key.key) {
14160 					*total_size += sizeof(opt->key.key);
14161 					rte_memcpy(data_tail - (*total_size),
14162 						   &opt->key.key,
14163 						   sizeof(opt->key.key));
14164 				}
14165 				if (opt->sequence.sequence) {
14166 					*total_size += sizeof(opt->sequence.sequence);
14167 					rte_memcpy(data_tail - (*total_size),
14168 						   &opt->sequence.sequence,
14169 						   sizeof(opt->sequence.sequence));
14170 				}
14171 			}
14172 			proto = 0x2F;
14173 			break;
14174 		default:
14175 			fprintf(stderr, "Error - Not supported item\n");
14176 			goto error;
14177 		}
14178 		if (size) {
14179 			*total_size += size;
14180 			rte_memcpy(data_tail - (*total_size), src_spec, size);
14181 			/* update some fields which cannot be set by cmdline */
14182 			update_fields((data_tail - (*total_size)), item,
14183 				      upper_layer);
14184 			upper_layer = proto;
14185 		}
14186 	}
14187 	if (verbose_level & 0x1)
14188 		printf("total data size is %zu\n", (*total_size));
14189 	RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
14190 	memmove(data, (data_tail - (*total_size)), *total_size);
14191 	return;
14192 
14193 error:
14194 	*total_size = 0;
14195 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
14196 }
14197 
14198 /** Populate help strings for current token (cmdline API). */
14199 static int
14200 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
14201 		     unsigned int size)
14202 {
14203 	struct context *ctx = &cmd_flow_context;
14204 	const struct token *token = &token_list[ctx->prev];
14205 
14206 	(void)hdr;
14207 	if (!size)
14208 		return -1;
14209 	/* Set token type and update global help with details. */
14210 	snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
14211 	if (token->help)
14212 		cmd_set_raw.help_str = token->help;
14213 	else
14214 		cmd_set_raw.help_str = token->name;
14215 	return 0;
14216 }
14217 
14218 /** Token definition template (cmdline API). */
14219 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
14220 	.ops = &(struct cmdline_token_ops){
14221 		.parse = cmd_flow_parse,
14222 		.complete_get_nb = cmd_flow_complete_get_nb,
14223 		.complete_get_elt = cmd_flow_complete_get_elt,
14224 		.get_help = cmd_set_raw_get_help,
14225 	},
14226 	.offset = 0,
14227 };
14228 
14229 /** Populate the next dynamic token. */
14230 static void
14231 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
14232 	     cmdline_parse_token_hdr_t **hdr_inst)
14233 {
14234 	struct context *ctx = &cmd_flow_context;
14235 
14236 	/* Always reinitialize context before requesting the first token. */
14237 	if (!(hdr_inst - cmd_set_raw.tokens)) {
14238 		cmd_flow_context_init(ctx);
14239 		ctx->curr = START_SET;
14240 	}
14241 	/* Return NULL when no more tokens are expected. */
14242 	if (!ctx->next_num && (ctx->curr != START_SET)) {
14243 		*hdr = NULL;
14244 		return;
14245 	}
14246 	/* Determine if command should end here. */
14247 	if (ctx->eol && ctx->last && ctx->next_num) {
14248 		const enum index *list = ctx->next[ctx->next_num - 1];
14249 		int i;
14250 
14251 		for (i = 0; list[i]; ++i) {
14252 			if (list[i] != END)
14253 				continue;
14254 			*hdr = NULL;
14255 			return;
14256 		}
14257 	}
14258 	*hdr = &cmd_set_raw_token_hdr;
14259 }
14260 
14261 /** Token generator and output processing callback (cmdline API). */
14262 static void
14263 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
14264 {
14265 	if (cl == NULL)
14266 		cmd_set_raw_tok(arg0, arg2);
14267 	else
14268 		cmd_set_raw_parsed(arg0);
14269 }
14270 
14271 /** Global parser instance (cmdline API). */
14272 cmdline_parse_inst_t cmd_set_raw = {
14273 	.f = cmd_set_raw_cb,
14274 	.data = NULL, /**< Unused. */
14275 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
14276 	.tokens = {
14277 		NULL,
14278 	}, /**< Tokens are returned by cmd_flow_tok(). */
14279 };
14280 
14281 /* *** display raw_encap/raw_decap buf */
14282 struct cmd_show_set_raw_result {
14283 	cmdline_fixed_string_t cmd_show;
14284 	cmdline_fixed_string_t cmd_what;
14285 	cmdline_fixed_string_t cmd_all;
14286 	uint16_t cmd_index;
14287 };
14288 
14289 static void
14290 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
14291 {
14292 	struct cmd_show_set_raw_result *res = parsed_result;
14293 	uint16_t index = res->cmd_index;
14294 	uint8_t all = 0;
14295 	uint8_t *raw_data = NULL;
14296 	size_t raw_size = 0;
14297 	char title[16] = {0};
14298 
14299 	RTE_SET_USED(cl);
14300 	RTE_SET_USED(data);
14301 	if (!strcmp(res->cmd_all, "all")) {
14302 		all = 1;
14303 		index = 0;
14304 	} else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
14305 		fprintf(stderr, "index should be 0-%u\n",
14306 			RAW_ENCAP_CONFS_MAX_NUM - 1);
14307 		return;
14308 	}
14309 	do {
14310 		if (!strcmp(res->cmd_what, "raw_encap")) {
14311 			raw_data = (uint8_t *)&raw_encap_confs[index].data;
14312 			raw_size = raw_encap_confs[index].size;
14313 			snprintf(title, 16, "\nindex: %u", index);
14314 			rte_hexdump(stdout, title, raw_data, raw_size);
14315 		} else {
14316 			raw_data = (uint8_t *)&raw_decap_confs[index].data;
14317 			raw_size = raw_decap_confs[index].size;
14318 			snprintf(title, 16, "\nindex: %u", index);
14319 			rte_hexdump(stdout, title, raw_data, raw_size);
14320 		}
14321 	} while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
14322 }
14323 
14324 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
14325 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14326 			cmd_show, "show");
14327 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
14328 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14329 			cmd_what, "raw_encap#raw_decap");
14330 static cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
14331 	TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
14332 			cmd_index, RTE_UINT16);
14333 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
14334 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14335 			cmd_all, "all");
14336 cmdline_parse_inst_t cmd_show_set_raw = {
14337 	.f = cmd_show_set_raw_parsed,
14338 	.data = NULL,
14339 	.help_str = "show <raw_encap|raw_decap> <index>",
14340 	.tokens = {
14341 		(void *)&cmd_show_set_raw_cmd_show,
14342 		(void *)&cmd_show_set_raw_cmd_what,
14343 		(void *)&cmd_show_set_raw_cmd_index,
14344 		NULL,
14345 	},
14346 };
14347 cmdline_parse_inst_t cmd_show_set_raw_all = {
14348 	.f = cmd_show_set_raw_parsed,
14349 	.data = NULL,
14350 	.help_str = "show <raw_encap|raw_decap> all",
14351 	.tokens = {
14352 		(void *)&cmd_show_set_raw_cmd_show,
14353 		(void *)&cmd_show_set_raw_cmd_what,
14354 		(void *)&cmd_show_set_raw_cmd_all,
14355 		NULL,
14356 	},
14357 };
14358