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