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