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