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