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