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