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