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