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