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