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