xref: /dpdk/app/test-pmd/cmdline_flow.c (revision 6a42e7ef9dd86a554e060fcef0be03aa9ddd394c)
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 #include <arpa/inet.h>
14 #include <sys/socket.h>
15 
16 #include <rte_string_fns.h>
17 #include <rte_common.h>
18 #include <rte_ethdev.h>
19 #include <rte_byteorder.h>
20 #include <cmdline_parse.h>
21 #include <cmdline_parse_etheraddr.h>
22 #include <cmdline_parse_string.h>
23 #include <cmdline_parse_num.h>
24 #include <rte_flow.h>
25 #include <rte_hexdump.h>
26 
27 #include "testpmd.h"
28 
29 /** Parser token indices. */
30 enum index {
31 	/* Special tokens. */
32 	ZERO = 0,
33 	END,
34 	START_SET,
35 	END_SET,
36 
37 	/* Common tokens. */
38 	INTEGER,
39 	UNSIGNED,
40 	PREFIX,
41 	BOOLEAN,
42 	STRING,
43 	HEX,
44 	MAC_ADDR,
45 	IPV4_ADDR,
46 	IPV6_ADDR,
47 	RULE_ID,
48 	PORT_ID,
49 	GROUP_ID,
50 	PRIORITY_LEVEL,
51 
52 	/* Top-level command. */
53 	SET,
54 	/* Sub-leve commands. */
55 	SET_RAW_ENCAP,
56 	SET_RAW_DECAP,
57 	SET_RAW_INDEX,
58 
59 	/* Top-level command. */
60 	FLOW,
61 	/* Sub-level commands. */
62 	VALIDATE,
63 	CREATE,
64 	DESTROY,
65 	FLUSH,
66 	QUERY,
67 	LIST,
68 	ISOLATE,
69 
70 	/* Destroy arguments. */
71 	DESTROY_RULE,
72 
73 	/* Query arguments. */
74 	QUERY_ACTION,
75 
76 	/* List arguments. */
77 	LIST_GROUP,
78 
79 	/* Validate/create arguments. */
80 	GROUP,
81 	PRIORITY,
82 	INGRESS,
83 	EGRESS,
84 	TRANSFER,
85 
86 	/* Validate/create pattern. */
87 	PATTERN,
88 	ITEM_PARAM_IS,
89 	ITEM_PARAM_SPEC,
90 	ITEM_PARAM_LAST,
91 	ITEM_PARAM_MASK,
92 	ITEM_PARAM_PREFIX,
93 	ITEM_NEXT,
94 	ITEM_END,
95 	ITEM_VOID,
96 	ITEM_INVERT,
97 	ITEM_ANY,
98 	ITEM_ANY_NUM,
99 	ITEM_PF,
100 	ITEM_VF,
101 	ITEM_VF_ID,
102 	ITEM_PHY_PORT,
103 	ITEM_PHY_PORT_INDEX,
104 	ITEM_PORT_ID,
105 	ITEM_PORT_ID_ID,
106 	ITEM_MARK,
107 	ITEM_MARK_ID,
108 	ITEM_RAW,
109 	ITEM_RAW_RELATIVE,
110 	ITEM_RAW_SEARCH,
111 	ITEM_RAW_OFFSET,
112 	ITEM_RAW_LIMIT,
113 	ITEM_RAW_PATTERN,
114 	ITEM_ETH,
115 	ITEM_ETH_DST,
116 	ITEM_ETH_SRC,
117 	ITEM_ETH_TYPE,
118 	ITEM_VLAN,
119 	ITEM_VLAN_TCI,
120 	ITEM_VLAN_PCP,
121 	ITEM_VLAN_DEI,
122 	ITEM_VLAN_VID,
123 	ITEM_VLAN_INNER_TYPE,
124 	ITEM_IPV4,
125 	ITEM_IPV4_TOS,
126 	ITEM_IPV4_TTL,
127 	ITEM_IPV4_PROTO,
128 	ITEM_IPV4_SRC,
129 	ITEM_IPV4_DST,
130 	ITEM_IPV6,
131 	ITEM_IPV6_TC,
132 	ITEM_IPV6_FLOW,
133 	ITEM_IPV6_PROTO,
134 	ITEM_IPV6_HOP,
135 	ITEM_IPV6_SRC,
136 	ITEM_IPV6_DST,
137 	ITEM_ICMP,
138 	ITEM_ICMP_TYPE,
139 	ITEM_ICMP_CODE,
140 	ITEM_UDP,
141 	ITEM_UDP_SRC,
142 	ITEM_UDP_DST,
143 	ITEM_TCP,
144 	ITEM_TCP_SRC,
145 	ITEM_TCP_DST,
146 	ITEM_TCP_FLAGS,
147 	ITEM_SCTP,
148 	ITEM_SCTP_SRC,
149 	ITEM_SCTP_DST,
150 	ITEM_SCTP_TAG,
151 	ITEM_SCTP_CKSUM,
152 	ITEM_VXLAN,
153 	ITEM_VXLAN_VNI,
154 	ITEM_E_TAG,
155 	ITEM_E_TAG_GRP_ECID_B,
156 	ITEM_NVGRE,
157 	ITEM_NVGRE_TNI,
158 	ITEM_MPLS,
159 	ITEM_MPLS_LABEL,
160 	ITEM_MPLS_TC,
161 	ITEM_MPLS_S,
162 	ITEM_GRE,
163 	ITEM_GRE_PROTO,
164 	ITEM_GRE_C_RSVD0_VER,
165 	ITEM_GRE_C_BIT,
166 	ITEM_GRE_K_BIT,
167 	ITEM_GRE_S_BIT,
168 	ITEM_FUZZY,
169 	ITEM_FUZZY_THRESH,
170 	ITEM_GTP,
171 	ITEM_GTP_TEID,
172 	ITEM_GTPC,
173 	ITEM_GTPU,
174 	ITEM_GENEVE,
175 	ITEM_GENEVE_VNI,
176 	ITEM_GENEVE_PROTO,
177 	ITEM_VXLAN_GPE,
178 	ITEM_VXLAN_GPE_VNI,
179 	ITEM_ARP_ETH_IPV4,
180 	ITEM_ARP_ETH_IPV4_SHA,
181 	ITEM_ARP_ETH_IPV4_SPA,
182 	ITEM_ARP_ETH_IPV4_THA,
183 	ITEM_ARP_ETH_IPV4_TPA,
184 	ITEM_IPV6_EXT,
185 	ITEM_IPV6_EXT_NEXT_HDR,
186 	ITEM_ICMP6,
187 	ITEM_ICMP6_TYPE,
188 	ITEM_ICMP6_CODE,
189 	ITEM_ICMP6_ND_NS,
190 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
191 	ITEM_ICMP6_ND_NA,
192 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
193 	ITEM_ICMP6_ND_OPT,
194 	ITEM_ICMP6_ND_OPT_TYPE,
195 	ITEM_ICMP6_ND_OPT_SLA_ETH,
196 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
197 	ITEM_ICMP6_ND_OPT_TLA_ETH,
198 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
199 	ITEM_META,
200 	ITEM_META_DATA,
201 	ITEM_GRE_KEY,
202 	ITEM_GRE_KEY_VALUE,
203 	ITEM_GTP_PSC,
204 	ITEM_GTP_PSC_QFI,
205 	ITEM_GTP_PSC_PDU_T,
206 	ITEM_PPPOES,
207 	ITEM_PPPOED,
208 	ITEM_PPPOE_SEID,
209 	ITEM_PPPOE_PROTO_ID,
210 	ITEM_HIGIG2,
211 	ITEM_HIGIG2_CLASSIFICATION,
212 	ITEM_HIGIG2_VID,
213 	ITEM_TAG,
214 	ITEM_TAG_DATA,
215 	ITEM_TAG_INDEX,
216 	ITEM_L2TPV3OIP,
217 	ITEM_L2TPV3OIP_SESSION_ID,
218 	ITEM_ESP,
219 	ITEM_ESP_SPI,
220 
221 	/* Validate/create actions. */
222 	ACTIONS,
223 	ACTION_NEXT,
224 	ACTION_END,
225 	ACTION_VOID,
226 	ACTION_PASSTHRU,
227 	ACTION_JUMP,
228 	ACTION_JUMP_GROUP,
229 	ACTION_MARK,
230 	ACTION_MARK_ID,
231 	ACTION_FLAG,
232 	ACTION_QUEUE,
233 	ACTION_QUEUE_INDEX,
234 	ACTION_DROP,
235 	ACTION_COUNT,
236 	ACTION_COUNT_SHARED,
237 	ACTION_COUNT_ID,
238 	ACTION_RSS,
239 	ACTION_RSS_FUNC,
240 	ACTION_RSS_LEVEL,
241 	ACTION_RSS_FUNC_DEFAULT,
242 	ACTION_RSS_FUNC_TOEPLITZ,
243 	ACTION_RSS_FUNC_SIMPLE_XOR,
244 	ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
245 	ACTION_RSS_TYPES,
246 	ACTION_RSS_TYPE,
247 	ACTION_RSS_KEY,
248 	ACTION_RSS_KEY_LEN,
249 	ACTION_RSS_QUEUES,
250 	ACTION_RSS_QUEUE,
251 	ACTION_PF,
252 	ACTION_VF,
253 	ACTION_VF_ORIGINAL,
254 	ACTION_VF_ID,
255 	ACTION_PHY_PORT,
256 	ACTION_PHY_PORT_ORIGINAL,
257 	ACTION_PHY_PORT_INDEX,
258 	ACTION_PORT_ID,
259 	ACTION_PORT_ID_ORIGINAL,
260 	ACTION_PORT_ID_ID,
261 	ACTION_METER,
262 	ACTION_METER_ID,
263 	ACTION_OF_SET_MPLS_TTL,
264 	ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
265 	ACTION_OF_DEC_MPLS_TTL,
266 	ACTION_OF_SET_NW_TTL,
267 	ACTION_OF_SET_NW_TTL_NW_TTL,
268 	ACTION_OF_DEC_NW_TTL,
269 	ACTION_OF_COPY_TTL_OUT,
270 	ACTION_OF_COPY_TTL_IN,
271 	ACTION_OF_POP_VLAN,
272 	ACTION_OF_PUSH_VLAN,
273 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
274 	ACTION_OF_SET_VLAN_VID,
275 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
276 	ACTION_OF_SET_VLAN_PCP,
277 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
278 	ACTION_OF_POP_MPLS,
279 	ACTION_OF_POP_MPLS_ETHERTYPE,
280 	ACTION_OF_PUSH_MPLS,
281 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
282 	ACTION_VXLAN_ENCAP,
283 	ACTION_VXLAN_DECAP,
284 	ACTION_NVGRE_ENCAP,
285 	ACTION_NVGRE_DECAP,
286 	ACTION_L2_ENCAP,
287 	ACTION_L2_DECAP,
288 	ACTION_MPLSOGRE_ENCAP,
289 	ACTION_MPLSOGRE_DECAP,
290 	ACTION_MPLSOUDP_ENCAP,
291 	ACTION_MPLSOUDP_DECAP,
292 	ACTION_SET_IPV4_SRC,
293 	ACTION_SET_IPV4_SRC_IPV4_SRC,
294 	ACTION_SET_IPV4_DST,
295 	ACTION_SET_IPV4_DST_IPV4_DST,
296 	ACTION_SET_IPV6_SRC,
297 	ACTION_SET_IPV6_SRC_IPV6_SRC,
298 	ACTION_SET_IPV6_DST,
299 	ACTION_SET_IPV6_DST_IPV6_DST,
300 	ACTION_SET_TP_SRC,
301 	ACTION_SET_TP_SRC_TP_SRC,
302 	ACTION_SET_TP_DST,
303 	ACTION_SET_TP_DST_TP_DST,
304 	ACTION_MAC_SWAP,
305 	ACTION_DEC_TTL,
306 	ACTION_SET_TTL,
307 	ACTION_SET_TTL_TTL,
308 	ACTION_SET_MAC_SRC,
309 	ACTION_SET_MAC_SRC_MAC_SRC,
310 	ACTION_SET_MAC_DST,
311 	ACTION_SET_MAC_DST_MAC_DST,
312 	ACTION_INC_TCP_SEQ,
313 	ACTION_INC_TCP_SEQ_VALUE,
314 	ACTION_DEC_TCP_SEQ,
315 	ACTION_DEC_TCP_SEQ_VALUE,
316 	ACTION_INC_TCP_ACK,
317 	ACTION_INC_TCP_ACK_VALUE,
318 	ACTION_DEC_TCP_ACK,
319 	ACTION_DEC_TCP_ACK_VALUE,
320 	ACTION_RAW_ENCAP,
321 	ACTION_RAW_DECAP,
322 	ACTION_RAW_ENCAP_INDEX,
323 	ACTION_RAW_ENCAP_INDEX_VALUE,
324 	ACTION_RAW_DECAP_INDEX,
325 	ACTION_RAW_DECAP_INDEX_VALUE,
326 	ACTION_SET_TAG,
327 	ACTION_SET_TAG_DATA,
328 	ACTION_SET_TAG_INDEX,
329 	ACTION_SET_TAG_MASK,
330 	ACTION_SET_META,
331 	ACTION_SET_META_DATA,
332 	ACTION_SET_META_MASK,
333 	ACTION_SET_IPV4_DSCP,
334 	ACTION_SET_IPV4_DSCP_VALUE,
335 	ACTION_SET_IPV6_DSCP,
336 	ACTION_SET_IPV6_DSCP_VALUE,
337 };
338 
339 /** Maximum size for pattern in struct rte_flow_item_raw. */
340 #define ITEM_RAW_PATTERN_SIZE 40
341 
342 /** Storage size for struct rte_flow_item_raw including pattern. */
343 #define ITEM_RAW_SIZE \
344 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
345 
346 /** Maximum number of queue indices in struct rte_flow_action_rss. */
347 #define ACTION_RSS_QUEUE_NUM 128
348 
349 /** Storage for struct rte_flow_action_rss including external data. */
350 struct action_rss_data {
351 	struct rte_flow_action_rss conf;
352 	uint8_t key[RSS_HASH_KEY_LENGTH];
353 	uint16_t queue[ACTION_RSS_QUEUE_NUM];
354 };
355 
356 /** Maximum data size in struct rte_flow_action_raw_encap. */
357 #define ACTION_RAW_ENCAP_MAX_DATA 128
358 #define RAW_ENCAP_CONFS_MAX_NUM 8
359 
360 /** Storage for struct rte_flow_action_raw_encap. */
361 struct raw_encap_conf {
362 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
363 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
364 	size_t size;
365 };
366 
367 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
368 
369 /** Storage for struct rte_flow_action_raw_encap including external data. */
370 struct action_raw_encap_data {
371 	struct rte_flow_action_raw_encap conf;
372 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
373 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
374 	uint16_t idx;
375 };
376 
377 /** Storage for struct rte_flow_action_raw_decap. */
378 struct raw_decap_conf {
379 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
380 	size_t size;
381 };
382 
383 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
384 
385 /** Storage for struct rte_flow_action_raw_decap including external data. */
386 struct action_raw_decap_data {
387 	struct rte_flow_action_raw_decap conf;
388 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
389 	uint16_t idx;
390 };
391 
392 struct vxlan_encap_conf vxlan_encap_conf = {
393 	.select_ipv4 = 1,
394 	.select_vlan = 0,
395 	.select_tos_ttl = 0,
396 	.vni = "\x00\x00\x00",
397 	.udp_src = 0,
398 	.udp_dst = RTE_BE16(4789),
399 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
400 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
401 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
402 		"\x00\x00\x00\x00\x00\x00\x00\x01",
403 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
404 		"\x00\x00\x00\x00\x00\x00\x11\x11",
405 	.vlan_tci = 0,
406 	.ip_tos = 0,
407 	.ip_ttl = 255,
408 	.eth_src = "\x00\x00\x00\x00\x00\x00",
409 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
410 };
411 
412 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
413 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
414 
415 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
416 struct action_vxlan_encap_data {
417 	struct rte_flow_action_vxlan_encap conf;
418 	struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
419 	struct rte_flow_item_eth item_eth;
420 	struct rte_flow_item_vlan item_vlan;
421 	union {
422 		struct rte_flow_item_ipv4 item_ipv4;
423 		struct rte_flow_item_ipv6 item_ipv6;
424 	};
425 	struct rte_flow_item_udp item_udp;
426 	struct rte_flow_item_vxlan item_vxlan;
427 };
428 
429 struct nvgre_encap_conf nvgre_encap_conf = {
430 	.select_ipv4 = 1,
431 	.select_vlan = 0,
432 	.tni = "\x00\x00\x00",
433 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
434 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
435 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
436 		"\x00\x00\x00\x00\x00\x00\x00\x01",
437 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
438 		"\x00\x00\x00\x00\x00\x00\x11\x11",
439 	.vlan_tci = 0,
440 	.eth_src = "\x00\x00\x00\x00\x00\x00",
441 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
442 };
443 
444 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
445 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
446 
447 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
448 struct action_nvgre_encap_data {
449 	struct rte_flow_action_nvgre_encap conf;
450 	struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
451 	struct rte_flow_item_eth item_eth;
452 	struct rte_flow_item_vlan item_vlan;
453 	union {
454 		struct rte_flow_item_ipv4 item_ipv4;
455 		struct rte_flow_item_ipv6 item_ipv6;
456 	};
457 	struct rte_flow_item_nvgre item_nvgre;
458 };
459 
460 struct l2_encap_conf l2_encap_conf;
461 
462 struct l2_decap_conf l2_decap_conf;
463 
464 struct mplsogre_encap_conf mplsogre_encap_conf;
465 
466 struct mplsogre_decap_conf mplsogre_decap_conf;
467 
468 struct mplsoudp_encap_conf mplsoudp_encap_conf;
469 
470 struct mplsoudp_decap_conf mplsoudp_decap_conf;
471 
472 /** Maximum number of subsequent tokens and arguments on the stack. */
473 #define CTX_STACK_SIZE 16
474 
475 /** Parser context. */
476 struct context {
477 	/** Stack of subsequent token lists to process. */
478 	const enum index *next[CTX_STACK_SIZE];
479 	/** Arguments for stacked tokens. */
480 	const void *args[CTX_STACK_SIZE];
481 	enum index curr; /**< Current token index. */
482 	enum index prev; /**< Index of the last token seen. */
483 	int next_num; /**< Number of entries in next[]. */
484 	int args_num; /**< Number of entries in args[]. */
485 	uint32_t eol:1; /**< EOL has been detected. */
486 	uint32_t last:1; /**< No more arguments. */
487 	portid_t port; /**< Current port ID (for completions). */
488 	uint32_t objdata; /**< Object-specific data. */
489 	void *object; /**< Address of current object for relative offsets. */
490 	void *objmask; /**< Object a full mask must be written to. */
491 };
492 
493 /** Token argument. */
494 struct arg {
495 	uint32_t hton:1; /**< Use network byte ordering. */
496 	uint32_t sign:1; /**< Value is signed. */
497 	uint32_t bounded:1; /**< Value is bounded. */
498 	uintmax_t min; /**< Minimum value if bounded. */
499 	uintmax_t max; /**< Maximum value if bounded. */
500 	uint32_t offset; /**< Relative offset from ctx->object. */
501 	uint32_t size; /**< Field size. */
502 	const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
503 };
504 
505 /** Parser token definition. */
506 struct token {
507 	/** Type displayed during completion (defaults to "TOKEN"). */
508 	const char *type;
509 	/** Help displayed during completion (defaults to token name). */
510 	const char *help;
511 	/** Private data used by parser functions. */
512 	const void *priv;
513 	/**
514 	 * Lists of subsequent tokens to push on the stack. Each call to the
515 	 * parser consumes the last entry of that stack.
516 	 */
517 	const enum index *const *next;
518 	/** Arguments stack for subsequent tokens that need them. */
519 	const struct arg *const *args;
520 	/**
521 	 * Token-processing callback, returns -1 in case of error, the
522 	 * length of the matched string otherwise. If NULL, attempts to
523 	 * match the token name.
524 	 *
525 	 * If buf is not NULL, the result should be stored in it according
526 	 * to context. An error is returned if not large enough.
527 	 */
528 	int (*call)(struct context *ctx, const struct token *token,
529 		    const char *str, unsigned int len,
530 		    void *buf, unsigned int size);
531 	/**
532 	 * Callback that provides possible values for this token, used for
533 	 * completion. Returns -1 in case of error, the number of possible
534 	 * values otherwise. If NULL, the token name is used.
535 	 *
536 	 * If buf is not NULL, entry index ent is written to buf and the
537 	 * full length of the entry is returned (same behavior as
538 	 * snprintf()).
539 	 */
540 	int (*comp)(struct context *ctx, const struct token *token,
541 		    unsigned int ent, char *buf, unsigned int size);
542 	/** Mandatory token name, no default value. */
543 	const char *name;
544 };
545 
546 /** Static initializer for the next field. */
547 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
548 
549 /** Static initializer for a NEXT() entry. */
550 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
551 
552 /** Static initializer for the args field. */
553 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
554 
555 /** Static initializer for ARGS() to target a field. */
556 #define ARGS_ENTRY(s, f) \
557 	(&(const struct arg){ \
558 		.offset = offsetof(s, f), \
559 		.size = sizeof(((s *)0)->f), \
560 	})
561 
562 /** Static initializer for ARGS() to target a bit-field. */
563 #define ARGS_ENTRY_BF(s, f, b) \
564 	(&(const struct arg){ \
565 		.size = sizeof(s), \
566 		.mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
567 	})
568 
569 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
570 #define ARGS_ENTRY_MASK(s, f, m) \
571 	(&(const struct arg){ \
572 		.offset = offsetof(s, f), \
573 		.size = sizeof(((s *)0)->f), \
574 		.mask = (const void *)(m), \
575 	})
576 
577 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
578 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
579 	(&(const struct arg){ \
580 		.hton = 1, \
581 		.offset = offsetof(s, f), \
582 		.size = sizeof(((s *)0)->f), \
583 		.mask = (const void *)(m), \
584 	})
585 
586 /** Static initializer for ARGS() to target a pointer. */
587 #define ARGS_ENTRY_PTR(s, f) \
588 	(&(const struct arg){ \
589 		.size = sizeof(*((s *)0)->f), \
590 	})
591 
592 /** Static initializer for ARGS() with arbitrary offset and size. */
593 #define ARGS_ENTRY_ARB(o, s) \
594 	(&(const struct arg){ \
595 		.offset = (o), \
596 		.size = (s), \
597 	})
598 
599 /** Same as ARGS_ENTRY_ARB() with bounded values. */
600 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
601 	(&(const struct arg){ \
602 		.bounded = 1, \
603 		.min = (i), \
604 		.max = (a), \
605 		.offset = (o), \
606 		.size = (s), \
607 	})
608 
609 /** Same as ARGS_ENTRY() using network byte ordering. */
610 #define ARGS_ENTRY_HTON(s, f) \
611 	(&(const struct arg){ \
612 		.hton = 1, \
613 		.offset = offsetof(s, f), \
614 		.size = sizeof(((s *)0)->f), \
615 	})
616 
617 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
618 #define ARG_ENTRY_HTON(s) \
619 	(&(const struct arg){ \
620 		.hton = 1, \
621 		.offset = 0, \
622 		.size = sizeof(s), \
623 	})
624 
625 /** Parser output buffer layout expected by cmd_flow_parsed(). */
626 struct buffer {
627 	enum index command; /**< Flow command. */
628 	portid_t port; /**< Affected port ID. */
629 	union {
630 		struct {
631 			struct rte_flow_attr attr;
632 			struct rte_flow_item *pattern;
633 			struct rte_flow_action *actions;
634 			uint32_t pattern_n;
635 			uint32_t actions_n;
636 			uint8_t *data;
637 		} vc; /**< Validate/create arguments. */
638 		struct {
639 			uint32_t *rule;
640 			uint32_t rule_n;
641 		} destroy; /**< Destroy arguments. */
642 		struct {
643 			uint32_t rule;
644 			struct rte_flow_action action;
645 		} query; /**< Query arguments. */
646 		struct {
647 			uint32_t *group;
648 			uint32_t group_n;
649 		} list; /**< List arguments. */
650 		struct {
651 			int set;
652 		} isolate; /**< Isolated mode arguments. */
653 	} args; /**< Command arguments. */
654 };
655 
656 /** Private data for pattern items. */
657 struct parse_item_priv {
658 	enum rte_flow_item_type type; /**< Item type. */
659 	uint32_t size; /**< Size of item specification structure. */
660 };
661 
662 #define PRIV_ITEM(t, s) \
663 	(&(const struct parse_item_priv){ \
664 		.type = RTE_FLOW_ITEM_TYPE_ ## t, \
665 		.size = s, \
666 	})
667 
668 /** Private data for actions. */
669 struct parse_action_priv {
670 	enum rte_flow_action_type type; /**< Action type. */
671 	uint32_t size; /**< Size of action configuration structure. */
672 };
673 
674 #define PRIV_ACTION(t, s) \
675 	(&(const struct parse_action_priv){ \
676 		.type = RTE_FLOW_ACTION_TYPE_ ## t, \
677 		.size = s, \
678 	})
679 
680 static const enum index next_vc_attr[] = {
681 	GROUP,
682 	PRIORITY,
683 	INGRESS,
684 	EGRESS,
685 	TRANSFER,
686 	PATTERN,
687 	ZERO,
688 };
689 
690 static const enum index next_destroy_attr[] = {
691 	DESTROY_RULE,
692 	END,
693 	ZERO,
694 };
695 
696 static const enum index next_list_attr[] = {
697 	LIST_GROUP,
698 	END,
699 	ZERO,
700 };
701 
702 static const enum index item_param[] = {
703 	ITEM_PARAM_IS,
704 	ITEM_PARAM_SPEC,
705 	ITEM_PARAM_LAST,
706 	ITEM_PARAM_MASK,
707 	ITEM_PARAM_PREFIX,
708 	ZERO,
709 };
710 
711 static const enum index next_item[] = {
712 	ITEM_END,
713 	ITEM_VOID,
714 	ITEM_INVERT,
715 	ITEM_ANY,
716 	ITEM_PF,
717 	ITEM_VF,
718 	ITEM_PHY_PORT,
719 	ITEM_PORT_ID,
720 	ITEM_MARK,
721 	ITEM_RAW,
722 	ITEM_ETH,
723 	ITEM_VLAN,
724 	ITEM_IPV4,
725 	ITEM_IPV6,
726 	ITEM_ICMP,
727 	ITEM_UDP,
728 	ITEM_TCP,
729 	ITEM_SCTP,
730 	ITEM_VXLAN,
731 	ITEM_E_TAG,
732 	ITEM_NVGRE,
733 	ITEM_MPLS,
734 	ITEM_GRE,
735 	ITEM_FUZZY,
736 	ITEM_GTP,
737 	ITEM_GTPC,
738 	ITEM_GTPU,
739 	ITEM_GENEVE,
740 	ITEM_VXLAN_GPE,
741 	ITEM_ARP_ETH_IPV4,
742 	ITEM_IPV6_EXT,
743 	ITEM_ICMP6,
744 	ITEM_ICMP6_ND_NS,
745 	ITEM_ICMP6_ND_NA,
746 	ITEM_ICMP6_ND_OPT,
747 	ITEM_ICMP6_ND_OPT_SLA_ETH,
748 	ITEM_ICMP6_ND_OPT_TLA_ETH,
749 	ITEM_META,
750 	ITEM_GRE_KEY,
751 	ITEM_GTP_PSC,
752 	ITEM_PPPOES,
753 	ITEM_PPPOED,
754 	ITEM_PPPOE_PROTO_ID,
755 	ITEM_HIGIG2,
756 	ITEM_TAG,
757 	ITEM_L2TPV3OIP,
758 	ITEM_ESP,
759 	END_SET,
760 	ZERO,
761 };
762 
763 static const enum index item_fuzzy[] = {
764 	ITEM_FUZZY_THRESH,
765 	ITEM_NEXT,
766 	ZERO,
767 };
768 
769 static const enum index item_any[] = {
770 	ITEM_ANY_NUM,
771 	ITEM_NEXT,
772 	ZERO,
773 };
774 
775 static const enum index item_vf[] = {
776 	ITEM_VF_ID,
777 	ITEM_NEXT,
778 	ZERO,
779 };
780 
781 static const enum index item_phy_port[] = {
782 	ITEM_PHY_PORT_INDEX,
783 	ITEM_NEXT,
784 	ZERO,
785 };
786 
787 static const enum index item_port_id[] = {
788 	ITEM_PORT_ID_ID,
789 	ITEM_NEXT,
790 	ZERO,
791 };
792 
793 static const enum index item_mark[] = {
794 	ITEM_MARK_ID,
795 	ITEM_NEXT,
796 	ZERO,
797 };
798 
799 static const enum index item_raw[] = {
800 	ITEM_RAW_RELATIVE,
801 	ITEM_RAW_SEARCH,
802 	ITEM_RAW_OFFSET,
803 	ITEM_RAW_LIMIT,
804 	ITEM_RAW_PATTERN,
805 	ITEM_NEXT,
806 	ZERO,
807 };
808 
809 static const enum index item_eth[] = {
810 	ITEM_ETH_DST,
811 	ITEM_ETH_SRC,
812 	ITEM_ETH_TYPE,
813 	ITEM_NEXT,
814 	ZERO,
815 };
816 
817 static const enum index item_vlan[] = {
818 	ITEM_VLAN_TCI,
819 	ITEM_VLAN_PCP,
820 	ITEM_VLAN_DEI,
821 	ITEM_VLAN_VID,
822 	ITEM_VLAN_INNER_TYPE,
823 	ITEM_NEXT,
824 	ZERO,
825 };
826 
827 static const enum index item_ipv4[] = {
828 	ITEM_IPV4_TOS,
829 	ITEM_IPV4_TTL,
830 	ITEM_IPV4_PROTO,
831 	ITEM_IPV4_SRC,
832 	ITEM_IPV4_DST,
833 	ITEM_NEXT,
834 	ZERO,
835 };
836 
837 static const enum index item_ipv6[] = {
838 	ITEM_IPV6_TC,
839 	ITEM_IPV6_FLOW,
840 	ITEM_IPV6_PROTO,
841 	ITEM_IPV6_HOP,
842 	ITEM_IPV6_SRC,
843 	ITEM_IPV6_DST,
844 	ITEM_NEXT,
845 	ZERO,
846 };
847 
848 static const enum index item_icmp[] = {
849 	ITEM_ICMP_TYPE,
850 	ITEM_ICMP_CODE,
851 	ITEM_NEXT,
852 	ZERO,
853 };
854 
855 static const enum index item_udp[] = {
856 	ITEM_UDP_SRC,
857 	ITEM_UDP_DST,
858 	ITEM_NEXT,
859 	ZERO,
860 };
861 
862 static const enum index item_tcp[] = {
863 	ITEM_TCP_SRC,
864 	ITEM_TCP_DST,
865 	ITEM_TCP_FLAGS,
866 	ITEM_NEXT,
867 	ZERO,
868 };
869 
870 static const enum index item_sctp[] = {
871 	ITEM_SCTP_SRC,
872 	ITEM_SCTP_DST,
873 	ITEM_SCTP_TAG,
874 	ITEM_SCTP_CKSUM,
875 	ITEM_NEXT,
876 	ZERO,
877 };
878 
879 static const enum index item_vxlan[] = {
880 	ITEM_VXLAN_VNI,
881 	ITEM_NEXT,
882 	ZERO,
883 };
884 
885 static const enum index item_e_tag[] = {
886 	ITEM_E_TAG_GRP_ECID_B,
887 	ITEM_NEXT,
888 	ZERO,
889 };
890 
891 static const enum index item_nvgre[] = {
892 	ITEM_NVGRE_TNI,
893 	ITEM_NEXT,
894 	ZERO,
895 };
896 
897 static const enum index item_mpls[] = {
898 	ITEM_MPLS_LABEL,
899 	ITEM_MPLS_TC,
900 	ITEM_MPLS_S,
901 	ITEM_NEXT,
902 	ZERO,
903 };
904 
905 static const enum index item_gre[] = {
906 	ITEM_GRE_PROTO,
907 	ITEM_GRE_C_RSVD0_VER,
908 	ITEM_GRE_C_BIT,
909 	ITEM_GRE_K_BIT,
910 	ITEM_GRE_S_BIT,
911 	ITEM_NEXT,
912 	ZERO,
913 };
914 
915 static const enum index item_gre_key[] = {
916 	ITEM_GRE_KEY_VALUE,
917 	ITEM_NEXT,
918 	ZERO,
919 };
920 
921 static const enum index item_gtp[] = {
922 	ITEM_GTP_TEID,
923 	ITEM_NEXT,
924 	ZERO,
925 };
926 
927 static const enum index item_geneve[] = {
928 	ITEM_GENEVE_VNI,
929 	ITEM_GENEVE_PROTO,
930 	ITEM_NEXT,
931 	ZERO,
932 };
933 
934 static const enum index item_vxlan_gpe[] = {
935 	ITEM_VXLAN_GPE_VNI,
936 	ITEM_NEXT,
937 	ZERO,
938 };
939 
940 static const enum index item_arp_eth_ipv4[] = {
941 	ITEM_ARP_ETH_IPV4_SHA,
942 	ITEM_ARP_ETH_IPV4_SPA,
943 	ITEM_ARP_ETH_IPV4_THA,
944 	ITEM_ARP_ETH_IPV4_TPA,
945 	ITEM_NEXT,
946 	ZERO,
947 };
948 
949 static const enum index item_ipv6_ext[] = {
950 	ITEM_IPV6_EXT_NEXT_HDR,
951 	ITEM_NEXT,
952 	ZERO,
953 };
954 
955 static const enum index item_icmp6[] = {
956 	ITEM_ICMP6_TYPE,
957 	ITEM_ICMP6_CODE,
958 	ITEM_NEXT,
959 	ZERO,
960 };
961 
962 static const enum index item_icmp6_nd_ns[] = {
963 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
964 	ITEM_NEXT,
965 	ZERO,
966 };
967 
968 static const enum index item_icmp6_nd_na[] = {
969 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
970 	ITEM_NEXT,
971 	ZERO,
972 };
973 
974 static const enum index item_icmp6_nd_opt[] = {
975 	ITEM_ICMP6_ND_OPT_TYPE,
976 	ITEM_NEXT,
977 	ZERO,
978 };
979 
980 static const enum index item_icmp6_nd_opt_sla_eth[] = {
981 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
982 	ITEM_NEXT,
983 	ZERO,
984 };
985 
986 static const enum index item_icmp6_nd_opt_tla_eth[] = {
987 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
988 	ITEM_NEXT,
989 	ZERO,
990 };
991 
992 static const enum index item_meta[] = {
993 	ITEM_META_DATA,
994 	ITEM_NEXT,
995 	ZERO,
996 };
997 
998 static const enum index item_gtp_psc[] = {
999 	ITEM_GTP_PSC_QFI,
1000 	ITEM_GTP_PSC_PDU_T,
1001 	ITEM_NEXT,
1002 	ZERO,
1003 };
1004 
1005 static const enum index item_pppoed[] = {
1006 	ITEM_PPPOE_SEID,
1007 	ITEM_NEXT,
1008 	ZERO,
1009 };
1010 
1011 static const enum index item_pppoes[] = {
1012 	ITEM_PPPOE_SEID,
1013 	ITEM_NEXT,
1014 	ZERO,
1015 };
1016 
1017 static const enum index item_pppoe_proto_id[] = {
1018 	ITEM_PPPOE_PROTO_ID,
1019 	ITEM_NEXT,
1020 	ZERO,
1021 };
1022 
1023 static const enum index item_higig2[] = {
1024 	ITEM_HIGIG2_CLASSIFICATION,
1025 	ITEM_HIGIG2_VID,
1026 	ITEM_NEXT,
1027 	ZERO,
1028 };
1029 
1030 static const enum index item_esp[] = {
1031 	ITEM_ESP_SPI,
1032 	ITEM_NEXT,
1033 	ZERO,
1034 };
1035 
1036 static const enum index next_set_raw[] = {
1037 	SET_RAW_INDEX,
1038 	ITEM_ETH,
1039 	ZERO,
1040 };
1041 
1042 static const enum index item_tag[] = {
1043 	ITEM_TAG_DATA,
1044 	ITEM_TAG_INDEX,
1045 	ITEM_NEXT,
1046 	ZERO,
1047 };
1048 
1049 static const enum index item_l2tpv3oip[] = {
1050 	ITEM_L2TPV3OIP_SESSION_ID,
1051 	ITEM_NEXT,
1052 	ZERO,
1053 };
1054 
1055 static const enum index next_action[] = {
1056 	ACTION_END,
1057 	ACTION_VOID,
1058 	ACTION_PASSTHRU,
1059 	ACTION_JUMP,
1060 	ACTION_MARK,
1061 	ACTION_FLAG,
1062 	ACTION_QUEUE,
1063 	ACTION_DROP,
1064 	ACTION_COUNT,
1065 	ACTION_RSS,
1066 	ACTION_PF,
1067 	ACTION_VF,
1068 	ACTION_PHY_PORT,
1069 	ACTION_PORT_ID,
1070 	ACTION_METER,
1071 	ACTION_OF_SET_MPLS_TTL,
1072 	ACTION_OF_DEC_MPLS_TTL,
1073 	ACTION_OF_SET_NW_TTL,
1074 	ACTION_OF_DEC_NW_TTL,
1075 	ACTION_OF_COPY_TTL_OUT,
1076 	ACTION_OF_COPY_TTL_IN,
1077 	ACTION_OF_POP_VLAN,
1078 	ACTION_OF_PUSH_VLAN,
1079 	ACTION_OF_SET_VLAN_VID,
1080 	ACTION_OF_SET_VLAN_PCP,
1081 	ACTION_OF_POP_MPLS,
1082 	ACTION_OF_PUSH_MPLS,
1083 	ACTION_VXLAN_ENCAP,
1084 	ACTION_VXLAN_DECAP,
1085 	ACTION_NVGRE_ENCAP,
1086 	ACTION_NVGRE_DECAP,
1087 	ACTION_L2_ENCAP,
1088 	ACTION_L2_DECAP,
1089 	ACTION_MPLSOGRE_ENCAP,
1090 	ACTION_MPLSOGRE_DECAP,
1091 	ACTION_MPLSOUDP_ENCAP,
1092 	ACTION_MPLSOUDP_DECAP,
1093 	ACTION_SET_IPV4_SRC,
1094 	ACTION_SET_IPV4_DST,
1095 	ACTION_SET_IPV6_SRC,
1096 	ACTION_SET_IPV6_DST,
1097 	ACTION_SET_TP_SRC,
1098 	ACTION_SET_TP_DST,
1099 	ACTION_MAC_SWAP,
1100 	ACTION_DEC_TTL,
1101 	ACTION_SET_TTL,
1102 	ACTION_SET_MAC_SRC,
1103 	ACTION_SET_MAC_DST,
1104 	ACTION_INC_TCP_SEQ,
1105 	ACTION_DEC_TCP_SEQ,
1106 	ACTION_INC_TCP_ACK,
1107 	ACTION_DEC_TCP_ACK,
1108 	ACTION_RAW_ENCAP,
1109 	ACTION_RAW_DECAP,
1110 	ACTION_SET_TAG,
1111 	ACTION_SET_META,
1112 	ACTION_SET_IPV4_DSCP,
1113 	ACTION_SET_IPV6_DSCP,
1114 	ZERO,
1115 };
1116 
1117 static const enum index action_mark[] = {
1118 	ACTION_MARK_ID,
1119 	ACTION_NEXT,
1120 	ZERO,
1121 };
1122 
1123 static const enum index action_queue[] = {
1124 	ACTION_QUEUE_INDEX,
1125 	ACTION_NEXT,
1126 	ZERO,
1127 };
1128 
1129 static const enum index action_count[] = {
1130 	ACTION_COUNT_ID,
1131 	ACTION_COUNT_SHARED,
1132 	ACTION_NEXT,
1133 	ZERO,
1134 };
1135 
1136 static const enum index action_rss[] = {
1137 	ACTION_RSS_FUNC,
1138 	ACTION_RSS_LEVEL,
1139 	ACTION_RSS_TYPES,
1140 	ACTION_RSS_KEY,
1141 	ACTION_RSS_KEY_LEN,
1142 	ACTION_RSS_QUEUES,
1143 	ACTION_NEXT,
1144 	ZERO,
1145 };
1146 
1147 static const enum index action_vf[] = {
1148 	ACTION_VF_ORIGINAL,
1149 	ACTION_VF_ID,
1150 	ACTION_NEXT,
1151 	ZERO,
1152 };
1153 
1154 static const enum index action_phy_port[] = {
1155 	ACTION_PHY_PORT_ORIGINAL,
1156 	ACTION_PHY_PORT_INDEX,
1157 	ACTION_NEXT,
1158 	ZERO,
1159 };
1160 
1161 static const enum index action_port_id[] = {
1162 	ACTION_PORT_ID_ORIGINAL,
1163 	ACTION_PORT_ID_ID,
1164 	ACTION_NEXT,
1165 	ZERO,
1166 };
1167 
1168 static const enum index action_meter[] = {
1169 	ACTION_METER_ID,
1170 	ACTION_NEXT,
1171 	ZERO,
1172 };
1173 
1174 static const enum index action_of_set_mpls_ttl[] = {
1175 	ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
1176 	ACTION_NEXT,
1177 	ZERO,
1178 };
1179 
1180 static const enum index action_of_set_nw_ttl[] = {
1181 	ACTION_OF_SET_NW_TTL_NW_TTL,
1182 	ACTION_NEXT,
1183 	ZERO,
1184 };
1185 
1186 static const enum index action_of_push_vlan[] = {
1187 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
1188 	ACTION_NEXT,
1189 	ZERO,
1190 };
1191 
1192 static const enum index action_of_set_vlan_vid[] = {
1193 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
1194 	ACTION_NEXT,
1195 	ZERO,
1196 };
1197 
1198 static const enum index action_of_set_vlan_pcp[] = {
1199 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
1200 	ACTION_NEXT,
1201 	ZERO,
1202 };
1203 
1204 static const enum index action_of_pop_mpls[] = {
1205 	ACTION_OF_POP_MPLS_ETHERTYPE,
1206 	ACTION_NEXT,
1207 	ZERO,
1208 };
1209 
1210 static const enum index action_of_push_mpls[] = {
1211 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
1212 	ACTION_NEXT,
1213 	ZERO,
1214 };
1215 
1216 static const enum index action_set_ipv4_src[] = {
1217 	ACTION_SET_IPV4_SRC_IPV4_SRC,
1218 	ACTION_NEXT,
1219 	ZERO,
1220 };
1221 
1222 static const enum index action_set_mac_src[] = {
1223 	ACTION_SET_MAC_SRC_MAC_SRC,
1224 	ACTION_NEXT,
1225 	ZERO,
1226 };
1227 
1228 static const enum index action_set_ipv4_dst[] = {
1229 	ACTION_SET_IPV4_DST_IPV4_DST,
1230 	ACTION_NEXT,
1231 	ZERO,
1232 };
1233 
1234 static const enum index action_set_ipv6_src[] = {
1235 	ACTION_SET_IPV6_SRC_IPV6_SRC,
1236 	ACTION_NEXT,
1237 	ZERO,
1238 };
1239 
1240 static const enum index action_set_ipv6_dst[] = {
1241 	ACTION_SET_IPV6_DST_IPV6_DST,
1242 	ACTION_NEXT,
1243 	ZERO,
1244 };
1245 
1246 static const enum index action_set_tp_src[] = {
1247 	ACTION_SET_TP_SRC_TP_SRC,
1248 	ACTION_NEXT,
1249 	ZERO,
1250 };
1251 
1252 static const enum index action_set_tp_dst[] = {
1253 	ACTION_SET_TP_DST_TP_DST,
1254 	ACTION_NEXT,
1255 	ZERO,
1256 };
1257 
1258 static const enum index action_set_ttl[] = {
1259 	ACTION_SET_TTL_TTL,
1260 	ACTION_NEXT,
1261 	ZERO,
1262 };
1263 
1264 static const enum index action_jump[] = {
1265 	ACTION_JUMP_GROUP,
1266 	ACTION_NEXT,
1267 	ZERO,
1268 };
1269 
1270 static const enum index action_set_mac_dst[] = {
1271 	ACTION_SET_MAC_DST_MAC_DST,
1272 	ACTION_NEXT,
1273 	ZERO,
1274 };
1275 
1276 static const enum index action_inc_tcp_seq[] = {
1277 	ACTION_INC_TCP_SEQ_VALUE,
1278 	ACTION_NEXT,
1279 	ZERO,
1280 };
1281 
1282 static const enum index action_dec_tcp_seq[] = {
1283 	ACTION_DEC_TCP_SEQ_VALUE,
1284 	ACTION_NEXT,
1285 	ZERO,
1286 };
1287 
1288 static const enum index action_inc_tcp_ack[] = {
1289 	ACTION_INC_TCP_ACK_VALUE,
1290 	ACTION_NEXT,
1291 	ZERO,
1292 };
1293 
1294 static const enum index action_dec_tcp_ack[] = {
1295 	ACTION_DEC_TCP_ACK_VALUE,
1296 	ACTION_NEXT,
1297 	ZERO,
1298 };
1299 
1300 static const enum index action_raw_encap[] = {
1301 	ACTION_RAW_ENCAP_INDEX,
1302 	ACTION_NEXT,
1303 	ZERO,
1304 };
1305 
1306 static const enum index action_raw_decap[] = {
1307 	ACTION_RAW_DECAP_INDEX,
1308 	ACTION_NEXT,
1309 	ZERO,
1310 };
1311 
1312 static const enum index action_set_tag[] = {
1313 	ACTION_SET_TAG_DATA,
1314 	ACTION_SET_TAG_INDEX,
1315 	ACTION_SET_TAG_MASK,
1316 	ACTION_NEXT,
1317 	ZERO,
1318 };
1319 
1320 static const enum index action_set_meta[] = {
1321 	ACTION_SET_META_DATA,
1322 	ACTION_SET_META_MASK,
1323 	ACTION_NEXT,
1324 	ZERO,
1325 };
1326 
1327 static const enum index action_set_ipv4_dscp[] = {
1328 	ACTION_SET_IPV4_DSCP_VALUE,
1329 	ACTION_NEXT,
1330 	ZERO,
1331 };
1332 
1333 static const enum index action_set_ipv6_dscp[] = {
1334 	ACTION_SET_IPV6_DSCP_VALUE,
1335 	ACTION_NEXT,
1336 	ZERO,
1337 };
1338 
1339 static int parse_set_raw_encap_decap(struct context *, const struct token *,
1340 				     const char *, unsigned int,
1341 				     void *, unsigned int);
1342 static int parse_set_init(struct context *, const struct token *,
1343 			  const char *, unsigned int,
1344 			  void *, unsigned int);
1345 static int parse_init(struct context *, const struct token *,
1346 		      const char *, unsigned int,
1347 		      void *, unsigned int);
1348 static int parse_vc(struct context *, const struct token *,
1349 		    const char *, unsigned int,
1350 		    void *, unsigned int);
1351 static int parse_vc_spec(struct context *, const struct token *,
1352 			 const char *, unsigned int, void *, unsigned int);
1353 static int parse_vc_conf(struct context *, const struct token *,
1354 			 const char *, unsigned int, void *, unsigned int);
1355 static int parse_vc_action_rss(struct context *, const struct token *,
1356 			       const char *, unsigned int, void *,
1357 			       unsigned int);
1358 static int parse_vc_action_rss_func(struct context *, const struct token *,
1359 				    const char *, unsigned int, void *,
1360 				    unsigned int);
1361 static int parse_vc_action_rss_type(struct context *, const struct token *,
1362 				    const char *, unsigned int, void *,
1363 				    unsigned int);
1364 static int parse_vc_action_rss_queue(struct context *, const struct token *,
1365 				     const char *, unsigned int, void *,
1366 				     unsigned int);
1367 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
1368 				       const char *, unsigned int, void *,
1369 				       unsigned int);
1370 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
1371 				       const char *, unsigned int, void *,
1372 				       unsigned int);
1373 static int parse_vc_action_l2_encap(struct context *, const struct token *,
1374 				    const char *, unsigned int, void *,
1375 				    unsigned int);
1376 static int parse_vc_action_l2_decap(struct context *, const struct token *,
1377 				    const char *, unsigned int, void *,
1378 				    unsigned int);
1379 static int parse_vc_action_mplsogre_encap(struct context *,
1380 					  const struct token *, const char *,
1381 					  unsigned int, void *, unsigned int);
1382 static int parse_vc_action_mplsogre_decap(struct context *,
1383 					  const struct token *, const char *,
1384 					  unsigned int, void *, unsigned int);
1385 static int parse_vc_action_mplsoudp_encap(struct context *,
1386 					  const struct token *, const char *,
1387 					  unsigned int, void *, unsigned int);
1388 static int parse_vc_action_mplsoudp_decap(struct context *,
1389 					  const struct token *, const char *,
1390 					  unsigned int, void *, unsigned int);
1391 static int parse_vc_action_raw_encap(struct context *,
1392 				     const struct token *, const char *,
1393 				     unsigned int, void *, unsigned int);
1394 static int parse_vc_action_raw_decap(struct context *,
1395 				     const struct token *, const char *,
1396 				     unsigned int, void *, unsigned int);
1397 static int parse_vc_action_raw_encap_index(struct context *,
1398 					   const struct token *, const char *,
1399 					   unsigned int, void *, unsigned int);
1400 static int parse_vc_action_raw_decap_index(struct context *,
1401 					   const struct token *, const char *,
1402 					   unsigned int, void *, unsigned int);
1403 static int parse_vc_action_set_meta(struct context *ctx,
1404 				    const struct token *token, const char *str,
1405 				    unsigned int len, void *buf,
1406 				    unsigned int size);
1407 static int parse_destroy(struct context *, const struct token *,
1408 			 const char *, unsigned int,
1409 			 void *, unsigned int);
1410 static int parse_flush(struct context *, const struct token *,
1411 		       const char *, unsigned int,
1412 		       void *, unsigned int);
1413 static int parse_query(struct context *, const struct token *,
1414 		       const char *, unsigned int,
1415 		       void *, unsigned int);
1416 static int parse_action(struct context *, const struct token *,
1417 			const char *, unsigned int,
1418 			void *, unsigned int);
1419 static int parse_list(struct context *, const struct token *,
1420 		      const char *, unsigned int,
1421 		      void *, unsigned int);
1422 static int parse_isolate(struct context *, const struct token *,
1423 			 const char *, unsigned int,
1424 			 void *, unsigned int);
1425 static int parse_int(struct context *, const struct token *,
1426 		     const char *, unsigned int,
1427 		     void *, unsigned int);
1428 static int parse_prefix(struct context *, const struct token *,
1429 			const char *, unsigned int,
1430 			void *, unsigned int);
1431 static int parse_boolean(struct context *, const struct token *,
1432 			 const char *, unsigned int,
1433 			 void *, unsigned int);
1434 static int parse_string(struct context *, const struct token *,
1435 			const char *, unsigned int,
1436 			void *, unsigned int);
1437 static int parse_hex(struct context *ctx, const struct token *token,
1438 			const char *str, unsigned int len,
1439 			void *buf, unsigned int size);
1440 static int parse_mac_addr(struct context *, const struct token *,
1441 			  const char *, unsigned int,
1442 			  void *, unsigned int);
1443 static int parse_ipv4_addr(struct context *, const struct token *,
1444 			   const char *, unsigned int,
1445 			   void *, unsigned int);
1446 static int parse_ipv6_addr(struct context *, const struct token *,
1447 			   const char *, unsigned int,
1448 			   void *, unsigned int);
1449 static int parse_port(struct context *, const struct token *,
1450 		      const char *, unsigned int,
1451 		      void *, unsigned int);
1452 static int comp_none(struct context *, const struct token *,
1453 		     unsigned int, char *, unsigned int);
1454 static int comp_boolean(struct context *, const struct token *,
1455 			unsigned int, char *, unsigned int);
1456 static int comp_action(struct context *, const struct token *,
1457 		       unsigned int, char *, unsigned int);
1458 static int comp_port(struct context *, const struct token *,
1459 		     unsigned int, char *, unsigned int);
1460 static int comp_rule_id(struct context *, const struct token *,
1461 			unsigned int, char *, unsigned int);
1462 static int comp_vc_action_rss_type(struct context *, const struct token *,
1463 				   unsigned int, char *, unsigned int);
1464 static int comp_vc_action_rss_queue(struct context *, const struct token *,
1465 				    unsigned int, char *, unsigned int);
1466 static int comp_set_raw_index(struct context *, const struct token *,
1467 			      unsigned int, char *, unsigned int);
1468 
1469 /** Token definitions. */
1470 static const struct token token_list[] = {
1471 	/* Special tokens. */
1472 	[ZERO] = {
1473 		.name = "ZERO",
1474 		.help = "null entry, abused as the entry point",
1475 		.next = NEXT(NEXT_ENTRY(FLOW)),
1476 	},
1477 	[END] = {
1478 		.name = "",
1479 		.type = "RETURN",
1480 		.help = "command may end here",
1481 	},
1482 	[START_SET] = {
1483 		.name = "START_SET",
1484 		.help = "null entry, abused as the entry point for set",
1485 		.next = NEXT(NEXT_ENTRY(SET)),
1486 	},
1487 	[END_SET] = {
1488 		.name = "end_set",
1489 		.type = "RETURN",
1490 		.help = "set command may end here",
1491 	},
1492 	/* Common tokens. */
1493 	[INTEGER] = {
1494 		.name = "{int}",
1495 		.type = "INTEGER",
1496 		.help = "integer value",
1497 		.call = parse_int,
1498 		.comp = comp_none,
1499 	},
1500 	[UNSIGNED] = {
1501 		.name = "{unsigned}",
1502 		.type = "UNSIGNED",
1503 		.help = "unsigned integer value",
1504 		.call = parse_int,
1505 		.comp = comp_none,
1506 	},
1507 	[PREFIX] = {
1508 		.name = "{prefix}",
1509 		.type = "PREFIX",
1510 		.help = "prefix length for bit-mask",
1511 		.call = parse_prefix,
1512 		.comp = comp_none,
1513 	},
1514 	[BOOLEAN] = {
1515 		.name = "{boolean}",
1516 		.type = "BOOLEAN",
1517 		.help = "any boolean value",
1518 		.call = parse_boolean,
1519 		.comp = comp_boolean,
1520 	},
1521 	[STRING] = {
1522 		.name = "{string}",
1523 		.type = "STRING",
1524 		.help = "fixed string",
1525 		.call = parse_string,
1526 		.comp = comp_none,
1527 	},
1528 	[HEX] = {
1529 		.name = "{hex}",
1530 		.type = "HEX",
1531 		.help = "fixed string",
1532 		.call = parse_hex,
1533 		.comp = comp_none,
1534 	},
1535 	[MAC_ADDR] = {
1536 		.name = "{MAC address}",
1537 		.type = "MAC-48",
1538 		.help = "standard MAC address notation",
1539 		.call = parse_mac_addr,
1540 		.comp = comp_none,
1541 	},
1542 	[IPV4_ADDR] = {
1543 		.name = "{IPv4 address}",
1544 		.type = "IPV4 ADDRESS",
1545 		.help = "standard IPv4 address notation",
1546 		.call = parse_ipv4_addr,
1547 		.comp = comp_none,
1548 	},
1549 	[IPV6_ADDR] = {
1550 		.name = "{IPv6 address}",
1551 		.type = "IPV6 ADDRESS",
1552 		.help = "standard IPv6 address notation",
1553 		.call = parse_ipv6_addr,
1554 		.comp = comp_none,
1555 	},
1556 	[RULE_ID] = {
1557 		.name = "{rule id}",
1558 		.type = "RULE ID",
1559 		.help = "rule identifier",
1560 		.call = parse_int,
1561 		.comp = comp_rule_id,
1562 	},
1563 	[PORT_ID] = {
1564 		.name = "{port_id}",
1565 		.type = "PORT ID",
1566 		.help = "port identifier",
1567 		.call = parse_port,
1568 		.comp = comp_port,
1569 	},
1570 	[GROUP_ID] = {
1571 		.name = "{group_id}",
1572 		.type = "GROUP ID",
1573 		.help = "group identifier",
1574 		.call = parse_int,
1575 		.comp = comp_none,
1576 	},
1577 	[PRIORITY_LEVEL] = {
1578 		.name = "{level}",
1579 		.type = "PRIORITY",
1580 		.help = "priority level",
1581 		.call = parse_int,
1582 		.comp = comp_none,
1583 	},
1584 	/* Top-level command. */
1585 	[FLOW] = {
1586 		.name = "flow",
1587 		.type = "{command} {port_id} [{arg} [...]]",
1588 		.help = "manage ingress/egress flow rules",
1589 		.next = NEXT(NEXT_ENTRY
1590 			     (VALIDATE,
1591 			      CREATE,
1592 			      DESTROY,
1593 			      FLUSH,
1594 			      LIST,
1595 			      QUERY,
1596 			      ISOLATE)),
1597 		.call = parse_init,
1598 	},
1599 	/* Sub-level commands. */
1600 	[VALIDATE] = {
1601 		.name = "validate",
1602 		.help = "check whether a flow rule can be created",
1603 		.next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
1604 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
1605 		.call = parse_vc,
1606 	},
1607 	[CREATE] = {
1608 		.name = "create",
1609 		.help = "create a flow rule",
1610 		.next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
1611 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
1612 		.call = parse_vc,
1613 	},
1614 	[DESTROY] = {
1615 		.name = "destroy",
1616 		.help = "destroy specific flow rules",
1617 		.next = NEXT(NEXT_ENTRY(DESTROY_RULE), NEXT_ENTRY(PORT_ID)),
1618 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
1619 		.call = parse_destroy,
1620 	},
1621 	[FLUSH] = {
1622 		.name = "flush",
1623 		.help = "destroy all flow rules",
1624 		.next = NEXT(NEXT_ENTRY(PORT_ID)),
1625 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
1626 		.call = parse_flush,
1627 	},
1628 	[QUERY] = {
1629 		.name = "query",
1630 		.help = "query an existing flow rule",
1631 		.next = NEXT(NEXT_ENTRY(QUERY_ACTION),
1632 			     NEXT_ENTRY(RULE_ID),
1633 			     NEXT_ENTRY(PORT_ID)),
1634 		.args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
1635 			     ARGS_ENTRY(struct buffer, args.query.rule),
1636 			     ARGS_ENTRY(struct buffer, port)),
1637 		.call = parse_query,
1638 	},
1639 	[LIST] = {
1640 		.name = "list",
1641 		.help = "list existing flow rules",
1642 		.next = NEXT(next_list_attr, NEXT_ENTRY(PORT_ID)),
1643 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
1644 		.call = parse_list,
1645 	},
1646 	[ISOLATE] = {
1647 		.name = "isolate",
1648 		.help = "restrict ingress traffic to the defined flow rules",
1649 		.next = NEXT(NEXT_ENTRY(BOOLEAN),
1650 			     NEXT_ENTRY(PORT_ID)),
1651 		.args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
1652 			     ARGS_ENTRY(struct buffer, port)),
1653 		.call = parse_isolate,
1654 	},
1655 	/* Destroy arguments. */
1656 	[DESTROY_RULE] = {
1657 		.name = "rule",
1658 		.help = "specify a rule identifier",
1659 		.next = NEXT(next_destroy_attr, NEXT_ENTRY(RULE_ID)),
1660 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
1661 		.call = parse_destroy,
1662 	},
1663 	/* Query arguments. */
1664 	[QUERY_ACTION] = {
1665 		.name = "{action}",
1666 		.type = "ACTION",
1667 		.help = "action to query, must be part of the rule",
1668 		.call = parse_action,
1669 		.comp = comp_action,
1670 	},
1671 	/* List arguments. */
1672 	[LIST_GROUP] = {
1673 		.name = "group",
1674 		.help = "specify a group",
1675 		.next = NEXT(next_list_attr, NEXT_ENTRY(GROUP_ID)),
1676 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
1677 		.call = parse_list,
1678 	},
1679 	/* Validate/create attributes. */
1680 	[GROUP] = {
1681 		.name = "group",
1682 		.help = "specify a group",
1683 		.next = NEXT(next_vc_attr, NEXT_ENTRY(GROUP_ID)),
1684 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
1685 		.call = parse_vc,
1686 	},
1687 	[PRIORITY] = {
1688 		.name = "priority",
1689 		.help = "specify a priority level",
1690 		.next = NEXT(next_vc_attr, NEXT_ENTRY(PRIORITY_LEVEL)),
1691 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
1692 		.call = parse_vc,
1693 	},
1694 	[INGRESS] = {
1695 		.name = "ingress",
1696 		.help = "affect rule to ingress",
1697 		.next = NEXT(next_vc_attr),
1698 		.call = parse_vc,
1699 	},
1700 	[EGRESS] = {
1701 		.name = "egress",
1702 		.help = "affect rule to egress",
1703 		.next = NEXT(next_vc_attr),
1704 		.call = parse_vc,
1705 	},
1706 	[TRANSFER] = {
1707 		.name = "transfer",
1708 		.help = "apply rule directly to endpoints found in pattern",
1709 		.next = NEXT(next_vc_attr),
1710 		.call = parse_vc,
1711 	},
1712 	/* Validate/create pattern. */
1713 	[PATTERN] = {
1714 		.name = "pattern",
1715 		.help = "submit a list of pattern items",
1716 		.next = NEXT(next_item),
1717 		.call = parse_vc,
1718 	},
1719 	[ITEM_PARAM_IS] = {
1720 		.name = "is",
1721 		.help = "match value perfectly (with full bit-mask)",
1722 		.call = parse_vc_spec,
1723 	},
1724 	[ITEM_PARAM_SPEC] = {
1725 		.name = "spec",
1726 		.help = "match value according to configured bit-mask",
1727 		.call = parse_vc_spec,
1728 	},
1729 	[ITEM_PARAM_LAST] = {
1730 		.name = "last",
1731 		.help = "specify upper bound to establish a range",
1732 		.call = parse_vc_spec,
1733 	},
1734 	[ITEM_PARAM_MASK] = {
1735 		.name = "mask",
1736 		.help = "specify bit-mask with relevant bits set to one",
1737 		.call = parse_vc_spec,
1738 	},
1739 	[ITEM_PARAM_PREFIX] = {
1740 		.name = "prefix",
1741 		.help = "generate bit-mask from a prefix length",
1742 		.call = parse_vc_spec,
1743 	},
1744 	[ITEM_NEXT] = {
1745 		.name = "/",
1746 		.help = "specify next pattern item",
1747 		.next = NEXT(next_item),
1748 	},
1749 	[ITEM_END] = {
1750 		.name = "end",
1751 		.help = "end list of pattern items",
1752 		.priv = PRIV_ITEM(END, 0),
1753 		.next = NEXT(NEXT_ENTRY(ACTIONS)),
1754 		.call = parse_vc,
1755 	},
1756 	[ITEM_VOID] = {
1757 		.name = "void",
1758 		.help = "no-op pattern item",
1759 		.priv = PRIV_ITEM(VOID, 0),
1760 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
1761 		.call = parse_vc,
1762 	},
1763 	[ITEM_INVERT] = {
1764 		.name = "invert",
1765 		.help = "perform actions when pattern does not match",
1766 		.priv = PRIV_ITEM(INVERT, 0),
1767 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
1768 		.call = parse_vc,
1769 	},
1770 	[ITEM_ANY] = {
1771 		.name = "any",
1772 		.help = "match any protocol for the current layer",
1773 		.priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
1774 		.next = NEXT(item_any),
1775 		.call = parse_vc,
1776 	},
1777 	[ITEM_ANY_NUM] = {
1778 		.name = "num",
1779 		.help = "number of layers covered",
1780 		.next = NEXT(item_any, NEXT_ENTRY(UNSIGNED), item_param),
1781 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
1782 	},
1783 	[ITEM_PF] = {
1784 		.name = "pf",
1785 		.help = "match traffic from/to the physical function",
1786 		.priv = PRIV_ITEM(PF, 0),
1787 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
1788 		.call = parse_vc,
1789 	},
1790 	[ITEM_VF] = {
1791 		.name = "vf",
1792 		.help = "match traffic from/to a virtual function ID",
1793 		.priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
1794 		.next = NEXT(item_vf),
1795 		.call = parse_vc,
1796 	},
1797 	[ITEM_VF_ID] = {
1798 		.name = "id",
1799 		.help = "VF ID",
1800 		.next = NEXT(item_vf, NEXT_ENTRY(UNSIGNED), item_param),
1801 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
1802 	},
1803 	[ITEM_PHY_PORT] = {
1804 		.name = "phy_port",
1805 		.help = "match traffic from/to a specific physical port",
1806 		.priv = PRIV_ITEM(PHY_PORT,
1807 				  sizeof(struct rte_flow_item_phy_port)),
1808 		.next = NEXT(item_phy_port),
1809 		.call = parse_vc,
1810 	},
1811 	[ITEM_PHY_PORT_INDEX] = {
1812 		.name = "index",
1813 		.help = "physical port index",
1814 		.next = NEXT(item_phy_port, NEXT_ENTRY(UNSIGNED), item_param),
1815 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)),
1816 	},
1817 	[ITEM_PORT_ID] = {
1818 		.name = "port_id",
1819 		.help = "match traffic from/to a given DPDK port ID",
1820 		.priv = PRIV_ITEM(PORT_ID,
1821 				  sizeof(struct rte_flow_item_port_id)),
1822 		.next = NEXT(item_port_id),
1823 		.call = parse_vc,
1824 	},
1825 	[ITEM_PORT_ID_ID] = {
1826 		.name = "id",
1827 		.help = "DPDK port ID",
1828 		.next = NEXT(item_port_id, NEXT_ENTRY(UNSIGNED), item_param),
1829 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
1830 	},
1831 	[ITEM_MARK] = {
1832 		.name = "mark",
1833 		.help = "match traffic against value set in previously matched rule",
1834 		.priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
1835 		.next = NEXT(item_mark),
1836 		.call = parse_vc,
1837 	},
1838 	[ITEM_MARK_ID] = {
1839 		.name = "id",
1840 		.help = "Integer value to match against",
1841 		.next = NEXT(item_mark, NEXT_ENTRY(UNSIGNED), item_param),
1842 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
1843 	},
1844 	[ITEM_RAW] = {
1845 		.name = "raw",
1846 		.help = "match an arbitrary byte string",
1847 		.priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
1848 		.next = NEXT(item_raw),
1849 		.call = parse_vc,
1850 	},
1851 	[ITEM_RAW_RELATIVE] = {
1852 		.name = "relative",
1853 		.help = "look for pattern after the previous item",
1854 		.next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
1855 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
1856 					   relative, 1)),
1857 	},
1858 	[ITEM_RAW_SEARCH] = {
1859 		.name = "search",
1860 		.help = "search pattern from offset (see also limit)",
1861 		.next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
1862 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
1863 					   search, 1)),
1864 	},
1865 	[ITEM_RAW_OFFSET] = {
1866 		.name = "offset",
1867 		.help = "absolute or relative offset for pattern",
1868 		.next = NEXT(item_raw, NEXT_ENTRY(INTEGER), item_param),
1869 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
1870 	},
1871 	[ITEM_RAW_LIMIT] = {
1872 		.name = "limit",
1873 		.help = "search area limit for start of pattern",
1874 		.next = NEXT(item_raw, NEXT_ENTRY(UNSIGNED), item_param),
1875 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
1876 	},
1877 	[ITEM_RAW_PATTERN] = {
1878 		.name = "pattern",
1879 		.help = "byte string to look for",
1880 		.next = NEXT(item_raw,
1881 			     NEXT_ENTRY(STRING),
1882 			     NEXT_ENTRY(ITEM_PARAM_IS,
1883 					ITEM_PARAM_SPEC,
1884 					ITEM_PARAM_MASK)),
1885 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
1886 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
1887 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
1888 					    ITEM_RAW_PATTERN_SIZE)),
1889 	},
1890 	[ITEM_ETH] = {
1891 		.name = "eth",
1892 		.help = "match Ethernet header",
1893 		.priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
1894 		.next = NEXT(item_eth),
1895 		.call = parse_vc,
1896 	},
1897 	[ITEM_ETH_DST] = {
1898 		.name = "dst",
1899 		.help = "destination MAC",
1900 		.next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
1901 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
1902 	},
1903 	[ITEM_ETH_SRC] = {
1904 		.name = "src",
1905 		.help = "source MAC",
1906 		.next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
1907 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
1908 	},
1909 	[ITEM_ETH_TYPE] = {
1910 		.name = "type",
1911 		.help = "EtherType",
1912 		.next = NEXT(item_eth, NEXT_ENTRY(UNSIGNED), item_param),
1913 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
1914 	},
1915 	[ITEM_VLAN] = {
1916 		.name = "vlan",
1917 		.help = "match 802.1Q/ad VLAN tag",
1918 		.priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
1919 		.next = NEXT(item_vlan),
1920 		.call = parse_vc,
1921 	},
1922 	[ITEM_VLAN_TCI] = {
1923 		.name = "tci",
1924 		.help = "tag control information",
1925 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1926 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
1927 	},
1928 	[ITEM_VLAN_PCP] = {
1929 		.name = "pcp",
1930 		.help = "priority code point",
1931 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1932 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
1933 						  tci, "\xe0\x00")),
1934 	},
1935 	[ITEM_VLAN_DEI] = {
1936 		.name = "dei",
1937 		.help = "drop eligible indicator",
1938 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1939 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
1940 						  tci, "\x10\x00")),
1941 	},
1942 	[ITEM_VLAN_VID] = {
1943 		.name = "vid",
1944 		.help = "VLAN identifier",
1945 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1946 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
1947 						  tci, "\x0f\xff")),
1948 	},
1949 	[ITEM_VLAN_INNER_TYPE] = {
1950 		.name = "inner_type",
1951 		.help = "inner EtherType",
1952 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1953 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
1954 					     inner_type)),
1955 	},
1956 	[ITEM_IPV4] = {
1957 		.name = "ipv4",
1958 		.help = "match IPv4 header",
1959 		.priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
1960 		.next = NEXT(item_ipv4),
1961 		.call = parse_vc,
1962 	},
1963 	[ITEM_IPV4_TOS] = {
1964 		.name = "tos",
1965 		.help = "type of service",
1966 		.next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
1967 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1968 					     hdr.type_of_service)),
1969 	},
1970 	[ITEM_IPV4_TTL] = {
1971 		.name = "ttl",
1972 		.help = "time to live",
1973 		.next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
1974 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1975 					     hdr.time_to_live)),
1976 	},
1977 	[ITEM_IPV4_PROTO] = {
1978 		.name = "proto",
1979 		.help = "next protocol ID",
1980 		.next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
1981 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1982 					     hdr.next_proto_id)),
1983 	},
1984 	[ITEM_IPV4_SRC] = {
1985 		.name = "src",
1986 		.help = "source address",
1987 		.next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
1988 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1989 					     hdr.src_addr)),
1990 	},
1991 	[ITEM_IPV4_DST] = {
1992 		.name = "dst",
1993 		.help = "destination address",
1994 		.next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
1995 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1996 					     hdr.dst_addr)),
1997 	},
1998 	[ITEM_IPV6] = {
1999 		.name = "ipv6",
2000 		.help = "match IPv6 header",
2001 		.priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
2002 		.next = NEXT(item_ipv6),
2003 		.call = parse_vc,
2004 	},
2005 	[ITEM_IPV6_TC] = {
2006 		.name = "tc",
2007 		.help = "traffic class",
2008 		.next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
2009 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
2010 						  hdr.vtc_flow,
2011 						  "\x0f\xf0\x00\x00")),
2012 	},
2013 	[ITEM_IPV6_FLOW] = {
2014 		.name = "flow",
2015 		.help = "flow label",
2016 		.next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
2017 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
2018 						  hdr.vtc_flow,
2019 						  "\x00\x0f\xff\xff")),
2020 	},
2021 	[ITEM_IPV6_PROTO] = {
2022 		.name = "proto",
2023 		.help = "protocol (next header)",
2024 		.next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
2025 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2026 					     hdr.proto)),
2027 	},
2028 	[ITEM_IPV6_HOP] = {
2029 		.name = "hop",
2030 		.help = "hop limit",
2031 		.next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
2032 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2033 					     hdr.hop_limits)),
2034 	},
2035 	[ITEM_IPV6_SRC] = {
2036 		.name = "src",
2037 		.help = "source address",
2038 		.next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
2039 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2040 					     hdr.src_addr)),
2041 	},
2042 	[ITEM_IPV6_DST] = {
2043 		.name = "dst",
2044 		.help = "destination address",
2045 		.next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
2046 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2047 					     hdr.dst_addr)),
2048 	},
2049 	[ITEM_ICMP] = {
2050 		.name = "icmp",
2051 		.help = "match ICMP header",
2052 		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
2053 		.next = NEXT(item_icmp),
2054 		.call = parse_vc,
2055 	},
2056 	[ITEM_ICMP_TYPE] = {
2057 		.name = "type",
2058 		.help = "ICMP packet type",
2059 		.next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
2060 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2061 					     hdr.icmp_type)),
2062 	},
2063 	[ITEM_ICMP_CODE] = {
2064 		.name = "code",
2065 		.help = "ICMP packet code",
2066 		.next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
2067 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2068 					     hdr.icmp_code)),
2069 	},
2070 	[ITEM_UDP] = {
2071 		.name = "udp",
2072 		.help = "match UDP header",
2073 		.priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
2074 		.next = NEXT(item_udp),
2075 		.call = parse_vc,
2076 	},
2077 	[ITEM_UDP_SRC] = {
2078 		.name = "src",
2079 		.help = "UDP source port",
2080 		.next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
2081 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
2082 					     hdr.src_port)),
2083 	},
2084 	[ITEM_UDP_DST] = {
2085 		.name = "dst",
2086 		.help = "UDP destination port",
2087 		.next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
2088 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
2089 					     hdr.dst_port)),
2090 	},
2091 	[ITEM_TCP] = {
2092 		.name = "tcp",
2093 		.help = "match TCP header",
2094 		.priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
2095 		.next = NEXT(item_tcp),
2096 		.call = parse_vc,
2097 	},
2098 	[ITEM_TCP_SRC] = {
2099 		.name = "src",
2100 		.help = "TCP source port",
2101 		.next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
2102 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
2103 					     hdr.src_port)),
2104 	},
2105 	[ITEM_TCP_DST] = {
2106 		.name = "dst",
2107 		.help = "TCP destination port",
2108 		.next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
2109 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
2110 					     hdr.dst_port)),
2111 	},
2112 	[ITEM_TCP_FLAGS] = {
2113 		.name = "flags",
2114 		.help = "TCP flags",
2115 		.next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
2116 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
2117 					     hdr.tcp_flags)),
2118 	},
2119 	[ITEM_SCTP] = {
2120 		.name = "sctp",
2121 		.help = "match SCTP header",
2122 		.priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
2123 		.next = NEXT(item_sctp),
2124 		.call = parse_vc,
2125 	},
2126 	[ITEM_SCTP_SRC] = {
2127 		.name = "src",
2128 		.help = "SCTP source port",
2129 		.next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
2130 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2131 					     hdr.src_port)),
2132 	},
2133 	[ITEM_SCTP_DST] = {
2134 		.name = "dst",
2135 		.help = "SCTP destination port",
2136 		.next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
2137 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2138 					     hdr.dst_port)),
2139 	},
2140 	[ITEM_SCTP_TAG] = {
2141 		.name = "tag",
2142 		.help = "validation tag",
2143 		.next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
2144 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2145 					     hdr.tag)),
2146 	},
2147 	[ITEM_SCTP_CKSUM] = {
2148 		.name = "cksum",
2149 		.help = "checksum",
2150 		.next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
2151 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2152 					     hdr.cksum)),
2153 	},
2154 	[ITEM_VXLAN] = {
2155 		.name = "vxlan",
2156 		.help = "match VXLAN header",
2157 		.priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
2158 		.next = NEXT(item_vxlan),
2159 		.call = parse_vc,
2160 	},
2161 	[ITEM_VXLAN_VNI] = {
2162 		.name = "vni",
2163 		.help = "VXLAN identifier",
2164 		.next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED), item_param),
2165 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
2166 	},
2167 	[ITEM_E_TAG] = {
2168 		.name = "e_tag",
2169 		.help = "match E-Tag header",
2170 		.priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
2171 		.next = NEXT(item_e_tag),
2172 		.call = parse_vc,
2173 	},
2174 	[ITEM_E_TAG_GRP_ECID_B] = {
2175 		.name = "grp_ecid_b",
2176 		.help = "GRP and E-CID base",
2177 		.next = NEXT(item_e_tag, NEXT_ENTRY(UNSIGNED), item_param),
2178 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
2179 						  rsvd_grp_ecid_b,
2180 						  "\x3f\xff")),
2181 	},
2182 	[ITEM_NVGRE] = {
2183 		.name = "nvgre",
2184 		.help = "match NVGRE header",
2185 		.priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
2186 		.next = NEXT(item_nvgre),
2187 		.call = parse_vc,
2188 	},
2189 	[ITEM_NVGRE_TNI] = {
2190 		.name = "tni",
2191 		.help = "virtual subnet ID",
2192 		.next = NEXT(item_nvgre, NEXT_ENTRY(UNSIGNED), item_param),
2193 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
2194 	},
2195 	[ITEM_MPLS] = {
2196 		.name = "mpls",
2197 		.help = "match MPLS header",
2198 		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
2199 		.next = NEXT(item_mpls),
2200 		.call = parse_vc,
2201 	},
2202 	[ITEM_MPLS_LABEL] = {
2203 		.name = "label",
2204 		.help = "MPLS label",
2205 		.next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
2206 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
2207 						  label_tc_s,
2208 						  "\xff\xff\xf0")),
2209 	},
2210 	[ITEM_MPLS_TC] = {
2211 		.name = "tc",
2212 		.help = "MPLS Traffic Class",
2213 		.next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
2214 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
2215 						  label_tc_s,
2216 						  "\x00\x00\x0e")),
2217 	},
2218 	[ITEM_MPLS_S] = {
2219 		.name = "s",
2220 		.help = "MPLS Bottom-of-Stack",
2221 		.next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
2222 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
2223 						  label_tc_s,
2224 						  "\x00\x00\x01")),
2225 	},
2226 	[ITEM_GRE] = {
2227 		.name = "gre",
2228 		.help = "match GRE header",
2229 		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
2230 		.next = NEXT(item_gre),
2231 		.call = parse_vc,
2232 	},
2233 	[ITEM_GRE_PROTO] = {
2234 		.name = "protocol",
2235 		.help = "GRE protocol type",
2236 		.next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
2237 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
2238 					     protocol)),
2239 	},
2240 	[ITEM_GRE_C_RSVD0_VER] = {
2241 		.name = "c_rsvd0_ver",
2242 		.help =
2243 			"checksum (1b), undefined (1b), key bit (1b),"
2244 			" sequence number (1b), reserved 0 (9b),"
2245 			" version (3b)",
2246 		.next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
2247 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
2248 					     c_rsvd0_ver)),
2249 	},
2250 	[ITEM_GRE_C_BIT] = {
2251 		.name = "c_bit",
2252 		.help = "checksum bit (C)",
2253 		.next = NEXT(item_gre, NEXT_ENTRY(BOOLEAN), item_param),
2254 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
2255 						  c_rsvd0_ver,
2256 						  "\x80\x00\x00\x00")),
2257 	},
2258 	[ITEM_GRE_S_BIT] = {
2259 		.name = "s_bit",
2260 		.help = "sequence number bit (S)",
2261 		.next = NEXT(item_gre, NEXT_ENTRY(BOOLEAN), item_param),
2262 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
2263 						  c_rsvd0_ver,
2264 						  "\x10\x00\x00\x00")),
2265 	},
2266 	[ITEM_GRE_K_BIT] = {
2267 		.name = "k_bit",
2268 		.help = "key bit (K)",
2269 		.next = NEXT(item_gre, NEXT_ENTRY(BOOLEAN), item_param),
2270 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
2271 						  c_rsvd0_ver,
2272 						  "\x20\x00\x00\x00")),
2273 	},
2274 	[ITEM_FUZZY] = {
2275 		.name = "fuzzy",
2276 		.help = "fuzzy pattern match, expect faster than default",
2277 		.priv = PRIV_ITEM(FUZZY,
2278 				sizeof(struct rte_flow_item_fuzzy)),
2279 		.next = NEXT(item_fuzzy),
2280 		.call = parse_vc,
2281 	},
2282 	[ITEM_FUZZY_THRESH] = {
2283 		.name = "thresh",
2284 		.help = "match accuracy threshold",
2285 		.next = NEXT(item_fuzzy, NEXT_ENTRY(UNSIGNED), item_param),
2286 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
2287 					thresh)),
2288 	},
2289 	[ITEM_GTP] = {
2290 		.name = "gtp",
2291 		.help = "match GTP header",
2292 		.priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
2293 		.next = NEXT(item_gtp),
2294 		.call = parse_vc,
2295 	},
2296 	[ITEM_GTP_TEID] = {
2297 		.name = "teid",
2298 		.help = "tunnel endpoint identifier",
2299 		.next = NEXT(item_gtp, NEXT_ENTRY(UNSIGNED), item_param),
2300 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
2301 	},
2302 	[ITEM_GTPC] = {
2303 		.name = "gtpc",
2304 		.help = "match GTP header",
2305 		.priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
2306 		.next = NEXT(item_gtp),
2307 		.call = parse_vc,
2308 	},
2309 	[ITEM_GTPU] = {
2310 		.name = "gtpu",
2311 		.help = "match GTP header",
2312 		.priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
2313 		.next = NEXT(item_gtp),
2314 		.call = parse_vc,
2315 	},
2316 	[ITEM_GENEVE] = {
2317 		.name = "geneve",
2318 		.help = "match GENEVE header",
2319 		.priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
2320 		.next = NEXT(item_geneve),
2321 		.call = parse_vc,
2322 	},
2323 	[ITEM_GENEVE_VNI] = {
2324 		.name = "vni",
2325 		.help = "virtual network identifier",
2326 		.next = NEXT(item_geneve, NEXT_ENTRY(UNSIGNED), item_param),
2327 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
2328 	},
2329 	[ITEM_GENEVE_PROTO] = {
2330 		.name = "protocol",
2331 		.help = "GENEVE protocol type",
2332 		.next = NEXT(item_geneve, NEXT_ENTRY(UNSIGNED), item_param),
2333 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
2334 					     protocol)),
2335 	},
2336 	[ITEM_VXLAN_GPE] = {
2337 		.name = "vxlan-gpe",
2338 		.help = "match VXLAN-GPE header",
2339 		.priv = PRIV_ITEM(VXLAN_GPE,
2340 				  sizeof(struct rte_flow_item_vxlan_gpe)),
2341 		.next = NEXT(item_vxlan_gpe),
2342 		.call = parse_vc,
2343 	},
2344 	[ITEM_VXLAN_GPE_VNI] = {
2345 		.name = "vni",
2346 		.help = "VXLAN-GPE identifier",
2347 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(UNSIGNED), item_param),
2348 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
2349 					     vni)),
2350 	},
2351 	[ITEM_ARP_ETH_IPV4] = {
2352 		.name = "arp_eth_ipv4",
2353 		.help = "match ARP header for Ethernet/IPv4",
2354 		.priv = PRIV_ITEM(ARP_ETH_IPV4,
2355 				  sizeof(struct rte_flow_item_arp_eth_ipv4)),
2356 		.next = NEXT(item_arp_eth_ipv4),
2357 		.call = parse_vc,
2358 	},
2359 	[ITEM_ARP_ETH_IPV4_SHA] = {
2360 		.name = "sha",
2361 		.help = "sender hardware address",
2362 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(MAC_ADDR),
2363 			     item_param),
2364 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
2365 					     sha)),
2366 	},
2367 	[ITEM_ARP_ETH_IPV4_SPA] = {
2368 		.name = "spa",
2369 		.help = "sender IPv4 address",
2370 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(IPV4_ADDR),
2371 			     item_param),
2372 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
2373 					     spa)),
2374 	},
2375 	[ITEM_ARP_ETH_IPV4_THA] = {
2376 		.name = "tha",
2377 		.help = "target hardware address",
2378 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(MAC_ADDR),
2379 			     item_param),
2380 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
2381 					     tha)),
2382 	},
2383 	[ITEM_ARP_ETH_IPV4_TPA] = {
2384 		.name = "tpa",
2385 		.help = "target IPv4 address",
2386 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(IPV4_ADDR),
2387 			     item_param),
2388 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
2389 					     tpa)),
2390 	},
2391 	[ITEM_IPV6_EXT] = {
2392 		.name = "ipv6_ext",
2393 		.help = "match presence of any IPv6 extension header",
2394 		.priv = PRIV_ITEM(IPV6_EXT,
2395 				  sizeof(struct rte_flow_item_ipv6_ext)),
2396 		.next = NEXT(item_ipv6_ext),
2397 		.call = parse_vc,
2398 	},
2399 	[ITEM_IPV6_EXT_NEXT_HDR] = {
2400 		.name = "next_hdr",
2401 		.help = "next header",
2402 		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(UNSIGNED), item_param),
2403 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
2404 					     next_hdr)),
2405 	},
2406 	[ITEM_ICMP6] = {
2407 		.name = "icmp6",
2408 		.help = "match any ICMPv6 header",
2409 		.priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
2410 		.next = NEXT(item_icmp6),
2411 		.call = parse_vc,
2412 	},
2413 	[ITEM_ICMP6_TYPE] = {
2414 		.name = "type",
2415 		.help = "ICMPv6 type",
2416 		.next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
2417 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
2418 					     type)),
2419 	},
2420 	[ITEM_ICMP6_CODE] = {
2421 		.name = "code",
2422 		.help = "ICMPv6 code",
2423 		.next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
2424 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
2425 					     code)),
2426 	},
2427 	[ITEM_ICMP6_ND_NS] = {
2428 		.name = "icmp6_nd_ns",
2429 		.help = "match ICMPv6 neighbor discovery solicitation",
2430 		.priv = PRIV_ITEM(ICMP6_ND_NS,
2431 				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
2432 		.next = NEXT(item_icmp6_nd_ns),
2433 		.call = parse_vc,
2434 	},
2435 	[ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
2436 		.name = "target_addr",
2437 		.help = "target address",
2438 		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(IPV6_ADDR),
2439 			     item_param),
2440 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
2441 					     target_addr)),
2442 	},
2443 	[ITEM_ICMP6_ND_NA] = {
2444 		.name = "icmp6_nd_na",
2445 		.help = "match ICMPv6 neighbor discovery advertisement",
2446 		.priv = PRIV_ITEM(ICMP6_ND_NA,
2447 				  sizeof(struct rte_flow_item_icmp6_nd_na)),
2448 		.next = NEXT(item_icmp6_nd_na),
2449 		.call = parse_vc,
2450 	},
2451 	[ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
2452 		.name = "target_addr",
2453 		.help = "target address",
2454 		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(IPV6_ADDR),
2455 			     item_param),
2456 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
2457 					     target_addr)),
2458 	},
2459 	[ITEM_ICMP6_ND_OPT] = {
2460 		.name = "icmp6_nd_opt",
2461 		.help = "match presence of any ICMPv6 neighbor discovery"
2462 			" option",
2463 		.priv = PRIV_ITEM(ICMP6_ND_OPT,
2464 				  sizeof(struct rte_flow_item_icmp6_nd_opt)),
2465 		.next = NEXT(item_icmp6_nd_opt),
2466 		.call = parse_vc,
2467 	},
2468 	[ITEM_ICMP6_ND_OPT_TYPE] = {
2469 		.name = "type",
2470 		.help = "ND option type",
2471 		.next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(UNSIGNED),
2472 			     item_param),
2473 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
2474 					     type)),
2475 	},
2476 	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
2477 		.name = "icmp6_nd_opt_sla_eth",
2478 		.help = "match ICMPv6 neighbor discovery source Ethernet"
2479 			" link-layer address option",
2480 		.priv = PRIV_ITEM
2481 			(ICMP6_ND_OPT_SLA_ETH,
2482 			 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
2483 		.next = NEXT(item_icmp6_nd_opt_sla_eth),
2484 		.call = parse_vc,
2485 	},
2486 	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
2487 		.name = "sla",
2488 		.help = "source Ethernet LLA",
2489 		.next = NEXT(item_icmp6_nd_opt_sla_eth, NEXT_ENTRY(MAC_ADDR),
2490 			     item_param),
2491 		.args = ARGS(ARGS_ENTRY_HTON
2492 			     (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
2493 	},
2494 	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
2495 		.name = "icmp6_nd_opt_tla_eth",
2496 		.help = "match ICMPv6 neighbor discovery target Ethernet"
2497 			" link-layer address option",
2498 		.priv = PRIV_ITEM
2499 			(ICMP6_ND_OPT_TLA_ETH,
2500 			 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
2501 		.next = NEXT(item_icmp6_nd_opt_tla_eth),
2502 		.call = parse_vc,
2503 	},
2504 	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
2505 		.name = "tla",
2506 		.help = "target Ethernet LLA",
2507 		.next = NEXT(item_icmp6_nd_opt_tla_eth, NEXT_ENTRY(MAC_ADDR),
2508 			     item_param),
2509 		.args = ARGS(ARGS_ENTRY_HTON
2510 			     (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
2511 	},
2512 	[ITEM_META] = {
2513 		.name = "meta",
2514 		.help = "match metadata header",
2515 		.priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
2516 		.next = NEXT(item_meta),
2517 		.call = parse_vc,
2518 	},
2519 	[ITEM_META_DATA] = {
2520 		.name = "data",
2521 		.help = "metadata value",
2522 		.next = NEXT(item_meta, NEXT_ENTRY(UNSIGNED), item_param),
2523 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
2524 					     data, "\xff\xff\xff\xff")),
2525 	},
2526 	[ITEM_GRE_KEY] = {
2527 		.name = "gre_key",
2528 		.help = "match GRE key",
2529 		.priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
2530 		.next = NEXT(item_gre_key),
2531 		.call = parse_vc,
2532 	},
2533 	[ITEM_GRE_KEY_VALUE] = {
2534 		.name = "value",
2535 		.help = "key value",
2536 		.next = NEXT(item_gre_key, NEXT_ENTRY(UNSIGNED), item_param),
2537 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
2538 	},
2539 	[ITEM_GTP_PSC] = {
2540 		.name = "gtp_psc",
2541 		.help = "match GTP extension header with type 0x85",
2542 		.priv = PRIV_ITEM(GTP_PSC,
2543 				sizeof(struct rte_flow_item_gtp_psc)),
2544 		.next = NEXT(item_gtp_psc),
2545 		.call = parse_vc,
2546 	},
2547 	[ITEM_GTP_PSC_QFI] = {
2548 		.name = "qfi",
2549 		.help = "QoS flow identifier",
2550 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(UNSIGNED), item_param),
2551 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp_psc,
2552 					qfi)),
2553 	},
2554 	[ITEM_GTP_PSC_PDU_T] = {
2555 		.name = "pdu_t",
2556 		.help = "PDU type",
2557 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(UNSIGNED), item_param),
2558 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp_psc,
2559 					pdu_type)),
2560 	},
2561 	[ITEM_PPPOES] = {
2562 		.name = "pppoes",
2563 		.help = "match PPPoE session header",
2564 		.priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
2565 		.next = NEXT(item_pppoes),
2566 		.call = parse_vc,
2567 	},
2568 	[ITEM_PPPOED] = {
2569 		.name = "pppoed",
2570 		.help = "match PPPoE discovery header",
2571 		.priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
2572 		.next = NEXT(item_pppoed),
2573 		.call = parse_vc,
2574 	},
2575 	[ITEM_PPPOE_SEID] = {
2576 		.name = "seid",
2577 		.help = "session identifier",
2578 		.next = NEXT(item_pppoes, NEXT_ENTRY(UNSIGNED), item_param),
2579 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
2580 					session_id)),
2581 	},
2582 	[ITEM_PPPOE_PROTO_ID] = {
2583 		.name = "proto_id",
2584 		.help = "match PPPoE session protocol identifier",
2585 		.priv = PRIV_ITEM(PPPOE_PROTO_ID,
2586 				sizeof(struct rte_flow_item_pppoe_proto_id)),
2587 		.next = NEXT(item_pppoe_proto_id),
2588 		.call = parse_vc,
2589 	},
2590 	[ITEM_HIGIG2] = {
2591 		.name = "higig2",
2592 		.help = "matches higig2 header",
2593 		.priv = PRIV_ITEM(HIGIG2,
2594 				sizeof(struct rte_flow_item_higig2_hdr)),
2595 		.next = NEXT(item_higig2),
2596 		.call = parse_vc,
2597 	},
2598 	[ITEM_HIGIG2_CLASSIFICATION] = {
2599 		.name = "classification",
2600 		.help = "matches classification of higig2 header",
2601 		.next = NEXT(item_higig2, NEXT_ENTRY(UNSIGNED), item_param),
2602 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
2603 					hdr.ppt1.classification)),
2604 	},
2605 	[ITEM_HIGIG2_VID] = {
2606 		.name = "vid",
2607 		.help = "matches vid of higig2 header",
2608 		.next = NEXT(item_higig2, NEXT_ENTRY(UNSIGNED), item_param),
2609 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
2610 					hdr.ppt1.vid)),
2611 	},
2612 	[ITEM_TAG] = {
2613 		.name = "tag",
2614 		.help = "match tag value",
2615 		.priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
2616 		.next = NEXT(item_tag),
2617 		.call = parse_vc,
2618 	},
2619 	[ITEM_TAG_DATA] = {
2620 		.name = "data",
2621 		.help = "tag value to match",
2622 		.next = NEXT(item_tag, NEXT_ENTRY(UNSIGNED), item_param),
2623 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
2624 	},
2625 	[ITEM_TAG_INDEX] = {
2626 		.name = "index",
2627 		.help = "index of tag array to match",
2628 		.next = NEXT(item_tag, NEXT_ENTRY(UNSIGNED),
2629 			     NEXT_ENTRY(ITEM_PARAM_IS)),
2630 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
2631 	},
2632 	[ITEM_L2TPV3OIP] = {
2633 		.name = "l2tpv3oip",
2634 		.help = "match L2TPv3 over IP header",
2635 		.priv = PRIV_ITEM(L2TPV3OIP,
2636 				  sizeof(struct rte_flow_item_l2tpv3oip)),
2637 		.next = NEXT(item_l2tpv3oip),
2638 		.call = parse_vc,
2639 	},
2640 	[ITEM_L2TPV3OIP_SESSION_ID] = {
2641 		.name = "session_id",
2642 		.help = "session identifier",
2643 		.next = NEXT(item_l2tpv3oip, NEXT_ENTRY(UNSIGNED), item_param),
2644 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
2645 					     session_id)),
2646 	},
2647 	[ITEM_ESP] = {
2648 		.name = "esp",
2649 		.help = "match ESP header",
2650 		.priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
2651 		.next = NEXT(item_esp),
2652 		.call = parse_vc,
2653 	},
2654 	[ITEM_ESP_SPI] = {
2655 		.name = "spi",
2656 		.help = "security policy index",
2657 		.next = NEXT(item_esp, NEXT_ENTRY(UNSIGNED), item_param),
2658 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
2659 				hdr.spi)),
2660 	},
2661 	/* Validate/create actions. */
2662 	[ACTIONS] = {
2663 		.name = "actions",
2664 		.help = "submit a list of associated actions",
2665 		.next = NEXT(next_action),
2666 		.call = parse_vc,
2667 	},
2668 	[ACTION_NEXT] = {
2669 		.name = "/",
2670 		.help = "specify next action",
2671 		.next = NEXT(next_action),
2672 	},
2673 	[ACTION_END] = {
2674 		.name = "end",
2675 		.help = "end list of actions",
2676 		.priv = PRIV_ACTION(END, 0),
2677 		.call = parse_vc,
2678 	},
2679 	[ACTION_VOID] = {
2680 		.name = "void",
2681 		.help = "no-op action",
2682 		.priv = PRIV_ACTION(VOID, 0),
2683 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2684 		.call = parse_vc,
2685 	},
2686 	[ACTION_PASSTHRU] = {
2687 		.name = "passthru",
2688 		.help = "let subsequent rule process matched packets",
2689 		.priv = PRIV_ACTION(PASSTHRU, 0),
2690 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2691 		.call = parse_vc,
2692 	},
2693 	[ACTION_JUMP] = {
2694 		.name = "jump",
2695 		.help = "redirect traffic to a given group",
2696 		.priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
2697 		.next = NEXT(action_jump),
2698 		.call = parse_vc,
2699 	},
2700 	[ACTION_JUMP_GROUP] = {
2701 		.name = "group",
2702 		.help = "group to redirect traffic to",
2703 		.next = NEXT(action_jump, NEXT_ENTRY(UNSIGNED)),
2704 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
2705 		.call = parse_vc_conf,
2706 	},
2707 	[ACTION_MARK] = {
2708 		.name = "mark",
2709 		.help = "attach 32 bit value to packets",
2710 		.priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
2711 		.next = NEXT(action_mark),
2712 		.call = parse_vc,
2713 	},
2714 	[ACTION_MARK_ID] = {
2715 		.name = "id",
2716 		.help = "32 bit value to return with packets",
2717 		.next = NEXT(action_mark, NEXT_ENTRY(UNSIGNED)),
2718 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
2719 		.call = parse_vc_conf,
2720 	},
2721 	[ACTION_FLAG] = {
2722 		.name = "flag",
2723 		.help = "flag packets",
2724 		.priv = PRIV_ACTION(FLAG, 0),
2725 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2726 		.call = parse_vc,
2727 	},
2728 	[ACTION_QUEUE] = {
2729 		.name = "queue",
2730 		.help = "assign packets to a given queue index",
2731 		.priv = PRIV_ACTION(QUEUE,
2732 				    sizeof(struct rte_flow_action_queue)),
2733 		.next = NEXT(action_queue),
2734 		.call = parse_vc,
2735 	},
2736 	[ACTION_QUEUE_INDEX] = {
2737 		.name = "index",
2738 		.help = "queue index to use",
2739 		.next = NEXT(action_queue, NEXT_ENTRY(UNSIGNED)),
2740 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
2741 		.call = parse_vc_conf,
2742 	},
2743 	[ACTION_DROP] = {
2744 		.name = "drop",
2745 		.help = "drop packets (note: passthru has priority)",
2746 		.priv = PRIV_ACTION(DROP, 0),
2747 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2748 		.call = parse_vc,
2749 	},
2750 	[ACTION_COUNT] = {
2751 		.name = "count",
2752 		.help = "enable counters for this rule",
2753 		.priv = PRIV_ACTION(COUNT,
2754 				    sizeof(struct rte_flow_action_count)),
2755 		.next = NEXT(action_count),
2756 		.call = parse_vc,
2757 	},
2758 	[ACTION_COUNT_ID] = {
2759 		.name = "identifier",
2760 		.help = "counter identifier to use",
2761 		.next = NEXT(action_count, NEXT_ENTRY(UNSIGNED)),
2762 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
2763 		.call = parse_vc_conf,
2764 	},
2765 	[ACTION_COUNT_SHARED] = {
2766 		.name = "shared",
2767 		.help = "shared counter",
2768 		.next = NEXT(action_count, NEXT_ENTRY(BOOLEAN)),
2769 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_count,
2770 					   shared, 1)),
2771 		.call = parse_vc_conf,
2772 	},
2773 	[ACTION_RSS] = {
2774 		.name = "rss",
2775 		.help = "spread packets among several queues",
2776 		.priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
2777 		.next = NEXT(action_rss),
2778 		.call = parse_vc_action_rss,
2779 	},
2780 	[ACTION_RSS_FUNC] = {
2781 		.name = "func",
2782 		.help = "RSS hash function to apply",
2783 		.next = NEXT(action_rss,
2784 			     NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
2785 					ACTION_RSS_FUNC_TOEPLITZ,
2786 					ACTION_RSS_FUNC_SIMPLE_XOR,
2787 					ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
2788 	},
2789 	[ACTION_RSS_FUNC_DEFAULT] = {
2790 		.name = "default",
2791 		.help = "default hash function",
2792 		.call = parse_vc_action_rss_func,
2793 	},
2794 	[ACTION_RSS_FUNC_TOEPLITZ] = {
2795 		.name = "toeplitz",
2796 		.help = "Toeplitz hash function",
2797 		.call = parse_vc_action_rss_func,
2798 	},
2799 	[ACTION_RSS_FUNC_SIMPLE_XOR] = {
2800 		.name = "simple_xor",
2801 		.help = "simple XOR hash function",
2802 		.call = parse_vc_action_rss_func,
2803 	},
2804 	[ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
2805 		.name = "symmetric_toeplitz",
2806 		.help = "Symmetric Toeplitz hash function",
2807 		.call = parse_vc_action_rss_func,
2808 	},
2809 	[ACTION_RSS_LEVEL] = {
2810 		.name = "level",
2811 		.help = "encapsulation level for \"types\"",
2812 		.next = NEXT(action_rss, NEXT_ENTRY(UNSIGNED)),
2813 		.args = ARGS(ARGS_ENTRY_ARB
2814 			     (offsetof(struct action_rss_data, conf) +
2815 			      offsetof(struct rte_flow_action_rss, level),
2816 			      sizeof(((struct rte_flow_action_rss *)0)->
2817 				     level))),
2818 	},
2819 	[ACTION_RSS_TYPES] = {
2820 		.name = "types",
2821 		.help = "specific RSS hash types",
2822 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
2823 	},
2824 	[ACTION_RSS_TYPE] = {
2825 		.name = "{type}",
2826 		.help = "RSS hash type",
2827 		.call = parse_vc_action_rss_type,
2828 		.comp = comp_vc_action_rss_type,
2829 	},
2830 	[ACTION_RSS_KEY] = {
2831 		.name = "key",
2832 		.help = "RSS hash key",
2833 		.next = NEXT(action_rss, NEXT_ENTRY(HEX)),
2834 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
2835 			     ARGS_ENTRY_ARB
2836 			     (offsetof(struct action_rss_data, conf) +
2837 			      offsetof(struct rte_flow_action_rss, key_len),
2838 			      sizeof(((struct rte_flow_action_rss *)0)->
2839 				     key_len)),
2840 			     ARGS_ENTRY(struct action_rss_data, key)),
2841 	},
2842 	[ACTION_RSS_KEY_LEN] = {
2843 		.name = "key_len",
2844 		.help = "RSS hash key length in bytes",
2845 		.next = NEXT(action_rss, NEXT_ENTRY(UNSIGNED)),
2846 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
2847 			     (offsetof(struct action_rss_data, conf) +
2848 			      offsetof(struct rte_flow_action_rss, key_len),
2849 			      sizeof(((struct rte_flow_action_rss *)0)->
2850 				     key_len),
2851 			      0,
2852 			      RSS_HASH_KEY_LENGTH)),
2853 	},
2854 	[ACTION_RSS_QUEUES] = {
2855 		.name = "queues",
2856 		.help = "queue indices to use",
2857 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
2858 		.call = parse_vc_conf,
2859 	},
2860 	[ACTION_RSS_QUEUE] = {
2861 		.name = "{queue}",
2862 		.help = "queue index",
2863 		.call = parse_vc_action_rss_queue,
2864 		.comp = comp_vc_action_rss_queue,
2865 	},
2866 	[ACTION_PF] = {
2867 		.name = "pf",
2868 		.help = "direct traffic to physical function",
2869 		.priv = PRIV_ACTION(PF, 0),
2870 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2871 		.call = parse_vc,
2872 	},
2873 	[ACTION_VF] = {
2874 		.name = "vf",
2875 		.help = "direct traffic to a virtual function ID",
2876 		.priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
2877 		.next = NEXT(action_vf),
2878 		.call = parse_vc,
2879 	},
2880 	[ACTION_VF_ORIGINAL] = {
2881 		.name = "original",
2882 		.help = "use original VF ID if possible",
2883 		.next = NEXT(action_vf, NEXT_ENTRY(BOOLEAN)),
2884 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
2885 					   original, 1)),
2886 		.call = parse_vc_conf,
2887 	},
2888 	[ACTION_VF_ID] = {
2889 		.name = "id",
2890 		.help = "VF ID",
2891 		.next = NEXT(action_vf, NEXT_ENTRY(UNSIGNED)),
2892 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
2893 		.call = parse_vc_conf,
2894 	},
2895 	[ACTION_PHY_PORT] = {
2896 		.name = "phy_port",
2897 		.help = "direct packets to physical port index",
2898 		.priv = PRIV_ACTION(PHY_PORT,
2899 				    sizeof(struct rte_flow_action_phy_port)),
2900 		.next = NEXT(action_phy_port),
2901 		.call = parse_vc,
2902 	},
2903 	[ACTION_PHY_PORT_ORIGINAL] = {
2904 		.name = "original",
2905 		.help = "use original port index if possible",
2906 		.next = NEXT(action_phy_port, NEXT_ENTRY(BOOLEAN)),
2907 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port,
2908 					   original, 1)),
2909 		.call = parse_vc_conf,
2910 	},
2911 	[ACTION_PHY_PORT_INDEX] = {
2912 		.name = "index",
2913 		.help = "physical port index",
2914 		.next = NEXT(action_phy_port, NEXT_ENTRY(UNSIGNED)),
2915 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port,
2916 					index)),
2917 		.call = parse_vc_conf,
2918 	},
2919 	[ACTION_PORT_ID] = {
2920 		.name = "port_id",
2921 		.help = "direct matching traffic to a given DPDK port ID",
2922 		.priv = PRIV_ACTION(PORT_ID,
2923 				    sizeof(struct rte_flow_action_port_id)),
2924 		.next = NEXT(action_port_id),
2925 		.call = parse_vc,
2926 	},
2927 	[ACTION_PORT_ID_ORIGINAL] = {
2928 		.name = "original",
2929 		.help = "use original DPDK port ID if possible",
2930 		.next = NEXT(action_port_id, NEXT_ENTRY(BOOLEAN)),
2931 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
2932 					   original, 1)),
2933 		.call = parse_vc_conf,
2934 	},
2935 	[ACTION_PORT_ID_ID] = {
2936 		.name = "id",
2937 		.help = "DPDK port ID",
2938 		.next = NEXT(action_port_id, NEXT_ENTRY(UNSIGNED)),
2939 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
2940 		.call = parse_vc_conf,
2941 	},
2942 	[ACTION_METER] = {
2943 		.name = "meter",
2944 		.help = "meter the directed packets at given id",
2945 		.priv = PRIV_ACTION(METER,
2946 				    sizeof(struct rte_flow_action_meter)),
2947 		.next = NEXT(action_meter),
2948 		.call = parse_vc,
2949 	},
2950 	[ACTION_METER_ID] = {
2951 		.name = "mtr_id",
2952 		.help = "meter id to use",
2953 		.next = NEXT(action_meter, NEXT_ENTRY(UNSIGNED)),
2954 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
2955 		.call = parse_vc_conf,
2956 	},
2957 	[ACTION_OF_SET_MPLS_TTL] = {
2958 		.name = "of_set_mpls_ttl",
2959 		.help = "OpenFlow's OFPAT_SET_MPLS_TTL",
2960 		.priv = PRIV_ACTION
2961 			(OF_SET_MPLS_TTL,
2962 			 sizeof(struct rte_flow_action_of_set_mpls_ttl)),
2963 		.next = NEXT(action_of_set_mpls_ttl),
2964 		.call = parse_vc,
2965 	},
2966 	[ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = {
2967 		.name = "mpls_ttl",
2968 		.help = "MPLS TTL",
2969 		.next = NEXT(action_of_set_mpls_ttl, NEXT_ENTRY(UNSIGNED)),
2970 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl,
2971 					mpls_ttl)),
2972 		.call = parse_vc_conf,
2973 	},
2974 	[ACTION_OF_DEC_MPLS_TTL] = {
2975 		.name = "of_dec_mpls_ttl",
2976 		.help = "OpenFlow's OFPAT_DEC_MPLS_TTL",
2977 		.priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0),
2978 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2979 		.call = parse_vc,
2980 	},
2981 	[ACTION_OF_SET_NW_TTL] = {
2982 		.name = "of_set_nw_ttl",
2983 		.help = "OpenFlow's OFPAT_SET_NW_TTL",
2984 		.priv = PRIV_ACTION
2985 			(OF_SET_NW_TTL,
2986 			 sizeof(struct rte_flow_action_of_set_nw_ttl)),
2987 		.next = NEXT(action_of_set_nw_ttl),
2988 		.call = parse_vc,
2989 	},
2990 	[ACTION_OF_SET_NW_TTL_NW_TTL] = {
2991 		.name = "nw_ttl",
2992 		.help = "IP TTL",
2993 		.next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(UNSIGNED)),
2994 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl,
2995 					nw_ttl)),
2996 		.call = parse_vc_conf,
2997 	},
2998 	[ACTION_OF_DEC_NW_TTL] = {
2999 		.name = "of_dec_nw_ttl",
3000 		.help = "OpenFlow's OFPAT_DEC_NW_TTL",
3001 		.priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
3002 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3003 		.call = parse_vc,
3004 	},
3005 	[ACTION_OF_COPY_TTL_OUT] = {
3006 		.name = "of_copy_ttl_out",
3007 		.help = "OpenFlow's OFPAT_COPY_TTL_OUT",
3008 		.priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0),
3009 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3010 		.call = parse_vc,
3011 	},
3012 	[ACTION_OF_COPY_TTL_IN] = {
3013 		.name = "of_copy_ttl_in",
3014 		.help = "OpenFlow's OFPAT_COPY_TTL_IN",
3015 		.priv = PRIV_ACTION(OF_COPY_TTL_IN, 0),
3016 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3017 		.call = parse_vc,
3018 	},
3019 	[ACTION_OF_POP_VLAN] = {
3020 		.name = "of_pop_vlan",
3021 		.help = "OpenFlow's OFPAT_POP_VLAN",
3022 		.priv = PRIV_ACTION(OF_POP_VLAN, 0),
3023 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3024 		.call = parse_vc,
3025 	},
3026 	[ACTION_OF_PUSH_VLAN] = {
3027 		.name = "of_push_vlan",
3028 		.help = "OpenFlow's OFPAT_PUSH_VLAN",
3029 		.priv = PRIV_ACTION
3030 			(OF_PUSH_VLAN,
3031 			 sizeof(struct rte_flow_action_of_push_vlan)),
3032 		.next = NEXT(action_of_push_vlan),
3033 		.call = parse_vc,
3034 	},
3035 	[ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
3036 		.name = "ethertype",
3037 		.help = "EtherType",
3038 		.next = NEXT(action_of_push_vlan, NEXT_ENTRY(UNSIGNED)),
3039 		.args = ARGS(ARGS_ENTRY_HTON
3040 			     (struct rte_flow_action_of_push_vlan,
3041 			      ethertype)),
3042 		.call = parse_vc_conf,
3043 	},
3044 	[ACTION_OF_SET_VLAN_VID] = {
3045 		.name = "of_set_vlan_vid",
3046 		.help = "OpenFlow's OFPAT_SET_VLAN_VID",
3047 		.priv = PRIV_ACTION
3048 			(OF_SET_VLAN_VID,
3049 			 sizeof(struct rte_flow_action_of_set_vlan_vid)),
3050 		.next = NEXT(action_of_set_vlan_vid),
3051 		.call = parse_vc,
3052 	},
3053 	[ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
3054 		.name = "vlan_vid",
3055 		.help = "VLAN id",
3056 		.next = NEXT(action_of_set_vlan_vid, NEXT_ENTRY(UNSIGNED)),
3057 		.args = ARGS(ARGS_ENTRY_HTON
3058 			     (struct rte_flow_action_of_set_vlan_vid,
3059 			      vlan_vid)),
3060 		.call = parse_vc_conf,
3061 	},
3062 	[ACTION_OF_SET_VLAN_PCP] = {
3063 		.name = "of_set_vlan_pcp",
3064 		.help = "OpenFlow's OFPAT_SET_VLAN_PCP",
3065 		.priv = PRIV_ACTION
3066 			(OF_SET_VLAN_PCP,
3067 			 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
3068 		.next = NEXT(action_of_set_vlan_pcp),
3069 		.call = parse_vc,
3070 	},
3071 	[ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
3072 		.name = "vlan_pcp",
3073 		.help = "VLAN priority",
3074 		.next = NEXT(action_of_set_vlan_pcp, NEXT_ENTRY(UNSIGNED)),
3075 		.args = ARGS(ARGS_ENTRY_HTON
3076 			     (struct rte_flow_action_of_set_vlan_pcp,
3077 			      vlan_pcp)),
3078 		.call = parse_vc_conf,
3079 	},
3080 	[ACTION_OF_POP_MPLS] = {
3081 		.name = "of_pop_mpls",
3082 		.help = "OpenFlow's OFPAT_POP_MPLS",
3083 		.priv = PRIV_ACTION(OF_POP_MPLS,
3084 				    sizeof(struct rte_flow_action_of_pop_mpls)),
3085 		.next = NEXT(action_of_pop_mpls),
3086 		.call = parse_vc,
3087 	},
3088 	[ACTION_OF_POP_MPLS_ETHERTYPE] = {
3089 		.name = "ethertype",
3090 		.help = "EtherType",
3091 		.next = NEXT(action_of_pop_mpls, NEXT_ENTRY(UNSIGNED)),
3092 		.args = ARGS(ARGS_ENTRY_HTON
3093 			     (struct rte_flow_action_of_pop_mpls,
3094 			      ethertype)),
3095 		.call = parse_vc_conf,
3096 	},
3097 	[ACTION_OF_PUSH_MPLS] = {
3098 		.name = "of_push_mpls",
3099 		.help = "OpenFlow's OFPAT_PUSH_MPLS",
3100 		.priv = PRIV_ACTION
3101 			(OF_PUSH_MPLS,
3102 			 sizeof(struct rte_flow_action_of_push_mpls)),
3103 		.next = NEXT(action_of_push_mpls),
3104 		.call = parse_vc,
3105 	},
3106 	[ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
3107 		.name = "ethertype",
3108 		.help = "EtherType",
3109 		.next = NEXT(action_of_push_mpls, NEXT_ENTRY(UNSIGNED)),
3110 		.args = ARGS(ARGS_ENTRY_HTON
3111 			     (struct rte_flow_action_of_push_mpls,
3112 			      ethertype)),
3113 		.call = parse_vc_conf,
3114 	},
3115 	[ACTION_VXLAN_ENCAP] = {
3116 		.name = "vxlan_encap",
3117 		.help = "VXLAN encapsulation, uses configuration set by \"set"
3118 			" vxlan\"",
3119 		.priv = PRIV_ACTION(VXLAN_ENCAP,
3120 				    sizeof(struct action_vxlan_encap_data)),
3121 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3122 		.call = parse_vc_action_vxlan_encap,
3123 	},
3124 	[ACTION_VXLAN_DECAP] = {
3125 		.name = "vxlan_decap",
3126 		.help = "Performs a decapsulation action by stripping all"
3127 			" headers of the VXLAN tunnel network overlay from the"
3128 			" matched flow.",
3129 		.priv = PRIV_ACTION(VXLAN_DECAP, 0),
3130 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3131 		.call = parse_vc,
3132 	},
3133 	[ACTION_NVGRE_ENCAP] = {
3134 		.name = "nvgre_encap",
3135 		.help = "NVGRE encapsulation, uses configuration set by \"set"
3136 			" nvgre\"",
3137 		.priv = PRIV_ACTION(NVGRE_ENCAP,
3138 				    sizeof(struct action_nvgre_encap_data)),
3139 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3140 		.call = parse_vc_action_nvgre_encap,
3141 	},
3142 	[ACTION_NVGRE_DECAP] = {
3143 		.name = "nvgre_decap",
3144 		.help = "Performs a decapsulation action by stripping all"
3145 			" headers of the NVGRE tunnel network overlay from the"
3146 			" matched flow.",
3147 		.priv = PRIV_ACTION(NVGRE_DECAP, 0),
3148 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3149 		.call = parse_vc,
3150 	},
3151 	[ACTION_L2_ENCAP] = {
3152 		.name = "l2_encap",
3153 		.help = "l2 encap, uses configuration set by"
3154 			" \"set l2_encap\"",
3155 		.priv = PRIV_ACTION(RAW_ENCAP,
3156 				    sizeof(struct action_raw_encap_data)),
3157 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3158 		.call = parse_vc_action_l2_encap,
3159 	},
3160 	[ACTION_L2_DECAP] = {
3161 		.name = "l2_decap",
3162 		.help = "l2 decap, uses configuration set by"
3163 			" \"set l2_decap\"",
3164 		.priv = PRIV_ACTION(RAW_DECAP,
3165 				    sizeof(struct action_raw_decap_data)),
3166 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3167 		.call = parse_vc_action_l2_decap,
3168 	},
3169 	[ACTION_MPLSOGRE_ENCAP] = {
3170 		.name = "mplsogre_encap",
3171 		.help = "mplsogre encapsulation, uses configuration set by"
3172 			" \"set mplsogre_encap\"",
3173 		.priv = PRIV_ACTION(RAW_ENCAP,
3174 				    sizeof(struct action_raw_encap_data)),
3175 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3176 		.call = parse_vc_action_mplsogre_encap,
3177 	},
3178 	[ACTION_MPLSOGRE_DECAP] = {
3179 		.name = "mplsogre_decap",
3180 		.help = "mplsogre decapsulation, uses configuration set by"
3181 			" \"set mplsogre_decap\"",
3182 		.priv = PRIV_ACTION(RAW_DECAP,
3183 				    sizeof(struct action_raw_decap_data)),
3184 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3185 		.call = parse_vc_action_mplsogre_decap,
3186 	},
3187 	[ACTION_MPLSOUDP_ENCAP] = {
3188 		.name = "mplsoudp_encap",
3189 		.help = "mplsoudp encapsulation, uses configuration set by"
3190 			" \"set mplsoudp_encap\"",
3191 		.priv = PRIV_ACTION(RAW_ENCAP,
3192 				    sizeof(struct action_raw_encap_data)),
3193 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3194 		.call = parse_vc_action_mplsoudp_encap,
3195 	},
3196 	[ACTION_MPLSOUDP_DECAP] = {
3197 		.name = "mplsoudp_decap",
3198 		.help = "mplsoudp decapsulation, uses configuration set by"
3199 			" \"set mplsoudp_decap\"",
3200 		.priv = PRIV_ACTION(RAW_DECAP,
3201 				    sizeof(struct action_raw_decap_data)),
3202 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3203 		.call = parse_vc_action_mplsoudp_decap,
3204 	},
3205 	[ACTION_SET_IPV4_SRC] = {
3206 		.name = "set_ipv4_src",
3207 		.help = "Set a new IPv4 source address in the outermost"
3208 			" IPv4 header",
3209 		.priv = PRIV_ACTION(SET_IPV4_SRC,
3210 			sizeof(struct rte_flow_action_set_ipv4)),
3211 		.next = NEXT(action_set_ipv4_src),
3212 		.call = parse_vc,
3213 	},
3214 	[ACTION_SET_IPV4_SRC_IPV4_SRC] = {
3215 		.name = "ipv4_addr",
3216 		.help = "new IPv4 source address to set",
3217 		.next = NEXT(action_set_ipv4_src, NEXT_ENTRY(IPV4_ADDR)),
3218 		.args = ARGS(ARGS_ENTRY_HTON
3219 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
3220 		.call = parse_vc_conf,
3221 	},
3222 	[ACTION_SET_IPV4_DST] = {
3223 		.name = "set_ipv4_dst",
3224 		.help = "Set a new IPv4 destination address in the outermost"
3225 			" IPv4 header",
3226 		.priv = PRIV_ACTION(SET_IPV4_DST,
3227 			sizeof(struct rte_flow_action_set_ipv4)),
3228 		.next = NEXT(action_set_ipv4_dst),
3229 		.call = parse_vc,
3230 	},
3231 	[ACTION_SET_IPV4_DST_IPV4_DST] = {
3232 		.name = "ipv4_addr",
3233 		.help = "new IPv4 destination address to set",
3234 		.next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(IPV4_ADDR)),
3235 		.args = ARGS(ARGS_ENTRY_HTON
3236 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
3237 		.call = parse_vc_conf,
3238 	},
3239 	[ACTION_SET_IPV6_SRC] = {
3240 		.name = "set_ipv6_src",
3241 		.help = "Set a new IPv6 source address in the outermost"
3242 			" IPv6 header",
3243 		.priv = PRIV_ACTION(SET_IPV6_SRC,
3244 			sizeof(struct rte_flow_action_set_ipv6)),
3245 		.next = NEXT(action_set_ipv6_src),
3246 		.call = parse_vc,
3247 	},
3248 	[ACTION_SET_IPV6_SRC_IPV6_SRC] = {
3249 		.name = "ipv6_addr",
3250 		.help = "new IPv6 source address to set",
3251 		.next = NEXT(action_set_ipv6_src, NEXT_ENTRY(IPV6_ADDR)),
3252 		.args = ARGS(ARGS_ENTRY_HTON
3253 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
3254 		.call = parse_vc_conf,
3255 	},
3256 	[ACTION_SET_IPV6_DST] = {
3257 		.name = "set_ipv6_dst",
3258 		.help = "Set a new IPv6 destination address in the outermost"
3259 			" IPv6 header",
3260 		.priv = PRIV_ACTION(SET_IPV6_DST,
3261 			sizeof(struct rte_flow_action_set_ipv6)),
3262 		.next = NEXT(action_set_ipv6_dst),
3263 		.call = parse_vc,
3264 	},
3265 	[ACTION_SET_IPV6_DST_IPV6_DST] = {
3266 		.name = "ipv6_addr",
3267 		.help = "new IPv6 destination address to set",
3268 		.next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(IPV6_ADDR)),
3269 		.args = ARGS(ARGS_ENTRY_HTON
3270 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
3271 		.call = parse_vc_conf,
3272 	},
3273 	[ACTION_SET_TP_SRC] = {
3274 		.name = "set_tp_src",
3275 		.help = "set a new source port number in the outermost"
3276 			" TCP/UDP header",
3277 		.priv = PRIV_ACTION(SET_TP_SRC,
3278 			sizeof(struct rte_flow_action_set_tp)),
3279 		.next = NEXT(action_set_tp_src),
3280 		.call = parse_vc,
3281 	},
3282 	[ACTION_SET_TP_SRC_TP_SRC] = {
3283 		.name = "port",
3284 		.help = "new source port number to set",
3285 		.next = NEXT(action_set_tp_src, NEXT_ENTRY(UNSIGNED)),
3286 		.args = ARGS(ARGS_ENTRY_HTON
3287 			     (struct rte_flow_action_set_tp, port)),
3288 		.call = parse_vc_conf,
3289 	},
3290 	[ACTION_SET_TP_DST] = {
3291 		.name = "set_tp_dst",
3292 		.help = "set a new destination port number in the outermost"
3293 			" TCP/UDP header",
3294 		.priv = PRIV_ACTION(SET_TP_DST,
3295 			sizeof(struct rte_flow_action_set_tp)),
3296 		.next = NEXT(action_set_tp_dst),
3297 		.call = parse_vc,
3298 	},
3299 	[ACTION_SET_TP_DST_TP_DST] = {
3300 		.name = "port",
3301 		.help = "new destination port number to set",
3302 		.next = NEXT(action_set_tp_dst, NEXT_ENTRY(UNSIGNED)),
3303 		.args = ARGS(ARGS_ENTRY_HTON
3304 			     (struct rte_flow_action_set_tp, port)),
3305 		.call = parse_vc_conf,
3306 	},
3307 	[ACTION_MAC_SWAP] = {
3308 		.name = "mac_swap",
3309 		.help = "Swap the source and destination MAC addresses"
3310 			" in the outermost Ethernet header",
3311 		.priv = PRIV_ACTION(MAC_SWAP, 0),
3312 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3313 		.call = parse_vc,
3314 	},
3315 	[ACTION_DEC_TTL] = {
3316 		.name = "dec_ttl",
3317 		.help = "decrease network TTL if available",
3318 		.priv = PRIV_ACTION(DEC_TTL, 0),
3319 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3320 		.call = parse_vc,
3321 	},
3322 	[ACTION_SET_TTL] = {
3323 		.name = "set_ttl",
3324 		.help = "set ttl value",
3325 		.priv = PRIV_ACTION(SET_TTL,
3326 			sizeof(struct rte_flow_action_set_ttl)),
3327 		.next = NEXT(action_set_ttl),
3328 		.call = parse_vc,
3329 	},
3330 	[ACTION_SET_TTL_TTL] = {
3331 		.name = "ttl_value",
3332 		.help = "new ttl value to set",
3333 		.next = NEXT(action_set_ttl, NEXT_ENTRY(UNSIGNED)),
3334 		.args = ARGS(ARGS_ENTRY_HTON
3335 			     (struct rte_flow_action_set_ttl, ttl_value)),
3336 		.call = parse_vc_conf,
3337 	},
3338 	[ACTION_SET_MAC_SRC] = {
3339 		.name = "set_mac_src",
3340 		.help = "set source mac address",
3341 		.priv = PRIV_ACTION(SET_MAC_SRC,
3342 			sizeof(struct rte_flow_action_set_mac)),
3343 		.next = NEXT(action_set_mac_src),
3344 		.call = parse_vc,
3345 	},
3346 	[ACTION_SET_MAC_SRC_MAC_SRC] = {
3347 		.name = "mac_addr",
3348 		.help = "new source mac address",
3349 		.next = NEXT(action_set_mac_src, NEXT_ENTRY(MAC_ADDR)),
3350 		.args = ARGS(ARGS_ENTRY_HTON
3351 			     (struct rte_flow_action_set_mac, mac_addr)),
3352 		.call = parse_vc_conf,
3353 	},
3354 	[ACTION_SET_MAC_DST] = {
3355 		.name = "set_mac_dst",
3356 		.help = "set destination mac address",
3357 		.priv = PRIV_ACTION(SET_MAC_DST,
3358 			sizeof(struct rte_flow_action_set_mac)),
3359 		.next = NEXT(action_set_mac_dst),
3360 		.call = parse_vc,
3361 	},
3362 	[ACTION_SET_MAC_DST_MAC_DST] = {
3363 		.name = "mac_addr",
3364 		.help = "new destination mac address to set",
3365 		.next = NEXT(action_set_mac_dst, NEXT_ENTRY(MAC_ADDR)),
3366 		.args = ARGS(ARGS_ENTRY_HTON
3367 			     (struct rte_flow_action_set_mac, mac_addr)),
3368 		.call = parse_vc_conf,
3369 	},
3370 	[ACTION_INC_TCP_SEQ] = {
3371 		.name = "inc_tcp_seq",
3372 		.help = "increase TCP sequence number",
3373 		.priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
3374 		.next = NEXT(action_inc_tcp_seq),
3375 		.call = parse_vc,
3376 	},
3377 	[ACTION_INC_TCP_SEQ_VALUE] = {
3378 		.name = "value",
3379 		.help = "the value to increase TCP sequence number by",
3380 		.next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(UNSIGNED)),
3381 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
3382 		.call = parse_vc_conf,
3383 	},
3384 	[ACTION_DEC_TCP_SEQ] = {
3385 		.name = "dec_tcp_seq",
3386 		.help = "decrease TCP sequence number",
3387 		.priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
3388 		.next = NEXT(action_dec_tcp_seq),
3389 		.call = parse_vc,
3390 	},
3391 	[ACTION_DEC_TCP_SEQ_VALUE] = {
3392 		.name = "value",
3393 		.help = "the value to decrease TCP sequence number by",
3394 		.next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(UNSIGNED)),
3395 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
3396 		.call = parse_vc_conf,
3397 	},
3398 	[ACTION_INC_TCP_ACK] = {
3399 		.name = "inc_tcp_ack",
3400 		.help = "increase TCP acknowledgment number",
3401 		.priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
3402 		.next = NEXT(action_inc_tcp_ack),
3403 		.call = parse_vc,
3404 	},
3405 	[ACTION_INC_TCP_ACK_VALUE] = {
3406 		.name = "value",
3407 		.help = "the value to increase TCP acknowledgment number by",
3408 		.next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(UNSIGNED)),
3409 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
3410 		.call = parse_vc_conf,
3411 	},
3412 	[ACTION_DEC_TCP_ACK] = {
3413 		.name = "dec_tcp_ack",
3414 		.help = "decrease TCP acknowledgment number",
3415 		.priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
3416 		.next = NEXT(action_dec_tcp_ack),
3417 		.call = parse_vc,
3418 	},
3419 	[ACTION_DEC_TCP_ACK_VALUE] = {
3420 		.name = "value",
3421 		.help = "the value to decrease TCP acknowledgment number by",
3422 		.next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(UNSIGNED)),
3423 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
3424 		.call = parse_vc_conf,
3425 	},
3426 	[ACTION_RAW_ENCAP] = {
3427 		.name = "raw_encap",
3428 		.help = "encapsulation data, defined by set raw_encap",
3429 		.priv = PRIV_ACTION(RAW_ENCAP,
3430 			sizeof(struct action_raw_encap_data)),
3431 		.next = NEXT(action_raw_encap),
3432 		.call = parse_vc_action_raw_encap,
3433 	},
3434 	[ACTION_RAW_ENCAP_INDEX] = {
3435 		.name = "index",
3436 		.help = "the index of raw_encap_confs",
3437 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
3438 	},
3439 	[ACTION_RAW_ENCAP_INDEX_VALUE] = {
3440 		.name = "{index}",
3441 		.type = "UNSIGNED",
3442 		.help = "unsigned integer value",
3443 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3444 		.call = parse_vc_action_raw_encap_index,
3445 		.comp = comp_set_raw_index,
3446 	},
3447 	[ACTION_RAW_DECAP] = {
3448 		.name = "raw_decap",
3449 		.help = "decapsulation data, defined by set raw_encap",
3450 		.priv = PRIV_ACTION(RAW_DECAP,
3451 			sizeof(struct action_raw_decap_data)),
3452 		.next = NEXT(action_raw_decap),
3453 		.call = parse_vc_action_raw_decap,
3454 	},
3455 	[ACTION_RAW_DECAP_INDEX] = {
3456 		.name = "index",
3457 		.help = "the index of raw_encap_confs",
3458 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
3459 	},
3460 	[ACTION_RAW_DECAP_INDEX_VALUE] = {
3461 		.name = "{index}",
3462 		.type = "UNSIGNED",
3463 		.help = "unsigned integer value",
3464 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3465 		.call = parse_vc_action_raw_decap_index,
3466 		.comp = comp_set_raw_index,
3467 	},
3468 	/* Top level command. */
3469 	[SET] = {
3470 		.name = "set",
3471 		.help = "set raw encap/decap data",
3472 		.type = "set raw_encap|raw_decap <index> <pattern>",
3473 		.next = NEXT(NEXT_ENTRY
3474 			     (SET_RAW_ENCAP,
3475 			      SET_RAW_DECAP)),
3476 		.call = parse_set_init,
3477 	},
3478 	/* Sub-level commands. */
3479 	[SET_RAW_ENCAP] = {
3480 		.name = "raw_encap",
3481 		.help = "set raw encap data",
3482 		.next = NEXT(next_set_raw),
3483 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
3484 				(offsetof(struct buffer, port),
3485 				 sizeof(((struct buffer *)0)->port),
3486 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
3487 		.call = parse_set_raw_encap_decap,
3488 	},
3489 	[SET_RAW_DECAP] = {
3490 		.name = "raw_decap",
3491 		.help = "set raw decap data",
3492 		.next = NEXT(next_set_raw),
3493 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
3494 				(offsetof(struct buffer, port),
3495 				 sizeof(((struct buffer *)0)->port),
3496 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
3497 		.call = parse_set_raw_encap_decap,
3498 	},
3499 	[SET_RAW_INDEX] = {
3500 		.name = "{index}",
3501 		.type = "UNSIGNED",
3502 		.help = "index of raw_encap/raw_decap data",
3503 		.next = NEXT(next_item),
3504 		.call = parse_port,
3505 	},
3506 	[ACTION_SET_TAG] = {
3507 		.name = "set_tag",
3508 		.help = "set tag",
3509 		.priv = PRIV_ACTION(SET_TAG,
3510 			sizeof(struct rte_flow_action_set_tag)),
3511 		.next = NEXT(action_set_tag),
3512 		.call = parse_vc,
3513 	},
3514 	[ACTION_SET_TAG_INDEX] = {
3515 		.name = "index",
3516 		.help = "index of tag array",
3517 		.next = NEXT(action_set_tag, NEXT_ENTRY(UNSIGNED)),
3518 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
3519 		.call = parse_vc_conf,
3520 	},
3521 	[ACTION_SET_TAG_DATA] = {
3522 		.name = "data",
3523 		.help = "tag value",
3524 		.next = NEXT(action_set_tag, NEXT_ENTRY(UNSIGNED)),
3525 		.args = ARGS(ARGS_ENTRY
3526 			     (struct rte_flow_action_set_tag, data)),
3527 		.call = parse_vc_conf,
3528 	},
3529 	[ACTION_SET_TAG_MASK] = {
3530 		.name = "mask",
3531 		.help = "mask for tag value",
3532 		.next = NEXT(action_set_tag, NEXT_ENTRY(UNSIGNED)),
3533 		.args = ARGS(ARGS_ENTRY
3534 			     (struct rte_flow_action_set_tag, mask)),
3535 		.call = parse_vc_conf,
3536 	},
3537 	[ACTION_SET_META] = {
3538 		.name = "set_meta",
3539 		.help = "set metadata",
3540 		.priv = PRIV_ACTION(SET_META,
3541 			sizeof(struct rte_flow_action_set_meta)),
3542 		.next = NEXT(action_set_meta),
3543 		.call = parse_vc_action_set_meta,
3544 	},
3545 	[ACTION_SET_META_DATA] = {
3546 		.name = "data",
3547 		.help = "metadata value",
3548 		.next = NEXT(action_set_meta, NEXT_ENTRY(UNSIGNED)),
3549 		.args = ARGS(ARGS_ENTRY
3550 			     (struct rte_flow_action_set_meta, data)),
3551 		.call = parse_vc_conf,
3552 	},
3553 	[ACTION_SET_META_MASK] = {
3554 		.name = "mask",
3555 		.help = "mask for metadata value",
3556 		.next = NEXT(action_set_meta, NEXT_ENTRY(UNSIGNED)),
3557 		.args = ARGS(ARGS_ENTRY
3558 			     (struct rte_flow_action_set_meta, mask)),
3559 		.call = parse_vc_conf,
3560 	},
3561 	[ACTION_SET_IPV4_DSCP] = {
3562 		.name = "set_ipv4_dscp",
3563 		.help = "set DSCP value",
3564 		.priv = PRIV_ACTION(SET_IPV4_DSCP,
3565 			sizeof(struct rte_flow_action_set_dscp)),
3566 		.next = NEXT(action_set_ipv4_dscp),
3567 		.call = parse_vc,
3568 	},
3569 	[ACTION_SET_IPV4_DSCP_VALUE] = {
3570 		.name = "dscp_value",
3571 		.help = "new IPv4 DSCP value to set",
3572 		.next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(UNSIGNED)),
3573 		.args = ARGS(ARGS_ENTRY
3574 			     (struct rte_flow_action_set_dscp, dscp)),
3575 		.call = parse_vc_conf,
3576 	},
3577 	[ACTION_SET_IPV6_DSCP] = {
3578 		.name = "set_ipv6_dscp",
3579 		.help = "set DSCP value",
3580 		.priv = PRIV_ACTION(SET_IPV6_DSCP,
3581 			sizeof(struct rte_flow_action_set_dscp)),
3582 		.next = NEXT(action_set_ipv6_dscp),
3583 		.call = parse_vc,
3584 	},
3585 	[ACTION_SET_IPV6_DSCP_VALUE] = {
3586 		.name = "dscp_value",
3587 		.help = "new IPv6 DSCP value to set",
3588 		.next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(UNSIGNED)),
3589 		.args = ARGS(ARGS_ENTRY
3590 			     (struct rte_flow_action_set_dscp, dscp)),
3591 		.call = parse_vc_conf,
3592 	},
3593 };
3594 
3595 /** Remove and return last entry from argument stack. */
3596 static const struct arg *
3597 pop_args(struct context *ctx)
3598 {
3599 	return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
3600 }
3601 
3602 /** Add entry on top of the argument stack. */
3603 static int
3604 push_args(struct context *ctx, const struct arg *arg)
3605 {
3606 	if (ctx->args_num == CTX_STACK_SIZE)
3607 		return -1;
3608 	ctx->args[ctx->args_num++] = arg;
3609 	return 0;
3610 }
3611 
3612 /** Spread value into buffer according to bit-mask. */
3613 static size_t
3614 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
3615 {
3616 	uint32_t i = arg->size;
3617 	uint32_t end = 0;
3618 	int sub = 1;
3619 	int add = 0;
3620 	size_t len = 0;
3621 
3622 	if (!arg->mask)
3623 		return 0;
3624 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3625 	if (!arg->hton) {
3626 		i = 0;
3627 		end = arg->size;
3628 		sub = 0;
3629 		add = 1;
3630 	}
3631 #endif
3632 	while (i != end) {
3633 		unsigned int shift = 0;
3634 		uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
3635 
3636 		for (shift = 0; arg->mask[i] >> shift; ++shift) {
3637 			if (!(arg->mask[i] & (1 << shift)))
3638 				continue;
3639 			++len;
3640 			if (!dst)
3641 				continue;
3642 			*buf &= ~(1 << shift);
3643 			*buf |= (val & 1) << shift;
3644 			val >>= 1;
3645 		}
3646 		i += add;
3647 	}
3648 	return len;
3649 }
3650 
3651 /** Compare a string with a partial one of a given length. */
3652 static int
3653 strcmp_partial(const char *full, const char *partial, size_t partial_len)
3654 {
3655 	int r = strncmp(full, partial, partial_len);
3656 
3657 	if (r)
3658 		return r;
3659 	if (strlen(full) <= partial_len)
3660 		return 0;
3661 	return full[partial_len];
3662 }
3663 
3664 /**
3665  * Parse a prefix length and generate a bit-mask.
3666  *
3667  * Last argument (ctx->args) is retrieved to determine mask size, storage
3668  * location and whether the result must use network byte ordering.
3669  */
3670 static int
3671 parse_prefix(struct context *ctx, const struct token *token,
3672 	     const char *str, unsigned int len,
3673 	     void *buf, unsigned int size)
3674 {
3675 	const struct arg *arg = pop_args(ctx);
3676 	static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
3677 	char *end;
3678 	uintmax_t u;
3679 	unsigned int bytes;
3680 	unsigned int extra;
3681 
3682 	(void)token;
3683 	/* Argument is expected. */
3684 	if (!arg)
3685 		return -1;
3686 	errno = 0;
3687 	u = strtoumax(str, &end, 0);
3688 	if (errno || (size_t)(end - str) != len)
3689 		goto error;
3690 	if (arg->mask) {
3691 		uintmax_t v = 0;
3692 
3693 		extra = arg_entry_bf_fill(NULL, 0, arg);
3694 		if (u > extra)
3695 			goto error;
3696 		if (!ctx->object)
3697 			return len;
3698 		extra -= u;
3699 		while (u--)
3700 			(v <<= 1, v |= 1);
3701 		v <<= extra;
3702 		if (!arg_entry_bf_fill(ctx->object, v, arg) ||
3703 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
3704 			goto error;
3705 		return len;
3706 	}
3707 	bytes = u / 8;
3708 	extra = u % 8;
3709 	size = arg->size;
3710 	if (bytes > size || bytes + !!extra > size)
3711 		goto error;
3712 	if (!ctx->object)
3713 		return len;
3714 	buf = (uint8_t *)ctx->object + arg->offset;
3715 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3716 	if (!arg->hton) {
3717 		memset((uint8_t *)buf + size - bytes, 0xff, bytes);
3718 		memset(buf, 0x00, size - bytes);
3719 		if (extra)
3720 			((uint8_t *)buf)[size - bytes - 1] = conv[extra];
3721 	} else
3722 #endif
3723 	{
3724 		memset(buf, 0xff, bytes);
3725 		memset((uint8_t *)buf + bytes, 0x00, size - bytes);
3726 		if (extra)
3727 			((uint8_t *)buf)[bytes] = conv[extra];
3728 	}
3729 	if (ctx->objmask)
3730 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
3731 	return len;
3732 error:
3733 	push_args(ctx, arg);
3734 	return -1;
3735 }
3736 
3737 /** Default parsing function for token name matching. */
3738 static int
3739 parse_default(struct context *ctx, const struct token *token,
3740 	      const char *str, unsigned int len,
3741 	      void *buf, unsigned int size)
3742 {
3743 	(void)ctx;
3744 	(void)buf;
3745 	(void)size;
3746 	if (strcmp_partial(token->name, str, len))
3747 		return -1;
3748 	return len;
3749 }
3750 
3751 /** Parse flow command, initialize output buffer for subsequent tokens. */
3752 static int
3753 parse_init(struct context *ctx, const struct token *token,
3754 	   const char *str, unsigned int len,
3755 	   void *buf, unsigned int size)
3756 {
3757 	struct buffer *out = buf;
3758 
3759 	/* Token name must match. */
3760 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3761 		return -1;
3762 	/* Nothing else to do if there is no buffer. */
3763 	if (!out)
3764 		return len;
3765 	/* Make sure buffer is large enough. */
3766 	if (size < sizeof(*out))
3767 		return -1;
3768 	/* Initialize buffer. */
3769 	memset(out, 0x00, sizeof(*out));
3770 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
3771 	ctx->objdata = 0;
3772 	ctx->object = out;
3773 	ctx->objmask = NULL;
3774 	return len;
3775 }
3776 
3777 /** Parse tokens for validate/create commands. */
3778 static int
3779 parse_vc(struct context *ctx, const struct token *token,
3780 	 const char *str, unsigned int len,
3781 	 void *buf, unsigned int size)
3782 {
3783 	struct buffer *out = buf;
3784 	uint8_t *data;
3785 	uint32_t data_size;
3786 
3787 	/* Token name must match. */
3788 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3789 		return -1;
3790 	/* Nothing else to do if there is no buffer. */
3791 	if (!out)
3792 		return len;
3793 	if (!out->command) {
3794 		if (ctx->curr != VALIDATE && ctx->curr != CREATE)
3795 			return -1;
3796 		if (sizeof(*out) > size)
3797 			return -1;
3798 		out->command = ctx->curr;
3799 		ctx->objdata = 0;
3800 		ctx->object = out;
3801 		ctx->objmask = NULL;
3802 		out->args.vc.data = (uint8_t *)out + size;
3803 		return len;
3804 	}
3805 	ctx->objdata = 0;
3806 	ctx->object = &out->args.vc.attr;
3807 	ctx->objmask = NULL;
3808 	switch (ctx->curr) {
3809 	case GROUP:
3810 	case PRIORITY:
3811 		return len;
3812 	case INGRESS:
3813 		out->args.vc.attr.ingress = 1;
3814 		return len;
3815 	case EGRESS:
3816 		out->args.vc.attr.egress = 1;
3817 		return len;
3818 	case TRANSFER:
3819 		out->args.vc.attr.transfer = 1;
3820 		return len;
3821 	case PATTERN:
3822 		out->args.vc.pattern =
3823 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
3824 					       sizeof(double));
3825 		ctx->object = out->args.vc.pattern;
3826 		ctx->objmask = NULL;
3827 		return len;
3828 	case ACTIONS:
3829 		out->args.vc.actions =
3830 			(void *)RTE_ALIGN_CEIL((uintptr_t)
3831 					       (out->args.vc.pattern +
3832 						out->args.vc.pattern_n),
3833 					       sizeof(double));
3834 		ctx->object = out->args.vc.actions;
3835 		ctx->objmask = NULL;
3836 		return len;
3837 	default:
3838 		if (!token->priv)
3839 			return -1;
3840 		break;
3841 	}
3842 	if (!out->args.vc.actions) {
3843 		const struct parse_item_priv *priv = token->priv;
3844 		struct rte_flow_item *item =
3845 			out->args.vc.pattern + out->args.vc.pattern_n;
3846 
3847 		data_size = priv->size * 3; /* spec, last, mask */
3848 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
3849 					       (out->args.vc.data - data_size),
3850 					       sizeof(double));
3851 		if ((uint8_t *)item + sizeof(*item) > data)
3852 			return -1;
3853 		*item = (struct rte_flow_item){
3854 			.type = priv->type,
3855 		};
3856 		++out->args.vc.pattern_n;
3857 		ctx->object = item;
3858 		ctx->objmask = NULL;
3859 	} else {
3860 		const struct parse_action_priv *priv = token->priv;
3861 		struct rte_flow_action *action =
3862 			out->args.vc.actions + out->args.vc.actions_n;
3863 
3864 		data_size = priv->size; /* configuration */
3865 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
3866 					       (out->args.vc.data - data_size),
3867 					       sizeof(double));
3868 		if ((uint8_t *)action + sizeof(*action) > data)
3869 			return -1;
3870 		*action = (struct rte_flow_action){
3871 			.type = priv->type,
3872 			.conf = data_size ? data : NULL,
3873 		};
3874 		++out->args.vc.actions_n;
3875 		ctx->object = action;
3876 		ctx->objmask = NULL;
3877 	}
3878 	memset(data, 0, data_size);
3879 	out->args.vc.data = data;
3880 	ctx->objdata = data_size;
3881 	return len;
3882 }
3883 
3884 /** Parse pattern item parameter type. */
3885 static int
3886 parse_vc_spec(struct context *ctx, const struct token *token,
3887 	      const char *str, unsigned int len,
3888 	      void *buf, unsigned int size)
3889 {
3890 	struct buffer *out = buf;
3891 	struct rte_flow_item *item;
3892 	uint32_t data_size;
3893 	int index;
3894 	int objmask = 0;
3895 
3896 	(void)size;
3897 	/* Token name must match. */
3898 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3899 		return -1;
3900 	/* Parse parameter types. */
3901 	switch (ctx->curr) {
3902 		static const enum index prefix[] = NEXT_ENTRY(PREFIX);
3903 
3904 	case ITEM_PARAM_IS:
3905 		index = 0;
3906 		objmask = 1;
3907 		break;
3908 	case ITEM_PARAM_SPEC:
3909 		index = 0;
3910 		break;
3911 	case ITEM_PARAM_LAST:
3912 		index = 1;
3913 		break;
3914 	case ITEM_PARAM_PREFIX:
3915 		/* Modify next token to expect a prefix. */
3916 		if (ctx->next_num < 2)
3917 			return -1;
3918 		ctx->next[ctx->next_num - 2] = prefix;
3919 		/* Fall through. */
3920 	case ITEM_PARAM_MASK:
3921 		index = 2;
3922 		break;
3923 	default:
3924 		return -1;
3925 	}
3926 	/* Nothing else to do if there is no buffer. */
3927 	if (!out)
3928 		return len;
3929 	if (!out->args.vc.pattern_n)
3930 		return -1;
3931 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
3932 	data_size = ctx->objdata / 3; /* spec, last, mask */
3933 	/* Point to selected object. */
3934 	ctx->object = out->args.vc.data + (data_size * index);
3935 	if (objmask) {
3936 		ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
3937 		item->mask = ctx->objmask;
3938 	} else
3939 		ctx->objmask = NULL;
3940 	/* Update relevant item pointer. */
3941 	*((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
3942 		ctx->object;
3943 	return len;
3944 }
3945 
3946 /** Parse action configuration field. */
3947 static int
3948 parse_vc_conf(struct context *ctx, const struct token *token,
3949 	      const char *str, unsigned int len,
3950 	      void *buf, unsigned int size)
3951 {
3952 	struct buffer *out = buf;
3953 
3954 	(void)size;
3955 	/* Token name must match. */
3956 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3957 		return -1;
3958 	/* Nothing else to do if there is no buffer. */
3959 	if (!out)
3960 		return len;
3961 	/* Point to selected object. */
3962 	ctx->object = out->args.vc.data;
3963 	ctx->objmask = NULL;
3964 	return len;
3965 }
3966 
3967 /** Parse RSS action. */
3968 static int
3969 parse_vc_action_rss(struct context *ctx, const struct token *token,
3970 		    const char *str, unsigned int len,
3971 		    void *buf, unsigned int size)
3972 {
3973 	struct buffer *out = buf;
3974 	struct rte_flow_action *action;
3975 	struct action_rss_data *action_rss_data;
3976 	unsigned int i;
3977 	int ret;
3978 
3979 	ret = parse_vc(ctx, token, str, len, buf, size);
3980 	if (ret < 0)
3981 		return ret;
3982 	/* Nothing else to do if there is no buffer. */
3983 	if (!out)
3984 		return ret;
3985 	if (!out->args.vc.actions_n)
3986 		return -1;
3987 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3988 	/* Point to selected object. */
3989 	ctx->object = out->args.vc.data;
3990 	ctx->objmask = NULL;
3991 	/* Set up default configuration. */
3992 	action_rss_data = ctx->object;
3993 	*action_rss_data = (struct action_rss_data){
3994 		.conf = (struct rte_flow_action_rss){
3995 			.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
3996 			.level = 0,
3997 			.types = rss_hf,
3998 			.key_len = sizeof(action_rss_data->key),
3999 			.queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
4000 			.key = action_rss_data->key,
4001 			.queue = action_rss_data->queue,
4002 		},
4003 		.key = "testpmd's default RSS hash key, "
4004 			"override it for better balancing",
4005 		.queue = { 0 },
4006 	};
4007 	for (i = 0; i < action_rss_data->conf.queue_num; ++i)
4008 		action_rss_data->queue[i] = i;
4009 	if (!port_id_is_invalid(ctx->port, DISABLED_WARN) &&
4010 	    ctx->port != (portid_t)RTE_PORT_ALL) {
4011 		struct rte_eth_dev_info info;
4012 		int ret2;
4013 
4014 		ret2 = rte_eth_dev_info_get(ctx->port, &info);
4015 		if (ret2 != 0)
4016 			return ret2;
4017 
4018 		action_rss_data->conf.key_len =
4019 			RTE_MIN(sizeof(action_rss_data->key),
4020 				info.hash_key_size);
4021 	}
4022 	action->conf = &action_rss_data->conf;
4023 	return ret;
4024 }
4025 
4026 /**
4027  * Parse func field for RSS action.
4028  *
4029  * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
4030  * ACTION_RSS_FUNC_* index that called this function.
4031  */
4032 static int
4033 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
4034 			 const char *str, unsigned int len,
4035 			 void *buf, unsigned int size)
4036 {
4037 	struct action_rss_data *action_rss_data;
4038 	enum rte_eth_hash_function func;
4039 
4040 	(void)buf;
4041 	(void)size;
4042 	/* Token name must match. */
4043 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4044 		return -1;
4045 	switch (ctx->curr) {
4046 	case ACTION_RSS_FUNC_DEFAULT:
4047 		func = RTE_ETH_HASH_FUNCTION_DEFAULT;
4048 		break;
4049 	case ACTION_RSS_FUNC_TOEPLITZ:
4050 		func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
4051 		break;
4052 	case ACTION_RSS_FUNC_SIMPLE_XOR:
4053 		func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
4054 		break;
4055 	case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
4056 		func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
4057 		break;
4058 	default:
4059 		return -1;
4060 	}
4061 	if (!ctx->object)
4062 		return len;
4063 	action_rss_data = ctx->object;
4064 	action_rss_data->conf.func = func;
4065 	return len;
4066 }
4067 
4068 /**
4069  * Parse type field for RSS action.
4070  *
4071  * Valid tokens are type field names and the "end" token.
4072  */
4073 static int
4074 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
4075 			  const char *str, unsigned int len,
4076 			  void *buf, unsigned int size)
4077 {
4078 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
4079 	struct action_rss_data *action_rss_data;
4080 	unsigned int i;
4081 
4082 	(void)token;
4083 	(void)buf;
4084 	(void)size;
4085 	if (ctx->curr != ACTION_RSS_TYPE)
4086 		return -1;
4087 	if (!(ctx->objdata >> 16) && ctx->object) {
4088 		action_rss_data = ctx->object;
4089 		action_rss_data->conf.types = 0;
4090 	}
4091 	if (!strcmp_partial("end", str, len)) {
4092 		ctx->objdata &= 0xffff;
4093 		return len;
4094 	}
4095 	for (i = 0; rss_type_table[i].str; ++i)
4096 		if (!strcmp_partial(rss_type_table[i].str, str, len))
4097 			break;
4098 	if (!rss_type_table[i].str)
4099 		return -1;
4100 	ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
4101 	/* Repeat token. */
4102 	if (ctx->next_num == RTE_DIM(ctx->next))
4103 		return -1;
4104 	ctx->next[ctx->next_num++] = next;
4105 	if (!ctx->object)
4106 		return len;
4107 	action_rss_data = ctx->object;
4108 	action_rss_data->conf.types |= rss_type_table[i].rss_type;
4109 	return len;
4110 }
4111 
4112 /**
4113  * Parse queue field for RSS action.
4114  *
4115  * Valid tokens are queue indices and the "end" token.
4116  */
4117 static int
4118 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
4119 			  const char *str, unsigned int len,
4120 			  void *buf, unsigned int size)
4121 {
4122 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
4123 	struct action_rss_data *action_rss_data;
4124 	const struct arg *arg;
4125 	int ret;
4126 	int i;
4127 
4128 	(void)token;
4129 	(void)buf;
4130 	(void)size;
4131 	if (ctx->curr != ACTION_RSS_QUEUE)
4132 		return -1;
4133 	i = ctx->objdata >> 16;
4134 	if (!strcmp_partial("end", str, len)) {
4135 		ctx->objdata &= 0xffff;
4136 		goto end;
4137 	}
4138 	if (i >= ACTION_RSS_QUEUE_NUM)
4139 		return -1;
4140 	arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
4141 			     i * sizeof(action_rss_data->queue[i]),
4142 			     sizeof(action_rss_data->queue[i]));
4143 	if (push_args(ctx, arg))
4144 		return -1;
4145 	ret = parse_int(ctx, token, str, len, NULL, 0);
4146 	if (ret < 0) {
4147 		pop_args(ctx);
4148 		return -1;
4149 	}
4150 	++i;
4151 	ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
4152 	/* Repeat token. */
4153 	if (ctx->next_num == RTE_DIM(ctx->next))
4154 		return -1;
4155 	ctx->next[ctx->next_num++] = next;
4156 end:
4157 	if (!ctx->object)
4158 		return len;
4159 	action_rss_data = ctx->object;
4160 	action_rss_data->conf.queue_num = i;
4161 	action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
4162 	return len;
4163 }
4164 
4165 /** Parse VXLAN encap action. */
4166 static int
4167 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
4168 			    const char *str, unsigned int len,
4169 			    void *buf, unsigned int size)
4170 {
4171 	struct buffer *out = buf;
4172 	struct rte_flow_action *action;
4173 	struct action_vxlan_encap_data *action_vxlan_encap_data;
4174 	int ret;
4175 
4176 	ret = parse_vc(ctx, token, str, len, buf, size);
4177 	if (ret < 0)
4178 		return ret;
4179 	/* Nothing else to do if there is no buffer. */
4180 	if (!out)
4181 		return ret;
4182 	if (!out->args.vc.actions_n)
4183 		return -1;
4184 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4185 	/* Point to selected object. */
4186 	ctx->object = out->args.vc.data;
4187 	ctx->objmask = NULL;
4188 	/* Set up default configuration. */
4189 	action_vxlan_encap_data = ctx->object;
4190 	*action_vxlan_encap_data = (struct action_vxlan_encap_data){
4191 		.conf = (struct rte_flow_action_vxlan_encap){
4192 			.definition = action_vxlan_encap_data->items,
4193 		},
4194 		.items = {
4195 			{
4196 				.type = RTE_FLOW_ITEM_TYPE_ETH,
4197 				.spec = &action_vxlan_encap_data->item_eth,
4198 				.mask = &rte_flow_item_eth_mask,
4199 			},
4200 			{
4201 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
4202 				.spec = &action_vxlan_encap_data->item_vlan,
4203 				.mask = &rte_flow_item_vlan_mask,
4204 			},
4205 			{
4206 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
4207 				.spec = &action_vxlan_encap_data->item_ipv4,
4208 				.mask = &rte_flow_item_ipv4_mask,
4209 			},
4210 			{
4211 				.type = RTE_FLOW_ITEM_TYPE_UDP,
4212 				.spec = &action_vxlan_encap_data->item_udp,
4213 				.mask = &rte_flow_item_udp_mask,
4214 			},
4215 			{
4216 				.type = RTE_FLOW_ITEM_TYPE_VXLAN,
4217 				.spec = &action_vxlan_encap_data->item_vxlan,
4218 				.mask = &rte_flow_item_vxlan_mask,
4219 			},
4220 			{
4221 				.type = RTE_FLOW_ITEM_TYPE_END,
4222 			},
4223 		},
4224 		.item_eth.type = 0,
4225 		.item_vlan = {
4226 			.tci = vxlan_encap_conf.vlan_tci,
4227 			.inner_type = 0,
4228 		},
4229 		.item_ipv4.hdr = {
4230 			.src_addr = vxlan_encap_conf.ipv4_src,
4231 			.dst_addr = vxlan_encap_conf.ipv4_dst,
4232 		},
4233 		.item_udp.hdr = {
4234 			.src_port = vxlan_encap_conf.udp_src,
4235 			.dst_port = vxlan_encap_conf.udp_dst,
4236 		},
4237 		.item_vxlan.flags = 0,
4238 	};
4239 	memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes,
4240 	       vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
4241 	memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
4242 	       vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
4243 	if (!vxlan_encap_conf.select_ipv4) {
4244 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
4245 		       &vxlan_encap_conf.ipv6_src,
4246 		       sizeof(vxlan_encap_conf.ipv6_src));
4247 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
4248 		       &vxlan_encap_conf.ipv6_dst,
4249 		       sizeof(vxlan_encap_conf.ipv6_dst));
4250 		action_vxlan_encap_data->items[2] = (struct rte_flow_item){
4251 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
4252 			.spec = &action_vxlan_encap_data->item_ipv6,
4253 			.mask = &rte_flow_item_ipv6_mask,
4254 		};
4255 	}
4256 	if (!vxlan_encap_conf.select_vlan)
4257 		action_vxlan_encap_data->items[1].type =
4258 			RTE_FLOW_ITEM_TYPE_VOID;
4259 	if (vxlan_encap_conf.select_tos_ttl) {
4260 		if (vxlan_encap_conf.select_ipv4) {
4261 			static struct rte_flow_item_ipv4 ipv4_mask_tos;
4262 
4263 			memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
4264 			       sizeof(ipv4_mask_tos));
4265 			ipv4_mask_tos.hdr.type_of_service = 0xff;
4266 			ipv4_mask_tos.hdr.time_to_live = 0xff;
4267 			action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
4268 					vxlan_encap_conf.ip_tos;
4269 			action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
4270 					vxlan_encap_conf.ip_ttl;
4271 			action_vxlan_encap_data->items[2].mask =
4272 							&ipv4_mask_tos;
4273 		} else {
4274 			static struct rte_flow_item_ipv6 ipv6_mask_tos;
4275 
4276 			memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
4277 			       sizeof(ipv6_mask_tos));
4278 			ipv6_mask_tos.hdr.vtc_flow |=
4279 				RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
4280 			ipv6_mask_tos.hdr.hop_limits = 0xff;
4281 			action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
4282 				rte_cpu_to_be_32
4283 					((uint32_t)vxlan_encap_conf.ip_tos <<
4284 					 RTE_IPV6_HDR_TC_SHIFT);
4285 			action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
4286 					vxlan_encap_conf.ip_ttl;
4287 			action_vxlan_encap_data->items[2].mask =
4288 							&ipv6_mask_tos;
4289 		}
4290 	}
4291 	memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
4292 	       RTE_DIM(vxlan_encap_conf.vni));
4293 	action->conf = &action_vxlan_encap_data->conf;
4294 	return ret;
4295 }
4296 
4297 /** Parse NVGRE encap action. */
4298 static int
4299 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
4300 			    const char *str, unsigned int len,
4301 			    void *buf, unsigned int size)
4302 {
4303 	struct buffer *out = buf;
4304 	struct rte_flow_action *action;
4305 	struct action_nvgre_encap_data *action_nvgre_encap_data;
4306 	int ret;
4307 
4308 	ret = parse_vc(ctx, token, str, len, buf, size);
4309 	if (ret < 0)
4310 		return ret;
4311 	/* Nothing else to do if there is no buffer. */
4312 	if (!out)
4313 		return ret;
4314 	if (!out->args.vc.actions_n)
4315 		return -1;
4316 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4317 	/* Point to selected object. */
4318 	ctx->object = out->args.vc.data;
4319 	ctx->objmask = NULL;
4320 	/* Set up default configuration. */
4321 	action_nvgre_encap_data = ctx->object;
4322 	*action_nvgre_encap_data = (struct action_nvgre_encap_data){
4323 		.conf = (struct rte_flow_action_nvgre_encap){
4324 			.definition = action_nvgre_encap_data->items,
4325 		},
4326 		.items = {
4327 			{
4328 				.type = RTE_FLOW_ITEM_TYPE_ETH,
4329 				.spec = &action_nvgre_encap_data->item_eth,
4330 				.mask = &rte_flow_item_eth_mask,
4331 			},
4332 			{
4333 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
4334 				.spec = &action_nvgre_encap_data->item_vlan,
4335 				.mask = &rte_flow_item_vlan_mask,
4336 			},
4337 			{
4338 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
4339 				.spec = &action_nvgre_encap_data->item_ipv4,
4340 				.mask = &rte_flow_item_ipv4_mask,
4341 			},
4342 			{
4343 				.type = RTE_FLOW_ITEM_TYPE_NVGRE,
4344 				.spec = &action_nvgre_encap_data->item_nvgre,
4345 				.mask = &rte_flow_item_nvgre_mask,
4346 			},
4347 			{
4348 				.type = RTE_FLOW_ITEM_TYPE_END,
4349 			},
4350 		},
4351 		.item_eth.type = 0,
4352 		.item_vlan = {
4353 			.tci = nvgre_encap_conf.vlan_tci,
4354 			.inner_type = 0,
4355 		},
4356 		.item_ipv4.hdr = {
4357 		       .src_addr = nvgre_encap_conf.ipv4_src,
4358 		       .dst_addr = nvgre_encap_conf.ipv4_dst,
4359 		},
4360 		.item_nvgre.flow_id = 0,
4361 	};
4362 	memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
4363 	       nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
4364 	memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
4365 	       nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
4366 	if (!nvgre_encap_conf.select_ipv4) {
4367 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
4368 		       &nvgre_encap_conf.ipv6_src,
4369 		       sizeof(nvgre_encap_conf.ipv6_src));
4370 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
4371 		       &nvgre_encap_conf.ipv6_dst,
4372 		       sizeof(nvgre_encap_conf.ipv6_dst));
4373 		action_nvgre_encap_data->items[2] = (struct rte_flow_item){
4374 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
4375 			.spec = &action_nvgre_encap_data->item_ipv6,
4376 			.mask = &rte_flow_item_ipv6_mask,
4377 		};
4378 	}
4379 	if (!nvgre_encap_conf.select_vlan)
4380 		action_nvgre_encap_data->items[1].type =
4381 			RTE_FLOW_ITEM_TYPE_VOID;
4382 	memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
4383 	       RTE_DIM(nvgre_encap_conf.tni));
4384 	action->conf = &action_nvgre_encap_data->conf;
4385 	return ret;
4386 }
4387 
4388 /** Parse l2 encap action. */
4389 static int
4390 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
4391 			 const char *str, unsigned int len,
4392 			 void *buf, unsigned int size)
4393 {
4394 	struct buffer *out = buf;
4395 	struct rte_flow_action *action;
4396 	struct action_raw_encap_data *action_encap_data;
4397 	struct rte_flow_item_eth eth = { .type = 0, };
4398 	struct rte_flow_item_vlan vlan = {
4399 		.tci = mplsoudp_encap_conf.vlan_tci,
4400 		.inner_type = 0,
4401 	};
4402 	uint8_t *header;
4403 	int ret;
4404 
4405 	ret = parse_vc(ctx, token, str, len, buf, size);
4406 	if (ret < 0)
4407 		return ret;
4408 	/* Nothing else to do if there is no buffer. */
4409 	if (!out)
4410 		return ret;
4411 	if (!out->args.vc.actions_n)
4412 		return -1;
4413 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4414 	/* Point to selected object. */
4415 	ctx->object = out->args.vc.data;
4416 	ctx->objmask = NULL;
4417 	/* Copy the headers to the buffer. */
4418 	action_encap_data = ctx->object;
4419 	*action_encap_data = (struct action_raw_encap_data) {
4420 		.conf = (struct rte_flow_action_raw_encap){
4421 			.data = action_encap_data->data,
4422 		},
4423 		.data = {},
4424 	};
4425 	header = action_encap_data->data;
4426 	if (l2_encap_conf.select_vlan)
4427 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
4428 	else if (l2_encap_conf.select_ipv4)
4429 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4430 	else
4431 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4432 	memcpy(eth.dst.addr_bytes,
4433 	       l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
4434 	memcpy(eth.src.addr_bytes,
4435 	       l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
4436 	memcpy(header, &eth, sizeof(eth));
4437 	header += sizeof(eth);
4438 	if (l2_encap_conf.select_vlan) {
4439 		if (l2_encap_conf.select_ipv4)
4440 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4441 		else
4442 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4443 		memcpy(header, &vlan, sizeof(vlan));
4444 		header += sizeof(vlan);
4445 	}
4446 	action_encap_data->conf.size = header -
4447 		action_encap_data->data;
4448 	action->conf = &action_encap_data->conf;
4449 	return ret;
4450 }
4451 
4452 /** Parse l2 decap action. */
4453 static int
4454 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
4455 			 const char *str, unsigned int len,
4456 			 void *buf, unsigned int size)
4457 {
4458 	struct buffer *out = buf;
4459 	struct rte_flow_action *action;
4460 	struct action_raw_decap_data *action_decap_data;
4461 	struct rte_flow_item_eth eth = { .type = 0, };
4462 	struct rte_flow_item_vlan vlan = {
4463 		.tci = mplsoudp_encap_conf.vlan_tci,
4464 		.inner_type = 0,
4465 	};
4466 	uint8_t *header;
4467 	int ret;
4468 
4469 	ret = parse_vc(ctx, token, str, len, buf, size);
4470 	if (ret < 0)
4471 		return ret;
4472 	/* Nothing else to do if there is no buffer. */
4473 	if (!out)
4474 		return ret;
4475 	if (!out->args.vc.actions_n)
4476 		return -1;
4477 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4478 	/* Point to selected object. */
4479 	ctx->object = out->args.vc.data;
4480 	ctx->objmask = NULL;
4481 	/* Copy the headers to the buffer. */
4482 	action_decap_data = ctx->object;
4483 	*action_decap_data = (struct action_raw_decap_data) {
4484 		.conf = (struct rte_flow_action_raw_decap){
4485 			.data = action_decap_data->data,
4486 		},
4487 		.data = {},
4488 	};
4489 	header = action_decap_data->data;
4490 	if (l2_decap_conf.select_vlan)
4491 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
4492 	memcpy(header, &eth, sizeof(eth));
4493 	header += sizeof(eth);
4494 	if (l2_decap_conf.select_vlan) {
4495 		memcpy(header, &vlan, sizeof(vlan));
4496 		header += sizeof(vlan);
4497 	}
4498 	action_decap_data->conf.size = header -
4499 		action_decap_data->data;
4500 	action->conf = &action_decap_data->conf;
4501 	return ret;
4502 }
4503 
4504 #define ETHER_TYPE_MPLS_UNICAST 0x8847
4505 
4506 /** Parse MPLSOGRE encap action. */
4507 static int
4508 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
4509 			       const char *str, unsigned int len,
4510 			       void *buf, unsigned int size)
4511 {
4512 	struct buffer *out = buf;
4513 	struct rte_flow_action *action;
4514 	struct action_raw_encap_data *action_encap_data;
4515 	struct rte_flow_item_eth eth = { .type = 0, };
4516 	struct rte_flow_item_vlan vlan = {
4517 		.tci = mplsogre_encap_conf.vlan_tci,
4518 		.inner_type = 0,
4519 	};
4520 	struct rte_flow_item_ipv4 ipv4 = {
4521 		.hdr =  {
4522 			.src_addr = mplsogre_encap_conf.ipv4_src,
4523 			.dst_addr = mplsogre_encap_conf.ipv4_dst,
4524 			.next_proto_id = IPPROTO_GRE,
4525 			.version_ihl = RTE_IPV4_VHL_DEF,
4526 			.time_to_live = IPDEFTTL,
4527 		},
4528 	};
4529 	struct rte_flow_item_ipv6 ipv6 = {
4530 		.hdr =  {
4531 			.proto = IPPROTO_GRE,
4532 			.hop_limits = IPDEFTTL,
4533 		},
4534 	};
4535 	struct rte_flow_item_gre gre = {
4536 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
4537 	};
4538 	struct rte_flow_item_mpls mpls;
4539 	uint8_t *header;
4540 	int ret;
4541 
4542 	ret = parse_vc(ctx, token, str, len, buf, size);
4543 	if (ret < 0)
4544 		return ret;
4545 	/* Nothing else to do if there is no buffer. */
4546 	if (!out)
4547 		return ret;
4548 	if (!out->args.vc.actions_n)
4549 		return -1;
4550 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4551 	/* Point to selected object. */
4552 	ctx->object = out->args.vc.data;
4553 	ctx->objmask = NULL;
4554 	/* Copy the headers to the buffer. */
4555 	action_encap_data = ctx->object;
4556 	*action_encap_data = (struct action_raw_encap_data) {
4557 		.conf = (struct rte_flow_action_raw_encap){
4558 			.data = action_encap_data->data,
4559 		},
4560 		.data = {},
4561 		.preserve = {},
4562 	};
4563 	header = action_encap_data->data;
4564 	if (mplsogre_encap_conf.select_vlan)
4565 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
4566 	else if (mplsogre_encap_conf.select_ipv4)
4567 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4568 	else
4569 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4570 	memcpy(eth.dst.addr_bytes,
4571 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
4572 	memcpy(eth.src.addr_bytes,
4573 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
4574 	memcpy(header, &eth, sizeof(eth));
4575 	header += sizeof(eth);
4576 	if (mplsogre_encap_conf.select_vlan) {
4577 		if (mplsogre_encap_conf.select_ipv4)
4578 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4579 		else
4580 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4581 		memcpy(header, &vlan, sizeof(vlan));
4582 		header += sizeof(vlan);
4583 	}
4584 	if (mplsogre_encap_conf.select_ipv4) {
4585 		memcpy(header, &ipv4, sizeof(ipv4));
4586 		header += sizeof(ipv4);
4587 	} else {
4588 		memcpy(&ipv6.hdr.src_addr,
4589 		       &mplsogre_encap_conf.ipv6_src,
4590 		       sizeof(mplsogre_encap_conf.ipv6_src));
4591 		memcpy(&ipv6.hdr.dst_addr,
4592 		       &mplsogre_encap_conf.ipv6_dst,
4593 		       sizeof(mplsogre_encap_conf.ipv6_dst));
4594 		memcpy(header, &ipv6, sizeof(ipv6));
4595 		header += sizeof(ipv6);
4596 	}
4597 	memcpy(header, &gre, sizeof(gre));
4598 	header += sizeof(gre);
4599 	memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
4600 	       RTE_DIM(mplsogre_encap_conf.label));
4601 	mpls.label_tc_s[2] |= 0x1;
4602 	memcpy(header, &mpls, sizeof(mpls));
4603 	header += sizeof(mpls);
4604 	action_encap_data->conf.size = header -
4605 		action_encap_data->data;
4606 	action->conf = &action_encap_data->conf;
4607 	return ret;
4608 }
4609 
4610 /** Parse MPLSOGRE decap action. */
4611 static int
4612 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
4613 			       const char *str, unsigned int len,
4614 			       void *buf, unsigned int size)
4615 {
4616 	struct buffer *out = buf;
4617 	struct rte_flow_action *action;
4618 	struct action_raw_decap_data *action_decap_data;
4619 	struct rte_flow_item_eth eth = { .type = 0, };
4620 	struct rte_flow_item_vlan vlan = {.tci = 0};
4621 	struct rte_flow_item_ipv4 ipv4 = {
4622 		.hdr =  {
4623 			.next_proto_id = IPPROTO_GRE,
4624 		},
4625 	};
4626 	struct rte_flow_item_ipv6 ipv6 = {
4627 		.hdr =  {
4628 			.proto = IPPROTO_GRE,
4629 		},
4630 	};
4631 	struct rte_flow_item_gre gre = {
4632 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
4633 	};
4634 	struct rte_flow_item_mpls mpls;
4635 	uint8_t *header;
4636 	int ret;
4637 
4638 	ret = parse_vc(ctx, token, str, len, buf, size);
4639 	if (ret < 0)
4640 		return ret;
4641 	/* Nothing else to do if there is no buffer. */
4642 	if (!out)
4643 		return ret;
4644 	if (!out->args.vc.actions_n)
4645 		return -1;
4646 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4647 	/* Point to selected object. */
4648 	ctx->object = out->args.vc.data;
4649 	ctx->objmask = NULL;
4650 	/* Copy the headers to the buffer. */
4651 	action_decap_data = ctx->object;
4652 	*action_decap_data = (struct action_raw_decap_data) {
4653 		.conf = (struct rte_flow_action_raw_decap){
4654 			.data = action_decap_data->data,
4655 		},
4656 		.data = {},
4657 	};
4658 	header = action_decap_data->data;
4659 	if (mplsogre_decap_conf.select_vlan)
4660 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
4661 	else if (mplsogre_encap_conf.select_ipv4)
4662 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4663 	else
4664 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4665 	memcpy(eth.dst.addr_bytes,
4666 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
4667 	memcpy(eth.src.addr_bytes,
4668 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
4669 	memcpy(header, &eth, sizeof(eth));
4670 	header += sizeof(eth);
4671 	if (mplsogre_encap_conf.select_vlan) {
4672 		if (mplsogre_encap_conf.select_ipv4)
4673 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4674 		else
4675 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4676 		memcpy(header, &vlan, sizeof(vlan));
4677 		header += sizeof(vlan);
4678 	}
4679 	if (mplsogre_encap_conf.select_ipv4) {
4680 		memcpy(header, &ipv4, sizeof(ipv4));
4681 		header += sizeof(ipv4);
4682 	} else {
4683 		memcpy(header, &ipv6, sizeof(ipv6));
4684 		header += sizeof(ipv6);
4685 	}
4686 	memcpy(header, &gre, sizeof(gre));
4687 	header += sizeof(gre);
4688 	memset(&mpls, 0, sizeof(mpls));
4689 	memcpy(header, &mpls, sizeof(mpls));
4690 	header += sizeof(mpls);
4691 	action_decap_data->conf.size = header -
4692 		action_decap_data->data;
4693 	action->conf = &action_decap_data->conf;
4694 	return ret;
4695 }
4696 
4697 /** Parse MPLSOUDP encap action. */
4698 static int
4699 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
4700 			       const char *str, unsigned int len,
4701 			       void *buf, unsigned int size)
4702 {
4703 	struct buffer *out = buf;
4704 	struct rte_flow_action *action;
4705 	struct action_raw_encap_data *action_encap_data;
4706 	struct rte_flow_item_eth eth = { .type = 0, };
4707 	struct rte_flow_item_vlan vlan = {
4708 		.tci = mplsoudp_encap_conf.vlan_tci,
4709 		.inner_type = 0,
4710 	};
4711 	struct rte_flow_item_ipv4 ipv4 = {
4712 		.hdr =  {
4713 			.src_addr = mplsoudp_encap_conf.ipv4_src,
4714 			.dst_addr = mplsoudp_encap_conf.ipv4_dst,
4715 			.next_proto_id = IPPROTO_UDP,
4716 			.version_ihl = RTE_IPV4_VHL_DEF,
4717 			.time_to_live = IPDEFTTL,
4718 		},
4719 	};
4720 	struct rte_flow_item_ipv6 ipv6 = {
4721 		.hdr =  {
4722 			.proto = IPPROTO_UDP,
4723 			.hop_limits = IPDEFTTL,
4724 		},
4725 	};
4726 	struct rte_flow_item_udp udp = {
4727 		.hdr = {
4728 			.src_port = mplsoudp_encap_conf.udp_src,
4729 			.dst_port = mplsoudp_encap_conf.udp_dst,
4730 		},
4731 	};
4732 	struct rte_flow_item_mpls mpls;
4733 	uint8_t *header;
4734 	int ret;
4735 
4736 	ret = parse_vc(ctx, token, str, len, buf, size);
4737 	if (ret < 0)
4738 		return ret;
4739 	/* Nothing else to do if there is no buffer. */
4740 	if (!out)
4741 		return ret;
4742 	if (!out->args.vc.actions_n)
4743 		return -1;
4744 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4745 	/* Point to selected object. */
4746 	ctx->object = out->args.vc.data;
4747 	ctx->objmask = NULL;
4748 	/* Copy the headers to the buffer. */
4749 	action_encap_data = ctx->object;
4750 	*action_encap_data = (struct action_raw_encap_data) {
4751 		.conf = (struct rte_flow_action_raw_encap){
4752 			.data = action_encap_data->data,
4753 		},
4754 		.data = {},
4755 		.preserve = {},
4756 	};
4757 	header = action_encap_data->data;
4758 	if (mplsoudp_encap_conf.select_vlan)
4759 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
4760 	else if (mplsoudp_encap_conf.select_ipv4)
4761 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4762 	else
4763 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4764 	memcpy(eth.dst.addr_bytes,
4765 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
4766 	memcpy(eth.src.addr_bytes,
4767 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
4768 	memcpy(header, &eth, sizeof(eth));
4769 	header += sizeof(eth);
4770 	if (mplsoudp_encap_conf.select_vlan) {
4771 		if (mplsoudp_encap_conf.select_ipv4)
4772 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4773 		else
4774 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4775 		memcpy(header, &vlan, sizeof(vlan));
4776 		header += sizeof(vlan);
4777 	}
4778 	if (mplsoudp_encap_conf.select_ipv4) {
4779 		memcpy(header, &ipv4, sizeof(ipv4));
4780 		header += sizeof(ipv4);
4781 	} else {
4782 		memcpy(&ipv6.hdr.src_addr,
4783 		       &mplsoudp_encap_conf.ipv6_src,
4784 		       sizeof(mplsoudp_encap_conf.ipv6_src));
4785 		memcpy(&ipv6.hdr.dst_addr,
4786 		       &mplsoudp_encap_conf.ipv6_dst,
4787 		       sizeof(mplsoudp_encap_conf.ipv6_dst));
4788 		memcpy(header, &ipv6, sizeof(ipv6));
4789 		header += sizeof(ipv6);
4790 	}
4791 	memcpy(header, &udp, sizeof(udp));
4792 	header += sizeof(udp);
4793 	memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
4794 	       RTE_DIM(mplsoudp_encap_conf.label));
4795 	mpls.label_tc_s[2] |= 0x1;
4796 	memcpy(header, &mpls, sizeof(mpls));
4797 	header += sizeof(mpls);
4798 	action_encap_data->conf.size = header -
4799 		action_encap_data->data;
4800 	action->conf = &action_encap_data->conf;
4801 	return ret;
4802 }
4803 
4804 /** Parse MPLSOUDP decap action. */
4805 static int
4806 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
4807 			       const char *str, unsigned int len,
4808 			       void *buf, unsigned int size)
4809 {
4810 	struct buffer *out = buf;
4811 	struct rte_flow_action *action;
4812 	struct action_raw_decap_data *action_decap_data;
4813 	struct rte_flow_item_eth eth = { .type = 0, };
4814 	struct rte_flow_item_vlan vlan = {.tci = 0};
4815 	struct rte_flow_item_ipv4 ipv4 = {
4816 		.hdr =  {
4817 			.next_proto_id = IPPROTO_UDP,
4818 		},
4819 	};
4820 	struct rte_flow_item_ipv6 ipv6 = {
4821 		.hdr =  {
4822 			.proto = IPPROTO_UDP,
4823 		},
4824 	};
4825 	struct rte_flow_item_udp udp = {
4826 		.hdr = {
4827 			.dst_port = rte_cpu_to_be_16(6635),
4828 		},
4829 	};
4830 	struct rte_flow_item_mpls mpls;
4831 	uint8_t *header;
4832 	int ret;
4833 
4834 	ret = parse_vc(ctx, token, str, len, buf, size);
4835 	if (ret < 0)
4836 		return ret;
4837 	/* Nothing else to do if there is no buffer. */
4838 	if (!out)
4839 		return ret;
4840 	if (!out->args.vc.actions_n)
4841 		return -1;
4842 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4843 	/* Point to selected object. */
4844 	ctx->object = out->args.vc.data;
4845 	ctx->objmask = NULL;
4846 	/* Copy the headers to the buffer. */
4847 	action_decap_data = ctx->object;
4848 	*action_decap_data = (struct action_raw_decap_data) {
4849 		.conf = (struct rte_flow_action_raw_decap){
4850 			.data = action_decap_data->data,
4851 		},
4852 		.data = {},
4853 	};
4854 	header = action_decap_data->data;
4855 	if (mplsoudp_decap_conf.select_vlan)
4856 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
4857 	else if (mplsoudp_encap_conf.select_ipv4)
4858 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4859 	else
4860 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4861 	memcpy(eth.dst.addr_bytes,
4862 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
4863 	memcpy(eth.src.addr_bytes,
4864 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
4865 	memcpy(header, &eth, sizeof(eth));
4866 	header += sizeof(eth);
4867 	if (mplsoudp_encap_conf.select_vlan) {
4868 		if (mplsoudp_encap_conf.select_ipv4)
4869 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4870 		else
4871 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4872 		memcpy(header, &vlan, sizeof(vlan));
4873 		header += sizeof(vlan);
4874 	}
4875 	if (mplsoudp_encap_conf.select_ipv4) {
4876 		memcpy(header, &ipv4, sizeof(ipv4));
4877 		header += sizeof(ipv4);
4878 	} else {
4879 		memcpy(header, &ipv6, sizeof(ipv6));
4880 		header += sizeof(ipv6);
4881 	}
4882 	memcpy(header, &udp, sizeof(udp));
4883 	header += sizeof(udp);
4884 	memset(&mpls, 0, sizeof(mpls));
4885 	memcpy(header, &mpls, sizeof(mpls));
4886 	header += sizeof(mpls);
4887 	action_decap_data->conf.size = header -
4888 		action_decap_data->data;
4889 	action->conf = &action_decap_data->conf;
4890 	return ret;
4891 }
4892 
4893 static int
4894 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
4895 				const char *str, unsigned int len, void *buf,
4896 				unsigned int size)
4897 {
4898 	struct action_raw_decap_data *action_raw_decap_data;
4899 	struct rte_flow_action *action;
4900 	const struct arg *arg;
4901 	struct buffer *out = buf;
4902 	int ret;
4903 	uint16_t idx;
4904 
4905 	RTE_SET_USED(token);
4906 	RTE_SET_USED(buf);
4907 	RTE_SET_USED(size);
4908 	arg = ARGS_ENTRY_ARB_BOUNDED
4909 		(offsetof(struct action_raw_decap_data, idx),
4910 		 sizeof(((struct action_raw_decap_data *)0)->idx),
4911 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
4912 	if (push_args(ctx, arg))
4913 		return -1;
4914 	ret = parse_int(ctx, token, str, len, NULL, 0);
4915 	if (ret < 0) {
4916 		pop_args(ctx);
4917 		return -1;
4918 	}
4919 	if (!ctx->object)
4920 		return len;
4921 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4922 	action_raw_decap_data = ctx->object;
4923 	idx = action_raw_decap_data->idx;
4924 	action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
4925 	action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
4926 	action->conf = &action_raw_decap_data->conf;
4927 	return len;
4928 }
4929 
4930 
4931 static int
4932 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
4933 				const char *str, unsigned int len, void *buf,
4934 				unsigned int size)
4935 {
4936 	struct action_raw_encap_data *action_raw_encap_data;
4937 	struct rte_flow_action *action;
4938 	const struct arg *arg;
4939 	struct buffer *out = buf;
4940 	int ret;
4941 	uint16_t idx;
4942 
4943 	RTE_SET_USED(token);
4944 	RTE_SET_USED(buf);
4945 	RTE_SET_USED(size);
4946 	if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
4947 		return -1;
4948 	arg = ARGS_ENTRY_ARB_BOUNDED
4949 		(offsetof(struct action_raw_encap_data, idx),
4950 		 sizeof(((struct action_raw_encap_data *)0)->idx),
4951 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
4952 	if (push_args(ctx, arg))
4953 		return -1;
4954 	ret = parse_int(ctx, token, str, len, NULL, 0);
4955 	if (ret < 0) {
4956 		pop_args(ctx);
4957 		return -1;
4958 	}
4959 	if (!ctx->object)
4960 		return len;
4961 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4962 	action_raw_encap_data = ctx->object;
4963 	idx = action_raw_encap_data->idx;
4964 	action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
4965 	action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
4966 	action_raw_encap_data->conf.preserve = NULL;
4967 	action->conf = &action_raw_encap_data->conf;
4968 	return len;
4969 }
4970 
4971 static int
4972 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
4973 			  const char *str, unsigned int len, void *buf,
4974 			  unsigned int size)
4975 {
4976 	struct buffer *out = buf;
4977 	struct rte_flow_action *action;
4978 	struct action_raw_encap_data *action_raw_encap_data = NULL;
4979 	int ret;
4980 
4981 	ret = parse_vc(ctx, token, str, len, buf, size);
4982 	if (ret < 0)
4983 		return ret;
4984 	/* Nothing else to do if there is no buffer. */
4985 	if (!out)
4986 		return ret;
4987 	if (!out->args.vc.actions_n)
4988 		return -1;
4989 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4990 	/* Point to selected object. */
4991 	ctx->object = out->args.vc.data;
4992 	ctx->objmask = NULL;
4993 	/* Copy the headers to the buffer. */
4994 	action_raw_encap_data = ctx->object;
4995 	action_raw_encap_data->conf.data = raw_encap_confs[0].data;
4996 	action_raw_encap_data->conf.preserve = NULL;
4997 	action_raw_encap_data->conf.size = raw_encap_confs[0].size;
4998 	action->conf = &action_raw_encap_data->conf;
4999 	return ret;
5000 }
5001 
5002 static int
5003 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
5004 			  const char *str, unsigned int len, void *buf,
5005 			  unsigned int size)
5006 {
5007 	struct buffer *out = buf;
5008 	struct rte_flow_action *action;
5009 	struct action_raw_decap_data *action_raw_decap_data = NULL;
5010 	int ret;
5011 
5012 	ret = parse_vc(ctx, token, str, len, buf, size);
5013 	if (ret < 0)
5014 		return ret;
5015 	/* Nothing else to do if there is no buffer. */
5016 	if (!out)
5017 		return ret;
5018 	if (!out->args.vc.actions_n)
5019 		return -1;
5020 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5021 	/* Point to selected object. */
5022 	ctx->object = out->args.vc.data;
5023 	ctx->objmask = NULL;
5024 	/* Copy the headers to the buffer. */
5025 	action_raw_decap_data = ctx->object;
5026 	action_raw_decap_data->conf.data = raw_decap_confs[0].data;
5027 	action_raw_decap_data->conf.size = raw_decap_confs[0].size;
5028 	action->conf = &action_raw_decap_data->conf;
5029 	return ret;
5030 }
5031 
5032 static int
5033 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
5034 			 const char *str, unsigned int len, void *buf,
5035 			 unsigned int size)
5036 {
5037 	int ret;
5038 
5039 	ret = parse_vc(ctx, token, str, len, buf, size);
5040 	if (ret < 0)
5041 		return ret;
5042 	ret = rte_flow_dynf_metadata_register();
5043 	if (ret < 0)
5044 		return -1;
5045 	return len;
5046 }
5047 
5048 /** Parse tokens for destroy command. */
5049 static int
5050 parse_destroy(struct context *ctx, const struct token *token,
5051 	      const char *str, unsigned int len,
5052 	      void *buf, unsigned int size)
5053 {
5054 	struct buffer *out = buf;
5055 
5056 	/* Token name must match. */
5057 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5058 		return -1;
5059 	/* Nothing else to do if there is no buffer. */
5060 	if (!out)
5061 		return len;
5062 	if (!out->command) {
5063 		if (ctx->curr != DESTROY)
5064 			return -1;
5065 		if (sizeof(*out) > size)
5066 			return -1;
5067 		out->command = ctx->curr;
5068 		ctx->objdata = 0;
5069 		ctx->object = out;
5070 		ctx->objmask = NULL;
5071 		out->args.destroy.rule =
5072 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5073 					       sizeof(double));
5074 		return len;
5075 	}
5076 	if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
5077 	     sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
5078 		return -1;
5079 	ctx->objdata = 0;
5080 	ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
5081 	ctx->objmask = NULL;
5082 	return len;
5083 }
5084 
5085 /** Parse tokens for flush command. */
5086 static int
5087 parse_flush(struct context *ctx, const struct token *token,
5088 	    const char *str, unsigned int len,
5089 	    void *buf, unsigned int size)
5090 {
5091 	struct buffer *out = buf;
5092 
5093 	/* Token name must match. */
5094 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5095 		return -1;
5096 	/* Nothing else to do if there is no buffer. */
5097 	if (!out)
5098 		return len;
5099 	if (!out->command) {
5100 		if (ctx->curr != FLUSH)
5101 			return -1;
5102 		if (sizeof(*out) > size)
5103 			return -1;
5104 		out->command = ctx->curr;
5105 		ctx->objdata = 0;
5106 		ctx->object = out;
5107 		ctx->objmask = NULL;
5108 	}
5109 	return len;
5110 }
5111 
5112 /** Parse tokens for query command. */
5113 static int
5114 parse_query(struct context *ctx, const struct token *token,
5115 	    const char *str, unsigned int len,
5116 	    void *buf, unsigned int size)
5117 {
5118 	struct buffer *out = buf;
5119 
5120 	/* Token name must match. */
5121 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5122 		return -1;
5123 	/* Nothing else to do if there is no buffer. */
5124 	if (!out)
5125 		return len;
5126 	if (!out->command) {
5127 		if (ctx->curr != QUERY)
5128 			return -1;
5129 		if (sizeof(*out) > size)
5130 			return -1;
5131 		out->command = ctx->curr;
5132 		ctx->objdata = 0;
5133 		ctx->object = out;
5134 		ctx->objmask = NULL;
5135 	}
5136 	return len;
5137 }
5138 
5139 /** Parse action names. */
5140 static int
5141 parse_action(struct context *ctx, const struct token *token,
5142 	     const char *str, unsigned int len,
5143 	     void *buf, unsigned int size)
5144 {
5145 	struct buffer *out = buf;
5146 	const struct arg *arg = pop_args(ctx);
5147 	unsigned int i;
5148 
5149 	(void)size;
5150 	/* Argument is expected. */
5151 	if (!arg)
5152 		return -1;
5153 	/* Parse action name. */
5154 	for (i = 0; next_action[i]; ++i) {
5155 		const struct parse_action_priv *priv;
5156 
5157 		token = &token_list[next_action[i]];
5158 		if (strcmp_partial(token->name, str, len))
5159 			continue;
5160 		priv = token->priv;
5161 		if (!priv)
5162 			goto error;
5163 		if (out)
5164 			memcpy((uint8_t *)ctx->object + arg->offset,
5165 			       &priv->type,
5166 			       arg->size);
5167 		return len;
5168 	}
5169 error:
5170 	push_args(ctx, arg);
5171 	return -1;
5172 }
5173 
5174 /** Parse tokens for list command. */
5175 static int
5176 parse_list(struct context *ctx, const struct token *token,
5177 	   const char *str, unsigned int len,
5178 	   void *buf, unsigned int size)
5179 {
5180 	struct buffer *out = buf;
5181 
5182 	/* Token name must match. */
5183 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5184 		return -1;
5185 	/* Nothing else to do if there is no buffer. */
5186 	if (!out)
5187 		return len;
5188 	if (!out->command) {
5189 		if (ctx->curr != LIST)
5190 			return -1;
5191 		if (sizeof(*out) > size)
5192 			return -1;
5193 		out->command = ctx->curr;
5194 		ctx->objdata = 0;
5195 		ctx->object = out;
5196 		ctx->objmask = NULL;
5197 		out->args.list.group =
5198 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5199 					       sizeof(double));
5200 		return len;
5201 	}
5202 	if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
5203 	     sizeof(*out->args.list.group)) > (uint8_t *)out + size)
5204 		return -1;
5205 	ctx->objdata = 0;
5206 	ctx->object = out->args.list.group + out->args.list.group_n++;
5207 	ctx->objmask = NULL;
5208 	return len;
5209 }
5210 
5211 /** Parse tokens for isolate command. */
5212 static int
5213 parse_isolate(struct context *ctx, const struct token *token,
5214 	      const char *str, unsigned int len,
5215 	      void *buf, unsigned int size)
5216 {
5217 	struct buffer *out = buf;
5218 
5219 	/* Token name must match. */
5220 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5221 		return -1;
5222 	/* Nothing else to do if there is no buffer. */
5223 	if (!out)
5224 		return len;
5225 	if (!out->command) {
5226 		if (ctx->curr != ISOLATE)
5227 			return -1;
5228 		if (sizeof(*out) > size)
5229 			return -1;
5230 		out->command = ctx->curr;
5231 		ctx->objdata = 0;
5232 		ctx->object = out;
5233 		ctx->objmask = NULL;
5234 	}
5235 	return len;
5236 }
5237 
5238 /**
5239  * Parse signed/unsigned integers 8 to 64-bit long.
5240  *
5241  * Last argument (ctx->args) is retrieved to determine integer type and
5242  * storage location.
5243  */
5244 static int
5245 parse_int(struct context *ctx, const struct token *token,
5246 	  const char *str, unsigned int len,
5247 	  void *buf, unsigned int size)
5248 {
5249 	const struct arg *arg = pop_args(ctx);
5250 	uintmax_t u;
5251 	char *end;
5252 
5253 	(void)token;
5254 	/* Argument is expected. */
5255 	if (!arg)
5256 		return -1;
5257 	errno = 0;
5258 	u = arg->sign ?
5259 		(uintmax_t)strtoimax(str, &end, 0) :
5260 		strtoumax(str, &end, 0);
5261 	if (errno || (size_t)(end - str) != len)
5262 		goto error;
5263 	if (arg->bounded &&
5264 	    ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
5265 			    (intmax_t)u > (intmax_t)arg->max)) ||
5266 	     (!arg->sign && (u < arg->min || u > arg->max))))
5267 		goto error;
5268 	if (!ctx->object)
5269 		return len;
5270 	if (arg->mask) {
5271 		if (!arg_entry_bf_fill(ctx->object, u, arg) ||
5272 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
5273 			goto error;
5274 		return len;
5275 	}
5276 	buf = (uint8_t *)ctx->object + arg->offset;
5277 	size = arg->size;
5278 	if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
5279 		return -1;
5280 objmask:
5281 	switch (size) {
5282 	case sizeof(uint8_t):
5283 		*(uint8_t *)buf = u;
5284 		break;
5285 	case sizeof(uint16_t):
5286 		*(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
5287 		break;
5288 	case sizeof(uint8_t [3]):
5289 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5290 		if (!arg->hton) {
5291 			((uint8_t *)buf)[0] = u;
5292 			((uint8_t *)buf)[1] = u >> 8;
5293 			((uint8_t *)buf)[2] = u >> 16;
5294 			break;
5295 		}
5296 #endif
5297 		((uint8_t *)buf)[0] = u >> 16;
5298 		((uint8_t *)buf)[1] = u >> 8;
5299 		((uint8_t *)buf)[2] = u;
5300 		break;
5301 	case sizeof(uint32_t):
5302 		*(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
5303 		break;
5304 	case sizeof(uint64_t):
5305 		*(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
5306 		break;
5307 	default:
5308 		goto error;
5309 	}
5310 	if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
5311 		u = -1;
5312 		buf = (uint8_t *)ctx->objmask + arg->offset;
5313 		goto objmask;
5314 	}
5315 	return len;
5316 error:
5317 	push_args(ctx, arg);
5318 	return -1;
5319 }
5320 
5321 /**
5322  * Parse a string.
5323  *
5324  * Three arguments (ctx->args) are retrieved from the stack to store data,
5325  * its actual length and address (in that order).
5326  */
5327 static int
5328 parse_string(struct context *ctx, const struct token *token,
5329 	     const char *str, unsigned int len,
5330 	     void *buf, unsigned int size)
5331 {
5332 	const struct arg *arg_data = pop_args(ctx);
5333 	const struct arg *arg_len = pop_args(ctx);
5334 	const struct arg *arg_addr = pop_args(ctx);
5335 	char tmp[16]; /* Ought to be enough. */
5336 	int ret;
5337 
5338 	/* Arguments are expected. */
5339 	if (!arg_data)
5340 		return -1;
5341 	if (!arg_len) {
5342 		push_args(ctx, arg_data);
5343 		return -1;
5344 	}
5345 	if (!arg_addr) {
5346 		push_args(ctx, arg_len);
5347 		push_args(ctx, arg_data);
5348 		return -1;
5349 	}
5350 	size = arg_data->size;
5351 	/* Bit-mask fill is not supported. */
5352 	if (arg_data->mask || size < len)
5353 		goto error;
5354 	if (!ctx->object)
5355 		return len;
5356 	/* Let parse_int() fill length information first. */
5357 	ret = snprintf(tmp, sizeof(tmp), "%u", len);
5358 	if (ret < 0)
5359 		goto error;
5360 	push_args(ctx, arg_len);
5361 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
5362 	if (ret < 0) {
5363 		pop_args(ctx);
5364 		goto error;
5365 	}
5366 	buf = (uint8_t *)ctx->object + arg_data->offset;
5367 	/* Output buffer is not necessarily NUL-terminated. */
5368 	memcpy(buf, str, len);
5369 	memset((uint8_t *)buf + len, 0x00, size - len);
5370 	if (ctx->objmask)
5371 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
5372 	/* Save address if requested. */
5373 	if (arg_addr->size) {
5374 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
5375 		       (void *[]){
5376 			(uint8_t *)ctx->object + arg_data->offset
5377 		       },
5378 		       arg_addr->size);
5379 		if (ctx->objmask)
5380 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
5381 			       (void *[]){
5382 				(uint8_t *)ctx->objmask + arg_data->offset
5383 			       },
5384 			       arg_addr->size);
5385 	}
5386 	return len;
5387 error:
5388 	push_args(ctx, arg_addr);
5389 	push_args(ctx, arg_len);
5390 	push_args(ctx, arg_data);
5391 	return -1;
5392 }
5393 
5394 static int
5395 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
5396 {
5397 	char *c = NULL;
5398 	uint32_t i, len;
5399 	char tmp[3];
5400 
5401 	/* Check input parameters */
5402 	if ((src == NULL) ||
5403 		(dst == NULL) ||
5404 		(size == NULL) ||
5405 		(*size == 0))
5406 		return -1;
5407 
5408 	/* Convert chars to bytes */
5409 	for (i = 0, len = 0; i < *size; i += 2) {
5410 		snprintf(tmp, 3, "%s", src + i);
5411 		dst[len++] = strtoul(tmp, &c, 16);
5412 		if (*c != 0) {
5413 			len--;
5414 			dst[len] = 0;
5415 			*size = len;
5416 			return -1;
5417 		}
5418 	}
5419 	dst[len] = 0;
5420 	*size = len;
5421 
5422 	return 0;
5423 }
5424 
5425 static int
5426 parse_hex(struct context *ctx, const struct token *token,
5427 		const char *str, unsigned int len,
5428 		void *buf, unsigned int size)
5429 {
5430 	const struct arg *arg_data = pop_args(ctx);
5431 	const struct arg *arg_len = pop_args(ctx);
5432 	const struct arg *arg_addr = pop_args(ctx);
5433 	char tmp[16]; /* Ought to be enough. */
5434 	int ret;
5435 	unsigned int hexlen = len;
5436 	unsigned int length = 256;
5437 	uint8_t hex_tmp[length];
5438 
5439 	/* Arguments are expected. */
5440 	if (!arg_data)
5441 		return -1;
5442 	if (!arg_len) {
5443 		push_args(ctx, arg_data);
5444 		return -1;
5445 	}
5446 	if (!arg_addr) {
5447 		push_args(ctx, arg_len);
5448 		push_args(ctx, arg_data);
5449 		return -1;
5450 	}
5451 	size = arg_data->size;
5452 	/* Bit-mask fill is not supported. */
5453 	if (arg_data->mask)
5454 		goto error;
5455 	if (!ctx->object)
5456 		return len;
5457 
5458 	/* translate bytes string to array. */
5459 	if (str[0] == '0' && ((str[1] == 'x') ||
5460 			(str[1] == 'X'))) {
5461 		str += 2;
5462 		hexlen -= 2;
5463 	}
5464 	if (hexlen > length)
5465 		return -1;
5466 	ret = parse_hex_string(str, hex_tmp, &hexlen);
5467 	if (ret < 0)
5468 		goto error;
5469 	/* Let parse_int() fill length information first. */
5470 	ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
5471 	if (ret < 0)
5472 		goto error;
5473 	push_args(ctx, arg_len);
5474 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
5475 	if (ret < 0) {
5476 		pop_args(ctx);
5477 		goto error;
5478 	}
5479 	buf = (uint8_t *)ctx->object + arg_data->offset;
5480 	/* Output buffer is not necessarily NUL-terminated. */
5481 	memcpy(buf, hex_tmp, hexlen);
5482 	memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
5483 	if (ctx->objmask)
5484 		memset((uint8_t *)ctx->objmask + arg_data->offset,
5485 					0xff, hexlen);
5486 	/* Save address if requested. */
5487 	if (arg_addr->size) {
5488 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
5489 		       (void *[]){
5490 			(uint8_t *)ctx->object + arg_data->offset
5491 		       },
5492 		       arg_addr->size);
5493 		if (ctx->objmask)
5494 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
5495 			       (void *[]){
5496 				(uint8_t *)ctx->objmask + arg_data->offset
5497 			       },
5498 			       arg_addr->size);
5499 	}
5500 	return len;
5501 error:
5502 	push_args(ctx, arg_addr);
5503 	push_args(ctx, arg_len);
5504 	push_args(ctx, arg_data);
5505 	return -1;
5506 
5507 }
5508 
5509 /**
5510  * Parse a MAC address.
5511  *
5512  * Last argument (ctx->args) is retrieved to determine storage size and
5513  * location.
5514  */
5515 static int
5516 parse_mac_addr(struct context *ctx, const struct token *token,
5517 	       const char *str, unsigned int len,
5518 	       void *buf, unsigned int size)
5519 {
5520 	const struct arg *arg = pop_args(ctx);
5521 	struct rte_ether_addr tmp;
5522 	int ret;
5523 
5524 	(void)token;
5525 	/* Argument is expected. */
5526 	if (!arg)
5527 		return -1;
5528 	size = arg->size;
5529 	/* Bit-mask fill is not supported. */
5530 	if (arg->mask || size != sizeof(tmp))
5531 		goto error;
5532 	/* Only network endian is supported. */
5533 	if (!arg->hton)
5534 		goto error;
5535 	ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
5536 	if (ret < 0 || (unsigned int)ret != len)
5537 		goto error;
5538 	if (!ctx->object)
5539 		return len;
5540 	buf = (uint8_t *)ctx->object + arg->offset;
5541 	memcpy(buf, &tmp, size);
5542 	if (ctx->objmask)
5543 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
5544 	return len;
5545 error:
5546 	push_args(ctx, arg);
5547 	return -1;
5548 }
5549 
5550 /**
5551  * Parse an IPv4 address.
5552  *
5553  * Last argument (ctx->args) is retrieved to determine storage size and
5554  * location.
5555  */
5556 static int
5557 parse_ipv4_addr(struct context *ctx, const struct token *token,
5558 		const char *str, unsigned int len,
5559 		void *buf, unsigned int size)
5560 {
5561 	const struct arg *arg = pop_args(ctx);
5562 	char str2[len + 1];
5563 	struct in_addr tmp;
5564 	int ret;
5565 
5566 	/* Argument is expected. */
5567 	if (!arg)
5568 		return -1;
5569 	size = arg->size;
5570 	/* Bit-mask fill is not supported. */
5571 	if (arg->mask || size != sizeof(tmp))
5572 		goto error;
5573 	/* Only network endian is supported. */
5574 	if (!arg->hton)
5575 		goto error;
5576 	memcpy(str2, str, len);
5577 	str2[len] = '\0';
5578 	ret = inet_pton(AF_INET, str2, &tmp);
5579 	if (ret != 1) {
5580 		/* Attempt integer parsing. */
5581 		push_args(ctx, arg);
5582 		return parse_int(ctx, token, str, len, buf, size);
5583 	}
5584 	if (!ctx->object)
5585 		return len;
5586 	buf = (uint8_t *)ctx->object + arg->offset;
5587 	memcpy(buf, &tmp, size);
5588 	if (ctx->objmask)
5589 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
5590 	return len;
5591 error:
5592 	push_args(ctx, arg);
5593 	return -1;
5594 }
5595 
5596 /**
5597  * Parse an IPv6 address.
5598  *
5599  * Last argument (ctx->args) is retrieved to determine storage size and
5600  * location.
5601  */
5602 static int
5603 parse_ipv6_addr(struct context *ctx, const struct token *token,
5604 		const char *str, unsigned int len,
5605 		void *buf, unsigned int size)
5606 {
5607 	const struct arg *arg = pop_args(ctx);
5608 	char str2[len + 1];
5609 	struct in6_addr tmp;
5610 	int ret;
5611 
5612 	(void)token;
5613 	/* Argument is expected. */
5614 	if (!arg)
5615 		return -1;
5616 	size = arg->size;
5617 	/* Bit-mask fill is not supported. */
5618 	if (arg->mask || size != sizeof(tmp))
5619 		goto error;
5620 	/* Only network endian is supported. */
5621 	if (!arg->hton)
5622 		goto error;
5623 	memcpy(str2, str, len);
5624 	str2[len] = '\0';
5625 	ret = inet_pton(AF_INET6, str2, &tmp);
5626 	if (ret != 1)
5627 		goto error;
5628 	if (!ctx->object)
5629 		return len;
5630 	buf = (uint8_t *)ctx->object + arg->offset;
5631 	memcpy(buf, &tmp, size);
5632 	if (ctx->objmask)
5633 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
5634 	return len;
5635 error:
5636 	push_args(ctx, arg);
5637 	return -1;
5638 }
5639 
5640 /** Boolean values (even indices stand for false). */
5641 static const char *const boolean_name[] = {
5642 	"0", "1",
5643 	"false", "true",
5644 	"no", "yes",
5645 	"N", "Y",
5646 	"off", "on",
5647 	NULL,
5648 };
5649 
5650 /**
5651  * Parse a boolean value.
5652  *
5653  * Last argument (ctx->args) is retrieved to determine storage size and
5654  * location.
5655  */
5656 static int
5657 parse_boolean(struct context *ctx, const struct token *token,
5658 	      const char *str, unsigned int len,
5659 	      void *buf, unsigned int size)
5660 {
5661 	const struct arg *arg = pop_args(ctx);
5662 	unsigned int i;
5663 	int ret;
5664 
5665 	/* Argument is expected. */
5666 	if (!arg)
5667 		return -1;
5668 	for (i = 0; boolean_name[i]; ++i)
5669 		if (!strcmp_partial(boolean_name[i], str, len))
5670 			break;
5671 	/* Process token as integer. */
5672 	if (boolean_name[i])
5673 		str = i & 1 ? "1" : "0";
5674 	push_args(ctx, arg);
5675 	ret = parse_int(ctx, token, str, strlen(str), buf, size);
5676 	return ret > 0 ? (int)len : ret;
5677 }
5678 
5679 /** Parse port and update context. */
5680 static int
5681 parse_port(struct context *ctx, const struct token *token,
5682 	   const char *str, unsigned int len,
5683 	   void *buf, unsigned int size)
5684 {
5685 	struct buffer *out = &(struct buffer){ .port = 0 };
5686 	int ret;
5687 
5688 	if (buf)
5689 		out = buf;
5690 	else {
5691 		ctx->objdata = 0;
5692 		ctx->object = out;
5693 		ctx->objmask = NULL;
5694 		size = sizeof(*out);
5695 	}
5696 	ret = parse_int(ctx, token, str, len, out, size);
5697 	if (ret >= 0)
5698 		ctx->port = out->port;
5699 	if (!buf)
5700 		ctx->object = NULL;
5701 	return ret;
5702 }
5703 
5704 /** Parse set command, initialize output buffer for subsequent tokens. */
5705 static int
5706 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
5707 			  const char *str, unsigned int len,
5708 			  void *buf, unsigned int size)
5709 {
5710 	struct buffer *out = buf;
5711 
5712 	/* Token name must match. */
5713 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5714 		return -1;
5715 	/* Nothing else to do if there is no buffer. */
5716 	if (!out)
5717 		return len;
5718 	/* Make sure buffer is large enough. */
5719 	if (size < sizeof(*out))
5720 		return -1;
5721 	ctx->objdata = 0;
5722 	ctx->objmask = NULL;
5723 	ctx->object = out;
5724 	if (!out->command)
5725 		return -1;
5726 	out->command = ctx->curr;
5727 	return len;
5728 }
5729 
5730 /**
5731  * Parse set raw_encap/raw_decap command,
5732  * initialize output buffer for subsequent tokens.
5733  */
5734 static int
5735 parse_set_init(struct context *ctx, const struct token *token,
5736 	       const char *str, unsigned int len,
5737 	       void *buf, unsigned int size)
5738 {
5739 	struct buffer *out = buf;
5740 
5741 	/* Token name must match. */
5742 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5743 		return -1;
5744 	/* Nothing else to do if there is no buffer. */
5745 	if (!out)
5746 		return len;
5747 	/* Make sure buffer is large enough. */
5748 	if (size < sizeof(*out))
5749 		return -1;
5750 	/* Initialize buffer. */
5751 	memset(out, 0x00, sizeof(*out));
5752 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
5753 	ctx->objdata = 0;
5754 	ctx->object = out;
5755 	ctx->objmask = NULL;
5756 	if (!out->command) {
5757 		if (ctx->curr != SET)
5758 			return -1;
5759 		if (sizeof(*out) > size)
5760 			return -1;
5761 		out->command = ctx->curr;
5762 		out->args.vc.data = (uint8_t *)out + size;
5763 		/* All we need is pattern */
5764 		out->args.vc.pattern =
5765 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5766 					       sizeof(double));
5767 		ctx->object = out->args.vc.pattern;
5768 	}
5769 	return len;
5770 }
5771 
5772 /** No completion. */
5773 static int
5774 comp_none(struct context *ctx, const struct token *token,
5775 	  unsigned int ent, char *buf, unsigned int size)
5776 {
5777 	(void)ctx;
5778 	(void)token;
5779 	(void)ent;
5780 	(void)buf;
5781 	(void)size;
5782 	return 0;
5783 }
5784 
5785 /** Complete boolean values. */
5786 static int
5787 comp_boolean(struct context *ctx, const struct token *token,
5788 	     unsigned int ent, char *buf, unsigned int size)
5789 {
5790 	unsigned int i;
5791 
5792 	(void)ctx;
5793 	(void)token;
5794 	for (i = 0; boolean_name[i]; ++i)
5795 		if (buf && i == ent)
5796 			return strlcpy(buf, boolean_name[i], size);
5797 	if (buf)
5798 		return -1;
5799 	return i;
5800 }
5801 
5802 /** Complete action names. */
5803 static int
5804 comp_action(struct context *ctx, const struct token *token,
5805 	    unsigned int ent, char *buf, unsigned int size)
5806 {
5807 	unsigned int i;
5808 
5809 	(void)ctx;
5810 	(void)token;
5811 	for (i = 0; next_action[i]; ++i)
5812 		if (buf && i == ent)
5813 			return strlcpy(buf, token_list[next_action[i]].name,
5814 				       size);
5815 	if (buf)
5816 		return -1;
5817 	return i;
5818 }
5819 
5820 /** Complete available ports. */
5821 static int
5822 comp_port(struct context *ctx, const struct token *token,
5823 	  unsigned int ent, char *buf, unsigned int size)
5824 {
5825 	unsigned int i = 0;
5826 	portid_t p;
5827 
5828 	(void)ctx;
5829 	(void)token;
5830 	RTE_ETH_FOREACH_DEV(p) {
5831 		if (buf && i == ent)
5832 			return snprintf(buf, size, "%u", p);
5833 		++i;
5834 	}
5835 	if (buf)
5836 		return -1;
5837 	return i;
5838 }
5839 
5840 /** Complete available rule IDs. */
5841 static int
5842 comp_rule_id(struct context *ctx, const struct token *token,
5843 	     unsigned int ent, char *buf, unsigned int size)
5844 {
5845 	unsigned int i = 0;
5846 	struct rte_port *port;
5847 	struct port_flow *pf;
5848 
5849 	(void)token;
5850 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
5851 	    ctx->port == (portid_t)RTE_PORT_ALL)
5852 		return -1;
5853 	port = &ports[ctx->port];
5854 	for (pf = port->flow_list; pf != NULL; pf = pf->next) {
5855 		if (buf && i == ent)
5856 			return snprintf(buf, size, "%u", pf->id);
5857 		++i;
5858 	}
5859 	if (buf)
5860 		return -1;
5861 	return i;
5862 }
5863 
5864 /** Complete type field for RSS action. */
5865 static int
5866 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
5867 			unsigned int ent, char *buf, unsigned int size)
5868 {
5869 	unsigned int i;
5870 
5871 	(void)ctx;
5872 	(void)token;
5873 	for (i = 0; rss_type_table[i].str; ++i)
5874 		;
5875 	if (!buf)
5876 		return i + 1;
5877 	if (ent < i)
5878 		return strlcpy(buf, rss_type_table[ent].str, size);
5879 	if (ent == i)
5880 		return snprintf(buf, size, "end");
5881 	return -1;
5882 }
5883 
5884 /** Complete queue field for RSS action. */
5885 static int
5886 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
5887 			 unsigned int ent, char *buf, unsigned int size)
5888 {
5889 	(void)ctx;
5890 	(void)token;
5891 	if (!buf)
5892 		return nb_rxq + 1;
5893 	if (ent < nb_rxq)
5894 		return snprintf(buf, size, "%u", ent);
5895 	if (ent == nb_rxq)
5896 		return snprintf(buf, size, "end");
5897 	return -1;
5898 }
5899 
5900 /** Complete index number for set raw_encap/raw_decap commands. */
5901 static int
5902 comp_set_raw_index(struct context *ctx, const struct token *token,
5903 		   unsigned int ent, char *buf, unsigned int size)
5904 {
5905 	uint16_t idx = 0;
5906 	uint16_t nb = 0;
5907 
5908 	RTE_SET_USED(ctx);
5909 	RTE_SET_USED(token);
5910 	for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
5911 		if (buf && idx == ent)
5912 			return snprintf(buf, size, "%u", idx);
5913 		++nb;
5914 	}
5915 	return nb;
5916 }
5917 
5918 /** Internal context. */
5919 static struct context cmd_flow_context;
5920 
5921 /** Global parser instance (cmdline API). */
5922 cmdline_parse_inst_t cmd_flow;
5923 cmdline_parse_inst_t cmd_set_raw;
5924 
5925 /** Initialize context. */
5926 static void
5927 cmd_flow_context_init(struct context *ctx)
5928 {
5929 	/* A full memset() is not necessary. */
5930 	ctx->curr = ZERO;
5931 	ctx->prev = ZERO;
5932 	ctx->next_num = 0;
5933 	ctx->args_num = 0;
5934 	ctx->eol = 0;
5935 	ctx->last = 0;
5936 	ctx->port = 0;
5937 	ctx->objdata = 0;
5938 	ctx->object = NULL;
5939 	ctx->objmask = NULL;
5940 }
5941 
5942 /** Parse a token (cmdline API). */
5943 static int
5944 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
5945 	       unsigned int size)
5946 {
5947 	struct context *ctx = &cmd_flow_context;
5948 	const struct token *token;
5949 	const enum index *list;
5950 	int len;
5951 	int i;
5952 
5953 	(void)hdr;
5954 	token = &token_list[ctx->curr];
5955 	/* Check argument length. */
5956 	ctx->eol = 0;
5957 	ctx->last = 1;
5958 	for (len = 0; src[len]; ++len)
5959 		if (src[len] == '#' || isspace(src[len]))
5960 			break;
5961 	if (!len)
5962 		return -1;
5963 	/* Last argument and EOL detection. */
5964 	for (i = len; src[i]; ++i)
5965 		if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
5966 			break;
5967 		else if (!isspace(src[i])) {
5968 			ctx->last = 0;
5969 			break;
5970 		}
5971 	for (; src[i]; ++i)
5972 		if (src[i] == '\r' || src[i] == '\n') {
5973 			ctx->eol = 1;
5974 			break;
5975 		}
5976 	/* Initialize context if necessary. */
5977 	if (!ctx->next_num) {
5978 		if (!token->next)
5979 			return 0;
5980 		ctx->next[ctx->next_num++] = token->next[0];
5981 	}
5982 	/* Process argument through candidates. */
5983 	ctx->prev = ctx->curr;
5984 	list = ctx->next[ctx->next_num - 1];
5985 	for (i = 0; list[i]; ++i) {
5986 		const struct token *next = &token_list[list[i]];
5987 		int tmp;
5988 
5989 		ctx->curr = list[i];
5990 		if (next->call)
5991 			tmp = next->call(ctx, next, src, len, result, size);
5992 		else
5993 			tmp = parse_default(ctx, next, src, len, result, size);
5994 		if (tmp == -1 || tmp != len)
5995 			continue;
5996 		token = next;
5997 		break;
5998 	}
5999 	if (!list[i])
6000 		return -1;
6001 	--ctx->next_num;
6002 	/* Push subsequent tokens if any. */
6003 	if (token->next)
6004 		for (i = 0; token->next[i]; ++i) {
6005 			if (ctx->next_num == RTE_DIM(ctx->next))
6006 				return -1;
6007 			ctx->next[ctx->next_num++] = token->next[i];
6008 		}
6009 	/* Push arguments if any. */
6010 	if (token->args)
6011 		for (i = 0; token->args[i]; ++i) {
6012 			if (ctx->args_num == RTE_DIM(ctx->args))
6013 				return -1;
6014 			ctx->args[ctx->args_num++] = token->args[i];
6015 		}
6016 	return len;
6017 }
6018 
6019 /** Return number of completion entries (cmdline API). */
6020 static int
6021 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
6022 {
6023 	struct context *ctx = &cmd_flow_context;
6024 	const struct token *token = &token_list[ctx->curr];
6025 	const enum index *list;
6026 	int i;
6027 
6028 	(void)hdr;
6029 	/* Count number of tokens in current list. */
6030 	if (ctx->next_num)
6031 		list = ctx->next[ctx->next_num - 1];
6032 	else
6033 		list = token->next[0];
6034 	for (i = 0; list[i]; ++i)
6035 		;
6036 	if (!i)
6037 		return 0;
6038 	/*
6039 	 * If there is a single token, use its completion callback, otherwise
6040 	 * return the number of entries.
6041 	 */
6042 	token = &token_list[list[0]];
6043 	if (i == 1 && token->comp) {
6044 		/* Save index for cmd_flow_get_help(). */
6045 		ctx->prev = list[0];
6046 		return token->comp(ctx, token, 0, NULL, 0);
6047 	}
6048 	return i;
6049 }
6050 
6051 /** Return a completion entry (cmdline API). */
6052 static int
6053 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
6054 			  char *dst, unsigned int size)
6055 {
6056 	struct context *ctx = &cmd_flow_context;
6057 	const struct token *token = &token_list[ctx->curr];
6058 	const enum index *list;
6059 	int i;
6060 
6061 	(void)hdr;
6062 	/* Count number of tokens in current list. */
6063 	if (ctx->next_num)
6064 		list = ctx->next[ctx->next_num - 1];
6065 	else
6066 		list = token->next[0];
6067 	for (i = 0; list[i]; ++i)
6068 		;
6069 	if (!i)
6070 		return -1;
6071 	/* If there is a single token, use its completion callback. */
6072 	token = &token_list[list[0]];
6073 	if (i == 1 && token->comp) {
6074 		/* Save index for cmd_flow_get_help(). */
6075 		ctx->prev = list[0];
6076 		return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
6077 	}
6078 	/* Otherwise make sure the index is valid and use defaults. */
6079 	if (index >= i)
6080 		return -1;
6081 	token = &token_list[list[index]];
6082 	strlcpy(dst, token->name, size);
6083 	/* Save index for cmd_flow_get_help(). */
6084 	ctx->prev = list[index];
6085 	return 0;
6086 }
6087 
6088 /** Populate help strings for current token (cmdline API). */
6089 static int
6090 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
6091 {
6092 	struct context *ctx = &cmd_flow_context;
6093 	const struct token *token = &token_list[ctx->prev];
6094 
6095 	(void)hdr;
6096 	if (!size)
6097 		return -1;
6098 	/* Set token type and update global help with details. */
6099 	strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
6100 	if (token->help)
6101 		cmd_flow.help_str = token->help;
6102 	else
6103 		cmd_flow.help_str = token->name;
6104 	return 0;
6105 }
6106 
6107 /** Token definition template (cmdline API). */
6108 static struct cmdline_token_hdr cmd_flow_token_hdr = {
6109 	.ops = &(struct cmdline_token_ops){
6110 		.parse = cmd_flow_parse,
6111 		.complete_get_nb = cmd_flow_complete_get_nb,
6112 		.complete_get_elt = cmd_flow_complete_get_elt,
6113 		.get_help = cmd_flow_get_help,
6114 	},
6115 	.offset = 0,
6116 };
6117 
6118 /** Populate the next dynamic token. */
6119 static void
6120 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
6121 	     cmdline_parse_token_hdr_t **hdr_inst)
6122 {
6123 	struct context *ctx = &cmd_flow_context;
6124 
6125 	/* Always reinitialize context before requesting the first token. */
6126 	if (!(hdr_inst - cmd_flow.tokens))
6127 		cmd_flow_context_init(ctx);
6128 	/* Return NULL when no more tokens are expected. */
6129 	if (!ctx->next_num && ctx->curr) {
6130 		*hdr = NULL;
6131 		return;
6132 	}
6133 	/* Determine if command should end here. */
6134 	if (ctx->eol && ctx->last && ctx->next_num) {
6135 		const enum index *list = ctx->next[ctx->next_num - 1];
6136 		int i;
6137 
6138 		for (i = 0; list[i]; ++i) {
6139 			if (list[i] != END)
6140 				continue;
6141 			*hdr = NULL;
6142 			return;
6143 		}
6144 	}
6145 	*hdr = &cmd_flow_token_hdr;
6146 }
6147 
6148 /** Dispatch parsed buffer to function calls. */
6149 static void
6150 cmd_flow_parsed(const struct buffer *in)
6151 {
6152 	switch (in->command) {
6153 	case VALIDATE:
6154 		port_flow_validate(in->port, &in->args.vc.attr,
6155 				   in->args.vc.pattern, in->args.vc.actions);
6156 		break;
6157 	case CREATE:
6158 		port_flow_create(in->port, &in->args.vc.attr,
6159 				 in->args.vc.pattern, in->args.vc.actions);
6160 		break;
6161 	case DESTROY:
6162 		port_flow_destroy(in->port, in->args.destroy.rule_n,
6163 				  in->args.destroy.rule);
6164 		break;
6165 	case FLUSH:
6166 		port_flow_flush(in->port);
6167 		break;
6168 	case QUERY:
6169 		port_flow_query(in->port, in->args.query.rule,
6170 				&in->args.query.action);
6171 		break;
6172 	case LIST:
6173 		port_flow_list(in->port, in->args.list.group_n,
6174 			       in->args.list.group);
6175 		break;
6176 	case ISOLATE:
6177 		port_flow_isolate(in->port, in->args.isolate.set);
6178 		break;
6179 	default:
6180 		break;
6181 	}
6182 }
6183 
6184 /** Token generator and output processing callback (cmdline API). */
6185 static void
6186 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
6187 {
6188 	if (cl == NULL)
6189 		cmd_flow_tok(arg0, arg2);
6190 	else
6191 		cmd_flow_parsed(arg0);
6192 }
6193 
6194 /** Global parser instance (cmdline API). */
6195 cmdline_parse_inst_t cmd_flow = {
6196 	.f = cmd_flow_cb,
6197 	.data = NULL, /**< Unused. */
6198 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
6199 	.tokens = {
6200 		NULL,
6201 	}, /**< Tokens are returned by cmd_flow_tok(). */
6202 };
6203 
6204 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
6205 
6206 static void
6207 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
6208 {
6209 	struct rte_flow_item_ipv4 *ipv4;
6210 	struct rte_flow_item_eth *eth;
6211 	struct rte_flow_item_ipv6 *ipv6;
6212 	struct rte_flow_item_vxlan *vxlan;
6213 	struct rte_flow_item_vxlan_gpe *gpe;
6214 	struct rte_flow_item_nvgre *nvgre;
6215 	uint32_t ipv6_vtc_flow;
6216 
6217 	switch (item->type) {
6218 	case RTE_FLOW_ITEM_TYPE_ETH:
6219 		eth = (struct rte_flow_item_eth *)buf;
6220 		if (next_proto)
6221 			eth->type = rte_cpu_to_be_16(next_proto);
6222 		break;
6223 	case RTE_FLOW_ITEM_TYPE_IPV4:
6224 		ipv4 = (struct rte_flow_item_ipv4 *)buf;
6225 		ipv4->hdr.version_ihl = 0x45;
6226 		if (next_proto && ipv4->hdr.next_proto_id == 0)
6227 			ipv4->hdr.next_proto_id = (uint8_t)next_proto;
6228 		break;
6229 	case RTE_FLOW_ITEM_TYPE_IPV6:
6230 		ipv6 = (struct rte_flow_item_ipv6 *)buf;
6231 		if (next_proto && ipv6->hdr.proto == 0)
6232 			ipv6->hdr.proto = (uint8_t)next_proto;
6233 		ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->hdr.vtc_flow);
6234 		ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
6235 		ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
6236 		ipv6->hdr.vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
6237 		break;
6238 	case RTE_FLOW_ITEM_TYPE_VXLAN:
6239 		vxlan = (struct rte_flow_item_vxlan *)buf;
6240 		vxlan->flags = 0x08;
6241 		break;
6242 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
6243 		gpe = (struct rte_flow_item_vxlan_gpe *)buf;
6244 		gpe->flags = 0x0C;
6245 		break;
6246 	case RTE_FLOW_ITEM_TYPE_NVGRE:
6247 		nvgre = (struct rte_flow_item_nvgre *)buf;
6248 		nvgre->protocol = rte_cpu_to_be_16(0x6558);
6249 		nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
6250 		break;
6251 	default:
6252 		break;
6253 	}
6254 }
6255 
6256 /** Helper of get item's default mask. */
6257 static const void *
6258 flow_item_default_mask(const struct rte_flow_item *item)
6259 {
6260 	const void *mask = NULL;
6261 	static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
6262 
6263 	switch (item->type) {
6264 	case RTE_FLOW_ITEM_TYPE_ANY:
6265 		mask = &rte_flow_item_any_mask;
6266 		break;
6267 	case RTE_FLOW_ITEM_TYPE_VF:
6268 		mask = &rte_flow_item_vf_mask;
6269 		break;
6270 	case RTE_FLOW_ITEM_TYPE_PORT_ID:
6271 		mask = &rte_flow_item_port_id_mask;
6272 		break;
6273 	case RTE_FLOW_ITEM_TYPE_RAW:
6274 		mask = &rte_flow_item_raw_mask;
6275 		break;
6276 	case RTE_FLOW_ITEM_TYPE_ETH:
6277 		mask = &rte_flow_item_eth_mask;
6278 		break;
6279 	case RTE_FLOW_ITEM_TYPE_VLAN:
6280 		mask = &rte_flow_item_vlan_mask;
6281 		break;
6282 	case RTE_FLOW_ITEM_TYPE_IPV4:
6283 		mask = &rte_flow_item_ipv4_mask;
6284 		break;
6285 	case RTE_FLOW_ITEM_TYPE_IPV6:
6286 		mask = &rte_flow_item_ipv6_mask;
6287 		break;
6288 	case RTE_FLOW_ITEM_TYPE_ICMP:
6289 		mask = &rte_flow_item_icmp_mask;
6290 		break;
6291 	case RTE_FLOW_ITEM_TYPE_UDP:
6292 		mask = &rte_flow_item_udp_mask;
6293 		break;
6294 	case RTE_FLOW_ITEM_TYPE_TCP:
6295 		mask = &rte_flow_item_tcp_mask;
6296 		break;
6297 	case RTE_FLOW_ITEM_TYPE_SCTP:
6298 		mask = &rte_flow_item_sctp_mask;
6299 		break;
6300 	case RTE_FLOW_ITEM_TYPE_VXLAN:
6301 		mask = &rte_flow_item_vxlan_mask;
6302 		break;
6303 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
6304 		mask = &rte_flow_item_vxlan_gpe_mask;
6305 		break;
6306 	case RTE_FLOW_ITEM_TYPE_E_TAG:
6307 		mask = &rte_flow_item_e_tag_mask;
6308 		break;
6309 	case RTE_FLOW_ITEM_TYPE_NVGRE:
6310 		mask = &rte_flow_item_nvgre_mask;
6311 		break;
6312 	case RTE_FLOW_ITEM_TYPE_MPLS:
6313 		mask = &rte_flow_item_mpls_mask;
6314 		break;
6315 	case RTE_FLOW_ITEM_TYPE_GRE:
6316 		mask = &rte_flow_item_gre_mask;
6317 		break;
6318 	case RTE_FLOW_ITEM_TYPE_GRE_KEY:
6319 		mask = &gre_key_default_mask;
6320 		break;
6321 	case RTE_FLOW_ITEM_TYPE_META:
6322 		mask = &rte_flow_item_meta_mask;
6323 		break;
6324 	case RTE_FLOW_ITEM_TYPE_FUZZY:
6325 		mask = &rte_flow_item_fuzzy_mask;
6326 		break;
6327 	case RTE_FLOW_ITEM_TYPE_GTP:
6328 		mask = &rte_flow_item_gtp_mask;
6329 		break;
6330 	case RTE_FLOW_ITEM_TYPE_GTP_PSC:
6331 		mask = &rte_flow_item_gtp_psc_mask;
6332 		break;
6333 	case RTE_FLOW_ITEM_TYPE_GENEVE:
6334 		mask = &rte_flow_item_geneve_mask;
6335 		break;
6336 	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
6337 		mask = &rte_flow_item_pppoe_proto_id_mask;
6338 		break;
6339 	case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
6340 		mask = &rte_flow_item_l2tpv3oip_mask;
6341 		break;
6342 	case RTE_FLOW_ITEM_TYPE_ESP:
6343 		mask = &rte_flow_item_esp_mask;
6344 		break;
6345 	default:
6346 		break;
6347 	}
6348 	return mask;
6349 }
6350 
6351 
6352 
6353 /** Dispatch parsed buffer to function calls. */
6354 static void
6355 cmd_set_raw_parsed(const struct buffer *in)
6356 {
6357 	uint32_t n = in->args.vc.pattern_n;
6358 	int i = 0;
6359 	struct rte_flow_item *item = NULL;
6360 	size_t size = 0;
6361 	uint8_t *data = NULL;
6362 	uint8_t *data_tail = NULL;
6363 	size_t *total_size = NULL;
6364 	uint16_t upper_layer = 0;
6365 	uint16_t proto = 0;
6366 	uint16_t idx = in->port; /* We borrow port field as index */
6367 
6368 	RTE_ASSERT(in->command == SET_RAW_ENCAP ||
6369 		   in->command == SET_RAW_DECAP);
6370 	if (in->command == SET_RAW_ENCAP) {
6371 		total_size = &raw_encap_confs[idx].size;
6372 		data = (uint8_t *)&raw_encap_confs[idx].data;
6373 	} else {
6374 		total_size = &raw_decap_confs[idx].size;
6375 		data = (uint8_t *)&raw_decap_confs[idx].data;
6376 	}
6377 	*total_size = 0;
6378 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
6379 	/* process hdr from upper layer to low layer (L3/L4 -> L2). */
6380 	data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
6381 	for (i = n - 1 ; i >= 0; --i) {
6382 		item = in->args.vc.pattern + i;
6383 		if (item->spec == NULL)
6384 			item->spec = flow_item_default_mask(item);
6385 		switch (item->type) {
6386 		case RTE_FLOW_ITEM_TYPE_ETH:
6387 			size = sizeof(struct rte_flow_item_eth);
6388 			break;
6389 		case RTE_FLOW_ITEM_TYPE_VLAN:
6390 			size = sizeof(struct rte_flow_item_vlan);
6391 			proto = RTE_ETHER_TYPE_VLAN;
6392 			break;
6393 		case RTE_FLOW_ITEM_TYPE_IPV4:
6394 			size = sizeof(struct rte_flow_item_ipv4);
6395 			proto = RTE_ETHER_TYPE_IPV4;
6396 			break;
6397 		case RTE_FLOW_ITEM_TYPE_IPV6:
6398 			size = sizeof(struct rte_flow_item_ipv6);
6399 			proto = RTE_ETHER_TYPE_IPV6;
6400 			break;
6401 		case RTE_FLOW_ITEM_TYPE_UDP:
6402 			size = sizeof(struct rte_flow_item_udp);
6403 			proto = 0x11;
6404 			break;
6405 		case RTE_FLOW_ITEM_TYPE_TCP:
6406 			size = sizeof(struct rte_flow_item_tcp);
6407 			proto = 0x06;
6408 			break;
6409 		case RTE_FLOW_ITEM_TYPE_VXLAN:
6410 			size = sizeof(struct rte_flow_item_vxlan);
6411 			break;
6412 		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
6413 			size = sizeof(struct rte_flow_item_vxlan_gpe);
6414 			break;
6415 		case RTE_FLOW_ITEM_TYPE_GRE:
6416 			size = sizeof(struct rte_flow_item_gre);
6417 			proto = 0x2F;
6418 			break;
6419 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
6420 			size = sizeof(rte_be32_t);
6421 			proto = 0x0;
6422 			break;
6423 		case RTE_FLOW_ITEM_TYPE_MPLS:
6424 			size = sizeof(struct rte_flow_item_mpls);
6425 			proto = 0x0;
6426 			break;
6427 		case RTE_FLOW_ITEM_TYPE_NVGRE:
6428 			size = sizeof(struct rte_flow_item_nvgre);
6429 			proto = 0x2F;
6430 			break;
6431 		case RTE_FLOW_ITEM_TYPE_GENEVE:
6432 			size = sizeof(struct rte_flow_item_geneve);
6433 			break;
6434 		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
6435 			size = sizeof(struct rte_flow_item_l2tpv3oip);
6436 			proto = 0x73;
6437 			break;
6438 		case RTE_FLOW_ITEM_TYPE_ESP:
6439 			size = sizeof(struct rte_flow_item_esp);
6440 			proto = 0x32;
6441 			break;
6442 		default:
6443 			printf("Error - Not supported item\n");
6444 			*total_size = 0;
6445 			memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
6446 			return;
6447 		}
6448 		*total_size += size;
6449 		rte_memcpy(data_tail - (*total_size), item->spec, size);
6450 		/* update some fields which cannot be set by cmdline */
6451 		update_fields((data_tail - (*total_size)), item,
6452 			      upper_layer);
6453 		upper_layer = proto;
6454 	}
6455 	if (verbose_level & 0x1)
6456 		printf("total data size is %zu\n", (*total_size));
6457 	RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
6458 	memmove(data, (data_tail - (*total_size)), *total_size);
6459 }
6460 
6461 /** Populate help strings for current token (cmdline API). */
6462 static int
6463 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
6464 		     unsigned int size)
6465 {
6466 	struct context *ctx = &cmd_flow_context;
6467 	const struct token *token = &token_list[ctx->prev];
6468 
6469 	(void)hdr;
6470 	if (!size)
6471 		return -1;
6472 	/* Set token type and update global help with details. */
6473 	snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
6474 	if (token->help)
6475 		cmd_set_raw.help_str = token->help;
6476 	else
6477 		cmd_set_raw.help_str = token->name;
6478 	return 0;
6479 }
6480 
6481 /** Token definition template (cmdline API). */
6482 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
6483 	.ops = &(struct cmdline_token_ops){
6484 		.parse = cmd_flow_parse,
6485 		.complete_get_nb = cmd_flow_complete_get_nb,
6486 		.complete_get_elt = cmd_flow_complete_get_elt,
6487 		.get_help = cmd_set_raw_get_help,
6488 	},
6489 	.offset = 0,
6490 };
6491 
6492 /** Populate the next dynamic token. */
6493 static void
6494 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
6495 	     cmdline_parse_token_hdr_t **hdr_inst)
6496 {
6497 	struct context *ctx = &cmd_flow_context;
6498 
6499 	/* Always reinitialize context before requesting the first token. */
6500 	if (!(hdr_inst - cmd_set_raw.tokens)) {
6501 		cmd_flow_context_init(ctx);
6502 		ctx->curr = START_SET;
6503 	}
6504 	/* Return NULL when no more tokens are expected. */
6505 	if (!ctx->next_num && (ctx->curr != START_SET)) {
6506 		*hdr = NULL;
6507 		return;
6508 	}
6509 	/* Determine if command should end here. */
6510 	if (ctx->eol && ctx->last && ctx->next_num) {
6511 		const enum index *list = ctx->next[ctx->next_num - 1];
6512 		int i;
6513 
6514 		for (i = 0; list[i]; ++i) {
6515 			if (list[i] != END)
6516 				continue;
6517 			*hdr = NULL;
6518 			return;
6519 		}
6520 	}
6521 	*hdr = &cmd_set_raw_token_hdr;
6522 }
6523 
6524 /** Token generator and output processing callback (cmdline API). */
6525 static void
6526 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
6527 {
6528 	if (cl == NULL)
6529 		cmd_set_raw_tok(arg0, arg2);
6530 	else
6531 		cmd_set_raw_parsed(arg0);
6532 }
6533 
6534 /** Global parser instance (cmdline API). */
6535 cmdline_parse_inst_t cmd_set_raw = {
6536 	.f = cmd_set_raw_cb,
6537 	.data = NULL, /**< Unused. */
6538 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
6539 	.tokens = {
6540 		NULL,
6541 	}, /**< Tokens are returned by cmd_flow_tok(). */
6542 };
6543 
6544 /* *** display raw_encap/raw_decap buf */
6545 struct cmd_show_set_raw_result {
6546 	cmdline_fixed_string_t cmd_show;
6547 	cmdline_fixed_string_t cmd_what;
6548 	cmdline_fixed_string_t cmd_all;
6549 	uint16_t cmd_index;
6550 };
6551 
6552 static void
6553 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
6554 {
6555 	struct cmd_show_set_raw_result *res = parsed_result;
6556 	uint16_t index = res->cmd_index;
6557 	uint8_t all = 0;
6558 	uint8_t *raw_data = NULL;
6559 	size_t raw_size = 0;
6560 	char title[16] = {0};
6561 
6562 	RTE_SET_USED(cl);
6563 	RTE_SET_USED(data);
6564 	if (!strcmp(res->cmd_all, "all")) {
6565 		all = 1;
6566 		index = 0;
6567 	} else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
6568 		printf("index should be 0-%u\n", RAW_ENCAP_CONFS_MAX_NUM - 1);
6569 		return;
6570 	}
6571 	do {
6572 		if (!strcmp(res->cmd_what, "raw_encap")) {
6573 			raw_data = (uint8_t *)&raw_encap_confs[index].data;
6574 			raw_size = raw_encap_confs[index].size;
6575 			snprintf(title, 16, "\nindex: %u", index);
6576 			rte_hexdump(stdout, title, raw_data, raw_size);
6577 		} else {
6578 			raw_data = (uint8_t *)&raw_decap_confs[index].data;
6579 			raw_size = raw_decap_confs[index].size;
6580 			snprintf(title, 16, "\nindex: %u", index);
6581 			rte_hexdump(stdout, title, raw_data, raw_size);
6582 		}
6583 	} while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
6584 }
6585 
6586 cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
6587 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
6588 			cmd_show, "show");
6589 cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
6590 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
6591 			cmd_what, "raw_encap#raw_decap");
6592 cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
6593 	TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
6594 			cmd_index, UINT16);
6595 cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
6596 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
6597 			cmd_all, "all");
6598 cmdline_parse_inst_t cmd_show_set_raw = {
6599 	.f = cmd_show_set_raw_parsed,
6600 	.data = NULL,
6601 	.help_str = "show <raw_encap|raw_decap> <index>",
6602 	.tokens = {
6603 		(void *)&cmd_show_set_raw_cmd_show,
6604 		(void *)&cmd_show_set_raw_cmd_what,
6605 		(void *)&cmd_show_set_raw_cmd_index,
6606 		NULL,
6607 	},
6608 };
6609 cmdline_parse_inst_t cmd_show_set_raw_all = {
6610 	.f = cmd_show_set_raw_parsed,
6611 	.data = NULL,
6612 	.help_str = "show <raw_encap|raw_decap> all",
6613 	.tokens = {
6614 		(void *)&cmd_show_set_raw_cmd_show,
6615 		(void *)&cmd_show_set_raw_cmd_what,
6616 		(void *)&cmd_show_set_raw_cmd_all,
6617 		NULL,
6618 	},
6619 };
6620