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