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