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