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