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