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