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