xref: /dpdk/app/test-pmd/cmdline_flow.c (revision a997a33b2a0145ad3e6320ea1fc7df8d51a2fcdf)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright 2016 6WIND S.A.
5  *   Copyright 2016 Mellanox.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of 6WIND S.A. nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <stddef.h>
35 #include <stdint.h>
36 #include <stdio.h>
37 #include <inttypes.h>
38 #include <errno.h>
39 #include <ctype.h>
40 #include <string.h>
41 #include <arpa/inet.h>
42 
43 #include <rte_common.h>
44 #include <rte_ethdev.h>
45 #include <rte_byteorder.h>
46 #include <cmdline_parse.h>
47 #include <cmdline_parse_etheraddr.h>
48 #include <rte_flow.h>
49 
50 #include "testpmd.h"
51 
52 /** Parser token indices. */
53 enum index {
54 	/* Special tokens. */
55 	ZERO = 0,
56 	END,
57 
58 	/* Common tokens. */
59 	INTEGER,
60 	UNSIGNED,
61 	PREFIX,
62 	BOOLEAN,
63 	STRING,
64 	MAC_ADDR,
65 	IPV4_ADDR,
66 	IPV6_ADDR,
67 	RULE_ID,
68 	PORT_ID,
69 	GROUP_ID,
70 	PRIORITY_LEVEL,
71 
72 	/* Top-level command. */
73 	FLOW,
74 
75 	/* Sub-level commands. */
76 	VALIDATE,
77 	CREATE,
78 	DESTROY,
79 	FLUSH,
80 	QUERY,
81 	LIST,
82 
83 	/* Destroy arguments. */
84 	DESTROY_RULE,
85 
86 	/* Query arguments. */
87 	QUERY_ACTION,
88 
89 	/* List arguments. */
90 	LIST_GROUP,
91 
92 	/* Validate/create arguments. */
93 	GROUP,
94 	PRIORITY,
95 	INGRESS,
96 	EGRESS,
97 
98 	/* Validate/create pattern. */
99 	PATTERN,
100 	ITEM_PARAM_IS,
101 	ITEM_PARAM_SPEC,
102 	ITEM_PARAM_LAST,
103 	ITEM_PARAM_MASK,
104 	ITEM_PARAM_PREFIX,
105 	ITEM_NEXT,
106 	ITEM_END,
107 	ITEM_VOID,
108 	ITEM_INVERT,
109 	ITEM_ANY,
110 	ITEM_ANY_NUM,
111 	ITEM_PF,
112 	ITEM_VF,
113 	ITEM_VF_ID,
114 	ITEM_PORT,
115 	ITEM_PORT_INDEX,
116 	ITEM_RAW,
117 	ITEM_RAW_RELATIVE,
118 	ITEM_RAW_SEARCH,
119 	ITEM_RAW_OFFSET,
120 	ITEM_RAW_LIMIT,
121 	ITEM_RAW_PATTERN,
122 	ITEM_ETH,
123 	ITEM_ETH_DST,
124 	ITEM_ETH_SRC,
125 	ITEM_ETH_TYPE,
126 	ITEM_VLAN,
127 	ITEM_VLAN_TPID,
128 	ITEM_VLAN_TCI,
129 	ITEM_IPV4,
130 	ITEM_IPV4_SRC,
131 	ITEM_IPV4_DST,
132 	ITEM_IPV6,
133 	ITEM_IPV6_SRC,
134 	ITEM_IPV6_DST,
135 	ITEM_ICMP,
136 	ITEM_ICMP_TYPE,
137 	ITEM_ICMP_CODE,
138 	ITEM_UDP,
139 	ITEM_UDP_SRC,
140 	ITEM_UDP_DST,
141 	ITEM_TCP,
142 	ITEM_TCP_SRC,
143 	ITEM_TCP_DST,
144 	ITEM_SCTP,
145 	ITEM_SCTP_SRC,
146 	ITEM_SCTP_DST,
147 	ITEM_VXLAN,
148 	ITEM_VXLAN_VNI,
149 
150 	/* Validate/create actions. */
151 	ACTIONS,
152 	ACTION_NEXT,
153 	ACTION_END,
154 	ACTION_VOID,
155 	ACTION_PASSTHRU,
156 	ACTION_MARK,
157 	ACTION_MARK_ID,
158 	ACTION_FLAG,
159 	ACTION_QUEUE,
160 	ACTION_QUEUE_INDEX,
161 	ACTION_DROP,
162 	ACTION_COUNT,
163 	ACTION_DUP,
164 	ACTION_DUP_INDEX,
165 	ACTION_RSS,
166 	ACTION_RSS_QUEUES,
167 	ACTION_RSS_QUEUE,
168 	ACTION_PF,
169 	ACTION_VF,
170 	ACTION_VF_ORIGINAL,
171 	ACTION_VF_ID,
172 };
173 
174 /** Size of pattern[] field in struct rte_flow_item_raw. */
175 #define ITEM_RAW_PATTERN_SIZE 36
176 
177 /** Storage size for struct rte_flow_item_raw including pattern. */
178 #define ITEM_RAW_SIZE \
179 	(offsetof(struct rte_flow_item_raw, pattern) + ITEM_RAW_PATTERN_SIZE)
180 
181 /** Number of queue[] entries in struct rte_flow_action_rss. */
182 #define ACTION_RSS_NUM 32
183 
184 /** Storage size for struct rte_flow_action_rss including queues. */
185 #define ACTION_RSS_SIZE \
186 	(offsetof(struct rte_flow_action_rss, queue) + \
187 	 sizeof(*((struct rte_flow_action_rss *)0)->queue) * ACTION_RSS_NUM)
188 
189 /** Maximum number of subsequent tokens and arguments on the stack. */
190 #define CTX_STACK_SIZE 16
191 
192 /** Parser context. */
193 struct context {
194 	/** Stack of subsequent token lists to process. */
195 	const enum index *next[CTX_STACK_SIZE];
196 	/** Arguments for stacked tokens. */
197 	const void *args[CTX_STACK_SIZE];
198 	enum index curr; /**< Current token index. */
199 	enum index prev; /**< Index of the last token seen. */
200 	int next_num; /**< Number of entries in next[]. */
201 	int args_num; /**< Number of entries in args[]. */
202 	uint32_t reparse:1; /**< Start over from the beginning. */
203 	uint32_t eol:1; /**< EOL has been detected. */
204 	uint32_t last:1; /**< No more arguments. */
205 	uint16_t port; /**< Current port ID (for completions). */
206 	uint32_t objdata; /**< Object-specific data. */
207 	void *object; /**< Address of current object for relative offsets. */
208 	void *objmask; /**< Object a full mask must be written to. */
209 };
210 
211 /** Token argument. */
212 struct arg {
213 	uint32_t hton:1; /**< Use network byte ordering. */
214 	uint32_t sign:1; /**< Value is signed. */
215 	uint32_t offset; /**< Relative offset from ctx->object. */
216 	uint32_t size; /**< Field size. */
217 	const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
218 };
219 
220 /** Parser token definition. */
221 struct token {
222 	/** Type displayed during completion (defaults to "TOKEN"). */
223 	const char *type;
224 	/** Help displayed during completion (defaults to token name). */
225 	const char *help;
226 	/** Private data used by parser functions. */
227 	const void *priv;
228 	/**
229 	 * Lists of subsequent tokens to push on the stack. Each call to the
230 	 * parser consumes the last entry of that stack.
231 	 */
232 	const enum index *const *next;
233 	/** Arguments stack for subsequent tokens that need them. */
234 	const struct arg *const *args;
235 	/**
236 	 * Token-processing callback, returns -1 in case of error, the
237 	 * length of the matched string otherwise. If NULL, attempts to
238 	 * match the token name.
239 	 *
240 	 * If buf is not NULL, the result should be stored in it according
241 	 * to context. An error is returned if not large enough.
242 	 */
243 	int (*call)(struct context *ctx, const struct token *token,
244 		    const char *str, unsigned int len,
245 		    void *buf, unsigned int size);
246 	/**
247 	 * Callback that provides possible values for this token, used for
248 	 * completion. Returns -1 in case of error, the number of possible
249 	 * values otherwise. If NULL, the token name is used.
250 	 *
251 	 * If buf is not NULL, entry index ent is written to buf and the
252 	 * full length of the entry is returned (same behavior as
253 	 * snprintf()).
254 	 */
255 	int (*comp)(struct context *ctx, const struct token *token,
256 		    unsigned int ent, char *buf, unsigned int size);
257 	/** Mandatory token name, no default value. */
258 	const char *name;
259 };
260 
261 /** Static initializer for the next field. */
262 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
263 
264 /** Static initializer for a NEXT() entry. */
265 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
266 
267 /** Static initializer for the args field. */
268 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
269 
270 /** Static initializer for ARGS() to target a field. */
271 #define ARGS_ENTRY(s, f) \
272 	(&(const struct arg){ \
273 		.offset = offsetof(s, f), \
274 		.size = sizeof(((s *)0)->f), \
275 	})
276 
277 /** Static initializer for ARGS() to target a bit-field. */
278 #define ARGS_ENTRY_BF(s, f, b) \
279 	(&(const struct arg){ \
280 		.size = sizeof(s), \
281 		.mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
282 	})
283 
284 /** Static initializer for ARGS() to target a pointer. */
285 #define ARGS_ENTRY_PTR(s, f) \
286 	(&(const struct arg){ \
287 		.size = sizeof(*((s *)0)->f), \
288 	})
289 
290 /** Static initializer for ARGS() with arbitrary size. */
291 #define ARGS_ENTRY_USZ(s, f, sz) \
292 	(&(const struct arg){ \
293 		.offset = offsetof(s, f), \
294 		.size = (sz), \
295 	})
296 
297 /** Same as ARGS_ENTRY() using network byte ordering. */
298 #define ARGS_ENTRY_HTON(s, f) \
299 	(&(const struct arg){ \
300 		.hton = 1, \
301 		.offset = offsetof(s, f), \
302 		.size = sizeof(((s *)0)->f), \
303 	})
304 
305 /** Parser output buffer layout expected by cmd_flow_parsed(). */
306 struct buffer {
307 	enum index command; /**< Flow command. */
308 	uint16_t port; /**< Affected port ID. */
309 	union {
310 		struct {
311 			struct rte_flow_attr attr;
312 			struct rte_flow_item *pattern;
313 			struct rte_flow_action *actions;
314 			uint32_t pattern_n;
315 			uint32_t actions_n;
316 			uint8_t *data;
317 		} vc; /**< Validate/create arguments. */
318 		struct {
319 			uint32_t *rule;
320 			uint32_t rule_n;
321 		} destroy; /**< Destroy arguments. */
322 		struct {
323 			uint32_t rule;
324 			enum rte_flow_action_type action;
325 		} query; /**< Query arguments. */
326 		struct {
327 			uint32_t *group;
328 			uint32_t group_n;
329 		} list; /**< List arguments. */
330 	} args; /**< Command arguments. */
331 };
332 
333 /** Private data for pattern items. */
334 struct parse_item_priv {
335 	enum rte_flow_item_type type; /**< Item type. */
336 	uint32_t size; /**< Size of item specification structure. */
337 };
338 
339 #define PRIV_ITEM(t, s) \
340 	(&(const struct parse_item_priv){ \
341 		.type = RTE_FLOW_ITEM_TYPE_ ## t, \
342 		.size = s, \
343 	})
344 
345 /** Private data for actions. */
346 struct parse_action_priv {
347 	enum rte_flow_action_type type; /**< Action type. */
348 	uint32_t size; /**< Size of action configuration structure. */
349 };
350 
351 #define PRIV_ACTION(t, s) \
352 	(&(const struct parse_action_priv){ \
353 		.type = RTE_FLOW_ACTION_TYPE_ ## t, \
354 		.size = s, \
355 	})
356 
357 static const enum index next_vc_attr[] = {
358 	GROUP,
359 	PRIORITY,
360 	INGRESS,
361 	EGRESS,
362 	PATTERN,
363 	ZERO,
364 };
365 
366 static const enum index next_destroy_attr[] = {
367 	DESTROY_RULE,
368 	END,
369 	ZERO,
370 };
371 
372 static const enum index next_list_attr[] = {
373 	LIST_GROUP,
374 	END,
375 	ZERO,
376 };
377 
378 static const enum index item_param[] = {
379 	ITEM_PARAM_IS,
380 	ITEM_PARAM_SPEC,
381 	ITEM_PARAM_LAST,
382 	ITEM_PARAM_MASK,
383 	ITEM_PARAM_PREFIX,
384 	ZERO,
385 };
386 
387 static const enum index next_item[] = {
388 	ITEM_END,
389 	ITEM_VOID,
390 	ITEM_INVERT,
391 	ITEM_ANY,
392 	ITEM_PF,
393 	ITEM_VF,
394 	ITEM_PORT,
395 	ITEM_RAW,
396 	ITEM_ETH,
397 	ITEM_VLAN,
398 	ITEM_IPV4,
399 	ITEM_IPV6,
400 	ITEM_ICMP,
401 	ITEM_UDP,
402 	ITEM_TCP,
403 	ITEM_SCTP,
404 	ITEM_VXLAN,
405 	ZERO,
406 };
407 
408 static const enum index item_any[] = {
409 	ITEM_ANY_NUM,
410 	ITEM_NEXT,
411 	ZERO,
412 };
413 
414 static const enum index item_vf[] = {
415 	ITEM_VF_ID,
416 	ITEM_NEXT,
417 	ZERO,
418 };
419 
420 static const enum index item_port[] = {
421 	ITEM_PORT_INDEX,
422 	ITEM_NEXT,
423 	ZERO,
424 };
425 
426 static const enum index item_raw[] = {
427 	ITEM_RAW_RELATIVE,
428 	ITEM_RAW_SEARCH,
429 	ITEM_RAW_OFFSET,
430 	ITEM_RAW_LIMIT,
431 	ITEM_RAW_PATTERN,
432 	ITEM_NEXT,
433 	ZERO,
434 };
435 
436 static const enum index item_eth[] = {
437 	ITEM_ETH_DST,
438 	ITEM_ETH_SRC,
439 	ITEM_ETH_TYPE,
440 	ITEM_NEXT,
441 	ZERO,
442 };
443 
444 static const enum index item_vlan[] = {
445 	ITEM_VLAN_TPID,
446 	ITEM_VLAN_TCI,
447 	ITEM_NEXT,
448 	ZERO,
449 };
450 
451 static const enum index item_ipv4[] = {
452 	ITEM_IPV4_SRC,
453 	ITEM_IPV4_DST,
454 	ITEM_NEXT,
455 	ZERO,
456 };
457 
458 static const enum index item_ipv6[] = {
459 	ITEM_IPV6_SRC,
460 	ITEM_IPV6_DST,
461 	ITEM_NEXT,
462 	ZERO,
463 };
464 
465 static const enum index item_icmp[] = {
466 	ITEM_ICMP_TYPE,
467 	ITEM_ICMP_CODE,
468 	ITEM_NEXT,
469 	ZERO,
470 };
471 
472 static const enum index item_udp[] = {
473 	ITEM_UDP_SRC,
474 	ITEM_UDP_DST,
475 	ITEM_NEXT,
476 	ZERO,
477 };
478 
479 static const enum index item_tcp[] = {
480 	ITEM_TCP_SRC,
481 	ITEM_TCP_DST,
482 	ITEM_NEXT,
483 	ZERO,
484 };
485 
486 static const enum index item_sctp[] = {
487 	ITEM_SCTP_SRC,
488 	ITEM_SCTP_DST,
489 	ITEM_NEXT,
490 	ZERO,
491 };
492 
493 static const enum index item_vxlan[] = {
494 	ITEM_VXLAN_VNI,
495 	ITEM_NEXT,
496 	ZERO,
497 };
498 
499 static const enum index next_action[] = {
500 	ACTION_END,
501 	ACTION_VOID,
502 	ACTION_PASSTHRU,
503 	ACTION_MARK,
504 	ACTION_FLAG,
505 	ACTION_QUEUE,
506 	ACTION_DROP,
507 	ACTION_COUNT,
508 	ACTION_DUP,
509 	ACTION_RSS,
510 	ACTION_PF,
511 	ACTION_VF,
512 	ZERO,
513 };
514 
515 static const enum index action_mark[] = {
516 	ACTION_MARK_ID,
517 	ACTION_NEXT,
518 	ZERO,
519 };
520 
521 static const enum index action_queue[] = {
522 	ACTION_QUEUE_INDEX,
523 	ACTION_NEXT,
524 	ZERO,
525 };
526 
527 static const enum index action_dup[] = {
528 	ACTION_DUP_INDEX,
529 	ACTION_NEXT,
530 	ZERO,
531 };
532 
533 static const enum index action_rss[] = {
534 	ACTION_RSS_QUEUES,
535 	ACTION_NEXT,
536 	ZERO,
537 };
538 
539 static const enum index action_vf[] = {
540 	ACTION_VF_ORIGINAL,
541 	ACTION_VF_ID,
542 	ACTION_NEXT,
543 	ZERO,
544 };
545 
546 static int parse_init(struct context *, const struct token *,
547 		      const char *, unsigned int,
548 		      void *, unsigned int);
549 static int parse_vc(struct context *, const struct token *,
550 		    const char *, unsigned int,
551 		    void *, unsigned int);
552 static int parse_vc_spec(struct context *, const struct token *,
553 			 const char *, unsigned int, void *, unsigned int);
554 static int parse_vc_conf(struct context *, const struct token *,
555 			 const char *, unsigned int, void *, unsigned int);
556 static int parse_vc_action_rss_queue(struct context *, const struct token *,
557 				     const char *, unsigned int, void *,
558 				     unsigned int);
559 static int parse_destroy(struct context *, const struct token *,
560 			 const char *, unsigned int,
561 			 void *, unsigned int);
562 static int parse_flush(struct context *, const struct token *,
563 		       const char *, unsigned int,
564 		       void *, unsigned int);
565 static int parse_query(struct context *, const struct token *,
566 		       const char *, unsigned int,
567 		       void *, unsigned int);
568 static int parse_action(struct context *, const struct token *,
569 			const char *, unsigned int,
570 			void *, unsigned int);
571 static int parse_list(struct context *, const struct token *,
572 		      const char *, unsigned int,
573 		      void *, unsigned int);
574 static int parse_int(struct context *, const struct token *,
575 		     const char *, unsigned int,
576 		     void *, unsigned int);
577 static int parse_prefix(struct context *, const struct token *,
578 			const char *, unsigned int,
579 			void *, unsigned int);
580 static int parse_boolean(struct context *, const struct token *,
581 			 const char *, unsigned int,
582 			 void *, unsigned int);
583 static int parse_string(struct context *, const struct token *,
584 			const char *, unsigned int,
585 			void *, unsigned int);
586 static int parse_mac_addr(struct context *, const struct token *,
587 			  const char *, unsigned int,
588 			  void *, unsigned int);
589 static int parse_ipv4_addr(struct context *, const struct token *,
590 			   const char *, unsigned int,
591 			   void *, unsigned int);
592 static int parse_ipv6_addr(struct context *, const struct token *,
593 			   const char *, unsigned int,
594 			   void *, unsigned int);
595 static int parse_port(struct context *, const struct token *,
596 		      const char *, unsigned int,
597 		      void *, unsigned int);
598 static int comp_none(struct context *, const struct token *,
599 		     unsigned int, char *, unsigned int);
600 static int comp_boolean(struct context *, const struct token *,
601 			unsigned int, char *, unsigned int);
602 static int comp_action(struct context *, const struct token *,
603 		       unsigned int, char *, unsigned int);
604 static int comp_port(struct context *, const struct token *,
605 		     unsigned int, char *, unsigned int);
606 static int comp_rule_id(struct context *, const struct token *,
607 			unsigned int, char *, unsigned int);
608 static int comp_vc_action_rss_queue(struct context *, const struct token *,
609 				    unsigned int, char *, unsigned int);
610 
611 /** Token definitions. */
612 static const struct token token_list[] = {
613 	/* Special tokens. */
614 	[ZERO] = {
615 		.name = "ZERO",
616 		.help = "null entry, abused as the entry point",
617 		.next = NEXT(NEXT_ENTRY(FLOW)),
618 	},
619 	[END] = {
620 		.name = "",
621 		.type = "RETURN",
622 		.help = "command may end here",
623 	},
624 	/* Common tokens. */
625 	[INTEGER] = {
626 		.name = "{int}",
627 		.type = "INTEGER",
628 		.help = "integer value",
629 		.call = parse_int,
630 		.comp = comp_none,
631 	},
632 	[UNSIGNED] = {
633 		.name = "{unsigned}",
634 		.type = "UNSIGNED",
635 		.help = "unsigned integer value",
636 		.call = parse_int,
637 		.comp = comp_none,
638 	},
639 	[PREFIX] = {
640 		.name = "{prefix}",
641 		.type = "PREFIX",
642 		.help = "prefix length for bit-mask",
643 		.call = parse_prefix,
644 		.comp = comp_none,
645 	},
646 	[BOOLEAN] = {
647 		.name = "{boolean}",
648 		.type = "BOOLEAN",
649 		.help = "any boolean value",
650 		.call = parse_boolean,
651 		.comp = comp_boolean,
652 	},
653 	[STRING] = {
654 		.name = "{string}",
655 		.type = "STRING",
656 		.help = "fixed string",
657 		.call = parse_string,
658 		.comp = comp_none,
659 	},
660 	[MAC_ADDR] = {
661 		.name = "{MAC address}",
662 		.type = "MAC-48",
663 		.help = "standard MAC address notation",
664 		.call = parse_mac_addr,
665 		.comp = comp_none,
666 	},
667 	[IPV4_ADDR] = {
668 		.name = "{IPv4 address}",
669 		.type = "IPV4 ADDRESS",
670 		.help = "standard IPv4 address notation",
671 		.call = parse_ipv4_addr,
672 		.comp = comp_none,
673 	},
674 	[IPV6_ADDR] = {
675 		.name = "{IPv6 address}",
676 		.type = "IPV6 ADDRESS",
677 		.help = "standard IPv6 address notation",
678 		.call = parse_ipv6_addr,
679 		.comp = comp_none,
680 	},
681 	[RULE_ID] = {
682 		.name = "{rule id}",
683 		.type = "RULE ID",
684 		.help = "rule identifier",
685 		.call = parse_int,
686 		.comp = comp_rule_id,
687 	},
688 	[PORT_ID] = {
689 		.name = "{port_id}",
690 		.type = "PORT ID",
691 		.help = "port identifier",
692 		.call = parse_port,
693 		.comp = comp_port,
694 	},
695 	[GROUP_ID] = {
696 		.name = "{group_id}",
697 		.type = "GROUP ID",
698 		.help = "group identifier",
699 		.call = parse_int,
700 		.comp = comp_none,
701 	},
702 	[PRIORITY_LEVEL] = {
703 		.name = "{level}",
704 		.type = "PRIORITY",
705 		.help = "priority level",
706 		.call = parse_int,
707 		.comp = comp_none,
708 	},
709 	/* Top-level command. */
710 	[FLOW] = {
711 		.name = "flow",
712 		.type = "{command} {port_id} [{arg} [...]]",
713 		.help = "manage ingress/egress flow rules",
714 		.next = NEXT(NEXT_ENTRY
715 			     (VALIDATE,
716 			      CREATE,
717 			      DESTROY,
718 			      FLUSH,
719 			      LIST,
720 			      QUERY)),
721 		.call = parse_init,
722 	},
723 	/* Sub-level commands. */
724 	[VALIDATE] = {
725 		.name = "validate",
726 		.help = "check whether a flow rule can be created",
727 		.next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
728 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
729 		.call = parse_vc,
730 	},
731 	[CREATE] = {
732 		.name = "create",
733 		.help = "create a flow rule",
734 		.next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
735 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
736 		.call = parse_vc,
737 	},
738 	[DESTROY] = {
739 		.name = "destroy",
740 		.help = "destroy specific flow rules",
741 		.next = NEXT(NEXT_ENTRY(DESTROY_RULE), NEXT_ENTRY(PORT_ID)),
742 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
743 		.call = parse_destroy,
744 	},
745 	[FLUSH] = {
746 		.name = "flush",
747 		.help = "destroy all flow rules",
748 		.next = NEXT(NEXT_ENTRY(PORT_ID)),
749 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
750 		.call = parse_flush,
751 	},
752 	[QUERY] = {
753 		.name = "query",
754 		.help = "query an existing flow rule",
755 		.next = NEXT(NEXT_ENTRY(QUERY_ACTION),
756 			     NEXT_ENTRY(RULE_ID),
757 			     NEXT_ENTRY(PORT_ID)),
758 		.args = ARGS(ARGS_ENTRY(struct buffer, args.query.action),
759 			     ARGS_ENTRY(struct buffer, args.query.rule),
760 			     ARGS_ENTRY(struct buffer, port)),
761 		.call = parse_query,
762 	},
763 	[LIST] = {
764 		.name = "list",
765 		.help = "list existing flow rules",
766 		.next = NEXT(next_list_attr, NEXT_ENTRY(PORT_ID)),
767 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
768 		.call = parse_list,
769 	},
770 	/* Destroy arguments. */
771 	[DESTROY_RULE] = {
772 		.name = "rule",
773 		.help = "specify a rule identifier",
774 		.next = NEXT(next_destroy_attr, NEXT_ENTRY(RULE_ID)),
775 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
776 		.call = parse_destroy,
777 	},
778 	/* Query arguments. */
779 	[QUERY_ACTION] = {
780 		.name = "{action}",
781 		.type = "ACTION",
782 		.help = "action to query, must be part of the rule",
783 		.call = parse_action,
784 		.comp = comp_action,
785 	},
786 	/* List arguments. */
787 	[LIST_GROUP] = {
788 		.name = "group",
789 		.help = "specify a group",
790 		.next = NEXT(next_list_attr, NEXT_ENTRY(GROUP_ID)),
791 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
792 		.call = parse_list,
793 	},
794 	/* Validate/create attributes. */
795 	[GROUP] = {
796 		.name = "group",
797 		.help = "specify a group",
798 		.next = NEXT(next_vc_attr, NEXT_ENTRY(GROUP_ID)),
799 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
800 		.call = parse_vc,
801 	},
802 	[PRIORITY] = {
803 		.name = "priority",
804 		.help = "specify a priority level",
805 		.next = NEXT(next_vc_attr, NEXT_ENTRY(PRIORITY_LEVEL)),
806 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
807 		.call = parse_vc,
808 	},
809 	[INGRESS] = {
810 		.name = "ingress",
811 		.help = "affect rule to ingress",
812 		.next = NEXT(next_vc_attr),
813 		.call = parse_vc,
814 	},
815 	[EGRESS] = {
816 		.name = "egress",
817 		.help = "affect rule to egress",
818 		.next = NEXT(next_vc_attr),
819 		.call = parse_vc,
820 	},
821 	/* Validate/create pattern. */
822 	[PATTERN] = {
823 		.name = "pattern",
824 		.help = "submit a list of pattern items",
825 		.next = NEXT(next_item),
826 		.call = parse_vc,
827 	},
828 	[ITEM_PARAM_IS] = {
829 		.name = "is",
830 		.help = "match value perfectly (with full bit-mask)",
831 		.call = parse_vc_spec,
832 	},
833 	[ITEM_PARAM_SPEC] = {
834 		.name = "spec",
835 		.help = "match value according to configured bit-mask",
836 		.call = parse_vc_spec,
837 	},
838 	[ITEM_PARAM_LAST] = {
839 		.name = "last",
840 		.help = "specify upper bound to establish a range",
841 		.call = parse_vc_spec,
842 	},
843 	[ITEM_PARAM_MASK] = {
844 		.name = "mask",
845 		.help = "specify bit-mask with relevant bits set to one",
846 		.call = parse_vc_spec,
847 	},
848 	[ITEM_PARAM_PREFIX] = {
849 		.name = "prefix",
850 		.help = "generate bit-mask from a prefix length",
851 		.call = parse_vc_spec,
852 	},
853 	[ITEM_NEXT] = {
854 		.name = "/",
855 		.help = "specify next pattern item",
856 		.next = NEXT(next_item),
857 	},
858 	[ITEM_END] = {
859 		.name = "end",
860 		.help = "end list of pattern items",
861 		.priv = PRIV_ITEM(END, 0),
862 		.next = NEXT(NEXT_ENTRY(ACTIONS)),
863 		.call = parse_vc,
864 	},
865 	[ITEM_VOID] = {
866 		.name = "void",
867 		.help = "no-op pattern item",
868 		.priv = PRIV_ITEM(VOID, 0),
869 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
870 		.call = parse_vc,
871 	},
872 	[ITEM_INVERT] = {
873 		.name = "invert",
874 		.help = "perform actions when pattern does not match",
875 		.priv = PRIV_ITEM(INVERT, 0),
876 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
877 		.call = parse_vc,
878 	},
879 	[ITEM_ANY] = {
880 		.name = "any",
881 		.help = "match any protocol for the current layer",
882 		.priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
883 		.next = NEXT(item_any),
884 		.call = parse_vc,
885 	},
886 	[ITEM_ANY_NUM] = {
887 		.name = "num",
888 		.help = "number of layers covered",
889 		.next = NEXT(item_any, NEXT_ENTRY(UNSIGNED), item_param),
890 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
891 	},
892 	[ITEM_PF] = {
893 		.name = "pf",
894 		.help = "match packets addressed to the physical function",
895 		.priv = PRIV_ITEM(PF, 0),
896 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
897 		.call = parse_vc,
898 	},
899 	[ITEM_VF] = {
900 		.name = "vf",
901 		.help = "match packets addressed to a virtual function ID",
902 		.priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
903 		.next = NEXT(item_vf),
904 		.call = parse_vc,
905 	},
906 	[ITEM_VF_ID] = {
907 		.name = "id",
908 		.help = "destination VF ID",
909 		.next = NEXT(item_vf, NEXT_ENTRY(UNSIGNED), item_param),
910 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
911 	},
912 	[ITEM_PORT] = {
913 		.name = "port",
914 		.help = "device-specific physical port index to use",
915 		.priv = PRIV_ITEM(PORT, sizeof(struct rte_flow_item_port)),
916 		.next = NEXT(item_port),
917 		.call = parse_vc,
918 	},
919 	[ITEM_PORT_INDEX] = {
920 		.name = "index",
921 		.help = "physical port index",
922 		.next = NEXT(item_port, NEXT_ENTRY(UNSIGNED), item_param),
923 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_port, index)),
924 	},
925 	[ITEM_RAW] = {
926 		.name = "raw",
927 		.help = "match an arbitrary byte string",
928 		.priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
929 		.next = NEXT(item_raw),
930 		.call = parse_vc,
931 	},
932 	[ITEM_RAW_RELATIVE] = {
933 		.name = "relative",
934 		.help = "look for pattern after the previous item",
935 		.next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
936 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
937 					   relative, 1)),
938 	},
939 	[ITEM_RAW_SEARCH] = {
940 		.name = "search",
941 		.help = "search pattern from offset (see also limit)",
942 		.next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
943 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
944 					   search, 1)),
945 	},
946 	[ITEM_RAW_OFFSET] = {
947 		.name = "offset",
948 		.help = "absolute or relative offset for pattern",
949 		.next = NEXT(item_raw, NEXT_ENTRY(INTEGER), item_param),
950 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
951 	},
952 	[ITEM_RAW_LIMIT] = {
953 		.name = "limit",
954 		.help = "search area limit for start of pattern",
955 		.next = NEXT(item_raw, NEXT_ENTRY(UNSIGNED), item_param),
956 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
957 	},
958 	[ITEM_RAW_PATTERN] = {
959 		.name = "pattern",
960 		.help = "byte string to look for",
961 		.next = NEXT(item_raw,
962 			     NEXT_ENTRY(STRING),
963 			     NEXT_ENTRY(ITEM_PARAM_IS,
964 					ITEM_PARAM_SPEC,
965 					ITEM_PARAM_MASK)),
966 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, length),
967 			     ARGS_ENTRY_USZ(struct rte_flow_item_raw,
968 					    pattern,
969 					    ITEM_RAW_PATTERN_SIZE)),
970 	},
971 	[ITEM_ETH] = {
972 		.name = "eth",
973 		.help = "match Ethernet header",
974 		.priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
975 		.next = NEXT(item_eth),
976 		.call = parse_vc,
977 	},
978 	[ITEM_ETH_DST] = {
979 		.name = "dst",
980 		.help = "destination MAC",
981 		.next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
982 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_eth, dst)),
983 	},
984 	[ITEM_ETH_SRC] = {
985 		.name = "src",
986 		.help = "source MAC",
987 		.next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
988 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_eth, src)),
989 	},
990 	[ITEM_ETH_TYPE] = {
991 		.name = "type",
992 		.help = "EtherType",
993 		.next = NEXT(item_eth, NEXT_ENTRY(UNSIGNED), item_param),
994 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
995 	},
996 	[ITEM_VLAN] = {
997 		.name = "vlan",
998 		.help = "match 802.1Q/ad VLAN tag",
999 		.priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
1000 		.next = NEXT(item_vlan),
1001 		.call = parse_vc,
1002 	},
1003 	[ITEM_VLAN_TPID] = {
1004 		.name = "tpid",
1005 		.help = "tag protocol identifier",
1006 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1007 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tpid)),
1008 	},
1009 	[ITEM_VLAN_TCI] = {
1010 		.name = "tci",
1011 		.help = "tag control information",
1012 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1013 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
1014 	},
1015 	[ITEM_IPV4] = {
1016 		.name = "ipv4",
1017 		.help = "match IPv4 header",
1018 		.priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
1019 		.next = NEXT(item_ipv4),
1020 		.call = parse_vc,
1021 	},
1022 	[ITEM_IPV4_SRC] = {
1023 		.name = "src",
1024 		.help = "source address",
1025 		.next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
1026 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1027 					     hdr.src_addr)),
1028 	},
1029 	[ITEM_IPV4_DST] = {
1030 		.name = "dst",
1031 		.help = "destination address",
1032 		.next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
1033 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1034 					     hdr.dst_addr)),
1035 	},
1036 	[ITEM_IPV6] = {
1037 		.name = "ipv6",
1038 		.help = "match IPv6 header",
1039 		.priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
1040 		.next = NEXT(item_ipv6),
1041 		.call = parse_vc,
1042 	},
1043 	[ITEM_IPV6_SRC] = {
1044 		.name = "src",
1045 		.help = "source address",
1046 		.next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
1047 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
1048 					     hdr.src_addr)),
1049 	},
1050 	[ITEM_IPV6_DST] = {
1051 		.name = "dst",
1052 		.help = "destination address",
1053 		.next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
1054 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
1055 					     hdr.dst_addr)),
1056 	},
1057 	[ITEM_ICMP] = {
1058 		.name = "icmp",
1059 		.help = "match ICMP header",
1060 		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
1061 		.next = NEXT(item_icmp),
1062 		.call = parse_vc,
1063 	},
1064 	[ITEM_ICMP_TYPE] = {
1065 		.name = "type",
1066 		.help = "ICMP packet type",
1067 		.next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
1068 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
1069 					     hdr.icmp_type)),
1070 	},
1071 	[ITEM_ICMP_CODE] = {
1072 		.name = "code",
1073 		.help = "ICMP packet code",
1074 		.next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
1075 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
1076 					     hdr.icmp_code)),
1077 	},
1078 	[ITEM_UDP] = {
1079 		.name = "udp",
1080 		.help = "match UDP header",
1081 		.priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
1082 		.next = NEXT(item_udp),
1083 		.call = parse_vc,
1084 	},
1085 	[ITEM_UDP_SRC] = {
1086 		.name = "src",
1087 		.help = "UDP source port",
1088 		.next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
1089 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
1090 					     hdr.src_port)),
1091 	},
1092 	[ITEM_UDP_DST] = {
1093 		.name = "dst",
1094 		.help = "UDP destination port",
1095 		.next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
1096 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
1097 					     hdr.dst_port)),
1098 	},
1099 	[ITEM_TCP] = {
1100 		.name = "tcp",
1101 		.help = "match TCP header",
1102 		.priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
1103 		.next = NEXT(item_tcp),
1104 		.call = parse_vc,
1105 	},
1106 	[ITEM_TCP_SRC] = {
1107 		.name = "src",
1108 		.help = "TCP source port",
1109 		.next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
1110 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
1111 					     hdr.src_port)),
1112 	},
1113 	[ITEM_TCP_DST] = {
1114 		.name = "dst",
1115 		.help = "TCP destination port",
1116 		.next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
1117 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
1118 					     hdr.dst_port)),
1119 	},
1120 	[ITEM_SCTP] = {
1121 		.name = "sctp",
1122 		.help = "match SCTP header",
1123 		.priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
1124 		.next = NEXT(item_sctp),
1125 		.call = parse_vc,
1126 	},
1127 	[ITEM_SCTP_SRC] = {
1128 		.name = "src",
1129 		.help = "SCTP source port",
1130 		.next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
1131 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
1132 					     hdr.src_port)),
1133 	},
1134 	[ITEM_SCTP_DST] = {
1135 		.name = "dst",
1136 		.help = "SCTP destination port",
1137 		.next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
1138 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
1139 					     hdr.dst_port)),
1140 	},
1141 	[ITEM_VXLAN] = {
1142 		.name = "vxlan",
1143 		.help = "match VXLAN header",
1144 		.priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
1145 		.next = NEXT(item_vxlan),
1146 		.call = parse_vc,
1147 	},
1148 	[ITEM_VXLAN_VNI] = {
1149 		.name = "vni",
1150 		.help = "VXLAN identifier",
1151 		.next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED), item_param),
1152 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
1153 	},
1154 	/* Validate/create actions. */
1155 	[ACTIONS] = {
1156 		.name = "actions",
1157 		.help = "submit a list of associated actions",
1158 		.next = NEXT(next_action),
1159 		.call = parse_vc,
1160 	},
1161 	[ACTION_NEXT] = {
1162 		.name = "/",
1163 		.help = "specify next action",
1164 		.next = NEXT(next_action),
1165 	},
1166 	[ACTION_END] = {
1167 		.name = "end",
1168 		.help = "end list of actions",
1169 		.priv = PRIV_ACTION(END, 0),
1170 		.call = parse_vc,
1171 	},
1172 	[ACTION_VOID] = {
1173 		.name = "void",
1174 		.help = "no-op action",
1175 		.priv = PRIV_ACTION(VOID, 0),
1176 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
1177 		.call = parse_vc,
1178 	},
1179 	[ACTION_PASSTHRU] = {
1180 		.name = "passthru",
1181 		.help = "let subsequent rule process matched packets",
1182 		.priv = PRIV_ACTION(PASSTHRU, 0),
1183 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
1184 		.call = parse_vc,
1185 	},
1186 	[ACTION_MARK] = {
1187 		.name = "mark",
1188 		.help = "attach 32 bit value to packets",
1189 		.priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
1190 		.next = NEXT(action_mark),
1191 		.call = parse_vc,
1192 	},
1193 	[ACTION_MARK_ID] = {
1194 		.name = "id",
1195 		.help = "32 bit value to return with packets",
1196 		.next = NEXT(action_mark, NEXT_ENTRY(UNSIGNED)),
1197 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
1198 		.call = parse_vc_conf,
1199 	},
1200 	[ACTION_FLAG] = {
1201 		.name = "flag",
1202 		.help = "flag packets",
1203 		.priv = PRIV_ACTION(FLAG, 0),
1204 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
1205 		.call = parse_vc,
1206 	},
1207 	[ACTION_QUEUE] = {
1208 		.name = "queue",
1209 		.help = "assign packets to a given queue index",
1210 		.priv = PRIV_ACTION(QUEUE,
1211 				    sizeof(struct rte_flow_action_queue)),
1212 		.next = NEXT(action_queue),
1213 		.call = parse_vc,
1214 	},
1215 	[ACTION_QUEUE_INDEX] = {
1216 		.name = "index",
1217 		.help = "queue index to use",
1218 		.next = NEXT(action_queue, NEXT_ENTRY(UNSIGNED)),
1219 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
1220 		.call = parse_vc_conf,
1221 	},
1222 	[ACTION_DROP] = {
1223 		.name = "drop",
1224 		.help = "drop packets (note: passthru has priority)",
1225 		.priv = PRIV_ACTION(DROP, 0),
1226 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
1227 		.call = parse_vc,
1228 	},
1229 	[ACTION_COUNT] = {
1230 		.name = "count",
1231 		.help = "enable counters for this rule",
1232 		.priv = PRIV_ACTION(COUNT, 0),
1233 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
1234 		.call = parse_vc,
1235 	},
1236 	[ACTION_DUP] = {
1237 		.name = "dup",
1238 		.help = "duplicate packets to a given queue index",
1239 		.priv = PRIV_ACTION(DUP, sizeof(struct rte_flow_action_dup)),
1240 		.next = NEXT(action_dup),
1241 		.call = parse_vc,
1242 	},
1243 	[ACTION_DUP_INDEX] = {
1244 		.name = "index",
1245 		.help = "queue index to duplicate packets to",
1246 		.next = NEXT(action_dup, NEXT_ENTRY(UNSIGNED)),
1247 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_dup, index)),
1248 		.call = parse_vc_conf,
1249 	},
1250 	[ACTION_RSS] = {
1251 		.name = "rss",
1252 		.help = "spread packets among several queues",
1253 		.priv = PRIV_ACTION(RSS, ACTION_RSS_SIZE),
1254 		.next = NEXT(action_rss),
1255 		.call = parse_vc,
1256 	},
1257 	[ACTION_RSS_QUEUES] = {
1258 		.name = "queues",
1259 		.help = "queue indices to use",
1260 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
1261 		.call = parse_vc_conf,
1262 	},
1263 	[ACTION_RSS_QUEUE] = {
1264 		.name = "{queue}",
1265 		.help = "queue index",
1266 		.call = parse_vc_action_rss_queue,
1267 		.comp = comp_vc_action_rss_queue,
1268 	},
1269 	[ACTION_PF] = {
1270 		.name = "pf",
1271 		.help = "redirect packets to physical device function",
1272 		.priv = PRIV_ACTION(PF, 0),
1273 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
1274 		.call = parse_vc,
1275 	},
1276 	[ACTION_VF] = {
1277 		.name = "vf",
1278 		.help = "redirect packets to virtual device function",
1279 		.priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
1280 		.next = NEXT(action_vf),
1281 		.call = parse_vc,
1282 	},
1283 	[ACTION_VF_ORIGINAL] = {
1284 		.name = "original",
1285 		.help = "use original VF ID if possible",
1286 		.next = NEXT(action_vf, NEXT_ENTRY(BOOLEAN)),
1287 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
1288 					   original, 1)),
1289 		.call = parse_vc_conf,
1290 	},
1291 	[ACTION_VF_ID] = {
1292 		.name = "id",
1293 		.help = "VF ID to redirect packets to",
1294 		.next = NEXT(action_vf, NEXT_ENTRY(UNSIGNED)),
1295 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
1296 		.call = parse_vc_conf,
1297 	},
1298 };
1299 
1300 /** Remove and return last entry from argument stack. */
1301 static const struct arg *
1302 pop_args(struct context *ctx)
1303 {
1304 	return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
1305 }
1306 
1307 /** Add entry on top of the argument stack. */
1308 static int
1309 push_args(struct context *ctx, const struct arg *arg)
1310 {
1311 	if (ctx->args_num == CTX_STACK_SIZE)
1312 		return -1;
1313 	ctx->args[ctx->args_num++] = arg;
1314 	return 0;
1315 }
1316 
1317 /** Spread value into buffer according to bit-mask. */
1318 static size_t
1319 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
1320 {
1321 	uint32_t i = arg->size;
1322 	uint32_t end = 0;
1323 	int sub = 1;
1324 	int add = 0;
1325 	size_t len = 0;
1326 
1327 	if (!arg->mask)
1328 		return 0;
1329 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1330 	if (!arg->hton) {
1331 		i = 0;
1332 		end = arg->size;
1333 		sub = 0;
1334 		add = 1;
1335 	}
1336 #endif
1337 	while (i != end) {
1338 		unsigned int shift = 0;
1339 		uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
1340 
1341 		for (shift = 0; arg->mask[i] >> shift; ++shift) {
1342 			if (!(arg->mask[i] & (1 << shift)))
1343 				continue;
1344 			++len;
1345 			if (!dst)
1346 				continue;
1347 			*buf &= ~(1 << shift);
1348 			*buf |= (val & 1) << shift;
1349 			val >>= 1;
1350 		}
1351 		i += add;
1352 	}
1353 	return len;
1354 }
1355 
1356 /**
1357  * Parse a prefix length and generate a bit-mask.
1358  *
1359  * Last argument (ctx->args) is retrieved to determine mask size, storage
1360  * location and whether the result must use network byte ordering.
1361  */
1362 static int
1363 parse_prefix(struct context *ctx, const struct token *token,
1364 	     const char *str, unsigned int len,
1365 	     void *buf, unsigned int size)
1366 {
1367 	const struct arg *arg = pop_args(ctx);
1368 	static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
1369 	char *end;
1370 	uintmax_t u;
1371 	unsigned int bytes;
1372 	unsigned int extra;
1373 
1374 	(void)token;
1375 	/* Argument is expected. */
1376 	if (!arg)
1377 		return -1;
1378 	errno = 0;
1379 	u = strtoumax(str, &end, 0);
1380 	if (errno || (size_t)(end - str) != len)
1381 		goto error;
1382 	if (arg->mask) {
1383 		uintmax_t v = 0;
1384 
1385 		extra = arg_entry_bf_fill(NULL, 0, arg);
1386 		if (u > extra)
1387 			goto error;
1388 		if (!ctx->object)
1389 			return len;
1390 		extra -= u;
1391 		while (u--)
1392 			(v <<= 1, v |= 1);
1393 		v <<= extra;
1394 		if (!arg_entry_bf_fill(ctx->object, v, arg) ||
1395 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
1396 			goto error;
1397 		return len;
1398 	}
1399 	bytes = u / 8;
1400 	extra = u % 8;
1401 	size = arg->size;
1402 	if (bytes > size || bytes + !!extra > size)
1403 		goto error;
1404 	if (!ctx->object)
1405 		return len;
1406 	buf = (uint8_t *)ctx->object + arg->offset;
1407 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1408 	if (!arg->hton) {
1409 		memset((uint8_t *)buf + size - bytes, 0xff, bytes);
1410 		memset(buf, 0x00, size - bytes);
1411 		if (extra)
1412 			((uint8_t *)buf)[size - bytes - 1] = conv[extra];
1413 	} else
1414 #endif
1415 	{
1416 		memset(buf, 0xff, bytes);
1417 		memset((uint8_t *)buf + bytes, 0x00, size - bytes);
1418 		if (extra)
1419 			((uint8_t *)buf)[bytes] = conv[extra];
1420 	}
1421 	if (ctx->objmask)
1422 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
1423 	return len;
1424 error:
1425 	push_args(ctx, arg);
1426 	return -1;
1427 }
1428 
1429 /** Default parsing function for token name matching. */
1430 static int
1431 parse_default(struct context *ctx, const struct token *token,
1432 	      const char *str, unsigned int len,
1433 	      void *buf, unsigned int size)
1434 {
1435 	(void)ctx;
1436 	(void)buf;
1437 	(void)size;
1438 	if (strncmp(str, token->name, len))
1439 		return -1;
1440 	return len;
1441 }
1442 
1443 /** Parse flow command, initialize output buffer for subsequent tokens. */
1444 static int
1445 parse_init(struct context *ctx, const struct token *token,
1446 	   const char *str, unsigned int len,
1447 	   void *buf, unsigned int size)
1448 {
1449 	struct buffer *out = buf;
1450 
1451 	/* Token name must match. */
1452 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
1453 		return -1;
1454 	/* Nothing else to do if there is no buffer. */
1455 	if (!out)
1456 		return len;
1457 	/* Make sure buffer is large enough. */
1458 	if (size < sizeof(*out))
1459 		return -1;
1460 	/* Initialize buffer. */
1461 	memset(out, 0x00, sizeof(*out));
1462 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
1463 	ctx->objdata = 0;
1464 	ctx->object = out;
1465 	ctx->objmask = NULL;
1466 	return len;
1467 }
1468 
1469 /** Parse tokens for validate/create commands. */
1470 static int
1471 parse_vc(struct context *ctx, const struct token *token,
1472 	 const char *str, unsigned int len,
1473 	 void *buf, unsigned int size)
1474 {
1475 	struct buffer *out = buf;
1476 	uint8_t *data;
1477 	uint32_t data_size;
1478 
1479 	/* Token name must match. */
1480 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
1481 		return -1;
1482 	/* Nothing else to do if there is no buffer. */
1483 	if (!out)
1484 		return len;
1485 	if (!out->command) {
1486 		if (ctx->curr != VALIDATE && ctx->curr != CREATE)
1487 			return -1;
1488 		if (sizeof(*out) > size)
1489 			return -1;
1490 		out->command = ctx->curr;
1491 		ctx->objdata = 0;
1492 		ctx->object = out;
1493 		ctx->objmask = NULL;
1494 		out->args.vc.data = (uint8_t *)out + size;
1495 		return len;
1496 	}
1497 	ctx->objdata = 0;
1498 	ctx->object = &out->args.vc.attr;
1499 	ctx->objmask = NULL;
1500 	switch (ctx->curr) {
1501 	case GROUP:
1502 	case PRIORITY:
1503 		return len;
1504 	case INGRESS:
1505 		out->args.vc.attr.ingress = 1;
1506 		return len;
1507 	case EGRESS:
1508 		out->args.vc.attr.egress = 1;
1509 		return len;
1510 	case PATTERN:
1511 		out->args.vc.pattern =
1512 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
1513 					       sizeof(double));
1514 		ctx->object = out->args.vc.pattern;
1515 		ctx->objmask = NULL;
1516 		return len;
1517 	case ACTIONS:
1518 		out->args.vc.actions =
1519 			(void *)RTE_ALIGN_CEIL((uintptr_t)
1520 					       (out->args.vc.pattern +
1521 						out->args.vc.pattern_n),
1522 					       sizeof(double));
1523 		ctx->object = out->args.vc.actions;
1524 		ctx->objmask = NULL;
1525 		return len;
1526 	default:
1527 		if (!token->priv)
1528 			return -1;
1529 		break;
1530 	}
1531 	if (!out->args.vc.actions) {
1532 		const struct parse_item_priv *priv = token->priv;
1533 		struct rte_flow_item *item =
1534 			out->args.vc.pattern + out->args.vc.pattern_n;
1535 
1536 		data_size = priv->size * 3; /* spec, last, mask */
1537 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
1538 					       (out->args.vc.data - data_size),
1539 					       sizeof(double));
1540 		if ((uint8_t *)item + sizeof(*item) > data)
1541 			return -1;
1542 		*item = (struct rte_flow_item){
1543 			.type = priv->type,
1544 		};
1545 		++out->args.vc.pattern_n;
1546 		ctx->object = item;
1547 		ctx->objmask = NULL;
1548 	} else {
1549 		const struct parse_action_priv *priv = token->priv;
1550 		struct rte_flow_action *action =
1551 			out->args.vc.actions + out->args.vc.actions_n;
1552 
1553 		data_size = priv->size; /* configuration */
1554 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
1555 					       (out->args.vc.data - data_size),
1556 					       sizeof(double));
1557 		if ((uint8_t *)action + sizeof(*action) > data)
1558 			return -1;
1559 		*action = (struct rte_flow_action){
1560 			.type = priv->type,
1561 		};
1562 		++out->args.vc.actions_n;
1563 		ctx->object = action;
1564 		ctx->objmask = NULL;
1565 	}
1566 	memset(data, 0, data_size);
1567 	out->args.vc.data = data;
1568 	ctx->objdata = data_size;
1569 	return len;
1570 }
1571 
1572 /** Parse pattern item parameter type. */
1573 static int
1574 parse_vc_spec(struct context *ctx, const struct token *token,
1575 	      const char *str, unsigned int len,
1576 	      void *buf, unsigned int size)
1577 {
1578 	struct buffer *out = buf;
1579 	struct rte_flow_item *item;
1580 	uint32_t data_size;
1581 	int index;
1582 	int objmask = 0;
1583 
1584 	(void)size;
1585 	/* Token name must match. */
1586 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
1587 		return -1;
1588 	/* Parse parameter types. */
1589 	switch (ctx->curr) {
1590 	case ITEM_PARAM_IS:
1591 		index = 0;
1592 		objmask = 1;
1593 		break;
1594 	case ITEM_PARAM_SPEC:
1595 		index = 0;
1596 		break;
1597 	case ITEM_PARAM_LAST:
1598 		index = 1;
1599 		break;
1600 	case ITEM_PARAM_PREFIX:
1601 		/* Modify next token to expect a prefix. */
1602 		if (ctx->next_num < 2)
1603 			return -1;
1604 		ctx->next[ctx->next_num - 2] = NEXT_ENTRY(PREFIX);
1605 		/* Fall through. */
1606 	case ITEM_PARAM_MASK:
1607 		index = 2;
1608 		break;
1609 	default:
1610 		return -1;
1611 	}
1612 	/* Nothing else to do if there is no buffer. */
1613 	if (!out)
1614 		return len;
1615 	if (!out->args.vc.pattern_n)
1616 		return -1;
1617 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
1618 	data_size = ctx->objdata / 3; /* spec, last, mask */
1619 	/* Point to selected object. */
1620 	ctx->object = out->args.vc.data + (data_size * index);
1621 	if (objmask) {
1622 		ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
1623 		item->mask = ctx->objmask;
1624 	} else
1625 		ctx->objmask = NULL;
1626 	/* Update relevant item pointer. */
1627 	*((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
1628 		ctx->object;
1629 	return len;
1630 }
1631 
1632 /** Parse action configuration field. */
1633 static int
1634 parse_vc_conf(struct context *ctx, const struct token *token,
1635 	      const char *str, unsigned int len,
1636 	      void *buf, unsigned int size)
1637 {
1638 	struct buffer *out = buf;
1639 	struct rte_flow_action *action;
1640 
1641 	(void)size;
1642 	/* Token name must match. */
1643 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
1644 		return -1;
1645 	/* Nothing else to do if there is no buffer. */
1646 	if (!out)
1647 		return len;
1648 	if (!out->args.vc.actions_n)
1649 		return -1;
1650 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
1651 	/* Point to selected object. */
1652 	ctx->object = out->args.vc.data;
1653 	ctx->objmask = NULL;
1654 	/* Update configuration pointer. */
1655 	action->conf = ctx->object;
1656 	return len;
1657 }
1658 
1659 /**
1660  * Parse queue field for RSS action.
1661  *
1662  * Valid tokens are queue indices and the "end" token.
1663  */
1664 static int
1665 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
1666 			  const char *str, unsigned int len,
1667 			  void *buf, unsigned int size)
1668 {
1669 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
1670 	int ret;
1671 	int i;
1672 
1673 	(void)token;
1674 	(void)buf;
1675 	(void)size;
1676 	if (ctx->curr != ACTION_RSS_QUEUE)
1677 		return -1;
1678 	i = ctx->objdata >> 16;
1679 	if (!strncmp(str, "end", len)) {
1680 		ctx->objdata &= 0xffff;
1681 		return len;
1682 	}
1683 	if (i >= ACTION_RSS_NUM)
1684 		return -1;
1685 	if (push_args(ctx, ARGS_ENTRY(struct rte_flow_action_rss, queue[i])))
1686 		return -1;
1687 	ret = parse_int(ctx, token, str, len, NULL, 0);
1688 	if (ret < 0) {
1689 		pop_args(ctx);
1690 		return -1;
1691 	}
1692 	++i;
1693 	ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
1694 	/* Repeat token. */
1695 	if (ctx->next_num == RTE_DIM(ctx->next))
1696 		return -1;
1697 	ctx->next[ctx->next_num++] = next;
1698 	if (!ctx->object)
1699 		return len;
1700 	((struct rte_flow_action_rss *)ctx->object)->num = i;
1701 	return len;
1702 }
1703 
1704 /** Parse tokens for destroy command. */
1705 static int
1706 parse_destroy(struct context *ctx, const struct token *token,
1707 	      const char *str, unsigned int len,
1708 	      void *buf, unsigned int size)
1709 {
1710 	struct buffer *out = buf;
1711 
1712 	/* Token name must match. */
1713 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
1714 		return -1;
1715 	/* Nothing else to do if there is no buffer. */
1716 	if (!out)
1717 		return len;
1718 	if (!out->command) {
1719 		if (ctx->curr != DESTROY)
1720 			return -1;
1721 		if (sizeof(*out) > size)
1722 			return -1;
1723 		out->command = ctx->curr;
1724 		ctx->objdata = 0;
1725 		ctx->object = out;
1726 		ctx->objmask = NULL;
1727 		out->args.destroy.rule =
1728 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
1729 					       sizeof(double));
1730 		return len;
1731 	}
1732 	if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
1733 	     sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
1734 		return -1;
1735 	ctx->objdata = 0;
1736 	ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
1737 	ctx->objmask = NULL;
1738 	return len;
1739 }
1740 
1741 /** Parse tokens for flush command. */
1742 static int
1743 parse_flush(struct context *ctx, const struct token *token,
1744 	    const char *str, unsigned int len,
1745 	    void *buf, unsigned int size)
1746 {
1747 	struct buffer *out = buf;
1748 
1749 	/* Token name must match. */
1750 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
1751 		return -1;
1752 	/* Nothing else to do if there is no buffer. */
1753 	if (!out)
1754 		return len;
1755 	if (!out->command) {
1756 		if (ctx->curr != FLUSH)
1757 			return -1;
1758 		if (sizeof(*out) > size)
1759 			return -1;
1760 		out->command = ctx->curr;
1761 		ctx->objdata = 0;
1762 		ctx->object = out;
1763 		ctx->objmask = NULL;
1764 	}
1765 	return len;
1766 }
1767 
1768 /** Parse tokens for query command. */
1769 static int
1770 parse_query(struct context *ctx, const struct token *token,
1771 	    const char *str, unsigned int len,
1772 	    void *buf, unsigned int size)
1773 {
1774 	struct buffer *out = buf;
1775 
1776 	/* Token name must match. */
1777 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
1778 		return -1;
1779 	/* Nothing else to do if there is no buffer. */
1780 	if (!out)
1781 		return len;
1782 	if (!out->command) {
1783 		if (ctx->curr != QUERY)
1784 			return -1;
1785 		if (sizeof(*out) > size)
1786 			return -1;
1787 		out->command = ctx->curr;
1788 		ctx->objdata = 0;
1789 		ctx->object = out;
1790 		ctx->objmask = NULL;
1791 	}
1792 	return len;
1793 }
1794 
1795 /** Parse action names. */
1796 static int
1797 parse_action(struct context *ctx, const struct token *token,
1798 	     const char *str, unsigned int len,
1799 	     void *buf, unsigned int size)
1800 {
1801 	struct buffer *out = buf;
1802 	const struct arg *arg = pop_args(ctx);
1803 	unsigned int i;
1804 
1805 	(void)size;
1806 	/* Argument is expected. */
1807 	if (!arg)
1808 		return -1;
1809 	/* Parse action name. */
1810 	for (i = 0; next_action[i]; ++i) {
1811 		const struct parse_action_priv *priv;
1812 
1813 		token = &token_list[next_action[i]];
1814 		if (strncmp(token->name, str, len))
1815 			continue;
1816 		priv = token->priv;
1817 		if (!priv)
1818 			goto error;
1819 		if (out)
1820 			memcpy((uint8_t *)ctx->object + arg->offset,
1821 			       &priv->type,
1822 			       arg->size);
1823 		return len;
1824 	}
1825 error:
1826 	push_args(ctx, arg);
1827 	return -1;
1828 }
1829 
1830 /** Parse tokens for list command. */
1831 static int
1832 parse_list(struct context *ctx, const struct token *token,
1833 	   const char *str, unsigned int len,
1834 	   void *buf, unsigned int size)
1835 {
1836 	struct buffer *out = buf;
1837 
1838 	/* Token name must match. */
1839 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
1840 		return -1;
1841 	/* Nothing else to do if there is no buffer. */
1842 	if (!out)
1843 		return len;
1844 	if (!out->command) {
1845 		if (ctx->curr != LIST)
1846 			return -1;
1847 		if (sizeof(*out) > size)
1848 			return -1;
1849 		out->command = ctx->curr;
1850 		ctx->objdata = 0;
1851 		ctx->object = out;
1852 		ctx->objmask = NULL;
1853 		out->args.list.group =
1854 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
1855 					       sizeof(double));
1856 		return len;
1857 	}
1858 	if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
1859 	     sizeof(*out->args.list.group)) > (uint8_t *)out + size)
1860 		return -1;
1861 	ctx->objdata = 0;
1862 	ctx->object = out->args.list.group + out->args.list.group_n++;
1863 	ctx->objmask = NULL;
1864 	return len;
1865 }
1866 
1867 /**
1868  * Parse signed/unsigned integers 8 to 64-bit long.
1869  *
1870  * Last argument (ctx->args) is retrieved to determine integer type and
1871  * storage location.
1872  */
1873 static int
1874 parse_int(struct context *ctx, const struct token *token,
1875 	  const char *str, unsigned int len,
1876 	  void *buf, unsigned int size)
1877 {
1878 	const struct arg *arg = pop_args(ctx);
1879 	uintmax_t u;
1880 	char *end;
1881 
1882 	(void)token;
1883 	/* Argument is expected. */
1884 	if (!arg)
1885 		return -1;
1886 	errno = 0;
1887 	u = arg->sign ?
1888 		(uintmax_t)strtoimax(str, &end, 0) :
1889 		strtoumax(str, &end, 0);
1890 	if (errno || (size_t)(end - str) != len)
1891 		goto error;
1892 	if (!ctx->object)
1893 		return len;
1894 	if (arg->mask) {
1895 		if (!arg_entry_bf_fill(ctx->object, u, arg) ||
1896 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
1897 			goto error;
1898 		return len;
1899 	}
1900 	buf = (uint8_t *)ctx->object + arg->offset;
1901 	size = arg->size;
1902 objmask:
1903 	switch (size) {
1904 	case sizeof(uint8_t):
1905 		*(uint8_t *)buf = u;
1906 		break;
1907 	case sizeof(uint16_t):
1908 		*(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
1909 		break;
1910 	case sizeof(uint8_t [3]):
1911 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1912 		if (!arg->hton) {
1913 			((uint8_t *)buf)[0] = u;
1914 			((uint8_t *)buf)[1] = u >> 8;
1915 			((uint8_t *)buf)[2] = u >> 16;
1916 			break;
1917 		}
1918 #endif
1919 		((uint8_t *)buf)[0] = u >> 16;
1920 		((uint8_t *)buf)[1] = u >> 8;
1921 		((uint8_t *)buf)[2] = u;
1922 		break;
1923 	case sizeof(uint32_t):
1924 		*(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
1925 		break;
1926 	case sizeof(uint64_t):
1927 		*(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
1928 		break;
1929 	default:
1930 		goto error;
1931 	}
1932 	if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
1933 		u = -1;
1934 		buf = (uint8_t *)ctx->objmask + arg->offset;
1935 		goto objmask;
1936 	}
1937 	return len;
1938 error:
1939 	push_args(ctx, arg);
1940 	return -1;
1941 }
1942 
1943 /**
1944  * Parse a string.
1945  *
1946  * Two arguments (ctx->args) are retrieved from the stack to store data and
1947  * its length (in that order).
1948  */
1949 static int
1950 parse_string(struct context *ctx, const struct token *token,
1951 	     const char *str, unsigned int len,
1952 	     void *buf, unsigned int size)
1953 {
1954 	const struct arg *arg_data = pop_args(ctx);
1955 	const struct arg *arg_len = pop_args(ctx);
1956 	char tmp[16]; /* Ought to be enough. */
1957 	int ret;
1958 
1959 	/* Arguments are expected. */
1960 	if (!arg_data)
1961 		return -1;
1962 	if (!arg_len) {
1963 		push_args(ctx, arg_data);
1964 		return -1;
1965 	}
1966 	size = arg_data->size;
1967 	/* Bit-mask fill is not supported. */
1968 	if (arg_data->mask || size < len)
1969 		goto error;
1970 	if (!ctx->object)
1971 		return len;
1972 	/* Let parse_int() fill length information first. */
1973 	ret = snprintf(tmp, sizeof(tmp), "%u", len);
1974 	if (ret < 0)
1975 		goto error;
1976 	push_args(ctx, arg_len);
1977 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
1978 	if (ret < 0) {
1979 		pop_args(ctx);
1980 		goto error;
1981 	}
1982 	buf = (uint8_t *)ctx->object + arg_data->offset;
1983 	/* Output buffer is not necessarily NUL-terminated. */
1984 	memcpy(buf, str, len);
1985 	memset((uint8_t *)buf + len, 0x55, size - len);
1986 	if (ctx->objmask)
1987 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
1988 	return len;
1989 error:
1990 	push_args(ctx, arg_len);
1991 	push_args(ctx, arg_data);
1992 	return -1;
1993 }
1994 
1995 /**
1996  * Parse a MAC address.
1997  *
1998  * Last argument (ctx->args) is retrieved to determine storage size and
1999  * location.
2000  */
2001 static int
2002 parse_mac_addr(struct context *ctx, const struct token *token,
2003 	       const char *str, unsigned int len,
2004 	       void *buf, unsigned int size)
2005 {
2006 	const struct arg *arg = pop_args(ctx);
2007 	struct ether_addr tmp;
2008 	int ret;
2009 
2010 	(void)token;
2011 	/* Argument is expected. */
2012 	if (!arg)
2013 		return -1;
2014 	size = arg->size;
2015 	/* Bit-mask fill is not supported. */
2016 	if (arg->mask || size != sizeof(tmp))
2017 		goto error;
2018 	ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
2019 	if (ret < 0 || (unsigned int)ret != len)
2020 		goto error;
2021 	if (!ctx->object)
2022 		return len;
2023 	buf = (uint8_t *)ctx->object + arg->offset;
2024 	memcpy(buf, &tmp, size);
2025 	if (ctx->objmask)
2026 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
2027 	return len;
2028 error:
2029 	push_args(ctx, arg);
2030 	return -1;
2031 }
2032 
2033 /**
2034  * Parse an IPv4 address.
2035  *
2036  * Last argument (ctx->args) is retrieved to determine storage size and
2037  * location.
2038  */
2039 static int
2040 parse_ipv4_addr(struct context *ctx, const struct token *token,
2041 		const char *str, unsigned int len,
2042 		void *buf, unsigned int size)
2043 {
2044 	const struct arg *arg = pop_args(ctx);
2045 	char str2[len + 1];
2046 	struct in_addr tmp;
2047 	int ret;
2048 
2049 	/* Argument is expected. */
2050 	if (!arg)
2051 		return -1;
2052 	size = arg->size;
2053 	/* Bit-mask fill is not supported. */
2054 	if (arg->mask || size != sizeof(tmp))
2055 		goto error;
2056 	/* Only network endian is supported. */
2057 	if (!arg->hton)
2058 		goto error;
2059 	memcpy(str2, str, len);
2060 	str2[len] = '\0';
2061 	ret = inet_pton(AF_INET, str2, &tmp);
2062 	if (ret != 1) {
2063 		/* Attempt integer parsing. */
2064 		push_args(ctx, arg);
2065 		return parse_int(ctx, token, str, len, buf, size);
2066 	}
2067 	if (!ctx->object)
2068 		return len;
2069 	buf = (uint8_t *)ctx->object + arg->offset;
2070 	memcpy(buf, &tmp, size);
2071 	if (ctx->objmask)
2072 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
2073 	return len;
2074 error:
2075 	push_args(ctx, arg);
2076 	return -1;
2077 }
2078 
2079 /**
2080  * Parse an IPv6 address.
2081  *
2082  * Last argument (ctx->args) is retrieved to determine storage size and
2083  * location.
2084  */
2085 static int
2086 parse_ipv6_addr(struct context *ctx, const struct token *token,
2087 		const char *str, unsigned int len,
2088 		void *buf, unsigned int size)
2089 {
2090 	const struct arg *arg = pop_args(ctx);
2091 	char str2[len + 1];
2092 	struct in6_addr tmp;
2093 	int ret;
2094 
2095 	(void)token;
2096 	/* Argument is expected. */
2097 	if (!arg)
2098 		return -1;
2099 	size = arg->size;
2100 	/* Bit-mask fill is not supported. */
2101 	if (arg->mask || size != sizeof(tmp))
2102 		goto error;
2103 	/* Only network endian is supported. */
2104 	if (!arg->hton)
2105 		goto error;
2106 	memcpy(str2, str, len);
2107 	str2[len] = '\0';
2108 	ret = inet_pton(AF_INET6, str2, &tmp);
2109 	if (ret != 1)
2110 		goto error;
2111 	if (!ctx->object)
2112 		return len;
2113 	buf = (uint8_t *)ctx->object + arg->offset;
2114 	memcpy(buf, &tmp, size);
2115 	if (ctx->objmask)
2116 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
2117 	return len;
2118 error:
2119 	push_args(ctx, arg);
2120 	return -1;
2121 }
2122 
2123 /** Boolean values (even indices stand for false). */
2124 static const char *const boolean_name[] = {
2125 	"0", "1",
2126 	"false", "true",
2127 	"no", "yes",
2128 	"N", "Y",
2129 	NULL,
2130 };
2131 
2132 /**
2133  * Parse a boolean value.
2134  *
2135  * Last argument (ctx->args) is retrieved to determine storage size and
2136  * location.
2137  */
2138 static int
2139 parse_boolean(struct context *ctx, const struct token *token,
2140 	      const char *str, unsigned int len,
2141 	      void *buf, unsigned int size)
2142 {
2143 	const struct arg *arg = pop_args(ctx);
2144 	unsigned int i;
2145 	int ret;
2146 
2147 	/* Argument is expected. */
2148 	if (!arg)
2149 		return -1;
2150 	for (i = 0; boolean_name[i]; ++i)
2151 		if (!strncmp(str, boolean_name[i], len))
2152 			break;
2153 	/* Process token as integer. */
2154 	if (boolean_name[i])
2155 		str = i & 1 ? "1" : "0";
2156 	push_args(ctx, arg);
2157 	ret = parse_int(ctx, token, str, strlen(str), buf, size);
2158 	return ret > 0 ? (int)len : ret;
2159 }
2160 
2161 /** Parse port and update context. */
2162 static int
2163 parse_port(struct context *ctx, const struct token *token,
2164 	   const char *str, unsigned int len,
2165 	   void *buf, unsigned int size)
2166 {
2167 	struct buffer *out = &(struct buffer){ .port = 0 };
2168 	int ret;
2169 
2170 	if (buf)
2171 		out = buf;
2172 	else {
2173 		ctx->objdata = 0;
2174 		ctx->object = out;
2175 		ctx->objmask = NULL;
2176 		size = sizeof(*out);
2177 	}
2178 	ret = parse_int(ctx, token, str, len, out, size);
2179 	if (ret >= 0)
2180 		ctx->port = out->port;
2181 	if (!buf)
2182 		ctx->object = NULL;
2183 	return ret;
2184 }
2185 
2186 /** No completion. */
2187 static int
2188 comp_none(struct context *ctx, const struct token *token,
2189 	  unsigned int ent, char *buf, unsigned int size)
2190 {
2191 	(void)ctx;
2192 	(void)token;
2193 	(void)ent;
2194 	(void)buf;
2195 	(void)size;
2196 	return 0;
2197 }
2198 
2199 /** Complete boolean values. */
2200 static int
2201 comp_boolean(struct context *ctx, const struct token *token,
2202 	     unsigned int ent, char *buf, unsigned int size)
2203 {
2204 	unsigned int i;
2205 
2206 	(void)ctx;
2207 	(void)token;
2208 	for (i = 0; boolean_name[i]; ++i)
2209 		if (buf && i == ent)
2210 			return snprintf(buf, size, "%s", boolean_name[i]);
2211 	if (buf)
2212 		return -1;
2213 	return i;
2214 }
2215 
2216 /** Complete action names. */
2217 static int
2218 comp_action(struct context *ctx, const struct token *token,
2219 	    unsigned int ent, char *buf, unsigned int size)
2220 {
2221 	unsigned int i;
2222 
2223 	(void)ctx;
2224 	(void)token;
2225 	for (i = 0; next_action[i]; ++i)
2226 		if (buf && i == ent)
2227 			return snprintf(buf, size, "%s",
2228 					token_list[next_action[i]].name);
2229 	if (buf)
2230 		return -1;
2231 	return i;
2232 }
2233 
2234 /** Complete available ports. */
2235 static int
2236 comp_port(struct context *ctx, const struct token *token,
2237 	  unsigned int ent, char *buf, unsigned int size)
2238 {
2239 	unsigned int i = 0;
2240 	portid_t p;
2241 
2242 	(void)ctx;
2243 	(void)token;
2244 	FOREACH_PORT(p, ports) {
2245 		if (buf && i == ent)
2246 			return snprintf(buf, size, "%u", p);
2247 		++i;
2248 	}
2249 	if (buf)
2250 		return -1;
2251 	return i;
2252 }
2253 
2254 /** Complete available rule IDs. */
2255 static int
2256 comp_rule_id(struct context *ctx, const struct token *token,
2257 	     unsigned int ent, char *buf, unsigned int size)
2258 {
2259 	unsigned int i = 0;
2260 	struct rte_port *port;
2261 	struct port_flow *pf;
2262 
2263 	(void)token;
2264 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
2265 	    ctx->port == (uint16_t)RTE_PORT_ALL)
2266 		return -1;
2267 	port = &ports[ctx->port];
2268 	for (pf = port->flow_list; pf != NULL; pf = pf->next) {
2269 		if (buf && i == ent)
2270 			return snprintf(buf, size, "%u", pf->id);
2271 		++i;
2272 	}
2273 	if (buf)
2274 		return -1;
2275 	return i;
2276 }
2277 
2278 /** Complete queue field for RSS action. */
2279 static int
2280 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
2281 			 unsigned int ent, char *buf, unsigned int size)
2282 {
2283 	static const char *const str[] = { "", "end", NULL };
2284 	unsigned int i;
2285 
2286 	(void)ctx;
2287 	(void)token;
2288 	for (i = 0; str[i] != NULL; ++i)
2289 		if (buf && i == ent)
2290 			return snprintf(buf, size, "%s", str[i]);
2291 	if (buf)
2292 		return -1;
2293 	return i;
2294 }
2295 
2296 /** Internal context. */
2297 static struct context cmd_flow_context;
2298 
2299 /** Global parser instance (cmdline API). */
2300 cmdline_parse_inst_t cmd_flow;
2301 
2302 /** Initialize context. */
2303 static void
2304 cmd_flow_context_init(struct context *ctx)
2305 {
2306 	/* A full memset() is not necessary. */
2307 	ctx->curr = ZERO;
2308 	ctx->prev = ZERO;
2309 	ctx->next_num = 0;
2310 	ctx->args_num = 0;
2311 	ctx->reparse = 0;
2312 	ctx->eol = 0;
2313 	ctx->last = 0;
2314 	ctx->port = 0;
2315 	ctx->objdata = 0;
2316 	ctx->object = NULL;
2317 	ctx->objmask = NULL;
2318 }
2319 
2320 /** Parse a token (cmdline API). */
2321 static int
2322 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
2323 	       unsigned int size)
2324 {
2325 	struct context *ctx = &cmd_flow_context;
2326 	const struct token *token;
2327 	const enum index *list;
2328 	int len;
2329 	int i;
2330 
2331 	(void)hdr;
2332 	/* Restart as requested. */
2333 	if (ctx->reparse)
2334 		cmd_flow_context_init(ctx);
2335 	token = &token_list[ctx->curr];
2336 	/* Check argument length. */
2337 	ctx->eol = 0;
2338 	ctx->last = 1;
2339 	for (len = 0; src[len]; ++len)
2340 		if (src[len] == '#' || isspace(src[len]))
2341 			break;
2342 	if (!len)
2343 		return -1;
2344 	/* Last argument and EOL detection. */
2345 	for (i = len; src[i]; ++i)
2346 		if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
2347 			break;
2348 		else if (!isspace(src[i])) {
2349 			ctx->last = 0;
2350 			break;
2351 		}
2352 	for (; src[i]; ++i)
2353 		if (src[i] == '\r' || src[i] == '\n') {
2354 			ctx->eol = 1;
2355 			break;
2356 		}
2357 	/* Initialize context if necessary. */
2358 	if (!ctx->next_num) {
2359 		if (!token->next)
2360 			return 0;
2361 		ctx->next[ctx->next_num++] = token->next[0];
2362 	}
2363 	/* Process argument through candidates. */
2364 	ctx->prev = ctx->curr;
2365 	list = ctx->next[ctx->next_num - 1];
2366 	for (i = 0; list[i]; ++i) {
2367 		const struct token *next = &token_list[list[i]];
2368 		int tmp;
2369 
2370 		ctx->curr = list[i];
2371 		if (next->call)
2372 			tmp = next->call(ctx, next, src, len, result, size);
2373 		else
2374 			tmp = parse_default(ctx, next, src, len, result, size);
2375 		if (tmp == -1 || tmp != len)
2376 			continue;
2377 		token = next;
2378 		break;
2379 	}
2380 	if (!list[i])
2381 		return -1;
2382 	--ctx->next_num;
2383 	/* Push subsequent tokens if any. */
2384 	if (token->next)
2385 		for (i = 0; token->next[i]; ++i) {
2386 			if (ctx->next_num == RTE_DIM(ctx->next))
2387 				return -1;
2388 			ctx->next[ctx->next_num++] = token->next[i];
2389 		}
2390 	/* Push arguments if any. */
2391 	if (token->args)
2392 		for (i = 0; token->args[i]; ++i) {
2393 			if (ctx->args_num == RTE_DIM(ctx->args))
2394 				return -1;
2395 			ctx->args[ctx->args_num++] = token->args[i];
2396 		}
2397 	return len;
2398 }
2399 
2400 /** Return number of completion entries (cmdline API). */
2401 static int
2402 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
2403 {
2404 	struct context *ctx = &cmd_flow_context;
2405 	const struct token *token = &token_list[ctx->curr];
2406 	const enum index *list;
2407 	int i;
2408 
2409 	(void)hdr;
2410 	/* Tell cmd_flow_parse() that context must be reinitialized. */
2411 	ctx->reparse = 1;
2412 	/* Count number of tokens in current list. */
2413 	if (ctx->next_num)
2414 		list = ctx->next[ctx->next_num - 1];
2415 	else
2416 		list = token->next[0];
2417 	for (i = 0; list[i]; ++i)
2418 		;
2419 	if (!i)
2420 		return 0;
2421 	/*
2422 	 * If there is a single token, use its completion callback, otherwise
2423 	 * return the number of entries.
2424 	 */
2425 	token = &token_list[list[0]];
2426 	if (i == 1 && token->comp) {
2427 		/* Save index for cmd_flow_get_help(). */
2428 		ctx->prev = list[0];
2429 		return token->comp(ctx, token, 0, NULL, 0);
2430 	}
2431 	return i;
2432 }
2433 
2434 /** Return a completion entry (cmdline API). */
2435 static int
2436 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
2437 			  char *dst, unsigned int size)
2438 {
2439 	struct context *ctx = &cmd_flow_context;
2440 	const struct token *token = &token_list[ctx->curr];
2441 	const enum index *list;
2442 	int i;
2443 
2444 	(void)hdr;
2445 	/* Tell cmd_flow_parse() that context must be reinitialized. */
2446 	ctx->reparse = 1;
2447 	/* Count number of tokens in current list. */
2448 	if (ctx->next_num)
2449 		list = ctx->next[ctx->next_num - 1];
2450 	else
2451 		list = token->next[0];
2452 	for (i = 0; list[i]; ++i)
2453 		;
2454 	if (!i)
2455 		return -1;
2456 	/* If there is a single token, use its completion callback. */
2457 	token = &token_list[list[0]];
2458 	if (i == 1 && token->comp) {
2459 		/* Save index for cmd_flow_get_help(). */
2460 		ctx->prev = list[0];
2461 		return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
2462 	}
2463 	/* Otherwise make sure the index is valid and use defaults. */
2464 	if (index >= i)
2465 		return -1;
2466 	token = &token_list[list[index]];
2467 	snprintf(dst, size, "%s", token->name);
2468 	/* Save index for cmd_flow_get_help(). */
2469 	ctx->prev = list[index];
2470 	return 0;
2471 }
2472 
2473 /** Populate help strings for current token (cmdline API). */
2474 static int
2475 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
2476 {
2477 	struct context *ctx = &cmd_flow_context;
2478 	const struct token *token = &token_list[ctx->prev];
2479 
2480 	(void)hdr;
2481 	/* Tell cmd_flow_parse() that context must be reinitialized. */
2482 	ctx->reparse = 1;
2483 	if (!size)
2484 		return -1;
2485 	/* Set token type and update global help with details. */
2486 	snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
2487 	if (token->help)
2488 		cmd_flow.help_str = token->help;
2489 	else
2490 		cmd_flow.help_str = token->name;
2491 	return 0;
2492 }
2493 
2494 /** Token definition template (cmdline API). */
2495 static struct cmdline_token_hdr cmd_flow_token_hdr = {
2496 	.ops = &(struct cmdline_token_ops){
2497 		.parse = cmd_flow_parse,
2498 		.complete_get_nb = cmd_flow_complete_get_nb,
2499 		.complete_get_elt = cmd_flow_complete_get_elt,
2500 		.get_help = cmd_flow_get_help,
2501 	},
2502 	.offset = 0,
2503 };
2504 
2505 /** Populate the next dynamic token. */
2506 static void
2507 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
2508 	     cmdline_parse_token_hdr_t *(*hdrs)[])
2509 {
2510 	struct context *ctx = &cmd_flow_context;
2511 
2512 	/* Always reinitialize context before requesting the first token. */
2513 	if (!(hdr - *hdrs))
2514 		cmd_flow_context_init(ctx);
2515 	/* Return NULL when no more tokens are expected. */
2516 	if (!ctx->next_num && ctx->curr) {
2517 		*hdr = NULL;
2518 		return;
2519 	}
2520 	/* Determine if command should end here. */
2521 	if (ctx->eol && ctx->last && ctx->next_num) {
2522 		const enum index *list = ctx->next[ctx->next_num - 1];
2523 		int i;
2524 
2525 		for (i = 0; list[i]; ++i) {
2526 			if (list[i] != END)
2527 				continue;
2528 			*hdr = NULL;
2529 			return;
2530 		}
2531 	}
2532 	*hdr = &cmd_flow_token_hdr;
2533 }
2534 
2535 /** Dispatch parsed buffer to function calls. */
2536 static void
2537 cmd_flow_parsed(const struct buffer *in)
2538 {
2539 	switch (in->command) {
2540 	case VALIDATE:
2541 		port_flow_validate(in->port, &in->args.vc.attr,
2542 				   in->args.vc.pattern, in->args.vc.actions);
2543 		break;
2544 	case CREATE:
2545 		port_flow_create(in->port, &in->args.vc.attr,
2546 				 in->args.vc.pattern, in->args.vc.actions);
2547 		break;
2548 	case DESTROY:
2549 		port_flow_destroy(in->port, in->args.destroy.rule_n,
2550 				  in->args.destroy.rule);
2551 		break;
2552 	case FLUSH:
2553 		port_flow_flush(in->port);
2554 		break;
2555 	case QUERY:
2556 		port_flow_query(in->port, in->args.query.rule,
2557 				in->args.query.action);
2558 		break;
2559 	case LIST:
2560 		port_flow_list(in->port, in->args.list.group_n,
2561 			       in->args.list.group);
2562 		break;
2563 	default:
2564 		break;
2565 	}
2566 }
2567 
2568 /** Token generator and output processing callback (cmdline API). */
2569 static void
2570 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
2571 {
2572 	if (cl == NULL)
2573 		cmd_flow_tok(arg0, arg2);
2574 	else
2575 		cmd_flow_parsed(arg0);
2576 }
2577 
2578 /** Global parser instance (cmdline API). */
2579 cmdline_parse_inst_t cmd_flow = {
2580 	.f = cmd_flow_cb,
2581 	.data = NULL, /**< Unused. */
2582 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
2583 	.tokens = {
2584 		NULL,
2585 	}, /**< Tokens are returned by cmd_flow_tok(). */
2586 };
2587