xref: /dpdk/app/test-pmd/cmdline_flow.c (revision ac8d22de2394e03ba4a77d8fd24381147aafb1d3)
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_common.h>
17 #include <rte_ethdev.h>
18 #include <rte_byteorder.h>
19 #include <cmdline_parse.h>
20 #include <cmdline_parse_etheraddr.h>
21 #include <rte_flow.h>
22 
23 #include "testpmd.h"
24 
25 /** Parser token indices. */
26 enum index {
27 	/* Special tokens. */
28 	ZERO = 0,
29 	END,
30 
31 	/* Common tokens. */
32 	INTEGER,
33 	UNSIGNED,
34 	PREFIX,
35 	BOOLEAN,
36 	STRING,
37 	MAC_ADDR,
38 	IPV4_ADDR,
39 	IPV6_ADDR,
40 	RULE_ID,
41 	PORT_ID,
42 	GROUP_ID,
43 	PRIORITY_LEVEL,
44 
45 	/* Top-level command. */
46 	FLOW,
47 
48 	/* Sub-level commands. */
49 	VALIDATE,
50 	CREATE,
51 	DESTROY,
52 	FLUSH,
53 	QUERY,
54 	LIST,
55 	ISOLATE,
56 
57 	/* Destroy arguments. */
58 	DESTROY_RULE,
59 
60 	/* Query arguments. */
61 	QUERY_ACTION,
62 
63 	/* List arguments. */
64 	LIST_GROUP,
65 
66 	/* Validate/create arguments. */
67 	GROUP,
68 	PRIORITY,
69 	INGRESS,
70 	EGRESS,
71 
72 	/* Validate/create pattern. */
73 	PATTERN,
74 	ITEM_PARAM_IS,
75 	ITEM_PARAM_SPEC,
76 	ITEM_PARAM_LAST,
77 	ITEM_PARAM_MASK,
78 	ITEM_PARAM_PREFIX,
79 	ITEM_NEXT,
80 	ITEM_END,
81 	ITEM_VOID,
82 	ITEM_INVERT,
83 	ITEM_ANY,
84 	ITEM_ANY_NUM,
85 	ITEM_PF,
86 	ITEM_VF,
87 	ITEM_VF_ID,
88 	ITEM_PORT,
89 	ITEM_PORT_INDEX,
90 	ITEM_RAW,
91 	ITEM_RAW_RELATIVE,
92 	ITEM_RAW_SEARCH,
93 	ITEM_RAW_OFFSET,
94 	ITEM_RAW_LIMIT,
95 	ITEM_RAW_PATTERN,
96 	ITEM_ETH,
97 	ITEM_ETH_DST,
98 	ITEM_ETH_SRC,
99 	ITEM_ETH_TYPE,
100 	ITEM_VLAN,
101 	ITEM_VLAN_TPID,
102 	ITEM_VLAN_TCI,
103 	ITEM_VLAN_PCP,
104 	ITEM_VLAN_DEI,
105 	ITEM_VLAN_VID,
106 	ITEM_IPV4,
107 	ITEM_IPV4_TOS,
108 	ITEM_IPV4_TTL,
109 	ITEM_IPV4_PROTO,
110 	ITEM_IPV4_SRC,
111 	ITEM_IPV4_DST,
112 	ITEM_IPV6,
113 	ITEM_IPV6_TC,
114 	ITEM_IPV6_FLOW,
115 	ITEM_IPV6_PROTO,
116 	ITEM_IPV6_HOP,
117 	ITEM_IPV6_SRC,
118 	ITEM_IPV6_DST,
119 	ITEM_ICMP,
120 	ITEM_ICMP_TYPE,
121 	ITEM_ICMP_CODE,
122 	ITEM_UDP,
123 	ITEM_UDP_SRC,
124 	ITEM_UDP_DST,
125 	ITEM_TCP,
126 	ITEM_TCP_SRC,
127 	ITEM_TCP_DST,
128 	ITEM_TCP_FLAGS,
129 	ITEM_SCTP,
130 	ITEM_SCTP_SRC,
131 	ITEM_SCTP_DST,
132 	ITEM_SCTP_TAG,
133 	ITEM_SCTP_CKSUM,
134 	ITEM_VXLAN,
135 	ITEM_VXLAN_VNI,
136 	ITEM_E_TAG,
137 	ITEM_E_TAG_GRP_ECID_B,
138 	ITEM_NVGRE,
139 	ITEM_NVGRE_TNI,
140 	ITEM_MPLS,
141 	ITEM_MPLS_LABEL,
142 	ITEM_GRE,
143 	ITEM_GRE_PROTO,
144 	ITEM_FUZZY,
145 	ITEM_FUZZY_THRESH,
146 	ITEM_GTP,
147 	ITEM_GTP_TEID,
148 	ITEM_GTPC,
149 	ITEM_GTPU,
150 	ITEM_GENEVE,
151 	ITEM_GENEVE_VNI,
152 	ITEM_GENEVE_PROTO,
153 
154 	/* Validate/create actions. */
155 	ACTIONS,
156 	ACTION_NEXT,
157 	ACTION_END,
158 	ACTION_VOID,
159 	ACTION_PASSTHRU,
160 	ACTION_MARK,
161 	ACTION_MARK_ID,
162 	ACTION_FLAG,
163 	ACTION_QUEUE,
164 	ACTION_QUEUE_INDEX,
165 	ACTION_DROP,
166 	ACTION_COUNT,
167 	ACTION_RSS,
168 	ACTION_RSS_TYPES,
169 	ACTION_RSS_TYPE,
170 	ACTION_RSS_KEY,
171 	ACTION_RSS_KEY_LEN,
172 	ACTION_RSS_QUEUES,
173 	ACTION_RSS_QUEUE,
174 	ACTION_PF,
175 	ACTION_VF,
176 	ACTION_VF_ORIGINAL,
177 	ACTION_VF_ID,
178 	ACTION_METER,
179 	ACTION_METER_ID,
180 };
181 
182 /** Maximum size for pattern in struct rte_flow_item_raw. */
183 #define ITEM_RAW_PATTERN_SIZE 40
184 
185 /** Storage size for struct rte_flow_item_raw including pattern. */
186 #define ITEM_RAW_SIZE \
187 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
188 
189 /** Maximum number of queue indices in struct rte_flow_action_rss. */
190 #define ACTION_RSS_QUEUE_NUM 32
191 
192 /** Storage for struct rte_flow_action_rss including external data. */
193 struct action_rss_data {
194 	struct rte_flow_action_rss conf;
195 	uint8_t key[RSS_HASH_KEY_LENGTH];
196 	uint16_t queue[ACTION_RSS_QUEUE_NUM];
197 };
198 
199 /** Maximum number of subsequent tokens and arguments on the stack. */
200 #define CTX_STACK_SIZE 16
201 
202 /** Parser context. */
203 struct context {
204 	/** Stack of subsequent token lists to process. */
205 	const enum index *next[CTX_STACK_SIZE];
206 	/** Arguments for stacked tokens. */
207 	const void *args[CTX_STACK_SIZE];
208 	enum index curr; /**< Current token index. */
209 	enum index prev; /**< Index of the last token seen. */
210 	int next_num; /**< Number of entries in next[]. */
211 	int args_num; /**< Number of entries in args[]. */
212 	uint32_t eol:1; /**< EOL has been detected. */
213 	uint32_t last:1; /**< No more arguments. */
214 	portid_t port; /**< Current port ID (for completions). */
215 	uint32_t objdata; /**< Object-specific data. */
216 	void *object; /**< Address of current object for relative offsets. */
217 	void *objmask; /**< Object a full mask must be written to. */
218 };
219 
220 /** Token argument. */
221 struct arg {
222 	uint32_t hton:1; /**< Use network byte ordering. */
223 	uint32_t sign:1; /**< Value is signed. */
224 	uint32_t bounded:1; /**< Value is bounded. */
225 	uintmax_t min; /**< Minimum value if bounded. */
226 	uintmax_t max; /**< Maximum value if bounded. */
227 	uint32_t offset; /**< Relative offset from ctx->object. */
228 	uint32_t size; /**< Field size. */
229 	const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
230 };
231 
232 /** Parser token definition. */
233 struct token {
234 	/** Type displayed during completion (defaults to "TOKEN"). */
235 	const char *type;
236 	/** Help displayed during completion (defaults to token name). */
237 	const char *help;
238 	/** Private data used by parser functions. */
239 	const void *priv;
240 	/**
241 	 * Lists of subsequent tokens to push on the stack. Each call to the
242 	 * parser consumes the last entry of that stack.
243 	 */
244 	const enum index *const *next;
245 	/** Arguments stack for subsequent tokens that need them. */
246 	const struct arg *const *args;
247 	/**
248 	 * Token-processing callback, returns -1 in case of error, the
249 	 * length of the matched string otherwise. If NULL, attempts to
250 	 * match the token name.
251 	 *
252 	 * If buf is not NULL, the result should be stored in it according
253 	 * to context. An error is returned if not large enough.
254 	 */
255 	int (*call)(struct context *ctx, const struct token *token,
256 		    const char *str, unsigned int len,
257 		    void *buf, unsigned int size);
258 	/**
259 	 * Callback that provides possible values for this token, used for
260 	 * completion. Returns -1 in case of error, the number of possible
261 	 * values otherwise. If NULL, the token name is used.
262 	 *
263 	 * If buf is not NULL, entry index ent is written to buf and the
264 	 * full length of the entry is returned (same behavior as
265 	 * snprintf()).
266 	 */
267 	int (*comp)(struct context *ctx, const struct token *token,
268 		    unsigned int ent, char *buf, unsigned int size);
269 	/** Mandatory token name, no default value. */
270 	const char *name;
271 };
272 
273 /** Static initializer for the next field. */
274 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
275 
276 /** Static initializer for a NEXT() entry. */
277 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
278 
279 /** Static initializer for the args field. */
280 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
281 
282 /** Static initializer for ARGS() to target a field. */
283 #define ARGS_ENTRY(s, f) \
284 	(&(const struct arg){ \
285 		.offset = offsetof(s, f), \
286 		.size = sizeof(((s *)0)->f), \
287 	})
288 
289 /** Static initializer for ARGS() to target a bit-field. */
290 #define ARGS_ENTRY_BF(s, f, b) \
291 	(&(const struct arg){ \
292 		.size = sizeof(s), \
293 		.mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
294 	})
295 
296 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
297 #define ARGS_ENTRY_MASK(s, f, m) \
298 	(&(const struct arg){ \
299 		.offset = offsetof(s, f), \
300 		.size = sizeof(((s *)0)->f), \
301 		.mask = (const void *)(m), \
302 	})
303 
304 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
305 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
306 	(&(const struct arg){ \
307 		.hton = 1, \
308 		.offset = offsetof(s, f), \
309 		.size = sizeof(((s *)0)->f), \
310 		.mask = (const void *)(m), \
311 	})
312 
313 /** Static initializer for ARGS() to target a pointer. */
314 #define ARGS_ENTRY_PTR(s, f) \
315 	(&(const struct arg){ \
316 		.size = sizeof(*((s *)0)->f), \
317 	})
318 
319 /** Static initializer for ARGS() with arbitrary offset and size. */
320 #define ARGS_ENTRY_ARB(o, s) \
321 	(&(const struct arg){ \
322 		.offset = (o), \
323 		.size = (s), \
324 	})
325 
326 /** Same as ARGS_ENTRY_ARB() with bounded values. */
327 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
328 	(&(const struct arg){ \
329 		.bounded = 1, \
330 		.min = (i), \
331 		.max = (a), \
332 		.offset = (o), \
333 		.size = (s), \
334 	})
335 
336 /** Same as ARGS_ENTRY() using network byte ordering. */
337 #define ARGS_ENTRY_HTON(s, f) \
338 	(&(const struct arg){ \
339 		.hton = 1, \
340 		.offset = offsetof(s, f), \
341 		.size = sizeof(((s *)0)->f), \
342 	})
343 
344 /** Parser output buffer layout expected by cmd_flow_parsed(). */
345 struct buffer {
346 	enum index command; /**< Flow command. */
347 	portid_t port; /**< Affected port ID. */
348 	union {
349 		struct {
350 			struct rte_flow_attr attr;
351 			struct rte_flow_item *pattern;
352 			struct rte_flow_action *actions;
353 			uint32_t pattern_n;
354 			uint32_t actions_n;
355 			uint8_t *data;
356 		} vc; /**< Validate/create arguments. */
357 		struct {
358 			uint32_t *rule;
359 			uint32_t rule_n;
360 		} destroy; /**< Destroy arguments. */
361 		struct {
362 			uint32_t rule;
363 			enum rte_flow_action_type action;
364 		} query; /**< Query arguments. */
365 		struct {
366 			uint32_t *group;
367 			uint32_t group_n;
368 		} list; /**< List arguments. */
369 		struct {
370 			int set;
371 		} isolate; /**< Isolated mode arguments. */
372 	} args; /**< Command arguments. */
373 };
374 
375 /** Private data for pattern items. */
376 struct parse_item_priv {
377 	enum rte_flow_item_type type; /**< Item type. */
378 	uint32_t size; /**< Size of item specification structure. */
379 };
380 
381 #define PRIV_ITEM(t, s) \
382 	(&(const struct parse_item_priv){ \
383 		.type = RTE_FLOW_ITEM_TYPE_ ## t, \
384 		.size = s, \
385 	})
386 
387 /** Private data for actions. */
388 struct parse_action_priv {
389 	enum rte_flow_action_type type; /**< Action type. */
390 	uint32_t size; /**< Size of action configuration structure. */
391 };
392 
393 #define PRIV_ACTION(t, s) \
394 	(&(const struct parse_action_priv){ \
395 		.type = RTE_FLOW_ACTION_TYPE_ ## t, \
396 		.size = s, \
397 	})
398 
399 static const enum index next_vc_attr[] = {
400 	GROUP,
401 	PRIORITY,
402 	INGRESS,
403 	EGRESS,
404 	PATTERN,
405 	ZERO,
406 };
407 
408 static const enum index next_destroy_attr[] = {
409 	DESTROY_RULE,
410 	END,
411 	ZERO,
412 };
413 
414 static const enum index next_list_attr[] = {
415 	LIST_GROUP,
416 	END,
417 	ZERO,
418 };
419 
420 static const enum index item_param[] = {
421 	ITEM_PARAM_IS,
422 	ITEM_PARAM_SPEC,
423 	ITEM_PARAM_LAST,
424 	ITEM_PARAM_MASK,
425 	ITEM_PARAM_PREFIX,
426 	ZERO,
427 };
428 
429 static const enum index next_item[] = {
430 	ITEM_END,
431 	ITEM_VOID,
432 	ITEM_INVERT,
433 	ITEM_ANY,
434 	ITEM_PF,
435 	ITEM_VF,
436 	ITEM_PORT,
437 	ITEM_RAW,
438 	ITEM_ETH,
439 	ITEM_VLAN,
440 	ITEM_IPV4,
441 	ITEM_IPV6,
442 	ITEM_ICMP,
443 	ITEM_UDP,
444 	ITEM_TCP,
445 	ITEM_SCTP,
446 	ITEM_VXLAN,
447 	ITEM_E_TAG,
448 	ITEM_NVGRE,
449 	ITEM_MPLS,
450 	ITEM_GRE,
451 	ITEM_FUZZY,
452 	ITEM_GTP,
453 	ITEM_GTPC,
454 	ITEM_GTPU,
455 	ITEM_GENEVE,
456 	ZERO,
457 };
458 
459 static const enum index item_fuzzy[] = {
460 	ITEM_FUZZY_THRESH,
461 	ITEM_NEXT,
462 	ZERO,
463 };
464 
465 static const enum index item_any[] = {
466 	ITEM_ANY_NUM,
467 	ITEM_NEXT,
468 	ZERO,
469 };
470 
471 static const enum index item_vf[] = {
472 	ITEM_VF_ID,
473 	ITEM_NEXT,
474 	ZERO,
475 };
476 
477 static const enum index item_port[] = {
478 	ITEM_PORT_INDEX,
479 	ITEM_NEXT,
480 	ZERO,
481 };
482 
483 static const enum index item_raw[] = {
484 	ITEM_RAW_RELATIVE,
485 	ITEM_RAW_SEARCH,
486 	ITEM_RAW_OFFSET,
487 	ITEM_RAW_LIMIT,
488 	ITEM_RAW_PATTERN,
489 	ITEM_NEXT,
490 	ZERO,
491 };
492 
493 static const enum index item_eth[] = {
494 	ITEM_ETH_DST,
495 	ITEM_ETH_SRC,
496 	ITEM_ETH_TYPE,
497 	ITEM_NEXT,
498 	ZERO,
499 };
500 
501 static const enum index item_vlan[] = {
502 	ITEM_VLAN_TPID,
503 	ITEM_VLAN_TCI,
504 	ITEM_VLAN_PCP,
505 	ITEM_VLAN_DEI,
506 	ITEM_VLAN_VID,
507 	ITEM_NEXT,
508 	ZERO,
509 };
510 
511 static const enum index item_ipv4[] = {
512 	ITEM_IPV4_TOS,
513 	ITEM_IPV4_TTL,
514 	ITEM_IPV4_PROTO,
515 	ITEM_IPV4_SRC,
516 	ITEM_IPV4_DST,
517 	ITEM_NEXT,
518 	ZERO,
519 };
520 
521 static const enum index item_ipv6[] = {
522 	ITEM_IPV6_TC,
523 	ITEM_IPV6_FLOW,
524 	ITEM_IPV6_PROTO,
525 	ITEM_IPV6_HOP,
526 	ITEM_IPV6_SRC,
527 	ITEM_IPV6_DST,
528 	ITEM_NEXT,
529 	ZERO,
530 };
531 
532 static const enum index item_icmp[] = {
533 	ITEM_ICMP_TYPE,
534 	ITEM_ICMP_CODE,
535 	ITEM_NEXT,
536 	ZERO,
537 };
538 
539 static const enum index item_udp[] = {
540 	ITEM_UDP_SRC,
541 	ITEM_UDP_DST,
542 	ITEM_NEXT,
543 	ZERO,
544 };
545 
546 static const enum index item_tcp[] = {
547 	ITEM_TCP_SRC,
548 	ITEM_TCP_DST,
549 	ITEM_TCP_FLAGS,
550 	ITEM_NEXT,
551 	ZERO,
552 };
553 
554 static const enum index item_sctp[] = {
555 	ITEM_SCTP_SRC,
556 	ITEM_SCTP_DST,
557 	ITEM_SCTP_TAG,
558 	ITEM_SCTP_CKSUM,
559 	ITEM_NEXT,
560 	ZERO,
561 };
562 
563 static const enum index item_vxlan[] = {
564 	ITEM_VXLAN_VNI,
565 	ITEM_NEXT,
566 	ZERO,
567 };
568 
569 static const enum index item_e_tag[] = {
570 	ITEM_E_TAG_GRP_ECID_B,
571 	ITEM_NEXT,
572 	ZERO,
573 };
574 
575 static const enum index item_nvgre[] = {
576 	ITEM_NVGRE_TNI,
577 	ITEM_NEXT,
578 	ZERO,
579 };
580 
581 static const enum index item_mpls[] = {
582 	ITEM_MPLS_LABEL,
583 	ITEM_NEXT,
584 	ZERO,
585 };
586 
587 static const enum index item_gre[] = {
588 	ITEM_GRE_PROTO,
589 	ITEM_NEXT,
590 	ZERO,
591 };
592 
593 static const enum index item_gtp[] = {
594 	ITEM_GTP_TEID,
595 	ITEM_NEXT,
596 	ZERO,
597 };
598 
599 static const enum index item_geneve[] = {
600 	ITEM_GENEVE_VNI,
601 	ITEM_GENEVE_PROTO,
602 	ITEM_NEXT,
603 	ZERO,
604 };
605 
606 static const enum index next_action[] = {
607 	ACTION_END,
608 	ACTION_VOID,
609 	ACTION_PASSTHRU,
610 	ACTION_MARK,
611 	ACTION_FLAG,
612 	ACTION_QUEUE,
613 	ACTION_DROP,
614 	ACTION_COUNT,
615 	ACTION_RSS,
616 	ACTION_PF,
617 	ACTION_VF,
618 	ACTION_METER,
619 	ZERO,
620 };
621 
622 static const enum index action_mark[] = {
623 	ACTION_MARK_ID,
624 	ACTION_NEXT,
625 	ZERO,
626 };
627 
628 static const enum index action_queue[] = {
629 	ACTION_QUEUE_INDEX,
630 	ACTION_NEXT,
631 	ZERO,
632 };
633 
634 static const enum index action_rss[] = {
635 	ACTION_RSS_TYPES,
636 	ACTION_RSS_KEY,
637 	ACTION_RSS_KEY_LEN,
638 	ACTION_RSS_QUEUES,
639 	ACTION_NEXT,
640 	ZERO,
641 };
642 
643 static const enum index action_vf[] = {
644 	ACTION_VF_ORIGINAL,
645 	ACTION_VF_ID,
646 	ACTION_NEXT,
647 	ZERO,
648 };
649 
650 static const enum index action_meter[] = {
651 	ACTION_METER_ID,
652 	ACTION_NEXT,
653 	ZERO,
654 };
655 
656 static int parse_init(struct context *, const struct token *,
657 		      const char *, unsigned int,
658 		      void *, unsigned int);
659 static int parse_vc(struct context *, const struct token *,
660 		    const char *, unsigned int,
661 		    void *, unsigned int);
662 static int parse_vc_spec(struct context *, const struct token *,
663 			 const char *, unsigned int, void *, unsigned int);
664 static int parse_vc_conf(struct context *, const struct token *,
665 			 const char *, unsigned int, void *, unsigned int);
666 static int parse_vc_action_rss(struct context *, const struct token *,
667 			       const char *, unsigned int, void *,
668 			       unsigned int);
669 static int parse_vc_action_rss_type(struct context *, const struct token *,
670 				    const char *, unsigned int, void *,
671 				    unsigned int);
672 static int parse_vc_action_rss_queue(struct context *, const struct token *,
673 				     const char *, unsigned int, void *,
674 				     unsigned int);
675 static int parse_destroy(struct context *, const struct token *,
676 			 const char *, unsigned int,
677 			 void *, unsigned int);
678 static int parse_flush(struct context *, const struct token *,
679 		       const char *, unsigned int,
680 		       void *, unsigned int);
681 static int parse_query(struct context *, const struct token *,
682 		       const char *, unsigned int,
683 		       void *, unsigned int);
684 static int parse_action(struct context *, const struct token *,
685 			const char *, unsigned int,
686 			void *, unsigned int);
687 static int parse_list(struct context *, const struct token *,
688 		      const char *, unsigned int,
689 		      void *, unsigned int);
690 static int parse_isolate(struct context *, const struct token *,
691 			 const char *, unsigned int,
692 			 void *, unsigned int);
693 static int parse_int(struct context *, const struct token *,
694 		     const char *, unsigned int,
695 		     void *, unsigned int);
696 static int parse_prefix(struct context *, const struct token *,
697 			const char *, unsigned int,
698 			void *, unsigned int);
699 static int parse_boolean(struct context *, const struct token *,
700 			 const char *, unsigned int,
701 			 void *, unsigned int);
702 static int parse_string(struct context *, const struct token *,
703 			const char *, unsigned int,
704 			void *, unsigned int);
705 static int parse_mac_addr(struct context *, const struct token *,
706 			  const char *, unsigned int,
707 			  void *, unsigned int);
708 static int parse_ipv4_addr(struct context *, const struct token *,
709 			   const char *, unsigned int,
710 			   void *, unsigned int);
711 static int parse_ipv6_addr(struct context *, const struct token *,
712 			   const char *, unsigned int,
713 			   void *, unsigned int);
714 static int parse_port(struct context *, const struct token *,
715 		      const char *, unsigned int,
716 		      void *, unsigned int);
717 static int comp_none(struct context *, const struct token *,
718 		     unsigned int, char *, unsigned int);
719 static int comp_boolean(struct context *, const struct token *,
720 			unsigned int, char *, unsigned int);
721 static int comp_action(struct context *, const struct token *,
722 		       unsigned int, char *, unsigned int);
723 static int comp_port(struct context *, const struct token *,
724 		     unsigned int, char *, unsigned int);
725 static int comp_rule_id(struct context *, const struct token *,
726 			unsigned int, char *, unsigned int);
727 static int comp_vc_action_rss_type(struct context *, const struct token *,
728 				   unsigned int, char *, unsigned int);
729 static int comp_vc_action_rss_queue(struct context *, const struct token *,
730 				    unsigned int, char *, unsigned int);
731 
732 /** Token definitions. */
733 static const struct token token_list[] = {
734 	/* Special tokens. */
735 	[ZERO] = {
736 		.name = "ZERO",
737 		.help = "null entry, abused as the entry point",
738 		.next = NEXT(NEXT_ENTRY(FLOW)),
739 	},
740 	[END] = {
741 		.name = "",
742 		.type = "RETURN",
743 		.help = "command may end here",
744 	},
745 	/* Common tokens. */
746 	[INTEGER] = {
747 		.name = "{int}",
748 		.type = "INTEGER",
749 		.help = "integer value",
750 		.call = parse_int,
751 		.comp = comp_none,
752 	},
753 	[UNSIGNED] = {
754 		.name = "{unsigned}",
755 		.type = "UNSIGNED",
756 		.help = "unsigned integer value",
757 		.call = parse_int,
758 		.comp = comp_none,
759 	},
760 	[PREFIX] = {
761 		.name = "{prefix}",
762 		.type = "PREFIX",
763 		.help = "prefix length for bit-mask",
764 		.call = parse_prefix,
765 		.comp = comp_none,
766 	},
767 	[BOOLEAN] = {
768 		.name = "{boolean}",
769 		.type = "BOOLEAN",
770 		.help = "any boolean value",
771 		.call = parse_boolean,
772 		.comp = comp_boolean,
773 	},
774 	[STRING] = {
775 		.name = "{string}",
776 		.type = "STRING",
777 		.help = "fixed string",
778 		.call = parse_string,
779 		.comp = comp_none,
780 	},
781 	[MAC_ADDR] = {
782 		.name = "{MAC address}",
783 		.type = "MAC-48",
784 		.help = "standard MAC address notation",
785 		.call = parse_mac_addr,
786 		.comp = comp_none,
787 	},
788 	[IPV4_ADDR] = {
789 		.name = "{IPv4 address}",
790 		.type = "IPV4 ADDRESS",
791 		.help = "standard IPv4 address notation",
792 		.call = parse_ipv4_addr,
793 		.comp = comp_none,
794 	},
795 	[IPV6_ADDR] = {
796 		.name = "{IPv6 address}",
797 		.type = "IPV6 ADDRESS",
798 		.help = "standard IPv6 address notation",
799 		.call = parse_ipv6_addr,
800 		.comp = comp_none,
801 	},
802 	[RULE_ID] = {
803 		.name = "{rule id}",
804 		.type = "RULE ID",
805 		.help = "rule identifier",
806 		.call = parse_int,
807 		.comp = comp_rule_id,
808 	},
809 	[PORT_ID] = {
810 		.name = "{port_id}",
811 		.type = "PORT ID",
812 		.help = "port identifier",
813 		.call = parse_port,
814 		.comp = comp_port,
815 	},
816 	[GROUP_ID] = {
817 		.name = "{group_id}",
818 		.type = "GROUP ID",
819 		.help = "group identifier",
820 		.call = parse_int,
821 		.comp = comp_none,
822 	},
823 	[PRIORITY_LEVEL] = {
824 		.name = "{level}",
825 		.type = "PRIORITY",
826 		.help = "priority level",
827 		.call = parse_int,
828 		.comp = comp_none,
829 	},
830 	/* Top-level command. */
831 	[FLOW] = {
832 		.name = "flow",
833 		.type = "{command} {port_id} [{arg} [...]]",
834 		.help = "manage ingress/egress flow rules",
835 		.next = NEXT(NEXT_ENTRY
836 			     (VALIDATE,
837 			      CREATE,
838 			      DESTROY,
839 			      FLUSH,
840 			      LIST,
841 			      QUERY,
842 			      ISOLATE)),
843 		.call = parse_init,
844 	},
845 	/* Sub-level commands. */
846 	[VALIDATE] = {
847 		.name = "validate",
848 		.help = "check whether a flow rule can be created",
849 		.next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
850 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
851 		.call = parse_vc,
852 	},
853 	[CREATE] = {
854 		.name = "create",
855 		.help = "create a flow rule",
856 		.next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
857 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
858 		.call = parse_vc,
859 	},
860 	[DESTROY] = {
861 		.name = "destroy",
862 		.help = "destroy specific flow rules",
863 		.next = NEXT(NEXT_ENTRY(DESTROY_RULE), NEXT_ENTRY(PORT_ID)),
864 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
865 		.call = parse_destroy,
866 	},
867 	[FLUSH] = {
868 		.name = "flush",
869 		.help = "destroy all flow rules",
870 		.next = NEXT(NEXT_ENTRY(PORT_ID)),
871 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
872 		.call = parse_flush,
873 	},
874 	[QUERY] = {
875 		.name = "query",
876 		.help = "query an existing flow rule",
877 		.next = NEXT(NEXT_ENTRY(QUERY_ACTION),
878 			     NEXT_ENTRY(RULE_ID),
879 			     NEXT_ENTRY(PORT_ID)),
880 		.args = ARGS(ARGS_ENTRY(struct buffer, args.query.action),
881 			     ARGS_ENTRY(struct buffer, args.query.rule),
882 			     ARGS_ENTRY(struct buffer, port)),
883 		.call = parse_query,
884 	},
885 	[LIST] = {
886 		.name = "list",
887 		.help = "list existing flow rules",
888 		.next = NEXT(next_list_attr, NEXT_ENTRY(PORT_ID)),
889 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
890 		.call = parse_list,
891 	},
892 	[ISOLATE] = {
893 		.name = "isolate",
894 		.help = "restrict ingress traffic to the defined flow rules",
895 		.next = NEXT(NEXT_ENTRY(BOOLEAN),
896 			     NEXT_ENTRY(PORT_ID)),
897 		.args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
898 			     ARGS_ENTRY(struct buffer, port)),
899 		.call = parse_isolate,
900 	},
901 	/* Destroy arguments. */
902 	[DESTROY_RULE] = {
903 		.name = "rule",
904 		.help = "specify a rule identifier",
905 		.next = NEXT(next_destroy_attr, NEXT_ENTRY(RULE_ID)),
906 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
907 		.call = parse_destroy,
908 	},
909 	/* Query arguments. */
910 	[QUERY_ACTION] = {
911 		.name = "{action}",
912 		.type = "ACTION",
913 		.help = "action to query, must be part of the rule",
914 		.call = parse_action,
915 		.comp = comp_action,
916 	},
917 	/* List arguments. */
918 	[LIST_GROUP] = {
919 		.name = "group",
920 		.help = "specify a group",
921 		.next = NEXT(next_list_attr, NEXT_ENTRY(GROUP_ID)),
922 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
923 		.call = parse_list,
924 	},
925 	/* Validate/create attributes. */
926 	[GROUP] = {
927 		.name = "group",
928 		.help = "specify a group",
929 		.next = NEXT(next_vc_attr, NEXT_ENTRY(GROUP_ID)),
930 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
931 		.call = parse_vc,
932 	},
933 	[PRIORITY] = {
934 		.name = "priority",
935 		.help = "specify a priority level",
936 		.next = NEXT(next_vc_attr, NEXT_ENTRY(PRIORITY_LEVEL)),
937 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
938 		.call = parse_vc,
939 	},
940 	[INGRESS] = {
941 		.name = "ingress",
942 		.help = "affect rule to ingress",
943 		.next = NEXT(next_vc_attr),
944 		.call = parse_vc,
945 	},
946 	[EGRESS] = {
947 		.name = "egress",
948 		.help = "affect rule to egress",
949 		.next = NEXT(next_vc_attr),
950 		.call = parse_vc,
951 	},
952 	/* Validate/create pattern. */
953 	[PATTERN] = {
954 		.name = "pattern",
955 		.help = "submit a list of pattern items",
956 		.next = NEXT(next_item),
957 		.call = parse_vc,
958 	},
959 	[ITEM_PARAM_IS] = {
960 		.name = "is",
961 		.help = "match value perfectly (with full bit-mask)",
962 		.call = parse_vc_spec,
963 	},
964 	[ITEM_PARAM_SPEC] = {
965 		.name = "spec",
966 		.help = "match value according to configured bit-mask",
967 		.call = parse_vc_spec,
968 	},
969 	[ITEM_PARAM_LAST] = {
970 		.name = "last",
971 		.help = "specify upper bound to establish a range",
972 		.call = parse_vc_spec,
973 	},
974 	[ITEM_PARAM_MASK] = {
975 		.name = "mask",
976 		.help = "specify bit-mask with relevant bits set to one",
977 		.call = parse_vc_spec,
978 	},
979 	[ITEM_PARAM_PREFIX] = {
980 		.name = "prefix",
981 		.help = "generate bit-mask from a prefix length",
982 		.call = parse_vc_spec,
983 	},
984 	[ITEM_NEXT] = {
985 		.name = "/",
986 		.help = "specify next pattern item",
987 		.next = NEXT(next_item),
988 	},
989 	[ITEM_END] = {
990 		.name = "end",
991 		.help = "end list of pattern items",
992 		.priv = PRIV_ITEM(END, 0),
993 		.next = NEXT(NEXT_ENTRY(ACTIONS)),
994 		.call = parse_vc,
995 	},
996 	[ITEM_VOID] = {
997 		.name = "void",
998 		.help = "no-op pattern item",
999 		.priv = PRIV_ITEM(VOID, 0),
1000 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
1001 		.call = parse_vc,
1002 	},
1003 	[ITEM_INVERT] = {
1004 		.name = "invert",
1005 		.help = "perform actions when pattern does not match",
1006 		.priv = PRIV_ITEM(INVERT, 0),
1007 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
1008 		.call = parse_vc,
1009 	},
1010 	[ITEM_ANY] = {
1011 		.name = "any",
1012 		.help = "match any protocol for the current layer",
1013 		.priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
1014 		.next = NEXT(item_any),
1015 		.call = parse_vc,
1016 	},
1017 	[ITEM_ANY_NUM] = {
1018 		.name = "num",
1019 		.help = "number of layers covered",
1020 		.next = NEXT(item_any, NEXT_ENTRY(UNSIGNED), item_param),
1021 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
1022 	},
1023 	[ITEM_PF] = {
1024 		.name = "pf",
1025 		.help = "match packets addressed to the physical function",
1026 		.priv = PRIV_ITEM(PF, 0),
1027 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
1028 		.call = parse_vc,
1029 	},
1030 	[ITEM_VF] = {
1031 		.name = "vf",
1032 		.help = "match packets addressed to a virtual function ID",
1033 		.priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
1034 		.next = NEXT(item_vf),
1035 		.call = parse_vc,
1036 	},
1037 	[ITEM_VF_ID] = {
1038 		.name = "id",
1039 		.help = "destination VF ID",
1040 		.next = NEXT(item_vf, NEXT_ENTRY(UNSIGNED), item_param),
1041 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
1042 	},
1043 	[ITEM_PORT] = {
1044 		.name = "port",
1045 		.help = "device-specific physical port index to use",
1046 		.priv = PRIV_ITEM(PORT, sizeof(struct rte_flow_item_port)),
1047 		.next = NEXT(item_port),
1048 		.call = parse_vc,
1049 	},
1050 	[ITEM_PORT_INDEX] = {
1051 		.name = "index",
1052 		.help = "physical port index",
1053 		.next = NEXT(item_port, NEXT_ENTRY(UNSIGNED), item_param),
1054 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_port, index)),
1055 	},
1056 	[ITEM_RAW] = {
1057 		.name = "raw",
1058 		.help = "match an arbitrary byte string",
1059 		.priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
1060 		.next = NEXT(item_raw),
1061 		.call = parse_vc,
1062 	},
1063 	[ITEM_RAW_RELATIVE] = {
1064 		.name = "relative",
1065 		.help = "look for pattern after the previous item",
1066 		.next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
1067 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
1068 					   relative, 1)),
1069 	},
1070 	[ITEM_RAW_SEARCH] = {
1071 		.name = "search",
1072 		.help = "search pattern from offset (see also limit)",
1073 		.next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
1074 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
1075 					   search, 1)),
1076 	},
1077 	[ITEM_RAW_OFFSET] = {
1078 		.name = "offset",
1079 		.help = "absolute or relative offset for pattern",
1080 		.next = NEXT(item_raw, NEXT_ENTRY(INTEGER), item_param),
1081 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
1082 	},
1083 	[ITEM_RAW_LIMIT] = {
1084 		.name = "limit",
1085 		.help = "search area limit for start of pattern",
1086 		.next = NEXT(item_raw, NEXT_ENTRY(UNSIGNED), item_param),
1087 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
1088 	},
1089 	[ITEM_RAW_PATTERN] = {
1090 		.name = "pattern",
1091 		.help = "byte string to look for",
1092 		.next = NEXT(item_raw,
1093 			     NEXT_ENTRY(STRING),
1094 			     NEXT_ENTRY(ITEM_PARAM_IS,
1095 					ITEM_PARAM_SPEC,
1096 					ITEM_PARAM_MASK)),
1097 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
1098 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
1099 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
1100 					    ITEM_RAW_PATTERN_SIZE)),
1101 	},
1102 	[ITEM_ETH] = {
1103 		.name = "eth",
1104 		.help = "match Ethernet header",
1105 		.priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
1106 		.next = NEXT(item_eth),
1107 		.call = parse_vc,
1108 	},
1109 	[ITEM_ETH_DST] = {
1110 		.name = "dst",
1111 		.help = "destination MAC",
1112 		.next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
1113 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
1114 	},
1115 	[ITEM_ETH_SRC] = {
1116 		.name = "src",
1117 		.help = "source MAC",
1118 		.next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
1119 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
1120 	},
1121 	[ITEM_ETH_TYPE] = {
1122 		.name = "type",
1123 		.help = "EtherType",
1124 		.next = NEXT(item_eth, NEXT_ENTRY(UNSIGNED), item_param),
1125 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
1126 	},
1127 	[ITEM_VLAN] = {
1128 		.name = "vlan",
1129 		.help = "match 802.1Q/ad VLAN tag",
1130 		.priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
1131 		.next = NEXT(item_vlan),
1132 		.call = parse_vc,
1133 	},
1134 	[ITEM_VLAN_TPID] = {
1135 		.name = "tpid",
1136 		.help = "tag protocol identifier",
1137 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1138 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tpid)),
1139 	},
1140 	[ITEM_VLAN_TCI] = {
1141 		.name = "tci",
1142 		.help = "tag control information",
1143 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1144 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
1145 	},
1146 	[ITEM_VLAN_PCP] = {
1147 		.name = "pcp",
1148 		.help = "priority code point",
1149 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1150 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
1151 						  tci, "\xe0\x00")),
1152 	},
1153 	[ITEM_VLAN_DEI] = {
1154 		.name = "dei",
1155 		.help = "drop eligible indicator",
1156 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1157 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
1158 						  tci, "\x10\x00")),
1159 	},
1160 	[ITEM_VLAN_VID] = {
1161 		.name = "vid",
1162 		.help = "VLAN identifier",
1163 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1164 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
1165 						  tci, "\x0f\xff")),
1166 	},
1167 	[ITEM_IPV4] = {
1168 		.name = "ipv4",
1169 		.help = "match IPv4 header",
1170 		.priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
1171 		.next = NEXT(item_ipv4),
1172 		.call = parse_vc,
1173 	},
1174 	[ITEM_IPV4_TOS] = {
1175 		.name = "tos",
1176 		.help = "type of service",
1177 		.next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
1178 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1179 					     hdr.type_of_service)),
1180 	},
1181 	[ITEM_IPV4_TTL] = {
1182 		.name = "ttl",
1183 		.help = "time to live",
1184 		.next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
1185 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1186 					     hdr.time_to_live)),
1187 	},
1188 	[ITEM_IPV4_PROTO] = {
1189 		.name = "proto",
1190 		.help = "next protocol ID",
1191 		.next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
1192 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1193 					     hdr.next_proto_id)),
1194 	},
1195 	[ITEM_IPV4_SRC] = {
1196 		.name = "src",
1197 		.help = "source address",
1198 		.next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
1199 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1200 					     hdr.src_addr)),
1201 	},
1202 	[ITEM_IPV4_DST] = {
1203 		.name = "dst",
1204 		.help = "destination address",
1205 		.next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
1206 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1207 					     hdr.dst_addr)),
1208 	},
1209 	[ITEM_IPV6] = {
1210 		.name = "ipv6",
1211 		.help = "match IPv6 header",
1212 		.priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
1213 		.next = NEXT(item_ipv6),
1214 		.call = parse_vc,
1215 	},
1216 	[ITEM_IPV6_TC] = {
1217 		.name = "tc",
1218 		.help = "traffic class",
1219 		.next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
1220 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
1221 						  hdr.vtc_flow,
1222 						  "\x0f\xf0\x00\x00")),
1223 	},
1224 	[ITEM_IPV6_FLOW] = {
1225 		.name = "flow",
1226 		.help = "flow label",
1227 		.next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
1228 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
1229 						  hdr.vtc_flow,
1230 						  "\x00\x0f\xff\xff")),
1231 	},
1232 	[ITEM_IPV6_PROTO] = {
1233 		.name = "proto",
1234 		.help = "protocol (next header)",
1235 		.next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
1236 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
1237 					     hdr.proto)),
1238 	},
1239 	[ITEM_IPV6_HOP] = {
1240 		.name = "hop",
1241 		.help = "hop limit",
1242 		.next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
1243 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
1244 					     hdr.hop_limits)),
1245 	},
1246 	[ITEM_IPV6_SRC] = {
1247 		.name = "src",
1248 		.help = "source address",
1249 		.next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
1250 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
1251 					     hdr.src_addr)),
1252 	},
1253 	[ITEM_IPV6_DST] = {
1254 		.name = "dst",
1255 		.help = "destination address",
1256 		.next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
1257 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
1258 					     hdr.dst_addr)),
1259 	},
1260 	[ITEM_ICMP] = {
1261 		.name = "icmp",
1262 		.help = "match ICMP header",
1263 		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
1264 		.next = NEXT(item_icmp),
1265 		.call = parse_vc,
1266 	},
1267 	[ITEM_ICMP_TYPE] = {
1268 		.name = "type",
1269 		.help = "ICMP packet type",
1270 		.next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
1271 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
1272 					     hdr.icmp_type)),
1273 	},
1274 	[ITEM_ICMP_CODE] = {
1275 		.name = "code",
1276 		.help = "ICMP packet code",
1277 		.next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
1278 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
1279 					     hdr.icmp_code)),
1280 	},
1281 	[ITEM_UDP] = {
1282 		.name = "udp",
1283 		.help = "match UDP header",
1284 		.priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
1285 		.next = NEXT(item_udp),
1286 		.call = parse_vc,
1287 	},
1288 	[ITEM_UDP_SRC] = {
1289 		.name = "src",
1290 		.help = "UDP source port",
1291 		.next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
1292 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
1293 					     hdr.src_port)),
1294 	},
1295 	[ITEM_UDP_DST] = {
1296 		.name = "dst",
1297 		.help = "UDP destination port",
1298 		.next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
1299 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
1300 					     hdr.dst_port)),
1301 	},
1302 	[ITEM_TCP] = {
1303 		.name = "tcp",
1304 		.help = "match TCP header",
1305 		.priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
1306 		.next = NEXT(item_tcp),
1307 		.call = parse_vc,
1308 	},
1309 	[ITEM_TCP_SRC] = {
1310 		.name = "src",
1311 		.help = "TCP source port",
1312 		.next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
1313 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
1314 					     hdr.src_port)),
1315 	},
1316 	[ITEM_TCP_DST] = {
1317 		.name = "dst",
1318 		.help = "TCP destination port",
1319 		.next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
1320 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
1321 					     hdr.dst_port)),
1322 	},
1323 	[ITEM_TCP_FLAGS] = {
1324 		.name = "flags",
1325 		.help = "TCP flags",
1326 		.next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
1327 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
1328 					     hdr.tcp_flags)),
1329 	},
1330 	[ITEM_SCTP] = {
1331 		.name = "sctp",
1332 		.help = "match SCTP header",
1333 		.priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
1334 		.next = NEXT(item_sctp),
1335 		.call = parse_vc,
1336 	},
1337 	[ITEM_SCTP_SRC] = {
1338 		.name = "src",
1339 		.help = "SCTP source port",
1340 		.next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
1341 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
1342 					     hdr.src_port)),
1343 	},
1344 	[ITEM_SCTP_DST] = {
1345 		.name = "dst",
1346 		.help = "SCTP destination port",
1347 		.next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
1348 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
1349 					     hdr.dst_port)),
1350 	},
1351 	[ITEM_SCTP_TAG] = {
1352 		.name = "tag",
1353 		.help = "validation tag",
1354 		.next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
1355 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
1356 					     hdr.tag)),
1357 	},
1358 	[ITEM_SCTP_CKSUM] = {
1359 		.name = "cksum",
1360 		.help = "checksum",
1361 		.next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
1362 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
1363 					     hdr.cksum)),
1364 	},
1365 	[ITEM_VXLAN] = {
1366 		.name = "vxlan",
1367 		.help = "match VXLAN header",
1368 		.priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
1369 		.next = NEXT(item_vxlan),
1370 		.call = parse_vc,
1371 	},
1372 	[ITEM_VXLAN_VNI] = {
1373 		.name = "vni",
1374 		.help = "VXLAN identifier",
1375 		.next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED), item_param),
1376 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
1377 	},
1378 	[ITEM_E_TAG] = {
1379 		.name = "e_tag",
1380 		.help = "match E-Tag header",
1381 		.priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
1382 		.next = NEXT(item_e_tag),
1383 		.call = parse_vc,
1384 	},
1385 	[ITEM_E_TAG_GRP_ECID_B] = {
1386 		.name = "grp_ecid_b",
1387 		.help = "GRP and E-CID base",
1388 		.next = NEXT(item_e_tag, NEXT_ENTRY(UNSIGNED), item_param),
1389 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
1390 						  rsvd_grp_ecid_b,
1391 						  "\x3f\xff")),
1392 	},
1393 	[ITEM_NVGRE] = {
1394 		.name = "nvgre",
1395 		.help = "match NVGRE header",
1396 		.priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
1397 		.next = NEXT(item_nvgre),
1398 		.call = parse_vc,
1399 	},
1400 	[ITEM_NVGRE_TNI] = {
1401 		.name = "tni",
1402 		.help = "virtual subnet ID",
1403 		.next = NEXT(item_nvgre, NEXT_ENTRY(UNSIGNED), item_param),
1404 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
1405 	},
1406 	[ITEM_MPLS] = {
1407 		.name = "mpls",
1408 		.help = "match MPLS header",
1409 		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
1410 		.next = NEXT(item_mpls),
1411 		.call = parse_vc,
1412 	},
1413 	[ITEM_MPLS_LABEL] = {
1414 		.name = "label",
1415 		.help = "MPLS label",
1416 		.next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
1417 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
1418 						  label_tc_s,
1419 						  "\xff\xff\xf0")),
1420 	},
1421 	[ITEM_GRE] = {
1422 		.name = "gre",
1423 		.help = "match GRE header",
1424 		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
1425 		.next = NEXT(item_gre),
1426 		.call = parse_vc,
1427 	},
1428 	[ITEM_GRE_PROTO] = {
1429 		.name = "protocol",
1430 		.help = "GRE protocol type",
1431 		.next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
1432 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
1433 					     protocol)),
1434 	},
1435 	[ITEM_FUZZY] = {
1436 		.name = "fuzzy",
1437 		.help = "fuzzy pattern match, expect faster than default",
1438 		.priv = PRIV_ITEM(FUZZY,
1439 				sizeof(struct rte_flow_item_fuzzy)),
1440 		.next = NEXT(item_fuzzy),
1441 		.call = parse_vc,
1442 	},
1443 	[ITEM_FUZZY_THRESH] = {
1444 		.name = "thresh",
1445 		.help = "match accuracy threshold",
1446 		.next = NEXT(item_fuzzy, NEXT_ENTRY(UNSIGNED), item_param),
1447 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
1448 					thresh)),
1449 	},
1450 	[ITEM_GTP] = {
1451 		.name = "gtp",
1452 		.help = "match GTP header",
1453 		.priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
1454 		.next = NEXT(item_gtp),
1455 		.call = parse_vc,
1456 	},
1457 	[ITEM_GTP_TEID] = {
1458 		.name = "teid",
1459 		.help = "tunnel endpoint identifier",
1460 		.next = NEXT(item_gtp, NEXT_ENTRY(UNSIGNED), item_param),
1461 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
1462 	},
1463 	[ITEM_GTPC] = {
1464 		.name = "gtpc",
1465 		.help = "match GTP header",
1466 		.priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
1467 		.next = NEXT(item_gtp),
1468 		.call = parse_vc,
1469 	},
1470 	[ITEM_GTPU] = {
1471 		.name = "gtpu",
1472 		.help = "match GTP header",
1473 		.priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
1474 		.next = NEXT(item_gtp),
1475 		.call = parse_vc,
1476 	},
1477 	[ITEM_GENEVE] = {
1478 		.name = "geneve",
1479 		.help = "match GENEVE header",
1480 		.priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
1481 		.next = NEXT(item_geneve),
1482 		.call = parse_vc,
1483 	},
1484 	[ITEM_GENEVE_VNI] = {
1485 		.name = "vni",
1486 		.help = "virtual network identifier",
1487 		.next = NEXT(item_geneve, NEXT_ENTRY(UNSIGNED), item_param),
1488 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
1489 	},
1490 	[ITEM_GENEVE_PROTO] = {
1491 		.name = "protocol",
1492 		.help = "GENEVE protocol type",
1493 		.next = NEXT(item_geneve, NEXT_ENTRY(UNSIGNED), item_param),
1494 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
1495 					     protocol)),
1496 	},
1497 
1498 	/* Validate/create actions. */
1499 	[ACTIONS] = {
1500 		.name = "actions",
1501 		.help = "submit a list of associated actions",
1502 		.next = NEXT(next_action),
1503 		.call = parse_vc,
1504 	},
1505 	[ACTION_NEXT] = {
1506 		.name = "/",
1507 		.help = "specify next action",
1508 		.next = NEXT(next_action),
1509 	},
1510 	[ACTION_END] = {
1511 		.name = "end",
1512 		.help = "end list of actions",
1513 		.priv = PRIV_ACTION(END, 0),
1514 		.call = parse_vc,
1515 	},
1516 	[ACTION_VOID] = {
1517 		.name = "void",
1518 		.help = "no-op action",
1519 		.priv = PRIV_ACTION(VOID, 0),
1520 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
1521 		.call = parse_vc,
1522 	},
1523 	[ACTION_PASSTHRU] = {
1524 		.name = "passthru",
1525 		.help = "let subsequent rule process matched packets",
1526 		.priv = PRIV_ACTION(PASSTHRU, 0),
1527 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
1528 		.call = parse_vc,
1529 	},
1530 	[ACTION_MARK] = {
1531 		.name = "mark",
1532 		.help = "attach 32 bit value to packets",
1533 		.priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
1534 		.next = NEXT(action_mark),
1535 		.call = parse_vc,
1536 	},
1537 	[ACTION_MARK_ID] = {
1538 		.name = "id",
1539 		.help = "32 bit value to return with packets",
1540 		.next = NEXT(action_mark, NEXT_ENTRY(UNSIGNED)),
1541 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
1542 		.call = parse_vc_conf,
1543 	},
1544 	[ACTION_FLAG] = {
1545 		.name = "flag",
1546 		.help = "flag packets",
1547 		.priv = PRIV_ACTION(FLAG, 0),
1548 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
1549 		.call = parse_vc,
1550 	},
1551 	[ACTION_QUEUE] = {
1552 		.name = "queue",
1553 		.help = "assign packets to a given queue index",
1554 		.priv = PRIV_ACTION(QUEUE,
1555 				    sizeof(struct rte_flow_action_queue)),
1556 		.next = NEXT(action_queue),
1557 		.call = parse_vc,
1558 	},
1559 	[ACTION_QUEUE_INDEX] = {
1560 		.name = "index",
1561 		.help = "queue index to use",
1562 		.next = NEXT(action_queue, NEXT_ENTRY(UNSIGNED)),
1563 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
1564 		.call = parse_vc_conf,
1565 	},
1566 	[ACTION_DROP] = {
1567 		.name = "drop",
1568 		.help = "drop packets (note: passthru has priority)",
1569 		.priv = PRIV_ACTION(DROP, 0),
1570 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
1571 		.call = parse_vc,
1572 	},
1573 	[ACTION_COUNT] = {
1574 		.name = "count",
1575 		.help = "enable counters for this rule",
1576 		.priv = PRIV_ACTION(COUNT, 0),
1577 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
1578 		.call = parse_vc,
1579 	},
1580 	[ACTION_RSS] = {
1581 		.name = "rss",
1582 		.help = "spread packets among several queues",
1583 		.priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
1584 		.next = NEXT(action_rss),
1585 		.call = parse_vc_action_rss,
1586 	},
1587 	[ACTION_RSS_TYPES] = {
1588 		.name = "types",
1589 		.help = "specific RSS hash types",
1590 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
1591 	},
1592 	[ACTION_RSS_TYPE] = {
1593 		.name = "{type}",
1594 		.help = "RSS hash type",
1595 		.call = parse_vc_action_rss_type,
1596 		.comp = comp_vc_action_rss_type,
1597 	},
1598 	[ACTION_RSS_KEY] = {
1599 		.name = "key",
1600 		.help = "RSS hash key",
1601 		.next = NEXT(action_rss, NEXT_ENTRY(STRING)),
1602 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
1603 			     ARGS_ENTRY_ARB
1604 			     (offsetof(struct action_rss_data, conf) +
1605 			      offsetof(struct rte_flow_action_rss, key_len),
1606 			      sizeof(((struct rte_flow_action_rss *)0)->
1607 				     key_len)),
1608 			     ARGS_ENTRY(struct action_rss_data, key)),
1609 	},
1610 	[ACTION_RSS_KEY_LEN] = {
1611 		.name = "key_len",
1612 		.help = "RSS hash key length in bytes",
1613 		.next = NEXT(action_rss, NEXT_ENTRY(UNSIGNED)),
1614 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
1615 			     (offsetof(struct action_rss_data, conf) +
1616 			      offsetof(struct rte_flow_action_rss, key_len),
1617 			      sizeof(((struct rte_flow_action_rss *)0)->
1618 				     key_len),
1619 			      0,
1620 			      RSS_HASH_KEY_LENGTH)),
1621 	},
1622 	[ACTION_RSS_QUEUES] = {
1623 		.name = "queues",
1624 		.help = "queue indices to use",
1625 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
1626 		.call = parse_vc_conf,
1627 	},
1628 	[ACTION_RSS_QUEUE] = {
1629 		.name = "{queue}",
1630 		.help = "queue index",
1631 		.call = parse_vc_action_rss_queue,
1632 		.comp = comp_vc_action_rss_queue,
1633 	},
1634 	[ACTION_PF] = {
1635 		.name = "pf",
1636 		.help = "redirect packets to physical device function",
1637 		.priv = PRIV_ACTION(PF, 0),
1638 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
1639 		.call = parse_vc,
1640 	},
1641 	[ACTION_VF] = {
1642 		.name = "vf",
1643 		.help = "redirect packets to virtual device function",
1644 		.priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
1645 		.next = NEXT(action_vf),
1646 		.call = parse_vc,
1647 	},
1648 	[ACTION_VF_ORIGINAL] = {
1649 		.name = "original",
1650 		.help = "use original VF ID if possible",
1651 		.next = NEXT(action_vf, NEXT_ENTRY(BOOLEAN)),
1652 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
1653 					   original, 1)),
1654 		.call = parse_vc_conf,
1655 	},
1656 	[ACTION_VF_ID] = {
1657 		.name = "id",
1658 		.help = "VF ID to redirect packets to",
1659 		.next = NEXT(action_vf, NEXT_ENTRY(UNSIGNED)),
1660 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
1661 		.call = parse_vc_conf,
1662 	},
1663 	[ACTION_METER] = {
1664 		.name = "meter",
1665 		.help = "meter the directed packets at given id",
1666 		.priv = PRIV_ACTION(METER,
1667 				    sizeof(struct rte_flow_action_meter)),
1668 		.next = NEXT(action_meter),
1669 		.call = parse_vc,
1670 	},
1671 	[ACTION_METER_ID] = {
1672 		.name = "mtr_id",
1673 		.help = "meter id to use",
1674 		.next = NEXT(action_meter, NEXT_ENTRY(UNSIGNED)),
1675 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
1676 		.call = parse_vc_conf,
1677 	},
1678 };
1679 
1680 /** Remove and return last entry from argument stack. */
1681 static const struct arg *
1682 pop_args(struct context *ctx)
1683 {
1684 	return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
1685 }
1686 
1687 /** Add entry on top of the argument stack. */
1688 static int
1689 push_args(struct context *ctx, const struct arg *arg)
1690 {
1691 	if (ctx->args_num == CTX_STACK_SIZE)
1692 		return -1;
1693 	ctx->args[ctx->args_num++] = arg;
1694 	return 0;
1695 }
1696 
1697 /** Spread value into buffer according to bit-mask. */
1698 static size_t
1699 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
1700 {
1701 	uint32_t i = arg->size;
1702 	uint32_t end = 0;
1703 	int sub = 1;
1704 	int add = 0;
1705 	size_t len = 0;
1706 
1707 	if (!arg->mask)
1708 		return 0;
1709 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1710 	if (!arg->hton) {
1711 		i = 0;
1712 		end = arg->size;
1713 		sub = 0;
1714 		add = 1;
1715 	}
1716 #endif
1717 	while (i != end) {
1718 		unsigned int shift = 0;
1719 		uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
1720 
1721 		for (shift = 0; arg->mask[i] >> shift; ++shift) {
1722 			if (!(arg->mask[i] & (1 << shift)))
1723 				continue;
1724 			++len;
1725 			if (!dst)
1726 				continue;
1727 			*buf &= ~(1 << shift);
1728 			*buf |= (val & 1) << shift;
1729 			val >>= 1;
1730 		}
1731 		i += add;
1732 	}
1733 	return len;
1734 }
1735 
1736 /** Compare a string with a partial one of a given length. */
1737 static int
1738 strcmp_partial(const char *full, const char *partial, size_t partial_len)
1739 {
1740 	int r = strncmp(full, partial, partial_len);
1741 
1742 	if (r)
1743 		return r;
1744 	if (strlen(full) <= partial_len)
1745 		return 0;
1746 	return full[partial_len];
1747 }
1748 
1749 /**
1750  * Parse a prefix length and generate a bit-mask.
1751  *
1752  * Last argument (ctx->args) is retrieved to determine mask size, storage
1753  * location and whether the result must use network byte ordering.
1754  */
1755 static int
1756 parse_prefix(struct context *ctx, const struct token *token,
1757 	     const char *str, unsigned int len,
1758 	     void *buf, unsigned int size)
1759 {
1760 	const struct arg *arg = pop_args(ctx);
1761 	static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
1762 	char *end;
1763 	uintmax_t u;
1764 	unsigned int bytes;
1765 	unsigned int extra;
1766 
1767 	(void)token;
1768 	/* Argument is expected. */
1769 	if (!arg)
1770 		return -1;
1771 	errno = 0;
1772 	u = strtoumax(str, &end, 0);
1773 	if (errno || (size_t)(end - str) != len)
1774 		goto error;
1775 	if (arg->mask) {
1776 		uintmax_t v = 0;
1777 
1778 		extra = arg_entry_bf_fill(NULL, 0, arg);
1779 		if (u > extra)
1780 			goto error;
1781 		if (!ctx->object)
1782 			return len;
1783 		extra -= u;
1784 		while (u--)
1785 			(v <<= 1, v |= 1);
1786 		v <<= extra;
1787 		if (!arg_entry_bf_fill(ctx->object, v, arg) ||
1788 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
1789 			goto error;
1790 		return len;
1791 	}
1792 	bytes = u / 8;
1793 	extra = u % 8;
1794 	size = arg->size;
1795 	if (bytes > size || bytes + !!extra > size)
1796 		goto error;
1797 	if (!ctx->object)
1798 		return len;
1799 	buf = (uint8_t *)ctx->object + arg->offset;
1800 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1801 	if (!arg->hton) {
1802 		memset((uint8_t *)buf + size - bytes, 0xff, bytes);
1803 		memset(buf, 0x00, size - bytes);
1804 		if (extra)
1805 			((uint8_t *)buf)[size - bytes - 1] = conv[extra];
1806 	} else
1807 #endif
1808 	{
1809 		memset(buf, 0xff, bytes);
1810 		memset((uint8_t *)buf + bytes, 0x00, size - bytes);
1811 		if (extra)
1812 			((uint8_t *)buf)[bytes] = conv[extra];
1813 	}
1814 	if (ctx->objmask)
1815 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
1816 	return len;
1817 error:
1818 	push_args(ctx, arg);
1819 	return -1;
1820 }
1821 
1822 /** Default parsing function for token name matching. */
1823 static int
1824 parse_default(struct context *ctx, const struct token *token,
1825 	      const char *str, unsigned int len,
1826 	      void *buf, unsigned int size)
1827 {
1828 	(void)ctx;
1829 	(void)buf;
1830 	(void)size;
1831 	if (strcmp_partial(token->name, str, len))
1832 		return -1;
1833 	return len;
1834 }
1835 
1836 /** Parse flow command, initialize output buffer for subsequent tokens. */
1837 static int
1838 parse_init(struct context *ctx, const struct token *token,
1839 	   const char *str, unsigned int len,
1840 	   void *buf, unsigned int size)
1841 {
1842 	struct buffer *out = buf;
1843 
1844 	/* Token name must match. */
1845 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
1846 		return -1;
1847 	/* Nothing else to do if there is no buffer. */
1848 	if (!out)
1849 		return len;
1850 	/* Make sure buffer is large enough. */
1851 	if (size < sizeof(*out))
1852 		return -1;
1853 	/* Initialize buffer. */
1854 	memset(out, 0x00, sizeof(*out));
1855 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
1856 	ctx->objdata = 0;
1857 	ctx->object = out;
1858 	ctx->objmask = NULL;
1859 	return len;
1860 }
1861 
1862 /** Parse tokens for validate/create commands. */
1863 static int
1864 parse_vc(struct context *ctx, const struct token *token,
1865 	 const char *str, unsigned int len,
1866 	 void *buf, unsigned int size)
1867 {
1868 	struct buffer *out = buf;
1869 	uint8_t *data;
1870 	uint32_t data_size;
1871 
1872 	/* Token name must match. */
1873 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
1874 		return -1;
1875 	/* Nothing else to do if there is no buffer. */
1876 	if (!out)
1877 		return len;
1878 	if (!out->command) {
1879 		if (ctx->curr != VALIDATE && ctx->curr != CREATE)
1880 			return -1;
1881 		if (sizeof(*out) > size)
1882 			return -1;
1883 		out->command = ctx->curr;
1884 		ctx->objdata = 0;
1885 		ctx->object = out;
1886 		ctx->objmask = NULL;
1887 		out->args.vc.data = (uint8_t *)out + size;
1888 		return len;
1889 	}
1890 	ctx->objdata = 0;
1891 	ctx->object = &out->args.vc.attr;
1892 	ctx->objmask = NULL;
1893 	switch (ctx->curr) {
1894 	case GROUP:
1895 	case PRIORITY:
1896 		return len;
1897 	case INGRESS:
1898 		out->args.vc.attr.ingress = 1;
1899 		return len;
1900 	case EGRESS:
1901 		out->args.vc.attr.egress = 1;
1902 		return len;
1903 	case PATTERN:
1904 		out->args.vc.pattern =
1905 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
1906 					       sizeof(double));
1907 		ctx->object = out->args.vc.pattern;
1908 		ctx->objmask = NULL;
1909 		return len;
1910 	case ACTIONS:
1911 		out->args.vc.actions =
1912 			(void *)RTE_ALIGN_CEIL((uintptr_t)
1913 					       (out->args.vc.pattern +
1914 						out->args.vc.pattern_n),
1915 					       sizeof(double));
1916 		ctx->object = out->args.vc.actions;
1917 		ctx->objmask = NULL;
1918 		return len;
1919 	default:
1920 		if (!token->priv)
1921 			return -1;
1922 		break;
1923 	}
1924 	if (!out->args.vc.actions) {
1925 		const struct parse_item_priv *priv = token->priv;
1926 		struct rte_flow_item *item =
1927 			out->args.vc.pattern + out->args.vc.pattern_n;
1928 
1929 		data_size = priv->size * 3; /* spec, last, mask */
1930 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
1931 					       (out->args.vc.data - data_size),
1932 					       sizeof(double));
1933 		if ((uint8_t *)item + sizeof(*item) > data)
1934 			return -1;
1935 		*item = (struct rte_flow_item){
1936 			.type = priv->type,
1937 		};
1938 		++out->args.vc.pattern_n;
1939 		ctx->object = item;
1940 		ctx->objmask = NULL;
1941 	} else {
1942 		const struct parse_action_priv *priv = token->priv;
1943 		struct rte_flow_action *action =
1944 			out->args.vc.actions + out->args.vc.actions_n;
1945 
1946 		data_size = priv->size; /* configuration */
1947 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
1948 					       (out->args.vc.data - data_size),
1949 					       sizeof(double));
1950 		if ((uint8_t *)action + sizeof(*action) > data)
1951 			return -1;
1952 		*action = (struct rte_flow_action){
1953 			.type = priv->type,
1954 			.conf = data_size ? data : NULL,
1955 		};
1956 		++out->args.vc.actions_n;
1957 		ctx->object = action;
1958 		ctx->objmask = NULL;
1959 	}
1960 	memset(data, 0, data_size);
1961 	out->args.vc.data = data;
1962 	ctx->objdata = data_size;
1963 	return len;
1964 }
1965 
1966 /** Parse pattern item parameter type. */
1967 static int
1968 parse_vc_spec(struct context *ctx, const struct token *token,
1969 	      const char *str, unsigned int len,
1970 	      void *buf, unsigned int size)
1971 {
1972 	struct buffer *out = buf;
1973 	struct rte_flow_item *item;
1974 	uint32_t data_size;
1975 	int index;
1976 	int objmask = 0;
1977 
1978 	(void)size;
1979 	/* Token name must match. */
1980 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
1981 		return -1;
1982 	/* Parse parameter types. */
1983 	switch (ctx->curr) {
1984 		static const enum index prefix[] = NEXT_ENTRY(PREFIX);
1985 
1986 	case ITEM_PARAM_IS:
1987 		index = 0;
1988 		objmask = 1;
1989 		break;
1990 	case ITEM_PARAM_SPEC:
1991 		index = 0;
1992 		break;
1993 	case ITEM_PARAM_LAST:
1994 		index = 1;
1995 		break;
1996 	case ITEM_PARAM_PREFIX:
1997 		/* Modify next token to expect a prefix. */
1998 		if (ctx->next_num < 2)
1999 			return -1;
2000 		ctx->next[ctx->next_num - 2] = prefix;
2001 		/* Fall through. */
2002 	case ITEM_PARAM_MASK:
2003 		index = 2;
2004 		break;
2005 	default:
2006 		return -1;
2007 	}
2008 	/* Nothing else to do if there is no buffer. */
2009 	if (!out)
2010 		return len;
2011 	if (!out->args.vc.pattern_n)
2012 		return -1;
2013 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
2014 	data_size = ctx->objdata / 3; /* spec, last, mask */
2015 	/* Point to selected object. */
2016 	ctx->object = out->args.vc.data + (data_size * index);
2017 	if (objmask) {
2018 		ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
2019 		item->mask = ctx->objmask;
2020 	} else
2021 		ctx->objmask = NULL;
2022 	/* Update relevant item pointer. */
2023 	*((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
2024 		ctx->object;
2025 	return len;
2026 }
2027 
2028 /** Parse action configuration field. */
2029 static int
2030 parse_vc_conf(struct context *ctx, const struct token *token,
2031 	      const char *str, unsigned int len,
2032 	      void *buf, unsigned int size)
2033 {
2034 	struct buffer *out = buf;
2035 
2036 	(void)size;
2037 	/* Token name must match. */
2038 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
2039 		return -1;
2040 	/* Nothing else to do if there is no buffer. */
2041 	if (!out)
2042 		return len;
2043 	/* Point to selected object. */
2044 	ctx->object = out->args.vc.data;
2045 	ctx->objmask = NULL;
2046 	return len;
2047 }
2048 
2049 /** Parse RSS action. */
2050 static int
2051 parse_vc_action_rss(struct context *ctx, const struct token *token,
2052 		    const char *str, unsigned int len,
2053 		    void *buf, unsigned int size)
2054 {
2055 	struct buffer *out = buf;
2056 	struct rte_flow_action *action;
2057 	struct action_rss_data *action_rss_data;
2058 	unsigned int i;
2059 	int ret;
2060 
2061 	ret = parse_vc(ctx, token, str, len, buf, size);
2062 	if (ret < 0)
2063 		return ret;
2064 	/* Nothing else to do if there is no buffer. */
2065 	if (!out)
2066 		return ret;
2067 	if (!out->args.vc.actions_n)
2068 		return -1;
2069 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
2070 	/* Point to selected object. */
2071 	ctx->object = out->args.vc.data;
2072 	ctx->objmask = NULL;
2073 	/* Set up default configuration. */
2074 	action_rss_data = ctx->object;
2075 	*action_rss_data = (struct action_rss_data){
2076 		.conf = (struct rte_flow_action_rss){
2077 			.types = rss_hf,
2078 			.key_len = sizeof(action_rss_data->key),
2079 			.queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
2080 			.key = action_rss_data->key,
2081 			.queue = action_rss_data->queue,
2082 		},
2083 		.key = "testpmd's default RSS hash key",
2084 		.queue = { 0 },
2085 	};
2086 	for (i = 0; i < action_rss_data->conf.queue_num; ++i)
2087 		action_rss_data->queue[i] = i;
2088 	if (!port_id_is_invalid(ctx->port, DISABLED_WARN) &&
2089 	    ctx->port != (portid_t)RTE_PORT_ALL) {
2090 		struct rte_eth_dev_info info;
2091 
2092 		rte_eth_dev_info_get(ctx->port, &info);
2093 		action_rss_data->conf.key_len =
2094 			RTE_MIN(sizeof(action_rss_data->key),
2095 				info.hash_key_size);
2096 	}
2097 	action->conf = &action_rss_data->conf;
2098 	return ret;
2099 }
2100 
2101 /**
2102  * Parse type field for RSS action.
2103  *
2104  * Valid tokens are type field names and the "end" token.
2105  */
2106 static int
2107 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
2108 			  const char *str, unsigned int len,
2109 			  void *buf, unsigned int size)
2110 {
2111 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
2112 	struct action_rss_data *action_rss_data;
2113 	unsigned int i;
2114 
2115 	(void)token;
2116 	(void)buf;
2117 	(void)size;
2118 	if (ctx->curr != ACTION_RSS_TYPE)
2119 		return -1;
2120 	if (!(ctx->objdata >> 16) && ctx->object) {
2121 		action_rss_data = ctx->object;
2122 		action_rss_data->conf.types = 0;
2123 	}
2124 	if (!strcmp_partial("end", str, len)) {
2125 		ctx->objdata &= 0xffff;
2126 		return len;
2127 	}
2128 	for (i = 0; rss_type_table[i].str; ++i)
2129 		if (!strcmp_partial(rss_type_table[i].str, str, len))
2130 			break;
2131 	if (!rss_type_table[i].str)
2132 		return -1;
2133 	ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
2134 	/* Repeat token. */
2135 	if (ctx->next_num == RTE_DIM(ctx->next))
2136 		return -1;
2137 	ctx->next[ctx->next_num++] = next;
2138 	if (!ctx->object)
2139 		return len;
2140 	action_rss_data = ctx->object;
2141 	action_rss_data->conf.types |= rss_type_table[i].rss_type;
2142 	return len;
2143 }
2144 
2145 /**
2146  * Parse queue field for RSS action.
2147  *
2148  * Valid tokens are queue indices and the "end" token.
2149  */
2150 static int
2151 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
2152 			  const char *str, unsigned int len,
2153 			  void *buf, unsigned int size)
2154 {
2155 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
2156 	struct action_rss_data *action_rss_data;
2157 	int ret;
2158 	int i;
2159 
2160 	(void)token;
2161 	(void)buf;
2162 	(void)size;
2163 	if (ctx->curr != ACTION_RSS_QUEUE)
2164 		return -1;
2165 	i = ctx->objdata >> 16;
2166 	if (!strcmp_partial("end", str, len)) {
2167 		ctx->objdata &= 0xffff;
2168 		return len;
2169 	}
2170 	if (i >= ACTION_RSS_QUEUE_NUM)
2171 		return -1;
2172 	if (push_args(ctx,
2173 		      ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
2174 				     i * sizeof(action_rss_data->queue[i]),
2175 				     sizeof(action_rss_data->queue[i]))))
2176 		return -1;
2177 	ret = parse_int(ctx, token, str, len, NULL, 0);
2178 	if (ret < 0) {
2179 		pop_args(ctx);
2180 		return -1;
2181 	}
2182 	++i;
2183 	ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
2184 	/* Repeat token. */
2185 	if (ctx->next_num == RTE_DIM(ctx->next))
2186 		return -1;
2187 	ctx->next[ctx->next_num++] = next;
2188 	if (!ctx->object)
2189 		return len;
2190 	action_rss_data = ctx->object;
2191 	action_rss_data->conf.queue_num = i;
2192 	action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
2193 	return len;
2194 }
2195 
2196 /** Parse tokens for destroy command. */
2197 static int
2198 parse_destroy(struct context *ctx, const struct token *token,
2199 	      const char *str, unsigned int len,
2200 	      void *buf, unsigned int size)
2201 {
2202 	struct buffer *out = buf;
2203 
2204 	/* Token name must match. */
2205 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
2206 		return -1;
2207 	/* Nothing else to do if there is no buffer. */
2208 	if (!out)
2209 		return len;
2210 	if (!out->command) {
2211 		if (ctx->curr != DESTROY)
2212 			return -1;
2213 		if (sizeof(*out) > size)
2214 			return -1;
2215 		out->command = ctx->curr;
2216 		ctx->objdata = 0;
2217 		ctx->object = out;
2218 		ctx->objmask = NULL;
2219 		out->args.destroy.rule =
2220 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
2221 					       sizeof(double));
2222 		return len;
2223 	}
2224 	if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
2225 	     sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
2226 		return -1;
2227 	ctx->objdata = 0;
2228 	ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
2229 	ctx->objmask = NULL;
2230 	return len;
2231 }
2232 
2233 /** Parse tokens for flush command. */
2234 static int
2235 parse_flush(struct context *ctx, const struct token *token,
2236 	    const char *str, unsigned int len,
2237 	    void *buf, unsigned int size)
2238 {
2239 	struct buffer *out = buf;
2240 
2241 	/* Token name must match. */
2242 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
2243 		return -1;
2244 	/* Nothing else to do if there is no buffer. */
2245 	if (!out)
2246 		return len;
2247 	if (!out->command) {
2248 		if (ctx->curr != FLUSH)
2249 			return -1;
2250 		if (sizeof(*out) > size)
2251 			return -1;
2252 		out->command = ctx->curr;
2253 		ctx->objdata = 0;
2254 		ctx->object = out;
2255 		ctx->objmask = NULL;
2256 	}
2257 	return len;
2258 }
2259 
2260 /** Parse tokens for query command. */
2261 static int
2262 parse_query(struct context *ctx, const struct token *token,
2263 	    const char *str, unsigned int len,
2264 	    void *buf, unsigned int size)
2265 {
2266 	struct buffer *out = buf;
2267 
2268 	/* Token name must match. */
2269 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
2270 		return -1;
2271 	/* Nothing else to do if there is no buffer. */
2272 	if (!out)
2273 		return len;
2274 	if (!out->command) {
2275 		if (ctx->curr != QUERY)
2276 			return -1;
2277 		if (sizeof(*out) > size)
2278 			return -1;
2279 		out->command = ctx->curr;
2280 		ctx->objdata = 0;
2281 		ctx->object = out;
2282 		ctx->objmask = NULL;
2283 	}
2284 	return len;
2285 }
2286 
2287 /** Parse action names. */
2288 static int
2289 parse_action(struct context *ctx, const struct token *token,
2290 	     const char *str, unsigned int len,
2291 	     void *buf, unsigned int size)
2292 {
2293 	struct buffer *out = buf;
2294 	const struct arg *arg = pop_args(ctx);
2295 	unsigned int i;
2296 
2297 	(void)size;
2298 	/* Argument is expected. */
2299 	if (!arg)
2300 		return -1;
2301 	/* Parse action name. */
2302 	for (i = 0; next_action[i]; ++i) {
2303 		const struct parse_action_priv *priv;
2304 
2305 		token = &token_list[next_action[i]];
2306 		if (strcmp_partial(token->name, str, len))
2307 			continue;
2308 		priv = token->priv;
2309 		if (!priv)
2310 			goto error;
2311 		if (out)
2312 			memcpy((uint8_t *)ctx->object + arg->offset,
2313 			       &priv->type,
2314 			       arg->size);
2315 		return len;
2316 	}
2317 error:
2318 	push_args(ctx, arg);
2319 	return -1;
2320 }
2321 
2322 /** Parse tokens for list command. */
2323 static int
2324 parse_list(struct context *ctx, const struct token *token,
2325 	   const char *str, unsigned int len,
2326 	   void *buf, unsigned int size)
2327 {
2328 	struct buffer *out = buf;
2329 
2330 	/* Token name must match. */
2331 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
2332 		return -1;
2333 	/* Nothing else to do if there is no buffer. */
2334 	if (!out)
2335 		return len;
2336 	if (!out->command) {
2337 		if (ctx->curr != LIST)
2338 			return -1;
2339 		if (sizeof(*out) > size)
2340 			return -1;
2341 		out->command = ctx->curr;
2342 		ctx->objdata = 0;
2343 		ctx->object = out;
2344 		ctx->objmask = NULL;
2345 		out->args.list.group =
2346 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
2347 					       sizeof(double));
2348 		return len;
2349 	}
2350 	if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
2351 	     sizeof(*out->args.list.group)) > (uint8_t *)out + size)
2352 		return -1;
2353 	ctx->objdata = 0;
2354 	ctx->object = out->args.list.group + out->args.list.group_n++;
2355 	ctx->objmask = NULL;
2356 	return len;
2357 }
2358 
2359 /** Parse tokens for isolate command. */
2360 static int
2361 parse_isolate(struct context *ctx, const struct token *token,
2362 	      const char *str, unsigned int len,
2363 	      void *buf, unsigned int size)
2364 {
2365 	struct buffer *out = buf;
2366 
2367 	/* Token name must match. */
2368 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
2369 		return -1;
2370 	/* Nothing else to do if there is no buffer. */
2371 	if (!out)
2372 		return len;
2373 	if (!out->command) {
2374 		if (ctx->curr != ISOLATE)
2375 			return -1;
2376 		if (sizeof(*out) > size)
2377 			return -1;
2378 		out->command = ctx->curr;
2379 		ctx->objdata = 0;
2380 		ctx->object = out;
2381 		ctx->objmask = NULL;
2382 	}
2383 	return len;
2384 }
2385 
2386 /**
2387  * Parse signed/unsigned integers 8 to 64-bit long.
2388  *
2389  * Last argument (ctx->args) is retrieved to determine integer type and
2390  * storage location.
2391  */
2392 static int
2393 parse_int(struct context *ctx, const struct token *token,
2394 	  const char *str, unsigned int len,
2395 	  void *buf, unsigned int size)
2396 {
2397 	const struct arg *arg = pop_args(ctx);
2398 	uintmax_t u;
2399 	char *end;
2400 
2401 	(void)token;
2402 	/* Argument is expected. */
2403 	if (!arg)
2404 		return -1;
2405 	errno = 0;
2406 	u = arg->sign ?
2407 		(uintmax_t)strtoimax(str, &end, 0) :
2408 		strtoumax(str, &end, 0);
2409 	if (errno || (size_t)(end - str) != len)
2410 		goto error;
2411 	if (arg->bounded &&
2412 	    ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
2413 			    (intmax_t)u > (intmax_t)arg->max)) ||
2414 	     (!arg->sign && (u < arg->min || u > arg->max))))
2415 		goto error;
2416 	if (!ctx->object)
2417 		return len;
2418 	if (arg->mask) {
2419 		if (!arg_entry_bf_fill(ctx->object, u, arg) ||
2420 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
2421 			goto error;
2422 		return len;
2423 	}
2424 	buf = (uint8_t *)ctx->object + arg->offset;
2425 	size = arg->size;
2426 objmask:
2427 	switch (size) {
2428 	case sizeof(uint8_t):
2429 		*(uint8_t *)buf = u;
2430 		break;
2431 	case sizeof(uint16_t):
2432 		*(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
2433 		break;
2434 	case sizeof(uint8_t [3]):
2435 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
2436 		if (!arg->hton) {
2437 			((uint8_t *)buf)[0] = u;
2438 			((uint8_t *)buf)[1] = u >> 8;
2439 			((uint8_t *)buf)[2] = u >> 16;
2440 			break;
2441 		}
2442 #endif
2443 		((uint8_t *)buf)[0] = u >> 16;
2444 		((uint8_t *)buf)[1] = u >> 8;
2445 		((uint8_t *)buf)[2] = u;
2446 		break;
2447 	case sizeof(uint32_t):
2448 		*(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
2449 		break;
2450 	case sizeof(uint64_t):
2451 		*(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
2452 		break;
2453 	default:
2454 		goto error;
2455 	}
2456 	if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
2457 		u = -1;
2458 		buf = (uint8_t *)ctx->objmask + arg->offset;
2459 		goto objmask;
2460 	}
2461 	return len;
2462 error:
2463 	push_args(ctx, arg);
2464 	return -1;
2465 }
2466 
2467 /**
2468  * Parse a string.
2469  *
2470  * Three arguments (ctx->args) are retrieved from the stack to store data,
2471  * its actual length and address (in that order).
2472  */
2473 static int
2474 parse_string(struct context *ctx, const struct token *token,
2475 	     const char *str, unsigned int len,
2476 	     void *buf, unsigned int size)
2477 {
2478 	const struct arg *arg_data = pop_args(ctx);
2479 	const struct arg *arg_len = pop_args(ctx);
2480 	const struct arg *arg_addr = pop_args(ctx);
2481 	char tmp[16]; /* Ought to be enough. */
2482 	int ret;
2483 
2484 	/* Arguments are expected. */
2485 	if (!arg_data)
2486 		return -1;
2487 	if (!arg_len) {
2488 		push_args(ctx, arg_data);
2489 		return -1;
2490 	}
2491 	if (!arg_addr) {
2492 		push_args(ctx, arg_len);
2493 		push_args(ctx, arg_data);
2494 		return -1;
2495 	}
2496 	size = arg_data->size;
2497 	/* Bit-mask fill is not supported. */
2498 	if (arg_data->mask || size < len)
2499 		goto error;
2500 	if (!ctx->object)
2501 		return len;
2502 	/* Let parse_int() fill length information first. */
2503 	ret = snprintf(tmp, sizeof(tmp), "%u", len);
2504 	if (ret < 0)
2505 		goto error;
2506 	push_args(ctx, arg_len);
2507 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
2508 	if (ret < 0) {
2509 		pop_args(ctx);
2510 		goto error;
2511 	}
2512 	buf = (uint8_t *)ctx->object + arg_data->offset;
2513 	/* Output buffer is not necessarily NUL-terminated. */
2514 	memcpy(buf, str, len);
2515 	memset((uint8_t *)buf + len, 0x00, size - len);
2516 	if (ctx->objmask)
2517 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
2518 	/* Save address if requested. */
2519 	if (arg_addr->size) {
2520 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
2521 		       (void *[]){
2522 			(uint8_t *)ctx->object + arg_data->offset
2523 		       },
2524 		       arg_addr->size);
2525 		if (ctx->objmask)
2526 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
2527 			       (void *[]){
2528 				(uint8_t *)ctx->objmask + arg_data->offset
2529 			       },
2530 			       arg_addr->size);
2531 	}
2532 	return len;
2533 error:
2534 	push_args(ctx, arg_addr);
2535 	push_args(ctx, arg_len);
2536 	push_args(ctx, arg_data);
2537 	return -1;
2538 }
2539 
2540 /**
2541  * Parse a MAC address.
2542  *
2543  * Last argument (ctx->args) is retrieved to determine storage size and
2544  * location.
2545  */
2546 static int
2547 parse_mac_addr(struct context *ctx, const struct token *token,
2548 	       const char *str, unsigned int len,
2549 	       void *buf, unsigned int size)
2550 {
2551 	const struct arg *arg = pop_args(ctx);
2552 	struct ether_addr tmp;
2553 	int ret;
2554 
2555 	(void)token;
2556 	/* Argument is expected. */
2557 	if (!arg)
2558 		return -1;
2559 	size = arg->size;
2560 	/* Bit-mask fill is not supported. */
2561 	if (arg->mask || size != sizeof(tmp))
2562 		goto error;
2563 	/* Only network endian is supported. */
2564 	if (!arg->hton)
2565 		goto error;
2566 	ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
2567 	if (ret < 0 || (unsigned int)ret != len)
2568 		goto error;
2569 	if (!ctx->object)
2570 		return len;
2571 	buf = (uint8_t *)ctx->object + arg->offset;
2572 	memcpy(buf, &tmp, size);
2573 	if (ctx->objmask)
2574 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
2575 	return len;
2576 error:
2577 	push_args(ctx, arg);
2578 	return -1;
2579 }
2580 
2581 /**
2582  * Parse an IPv4 address.
2583  *
2584  * Last argument (ctx->args) is retrieved to determine storage size and
2585  * location.
2586  */
2587 static int
2588 parse_ipv4_addr(struct context *ctx, const struct token *token,
2589 		const char *str, unsigned int len,
2590 		void *buf, unsigned int size)
2591 {
2592 	const struct arg *arg = pop_args(ctx);
2593 	char str2[len + 1];
2594 	struct in_addr tmp;
2595 	int ret;
2596 
2597 	/* Argument is expected. */
2598 	if (!arg)
2599 		return -1;
2600 	size = arg->size;
2601 	/* Bit-mask fill is not supported. */
2602 	if (arg->mask || size != sizeof(tmp))
2603 		goto error;
2604 	/* Only network endian is supported. */
2605 	if (!arg->hton)
2606 		goto error;
2607 	memcpy(str2, str, len);
2608 	str2[len] = '\0';
2609 	ret = inet_pton(AF_INET, str2, &tmp);
2610 	if (ret != 1) {
2611 		/* Attempt integer parsing. */
2612 		push_args(ctx, arg);
2613 		return parse_int(ctx, token, str, len, buf, size);
2614 	}
2615 	if (!ctx->object)
2616 		return len;
2617 	buf = (uint8_t *)ctx->object + arg->offset;
2618 	memcpy(buf, &tmp, size);
2619 	if (ctx->objmask)
2620 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
2621 	return len;
2622 error:
2623 	push_args(ctx, arg);
2624 	return -1;
2625 }
2626 
2627 /**
2628  * Parse an IPv6 address.
2629  *
2630  * Last argument (ctx->args) is retrieved to determine storage size and
2631  * location.
2632  */
2633 static int
2634 parse_ipv6_addr(struct context *ctx, const struct token *token,
2635 		const char *str, unsigned int len,
2636 		void *buf, unsigned int size)
2637 {
2638 	const struct arg *arg = pop_args(ctx);
2639 	char str2[len + 1];
2640 	struct in6_addr tmp;
2641 	int ret;
2642 
2643 	(void)token;
2644 	/* Argument is expected. */
2645 	if (!arg)
2646 		return -1;
2647 	size = arg->size;
2648 	/* Bit-mask fill is not supported. */
2649 	if (arg->mask || size != sizeof(tmp))
2650 		goto error;
2651 	/* Only network endian is supported. */
2652 	if (!arg->hton)
2653 		goto error;
2654 	memcpy(str2, str, len);
2655 	str2[len] = '\0';
2656 	ret = inet_pton(AF_INET6, str2, &tmp);
2657 	if (ret != 1)
2658 		goto error;
2659 	if (!ctx->object)
2660 		return len;
2661 	buf = (uint8_t *)ctx->object + arg->offset;
2662 	memcpy(buf, &tmp, size);
2663 	if (ctx->objmask)
2664 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
2665 	return len;
2666 error:
2667 	push_args(ctx, arg);
2668 	return -1;
2669 }
2670 
2671 /** Boolean values (even indices stand for false). */
2672 static const char *const boolean_name[] = {
2673 	"0", "1",
2674 	"false", "true",
2675 	"no", "yes",
2676 	"N", "Y",
2677 	"off", "on",
2678 	NULL,
2679 };
2680 
2681 /**
2682  * Parse a boolean value.
2683  *
2684  * Last argument (ctx->args) is retrieved to determine storage size and
2685  * location.
2686  */
2687 static int
2688 parse_boolean(struct context *ctx, const struct token *token,
2689 	      const char *str, unsigned int len,
2690 	      void *buf, unsigned int size)
2691 {
2692 	const struct arg *arg = pop_args(ctx);
2693 	unsigned int i;
2694 	int ret;
2695 
2696 	/* Argument is expected. */
2697 	if (!arg)
2698 		return -1;
2699 	for (i = 0; boolean_name[i]; ++i)
2700 		if (!strcmp_partial(boolean_name[i], str, len))
2701 			break;
2702 	/* Process token as integer. */
2703 	if (boolean_name[i])
2704 		str = i & 1 ? "1" : "0";
2705 	push_args(ctx, arg);
2706 	ret = parse_int(ctx, token, str, strlen(str), buf, size);
2707 	return ret > 0 ? (int)len : ret;
2708 }
2709 
2710 /** Parse port and update context. */
2711 static int
2712 parse_port(struct context *ctx, const struct token *token,
2713 	   const char *str, unsigned int len,
2714 	   void *buf, unsigned int size)
2715 {
2716 	struct buffer *out = &(struct buffer){ .port = 0 };
2717 	int ret;
2718 
2719 	if (buf)
2720 		out = buf;
2721 	else {
2722 		ctx->objdata = 0;
2723 		ctx->object = out;
2724 		ctx->objmask = NULL;
2725 		size = sizeof(*out);
2726 	}
2727 	ret = parse_int(ctx, token, str, len, out, size);
2728 	if (ret >= 0)
2729 		ctx->port = out->port;
2730 	if (!buf)
2731 		ctx->object = NULL;
2732 	return ret;
2733 }
2734 
2735 /** No completion. */
2736 static int
2737 comp_none(struct context *ctx, const struct token *token,
2738 	  unsigned int ent, char *buf, unsigned int size)
2739 {
2740 	(void)ctx;
2741 	(void)token;
2742 	(void)ent;
2743 	(void)buf;
2744 	(void)size;
2745 	return 0;
2746 }
2747 
2748 /** Complete boolean values. */
2749 static int
2750 comp_boolean(struct context *ctx, const struct token *token,
2751 	     unsigned int ent, char *buf, unsigned int size)
2752 {
2753 	unsigned int i;
2754 
2755 	(void)ctx;
2756 	(void)token;
2757 	for (i = 0; boolean_name[i]; ++i)
2758 		if (buf && i == ent)
2759 			return snprintf(buf, size, "%s", boolean_name[i]);
2760 	if (buf)
2761 		return -1;
2762 	return i;
2763 }
2764 
2765 /** Complete action names. */
2766 static int
2767 comp_action(struct context *ctx, const struct token *token,
2768 	    unsigned int ent, char *buf, unsigned int size)
2769 {
2770 	unsigned int i;
2771 
2772 	(void)ctx;
2773 	(void)token;
2774 	for (i = 0; next_action[i]; ++i)
2775 		if (buf && i == ent)
2776 			return snprintf(buf, size, "%s",
2777 					token_list[next_action[i]].name);
2778 	if (buf)
2779 		return -1;
2780 	return i;
2781 }
2782 
2783 /** Complete available ports. */
2784 static int
2785 comp_port(struct context *ctx, const struct token *token,
2786 	  unsigned int ent, char *buf, unsigned int size)
2787 {
2788 	unsigned int i = 0;
2789 	portid_t p;
2790 
2791 	(void)ctx;
2792 	(void)token;
2793 	RTE_ETH_FOREACH_DEV(p) {
2794 		if (buf && i == ent)
2795 			return snprintf(buf, size, "%u", p);
2796 		++i;
2797 	}
2798 	if (buf)
2799 		return -1;
2800 	return i;
2801 }
2802 
2803 /** Complete available rule IDs. */
2804 static int
2805 comp_rule_id(struct context *ctx, const struct token *token,
2806 	     unsigned int ent, char *buf, unsigned int size)
2807 {
2808 	unsigned int i = 0;
2809 	struct rte_port *port;
2810 	struct port_flow *pf;
2811 
2812 	(void)token;
2813 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
2814 	    ctx->port == (portid_t)RTE_PORT_ALL)
2815 		return -1;
2816 	port = &ports[ctx->port];
2817 	for (pf = port->flow_list; pf != NULL; pf = pf->next) {
2818 		if (buf && i == ent)
2819 			return snprintf(buf, size, "%u", pf->id);
2820 		++i;
2821 	}
2822 	if (buf)
2823 		return -1;
2824 	return i;
2825 }
2826 
2827 /** Complete type field for RSS action. */
2828 static int
2829 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
2830 			unsigned int ent, char *buf, unsigned int size)
2831 {
2832 	unsigned int i;
2833 
2834 	(void)ctx;
2835 	(void)token;
2836 	for (i = 0; rss_type_table[i].str; ++i)
2837 		;
2838 	if (!buf)
2839 		return i + 1;
2840 	if (ent < i)
2841 		return snprintf(buf, size, "%s", rss_type_table[ent].str);
2842 	if (ent == i)
2843 		return snprintf(buf, size, "end");
2844 	return -1;
2845 }
2846 
2847 /** Complete queue field for RSS action. */
2848 static int
2849 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
2850 			 unsigned int ent, char *buf, unsigned int size)
2851 {
2852 	(void)ctx;
2853 	(void)token;
2854 	if (!buf)
2855 		return nb_rxq + 1;
2856 	if (ent < nb_rxq)
2857 		return snprintf(buf, size, "%u", ent);
2858 	if (ent == nb_rxq)
2859 		return snprintf(buf, size, "end");
2860 	return -1;
2861 }
2862 
2863 /** Internal context. */
2864 static struct context cmd_flow_context;
2865 
2866 /** Global parser instance (cmdline API). */
2867 cmdline_parse_inst_t cmd_flow;
2868 
2869 /** Initialize context. */
2870 static void
2871 cmd_flow_context_init(struct context *ctx)
2872 {
2873 	/* A full memset() is not necessary. */
2874 	ctx->curr = ZERO;
2875 	ctx->prev = ZERO;
2876 	ctx->next_num = 0;
2877 	ctx->args_num = 0;
2878 	ctx->eol = 0;
2879 	ctx->last = 0;
2880 	ctx->port = 0;
2881 	ctx->objdata = 0;
2882 	ctx->object = NULL;
2883 	ctx->objmask = NULL;
2884 }
2885 
2886 /** Parse a token (cmdline API). */
2887 static int
2888 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
2889 	       unsigned int size)
2890 {
2891 	struct context *ctx = &cmd_flow_context;
2892 	const struct token *token;
2893 	const enum index *list;
2894 	int len;
2895 	int i;
2896 
2897 	(void)hdr;
2898 	token = &token_list[ctx->curr];
2899 	/* Check argument length. */
2900 	ctx->eol = 0;
2901 	ctx->last = 1;
2902 	for (len = 0; src[len]; ++len)
2903 		if (src[len] == '#' || isspace(src[len]))
2904 			break;
2905 	if (!len)
2906 		return -1;
2907 	/* Last argument and EOL detection. */
2908 	for (i = len; src[i]; ++i)
2909 		if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
2910 			break;
2911 		else if (!isspace(src[i])) {
2912 			ctx->last = 0;
2913 			break;
2914 		}
2915 	for (; src[i]; ++i)
2916 		if (src[i] == '\r' || src[i] == '\n') {
2917 			ctx->eol = 1;
2918 			break;
2919 		}
2920 	/* Initialize context if necessary. */
2921 	if (!ctx->next_num) {
2922 		if (!token->next)
2923 			return 0;
2924 		ctx->next[ctx->next_num++] = token->next[0];
2925 	}
2926 	/* Process argument through candidates. */
2927 	ctx->prev = ctx->curr;
2928 	list = ctx->next[ctx->next_num - 1];
2929 	for (i = 0; list[i]; ++i) {
2930 		const struct token *next = &token_list[list[i]];
2931 		int tmp;
2932 
2933 		ctx->curr = list[i];
2934 		if (next->call)
2935 			tmp = next->call(ctx, next, src, len, result, size);
2936 		else
2937 			tmp = parse_default(ctx, next, src, len, result, size);
2938 		if (tmp == -1 || tmp != len)
2939 			continue;
2940 		token = next;
2941 		break;
2942 	}
2943 	if (!list[i])
2944 		return -1;
2945 	--ctx->next_num;
2946 	/* Push subsequent tokens if any. */
2947 	if (token->next)
2948 		for (i = 0; token->next[i]; ++i) {
2949 			if (ctx->next_num == RTE_DIM(ctx->next))
2950 				return -1;
2951 			ctx->next[ctx->next_num++] = token->next[i];
2952 		}
2953 	/* Push arguments if any. */
2954 	if (token->args)
2955 		for (i = 0; token->args[i]; ++i) {
2956 			if (ctx->args_num == RTE_DIM(ctx->args))
2957 				return -1;
2958 			ctx->args[ctx->args_num++] = token->args[i];
2959 		}
2960 	return len;
2961 }
2962 
2963 /** Return number of completion entries (cmdline API). */
2964 static int
2965 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
2966 {
2967 	struct context *ctx = &cmd_flow_context;
2968 	const struct token *token = &token_list[ctx->curr];
2969 	const enum index *list;
2970 	int i;
2971 
2972 	(void)hdr;
2973 	/* Count number of tokens in current list. */
2974 	if (ctx->next_num)
2975 		list = ctx->next[ctx->next_num - 1];
2976 	else
2977 		list = token->next[0];
2978 	for (i = 0; list[i]; ++i)
2979 		;
2980 	if (!i)
2981 		return 0;
2982 	/*
2983 	 * If there is a single token, use its completion callback, otherwise
2984 	 * return the number of entries.
2985 	 */
2986 	token = &token_list[list[0]];
2987 	if (i == 1 && token->comp) {
2988 		/* Save index for cmd_flow_get_help(). */
2989 		ctx->prev = list[0];
2990 		return token->comp(ctx, token, 0, NULL, 0);
2991 	}
2992 	return i;
2993 }
2994 
2995 /** Return a completion entry (cmdline API). */
2996 static int
2997 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
2998 			  char *dst, unsigned int size)
2999 {
3000 	struct context *ctx = &cmd_flow_context;
3001 	const struct token *token = &token_list[ctx->curr];
3002 	const enum index *list;
3003 	int i;
3004 
3005 	(void)hdr;
3006 	/* Count number of tokens in current list. */
3007 	if (ctx->next_num)
3008 		list = ctx->next[ctx->next_num - 1];
3009 	else
3010 		list = token->next[0];
3011 	for (i = 0; list[i]; ++i)
3012 		;
3013 	if (!i)
3014 		return -1;
3015 	/* If there is a single token, use its completion callback. */
3016 	token = &token_list[list[0]];
3017 	if (i == 1 && token->comp) {
3018 		/* Save index for cmd_flow_get_help(). */
3019 		ctx->prev = list[0];
3020 		return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
3021 	}
3022 	/* Otherwise make sure the index is valid and use defaults. */
3023 	if (index >= i)
3024 		return -1;
3025 	token = &token_list[list[index]];
3026 	snprintf(dst, size, "%s", token->name);
3027 	/* Save index for cmd_flow_get_help(). */
3028 	ctx->prev = list[index];
3029 	return 0;
3030 }
3031 
3032 /** Populate help strings for current token (cmdline API). */
3033 static int
3034 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
3035 {
3036 	struct context *ctx = &cmd_flow_context;
3037 	const struct token *token = &token_list[ctx->prev];
3038 
3039 	(void)hdr;
3040 	if (!size)
3041 		return -1;
3042 	/* Set token type and update global help with details. */
3043 	snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
3044 	if (token->help)
3045 		cmd_flow.help_str = token->help;
3046 	else
3047 		cmd_flow.help_str = token->name;
3048 	return 0;
3049 }
3050 
3051 /** Token definition template (cmdline API). */
3052 static struct cmdline_token_hdr cmd_flow_token_hdr = {
3053 	.ops = &(struct cmdline_token_ops){
3054 		.parse = cmd_flow_parse,
3055 		.complete_get_nb = cmd_flow_complete_get_nb,
3056 		.complete_get_elt = cmd_flow_complete_get_elt,
3057 		.get_help = cmd_flow_get_help,
3058 	},
3059 	.offset = 0,
3060 };
3061 
3062 /** Populate the next dynamic token. */
3063 static void
3064 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
3065 	     cmdline_parse_token_hdr_t **hdr_inst)
3066 {
3067 	struct context *ctx = &cmd_flow_context;
3068 
3069 	/* Always reinitialize context before requesting the first token. */
3070 	if (!(hdr_inst - cmd_flow.tokens))
3071 		cmd_flow_context_init(ctx);
3072 	/* Return NULL when no more tokens are expected. */
3073 	if (!ctx->next_num && ctx->curr) {
3074 		*hdr = NULL;
3075 		return;
3076 	}
3077 	/* Determine if command should end here. */
3078 	if (ctx->eol && ctx->last && ctx->next_num) {
3079 		const enum index *list = ctx->next[ctx->next_num - 1];
3080 		int i;
3081 
3082 		for (i = 0; list[i]; ++i) {
3083 			if (list[i] != END)
3084 				continue;
3085 			*hdr = NULL;
3086 			return;
3087 		}
3088 	}
3089 	*hdr = &cmd_flow_token_hdr;
3090 }
3091 
3092 /** Dispatch parsed buffer to function calls. */
3093 static void
3094 cmd_flow_parsed(const struct buffer *in)
3095 {
3096 	switch (in->command) {
3097 	case VALIDATE:
3098 		port_flow_validate(in->port, &in->args.vc.attr,
3099 				   in->args.vc.pattern, in->args.vc.actions);
3100 		break;
3101 	case CREATE:
3102 		port_flow_create(in->port, &in->args.vc.attr,
3103 				 in->args.vc.pattern, in->args.vc.actions);
3104 		break;
3105 	case DESTROY:
3106 		port_flow_destroy(in->port, in->args.destroy.rule_n,
3107 				  in->args.destroy.rule);
3108 		break;
3109 	case FLUSH:
3110 		port_flow_flush(in->port);
3111 		break;
3112 	case QUERY:
3113 		port_flow_query(in->port, in->args.query.rule,
3114 				in->args.query.action);
3115 		break;
3116 	case LIST:
3117 		port_flow_list(in->port, in->args.list.group_n,
3118 			       in->args.list.group);
3119 		break;
3120 	case ISOLATE:
3121 		port_flow_isolate(in->port, in->args.isolate.set);
3122 		break;
3123 	default:
3124 		break;
3125 	}
3126 }
3127 
3128 /** Token generator and output processing callback (cmdline API). */
3129 static void
3130 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
3131 {
3132 	if (cl == NULL)
3133 		cmd_flow_tok(arg0, arg2);
3134 	else
3135 		cmd_flow_parsed(arg0);
3136 }
3137 
3138 /** Global parser instance (cmdline API). */
3139 cmdline_parse_inst_t cmd_flow = {
3140 	.f = cmd_flow_cb,
3141 	.data = NULL, /**< Unused. */
3142 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
3143 	.tokens = {
3144 		NULL,
3145 	}, /**< Tokens are returned by cmd_flow_tok(). */
3146 };
3147