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