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