app/testpmd: add queue actions to flow command
[dpdk.git] / app / test-pmd / cmdline_flow.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright 2016 6WIND S.A.
5  *   Copyright 2016 Mellanox.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of 6WIND S.A. nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <stddef.h>
35 #include <stdint.h>
36 #include <stdio.h>
37 #include <inttypes.h>
38 #include <errno.h>
39 #include <ctype.h>
40 #include <string.h>
41 #include <arpa/inet.h>
42
43 #include <rte_common.h>
44 #include <rte_ethdev.h>
45 #include <rte_byteorder.h>
46 #include <cmdline_parse.h>
47 #include <cmdline_parse_etheraddr.h>
48 #include <rte_flow.h>
49
50 #include "testpmd.h"
51
52 /** Parser token indices. */
53 enum index {
54         /* Special tokens. */
55         ZERO = 0,
56         END,
57
58         /* Common tokens. */
59         INTEGER,
60         UNSIGNED,
61         PREFIX,
62         BOOLEAN,
63         STRING,
64         MAC_ADDR,
65         IPV4_ADDR,
66         IPV6_ADDR,
67         RULE_ID,
68         PORT_ID,
69         GROUP_ID,
70         PRIORITY_LEVEL,
71
72         /* Top-level command. */
73         FLOW,
74
75         /* Sub-level commands. */
76         VALIDATE,
77         CREATE,
78         DESTROY,
79         FLUSH,
80         QUERY,
81         LIST,
82
83         /* Destroy arguments. */
84         DESTROY_RULE,
85
86         /* Query arguments. */
87         QUERY_ACTION,
88
89         /* List arguments. */
90         LIST_GROUP,
91
92         /* Validate/create arguments. */
93         GROUP,
94         PRIORITY,
95         INGRESS,
96         EGRESS,
97
98         /* Validate/create pattern. */
99         PATTERN,
100         ITEM_PARAM_IS,
101         ITEM_PARAM_SPEC,
102         ITEM_PARAM_LAST,
103         ITEM_PARAM_MASK,
104         ITEM_PARAM_PREFIX,
105         ITEM_NEXT,
106         ITEM_END,
107         ITEM_VOID,
108         ITEM_INVERT,
109         ITEM_ANY,
110         ITEM_ANY_NUM,
111         ITEM_PF,
112         ITEM_VF,
113         ITEM_VF_ID,
114         ITEM_PORT,
115         ITEM_PORT_INDEX,
116         ITEM_RAW,
117         ITEM_RAW_RELATIVE,
118         ITEM_RAW_SEARCH,
119         ITEM_RAW_OFFSET,
120         ITEM_RAW_LIMIT,
121         ITEM_RAW_PATTERN,
122         ITEM_ETH,
123         ITEM_ETH_DST,
124         ITEM_ETH_SRC,
125         ITEM_ETH_TYPE,
126         ITEM_VLAN,
127         ITEM_VLAN_TPID,
128         ITEM_VLAN_TCI,
129         ITEM_IPV4,
130         ITEM_IPV4_SRC,
131         ITEM_IPV4_DST,
132         ITEM_IPV6,
133         ITEM_IPV6_SRC,
134         ITEM_IPV6_DST,
135         ITEM_ICMP,
136         ITEM_ICMP_TYPE,
137         ITEM_ICMP_CODE,
138         ITEM_UDP,
139         ITEM_UDP_SRC,
140         ITEM_UDP_DST,
141         ITEM_TCP,
142         ITEM_TCP_SRC,
143         ITEM_TCP_DST,
144         ITEM_SCTP,
145         ITEM_SCTP_SRC,
146         ITEM_SCTP_DST,
147         ITEM_VXLAN,
148         ITEM_VXLAN_VNI,
149
150         /* Validate/create actions. */
151         ACTIONS,
152         ACTION_NEXT,
153         ACTION_END,
154         ACTION_VOID,
155         ACTION_PASSTHRU,
156         ACTION_MARK,
157         ACTION_MARK_ID,
158         ACTION_FLAG,
159         ACTION_QUEUE,
160         ACTION_QUEUE_INDEX,
161         ACTION_DROP,
162         ACTION_COUNT,
163         ACTION_DUP,
164         ACTION_DUP_INDEX,
165         ACTION_RSS,
166         ACTION_RSS_QUEUES,
167         ACTION_RSS_QUEUE,
168         ACTION_PF,
169         ACTION_VF,
170         ACTION_VF_ORIGINAL,
171         ACTION_VF_ID,
172 };
173
174 /** Size of pattern[] field in struct rte_flow_item_raw. */
175 #define ITEM_RAW_PATTERN_SIZE 36
176
177 /** Storage size for struct rte_flow_item_raw including pattern. */
178 #define ITEM_RAW_SIZE \
179         (offsetof(struct rte_flow_item_raw, pattern) + ITEM_RAW_PATTERN_SIZE)
180
181 /** Number of queue[] entries in struct rte_flow_action_rss. */
182 #define ACTION_RSS_NUM 32
183
184 /** Storage size for struct rte_flow_action_rss including queues. */
185 #define ACTION_RSS_SIZE \
186         (offsetof(struct rte_flow_action_rss, queue) + \
187          sizeof(*((struct rte_flow_action_rss *)0)->queue) * ACTION_RSS_NUM)
188
189 /** Maximum number of subsequent tokens and arguments on the stack. */
190 #define CTX_STACK_SIZE 16
191
192 /** Parser context. */
193 struct context {
194         /** Stack of subsequent token lists to process. */
195         const enum index *next[CTX_STACK_SIZE];
196         /** Arguments for stacked tokens. */
197         const void *args[CTX_STACK_SIZE];
198         enum index curr; /**< Current token index. */
199         enum index prev; /**< Index of the last token seen. */
200         int next_num; /**< Number of entries in next[]. */
201         int args_num; /**< Number of entries in args[]. */
202         uint32_t reparse:1; /**< Start over from the beginning. */
203         uint32_t eol:1; /**< EOL has been detected. */
204         uint32_t last:1; /**< No more arguments. */
205         uint16_t port; /**< Current port ID (for completions). */
206         uint32_t objdata; /**< Object-specific data. */
207         void *object; /**< Address of current object for relative offsets. */
208         void *objmask; /**< Object a full mask must be written to. */
209 };
210
211 /** Token argument. */
212 struct arg {
213         uint32_t hton:1; /**< Use network byte ordering. */
214         uint32_t sign:1; /**< Value is signed. */
215         uint32_t offset; /**< Relative offset from ctx->object. */
216         uint32_t size; /**< Field size. */
217         const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
218 };
219
220 /** Parser token definition. */
221 struct token {
222         /** Type displayed during completion (defaults to "TOKEN"). */
223         const char *type;
224         /** Help displayed during completion (defaults to token name). */
225         const char *help;
226         /** Private data used by parser functions. */
227         const void *priv;
228         /**
229          * Lists of subsequent tokens to push on the stack. Each call to the
230          * parser consumes the last entry of that stack.
231          */
232         const enum index *const *next;
233         /** Arguments stack for subsequent tokens that need them. */
234         const struct arg *const *args;
235         /**
236          * Token-processing callback, returns -1 in case of error, the
237          * length of the matched string otherwise. If NULL, attempts to
238          * match the token name.
239          *
240          * If buf is not NULL, the result should be stored in it according
241          * to context. An error is returned if not large enough.
242          */
243         int (*call)(struct context *ctx, const struct token *token,
244                     const char *str, unsigned int len,
245                     void *buf, unsigned int size);
246         /**
247          * Callback that provides possible values for this token, used for
248          * completion. Returns -1 in case of error, the number of possible
249          * values otherwise. If NULL, the token name is used.
250          *
251          * If buf is not NULL, entry index ent is written to buf and the
252          * full length of the entry is returned (same behavior as
253          * snprintf()).
254          */
255         int (*comp)(struct context *ctx, const struct token *token,
256                     unsigned int ent, char *buf, unsigned int size);
257         /** Mandatory token name, no default value. */
258         const char *name;
259 };
260
261 /** Static initializer for the next field. */
262 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
263
264 /** Static initializer for a NEXT() entry. */
265 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
266
267 /** Static initializer for the args field. */
268 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
269
270 /** Static initializer for ARGS() to target a field. */
271 #define ARGS_ENTRY(s, f) \
272         (&(const struct arg){ \
273                 .offset = offsetof(s, f), \
274                 .size = sizeof(((s *)0)->f), \
275         })
276
277 /** Static initializer for ARGS() to target a bit-field. */
278 #define ARGS_ENTRY_BF(s, f, b) \
279         (&(const struct arg){ \
280                 .size = sizeof(s), \
281                 .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
282         })
283
284 /** Static initializer for ARGS() to target a pointer. */
285 #define ARGS_ENTRY_PTR(s, f) \
286         (&(const struct arg){ \
287                 .size = sizeof(*((s *)0)->f), \
288         })
289
290 /** Static initializer for ARGS() with arbitrary size. */
291 #define ARGS_ENTRY_USZ(s, f, sz) \
292         (&(const struct arg){ \
293                 .offset = offsetof(s, f), \
294                 .size = (sz), \
295         })
296
297 /** Same as ARGS_ENTRY() using network byte ordering. */
298 #define ARGS_ENTRY_HTON(s, f) \
299         (&(const struct arg){ \
300                 .hton = 1, \
301                 .offset = offsetof(s, f), \
302                 .size = sizeof(((s *)0)->f), \
303         })
304
305 /** Parser output buffer layout expected by cmd_flow_parsed(). */
306 struct buffer {
307         enum index command; /**< Flow command. */
308         uint16_t port; /**< Affected port ID. */
309         union {
310                 struct {
311                         struct rte_flow_attr attr;
312                         struct rte_flow_item *pattern;
313                         struct rte_flow_action *actions;
314                         uint32_t pattern_n;
315                         uint32_t actions_n;
316                         uint8_t *data;
317                 } vc; /**< Validate/create arguments. */
318                 struct {
319                         uint32_t *rule;
320                         uint32_t rule_n;
321                 } destroy; /**< Destroy arguments. */
322                 struct {
323                         uint32_t rule;
324                         enum rte_flow_action_type action;
325                 } query; /**< Query arguments. */
326                 struct {
327                         uint32_t *group;
328                         uint32_t group_n;
329                 } list; /**< List arguments. */
330         } args; /**< Command arguments. */
331 };
332
333 /** Private data for pattern items. */
334 struct parse_item_priv {
335         enum rte_flow_item_type type; /**< Item type. */
336         uint32_t size; /**< Size of item specification structure. */
337 };
338
339 #define PRIV_ITEM(t, s) \
340         (&(const struct parse_item_priv){ \
341                 .type = RTE_FLOW_ITEM_TYPE_ ## t, \
342                 .size = s, \
343         })
344
345 /** Private data for actions. */
346 struct parse_action_priv {
347         enum rte_flow_action_type type; /**< Action type. */
348         uint32_t size; /**< Size of action configuration structure. */
349 };
350
351 #define PRIV_ACTION(t, s) \
352         (&(const struct parse_action_priv){ \
353                 .type = RTE_FLOW_ACTION_TYPE_ ## t, \
354                 .size = s, \
355         })
356
357 static const enum index next_vc_attr[] = {
358         GROUP,
359         PRIORITY,
360         INGRESS,
361         EGRESS,
362         PATTERN,
363         ZERO,
364 };
365
366 static const enum index next_destroy_attr[] = {
367         DESTROY_RULE,
368         END,
369         ZERO,
370 };
371
372 static const enum index next_list_attr[] = {
373         LIST_GROUP,
374         END,
375         ZERO,
376 };
377
378 static const enum index item_param[] = {
379         ITEM_PARAM_IS,
380         ITEM_PARAM_SPEC,
381         ITEM_PARAM_LAST,
382         ITEM_PARAM_MASK,
383         ITEM_PARAM_PREFIX,
384         ZERO,
385 };
386
387 static const enum index next_item[] = {
388         ITEM_END,
389         ITEM_VOID,
390         ITEM_INVERT,
391         ITEM_ANY,
392         ITEM_PF,
393         ITEM_VF,
394         ITEM_PORT,
395         ITEM_RAW,
396         ITEM_ETH,
397         ITEM_VLAN,
398         ITEM_IPV4,
399         ITEM_IPV6,
400         ITEM_ICMP,
401         ITEM_UDP,
402         ITEM_TCP,
403         ITEM_SCTP,
404         ITEM_VXLAN,
405         ZERO,
406 };
407
408 static const enum index item_any[] = {
409         ITEM_ANY_NUM,
410         ITEM_NEXT,
411         ZERO,
412 };
413
414 static const enum index item_vf[] = {
415         ITEM_VF_ID,
416         ITEM_NEXT,
417         ZERO,
418 };
419
420 static const enum index item_port[] = {
421         ITEM_PORT_INDEX,
422         ITEM_NEXT,
423         ZERO,
424 };
425
426 static const enum index item_raw[] = {
427         ITEM_RAW_RELATIVE,
428         ITEM_RAW_SEARCH,
429         ITEM_RAW_OFFSET,
430         ITEM_RAW_LIMIT,
431         ITEM_RAW_PATTERN,
432         ITEM_NEXT,
433         ZERO,
434 };
435
436 static const enum index item_eth[] = {
437         ITEM_ETH_DST,
438         ITEM_ETH_SRC,
439         ITEM_ETH_TYPE,
440         ITEM_NEXT,
441         ZERO,
442 };
443
444 static const enum index item_vlan[] = {
445         ITEM_VLAN_TPID,
446         ITEM_VLAN_TCI,
447         ITEM_NEXT,
448         ZERO,
449 };
450
451 static const enum index item_ipv4[] = {
452         ITEM_IPV4_SRC,
453         ITEM_IPV4_DST,
454         ITEM_NEXT,
455         ZERO,
456 };
457
458 static const enum index item_ipv6[] = {
459         ITEM_IPV6_SRC,
460         ITEM_IPV6_DST,
461         ITEM_NEXT,
462         ZERO,
463 };
464
465 static const enum index item_icmp[] = {
466         ITEM_ICMP_TYPE,
467         ITEM_ICMP_CODE,
468         ITEM_NEXT,
469         ZERO,
470 };
471
472 static const enum index item_udp[] = {
473         ITEM_UDP_SRC,
474         ITEM_UDP_DST,
475         ITEM_NEXT,
476         ZERO,
477 };
478
479 static const enum index item_tcp[] = {
480         ITEM_TCP_SRC,
481         ITEM_TCP_DST,
482         ITEM_NEXT,
483         ZERO,
484 };
485
486 static const enum index item_sctp[] = {
487         ITEM_SCTP_SRC,
488         ITEM_SCTP_DST,
489         ITEM_NEXT,
490         ZERO,
491 };
492
493 static const enum index item_vxlan[] = {
494         ITEM_VXLAN_VNI,
495         ITEM_NEXT,
496         ZERO,
497 };
498
499 static const enum index next_action[] = {
500         ACTION_END,
501         ACTION_VOID,
502         ACTION_PASSTHRU,
503         ACTION_MARK,
504         ACTION_FLAG,
505         ACTION_QUEUE,
506         ACTION_DROP,
507         ACTION_COUNT,
508         ACTION_DUP,
509         ACTION_RSS,
510         ACTION_PF,
511         ACTION_VF,
512         ZERO,
513 };
514
515 static const enum index action_mark[] = {
516         ACTION_MARK_ID,
517         ACTION_NEXT,
518         ZERO,
519 };
520
521 static const enum index action_queue[] = {
522         ACTION_QUEUE_INDEX,
523         ACTION_NEXT,
524         ZERO,
525 };
526
527 static const enum index action_dup[] = {
528         ACTION_DUP_INDEX,
529         ACTION_NEXT,
530         ZERO,
531 };
532
533 static const enum index action_rss[] = {
534         ACTION_RSS_QUEUES,
535         ACTION_NEXT,
536         ZERO,
537 };
538
539 static const enum index action_vf[] = {
540         ACTION_VF_ORIGINAL,
541         ACTION_VF_ID,
542         ACTION_NEXT,
543         ZERO,
544 };
545
546 static int parse_init(struct context *, const struct token *,
547                       const char *, unsigned int,
548                       void *, unsigned int);
549 static int parse_vc(struct context *, const struct token *,
550                     const char *, unsigned int,
551                     void *, unsigned int);
552 static int parse_vc_spec(struct context *, const struct token *,
553                          const char *, unsigned int, void *, unsigned int);
554 static int parse_vc_conf(struct context *, const struct token *,
555                          const char *, unsigned int, void *, unsigned int);
556 static int parse_vc_action_rss_queue(struct context *, const struct token *,
557                                      const char *, unsigned int, void *,
558                                      unsigned int);
559 static int parse_destroy(struct context *, const struct token *,
560                          const char *, unsigned int,
561                          void *, unsigned int);
562 static int parse_flush(struct context *, const struct token *,
563                        const char *, unsigned int,
564                        void *, unsigned int);
565 static int parse_query(struct context *, const struct token *,
566                        const char *, unsigned int,
567                        void *, unsigned int);
568 static int parse_action(struct context *, const struct token *,
569                         const char *, unsigned int,
570                         void *, unsigned int);
571 static int parse_list(struct context *, const struct token *,
572                       const char *, unsigned int,
573                       void *, unsigned int);
574 static int parse_int(struct context *, const struct token *,
575                      const char *, unsigned int,
576                      void *, unsigned int);
577 static int parse_prefix(struct context *, const struct token *,
578                         const char *, unsigned int,
579                         void *, unsigned int);
580 static int parse_boolean(struct context *, const struct token *,
581                          const char *, unsigned int,
582                          void *, unsigned int);
583 static int parse_string(struct context *, const struct token *,
584                         const char *, unsigned int,
585                         void *, unsigned int);
586 static int parse_mac_addr(struct context *, const struct token *,
587                           const char *, unsigned int,
588                           void *, unsigned int);
589 static int parse_ipv4_addr(struct context *, const struct token *,
590                            const char *, unsigned int,
591                            void *, unsigned int);
592 static int parse_ipv6_addr(struct context *, const struct token *,
593                            const char *, unsigned int,
594                            void *, unsigned int);
595 static int parse_port(struct context *, const struct token *,
596                       const char *, unsigned int,
597                       void *, unsigned int);
598 static int comp_none(struct context *, const struct token *,
599                      unsigned int, char *, unsigned int);
600 static int comp_boolean(struct context *, const struct token *,
601                         unsigned int, char *, unsigned int);
602 static int comp_action(struct context *, const struct token *,
603                        unsigned int, char *, unsigned int);
604 static int comp_port(struct context *, const struct token *,
605                      unsigned int, char *, unsigned int);
606 static int comp_rule_id(struct context *, const struct token *,
607                         unsigned int, char *, unsigned int);
608 static int comp_vc_action_rss_queue(struct context *, const struct token *,
609                                     unsigned int, char *, unsigned int);
610
611 /** Token definitions. */
612 static const struct token token_list[] = {
613         /* Special tokens. */
614         [ZERO] = {
615                 .name = "ZERO",
616                 .help = "null entry, abused as the entry point",
617                 .next = NEXT(NEXT_ENTRY(FLOW)),
618         },
619         [END] = {
620                 .name = "",
621                 .type = "RETURN",
622                 .help = "command may end here",
623         },
624         /* Common tokens. */
625         [INTEGER] = {
626                 .name = "{int}",
627                 .type = "INTEGER",
628                 .help = "integer value",
629                 .call = parse_int,
630                 .comp = comp_none,
631         },
632         [UNSIGNED] = {
633                 .name = "{unsigned}",
634                 .type = "UNSIGNED",
635                 .help = "unsigned integer value",
636                 .call = parse_int,
637                 .comp = comp_none,
638         },
639         [PREFIX] = {
640                 .name = "{prefix}",
641                 .type = "PREFIX",
642                 .help = "prefix length for bit-mask",
643                 .call = parse_prefix,
644                 .comp = comp_none,
645         },
646         [BOOLEAN] = {
647                 .name = "{boolean}",
648                 .type = "BOOLEAN",
649                 .help = "any boolean value",
650                 .call = parse_boolean,
651                 .comp = comp_boolean,
652         },
653         [STRING] = {
654                 .name = "{string}",
655                 .type = "STRING",
656                 .help = "fixed string",
657                 .call = parse_string,
658                 .comp = comp_none,
659         },
660         [MAC_ADDR] = {
661                 .name = "{MAC address}",
662                 .type = "MAC-48",
663                 .help = "standard MAC address notation",
664                 .call = parse_mac_addr,
665                 .comp = comp_none,
666         },
667         [IPV4_ADDR] = {
668                 .name = "{IPv4 address}",
669                 .type = "IPV4 ADDRESS",
670                 .help = "standard IPv4 address notation",
671                 .call = parse_ipv4_addr,
672                 .comp = comp_none,
673         },
674         [IPV6_ADDR] = {
675                 .name = "{IPv6 address}",
676                 .type = "IPV6 ADDRESS",
677                 .help = "standard IPv6 address notation",
678                 .call = parse_ipv6_addr,
679                 .comp = comp_none,
680         },
681         [RULE_ID] = {
682                 .name = "{rule id}",
683                 .type = "RULE ID",
684                 .help = "rule identifier",
685                 .call = parse_int,
686                 .comp = comp_rule_id,
687         },
688         [PORT_ID] = {
689                 .name = "{port_id}",
690                 .type = "PORT ID",
691                 .help = "port identifier",
692                 .call = parse_port,
693                 .comp = comp_port,
694         },
695         [GROUP_ID] = {
696                 .name = "{group_id}",
697                 .type = "GROUP ID",
698                 .help = "group identifier",
699                 .call = parse_int,
700                 .comp = comp_none,
701         },
702         [PRIORITY_LEVEL] = {
703                 .name = "{level}",
704                 .type = "PRIORITY",
705                 .help = "priority level",
706                 .call = parse_int,
707                 .comp = comp_none,
708         },
709         /* Top-level command. */
710         [FLOW] = {
711                 .name = "flow",
712                 .type = "{command} {port_id} [{arg} [...]]",
713                 .help = "manage ingress/egress flow rules",
714                 .next = NEXT(NEXT_ENTRY
715                              (VALIDATE,
716                               CREATE,
717                               DESTROY,
718                               FLUSH,
719                               LIST,
720                               QUERY)),
721                 .call = parse_init,
722         },
723         /* Sub-level commands. */
724         [VALIDATE] = {
725                 .name = "validate",
726                 .help = "check whether a flow rule can be created",
727                 .next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
728                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
729                 .call = parse_vc,
730         },
731         [CREATE] = {
732                 .name = "create",
733                 .help = "create a flow rule",
734                 .next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
735                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
736                 .call = parse_vc,
737         },
738         [DESTROY] = {
739                 .name = "destroy",
740                 .help = "destroy specific flow rules",
741                 .next = NEXT(NEXT_ENTRY(DESTROY_RULE), NEXT_ENTRY(PORT_ID)),
742                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
743                 .call = parse_destroy,
744         },
745         [FLUSH] = {
746                 .name = "flush",
747                 .help = "destroy all flow rules",
748                 .next = NEXT(NEXT_ENTRY(PORT_ID)),
749                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
750                 .call = parse_flush,
751         },
752         [QUERY] = {
753                 .name = "query",
754                 .help = "query an existing flow rule",
755                 .next = NEXT(NEXT_ENTRY(QUERY_ACTION),
756                              NEXT_ENTRY(RULE_ID),
757                              NEXT_ENTRY(PORT_ID)),
758                 .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action),
759                              ARGS_ENTRY(struct buffer, args.query.rule),
760                              ARGS_ENTRY(struct buffer, port)),
761                 .call = parse_query,
762         },
763         [LIST] = {
764                 .name = "list",
765                 .help = "list existing flow rules",
766                 .next = NEXT(next_list_attr, NEXT_ENTRY(PORT_ID)),
767                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
768                 .call = parse_list,
769         },
770         /* Destroy arguments. */
771         [DESTROY_RULE] = {
772                 .name = "rule",
773                 .help = "specify a rule identifier",
774                 .next = NEXT(next_destroy_attr, NEXT_ENTRY(RULE_ID)),
775                 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
776                 .call = parse_destroy,
777         },
778         /* Query arguments. */
779         [QUERY_ACTION] = {
780                 .name = "{action}",
781                 .type = "ACTION",
782                 .help = "action to query, must be part of the rule",
783                 .call = parse_action,
784                 .comp = comp_action,
785         },
786         /* List arguments. */
787         [LIST_GROUP] = {
788                 .name = "group",
789                 .help = "specify a group",
790                 .next = NEXT(next_list_attr, NEXT_ENTRY(GROUP_ID)),
791                 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
792                 .call = parse_list,
793         },
794         /* Validate/create attributes. */
795         [GROUP] = {
796                 .name = "group",
797                 .help = "specify a group",
798                 .next = NEXT(next_vc_attr, NEXT_ENTRY(GROUP_ID)),
799                 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
800                 .call = parse_vc,
801         },
802         [PRIORITY] = {
803                 .name = "priority",
804                 .help = "specify a priority level",
805                 .next = NEXT(next_vc_attr, NEXT_ENTRY(PRIORITY_LEVEL)),
806                 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
807                 .call = parse_vc,
808         },
809         [INGRESS] = {
810                 .name = "ingress",
811                 .help = "affect rule to ingress",
812                 .next = NEXT(next_vc_attr),
813                 .call = parse_vc,
814         },
815         [EGRESS] = {
816                 .name = "egress",
817                 .help = "affect rule to egress",
818                 .next = NEXT(next_vc_attr),
819                 .call = parse_vc,
820         },
821         /* Validate/create pattern. */
822         [PATTERN] = {
823                 .name = "pattern",
824                 .help = "submit a list of pattern items",
825                 .next = NEXT(next_item),
826                 .call = parse_vc,
827         },
828         [ITEM_PARAM_IS] = {
829                 .name = "is",
830                 .help = "match value perfectly (with full bit-mask)",
831                 .call = parse_vc_spec,
832         },
833         [ITEM_PARAM_SPEC] = {
834                 .name = "spec",
835                 .help = "match value according to configured bit-mask",
836                 .call = parse_vc_spec,
837         },
838         [ITEM_PARAM_LAST] = {
839                 .name = "last",
840                 .help = "specify upper bound to establish a range",
841                 .call = parse_vc_spec,
842         },
843         [ITEM_PARAM_MASK] = {
844                 .name = "mask",
845                 .help = "specify bit-mask with relevant bits set to one",
846                 .call = parse_vc_spec,
847         },
848         [ITEM_PARAM_PREFIX] = {
849                 .name = "prefix",
850                 .help = "generate bit-mask from a prefix length",
851                 .call = parse_vc_spec,
852         },
853         [ITEM_NEXT] = {
854                 .name = "/",
855                 .help = "specify next pattern item",
856                 .next = NEXT(next_item),
857         },
858         [ITEM_END] = {
859                 .name = "end",
860                 .help = "end list of pattern items",
861                 .priv = PRIV_ITEM(END, 0),
862                 .next = NEXT(NEXT_ENTRY(ACTIONS)),
863                 .call = parse_vc,
864         },
865         [ITEM_VOID] = {
866                 .name = "void",
867                 .help = "no-op pattern item",
868                 .priv = PRIV_ITEM(VOID, 0),
869                 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
870                 .call = parse_vc,
871         },
872         [ITEM_INVERT] = {
873                 .name = "invert",
874                 .help = "perform actions when pattern does not match",
875                 .priv = PRIV_ITEM(INVERT, 0),
876                 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
877                 .call = parse_vc,
878         },
879         [ITEM_ANY] = {
880                 .name = "any",
881                 .help = "match any protocol for the current layer",
882                 .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
883                 .next = NEXT(item_any),
884                 .call = parse_vc,
885         },
886         [ITEM_ANY_NUM] = {
887                 .name = "num",
888                 .help = "number of layers covered",
889                 .next = NEXT(item_any, NEXT_ENTRY(UNSIGNED), item_param),
890                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
891         },
892         [ITEM_PF] = {
893                 .name = "pf",
894                 .help = "match packets addressed to the physical function",
895                 .priv = PRIV_ITEM(PF, 0),
896                 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
897                 .call = parse_vc,
898         },
899         [ITEM_VF] = {
900                 .name = "vf",
901                 .help = "match packets addressed to a virtual function ID",
902                 .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
903                 .next = NEXT(item_vf),
904                 .call = parse_vc,
905         },
906         [ITEM_VF_ID] = {
907                 .name = "id",
908                 .help = "destination VF ID",
909                 .next = NEXT(item_vf, NEXT_ENTRY(UNSIGNED), item_param),
910                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
911         },
912         [ITEM_PORT] = {
913                 .name = "port",
914                 .help = "device-specific physical port index to use",
915                 .priv = PRIV_ITEM(PORT, sizeof(struct rte_flow_item_port)),
916                 .next = NEXT(item_port),
917                 .call = parse_vc,
918         },
919         [ITEM_PORT_INDEX] = {
920                 .name = "index",
921                 .help = "physical port index",
922                 .next = NEXT(item_port, NEXT_ENTRY(UNSIGNED), item_param),
923                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port, index)),
924         },
925         [ITEM_RAW] = {
926                 .name = "raw",
927                 .help = "match an arbitrary byte string",
928                 .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
929                 .next = NEXT(item_raw),
930                 .call = parse_vc,
931         },
932         [ITEM_RAW_RELATIVE] = {
933                 .name = "relative",
934                 .help = "look for pattern after the previous item",
935                 .next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
936                 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
937                                            relative, 1)),
938         },
939         [ITEM_RAW_SEARCH] = {
940                 .name = "search",
941                 .help = "search pattern from offset (see also limit)",
942                 .next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
943                 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
944                                            search, 1)),
945         },
946         [ITEM_RAW_OFFSET] = {
947                 .name = "offset",
948                 .help = "absolute or relative offset for pattern",
949                 .next = NEXT(item_raw, NEXT_ENTRY(INTEGER), item_param),
950                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
951         },
952         [ITEM_RAW_LIMIT] = {
953                 .name = "limit",
954                 .help = "search area limit for start of pattern",
955                 .next = NEXT(item_raw, NEXT_ENTRY(UNSIGNED), item_param),
956                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
957         },
958         [ITEM_RAW_PATTERN] = {
959                 .name = "pattern",
960                 .help = "byte string to look for",
961                 .next = NEXT(item_raw,
962                              NEXT_ENTRY(STRING),
963                              NEXT_ENTRY(ITEM_PARAM_IS,
964                                         ITEM_PARAM_SPEC,
965                                         ITEM_PARAM_MASK)),
966                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, length),
967                              ARGS_ENTRY_USZ(struct rte_flow_item_raw,
968                                             pattern,
969                                             ITEM_RAW_PATTERN_SIZE)),
970         },
971         [ITEM_ETH] = {
972                 .name = "eth",
973                 .help = "match Ethernet header",
974                 .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
975                 .next = NEXT(item_eth),
976                 .call = parse_vc,
977         },
978         [ITEM_ETH_DST] = {
979                 .name = "dst",
980                 .help = "destination MAC",
981                 .next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
982                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_eth, dst)),
983         },
984         [ITEM_ETH_SRC] = {
985                 .name = "src",
986                 .help = "source MAC",
987                 .next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
988                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_eth, src)),
989         },
990         [ITEM_ETH_TYPE] = {
991                 .name = "type",
992                 .help = "EtherType",
993                 .next = NEXT(item_eth, NEXT_ENTRY(UNSIGNED), item_param),
994                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
995         },
996         [ITEM_VLAN] = {
997                 .name = "vlan",
998                 .help = "match 802.1Q/ad VLAN tag",
999                 .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
1000                 .next = NEXT(item_vlan),
1001                 .call = parse_vc,
1002         },
1003         [ITEM_VLAN_TPID] = {
1004                 .name = "tpid",
1005                 .help = "tag protocol identifier",
1006                 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1007                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tpid)),
1008         },
1009         [ITEM_VLAN_TCI] = {
1010                 .name = "tci",
1011                 .help = "tag control information",
1012                 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1013                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
1014         },
1015         [ITEM_IPV4] = {
1016                 .name = "ipv4",
1017                 .help = "match IPv4 header",
1018                 .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
1019                 .next = NEXT(item_ipv4),
1020                 .call = parse_vc,
1021         },
1022         [ITEM_IPV4_SRC] = {
1023                 .name = "src",
1024                 .help = "source address",
1025                 .next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
1026                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1027                                              hdr.src_addr)),
1028         },
1029         [ITEM_IPV4_DST] = {
1030                 .name = "dst",
1031                 .help = "destination address",
1032                 .next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
1033                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1034                                              hdr.dst_addr)),
1035         },
1036         [ITEM_IPV6] = {
1037                 .name = "ipv6",
1038                 .help = "match IPv6 header",
1039                 .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
1040                 .next = NEXT(item_ipv6),
1041                 .call = parse_vc,
1042         },
1043         [ITEM_IPV6_SRC] = {
1044                 .name = "src",
1045                 .help = "source address",
1046                 .next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
1047                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
1048                                              hdr.src_addr)),
1049         },
1050         [ITEM_IPV6_DST] = {
1051                 .name = "dst",
1052                 .help = "destination address",
1053                 .next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
1054                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
1055                                              hdr.dst_addr)),
1056         },
1057         [ITEM_ICMP] = {
1058                 .name = "icmp",
1059                 .help = "match ICMP header",
1060                 .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
1061                 .next = NEXT(item_icmp),
1062                 .call = parse_vc,
1063         },
1064         [ITEM_ICMP_TYPE] = {
1065                 .name = "type",
1066                 .help = "ICMP packet type",
1067                 .next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
1068                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
1069                                              hdr.icmp_type)),
1070         },
1071         [ITEM_ICMP_CODE] = {
1072                 .name = "code",
1073                 .help = "ICMP packet code",
1074                 .next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
1075                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
1076                                              hdr.icmp_code)),
1077         },
1078         [ITEM_UDP] = {
1079                 .name = "udp",
1080                 .help = "match UDP header",
1081                 .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
1082                 .next = NEXT(item_udp),
1083                 .call = parse_vc,
1084         },
1085         [ITEM_UDP_SRC] = {
1086                 .name = "src",
1087                 .help = "UDP source port",
1088                 .next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
1089                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
1090                                              hdr.src_port)),
1091         },
1092         [ITEM_UDP_DST] = {
1093                 .name = "dst",
1094                 .help = "UDP destination port",
1095                 .next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
1096                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
1097                                              hdr.dst_port)),
1098         },
1099         [ITEM_TCP] = {
1100                 .name = "tcp",
1101                 .help = "match TCP header",
1102                 .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
1103                 .next = NEXT(item_tcp),
1104                 .call = parse_vc,
1105         },
1106         [ITEM_TCP_SRC] = {
1107                 .name = "src",
1108                 .help = "TCP source port",
1109                 .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
1110                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
1111                                              hdr.src_port)),
1112         },
1113         [ITEM_TCP_DST] = {
1114                 .name = "dst",
1115                 .help = "TCP destination port",
1116                 .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
1117                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
1118                                              hdr.dst_port)),
1119         },
1120         [ITEM_SCTP] = {
1121                 .name = "sctp",
1122                 .help = "match SCTP header",
1123                 .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
1124                 .next = NEXT(item_sctp),
1125                 .call = parse_vc,
1126         },
1127         [ITEM_SCTP_SRC] = {
1128                 .name = "src",
1129                 .help = "SCTP source port",
1130                 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
1131                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
1132                                              hdr.src_port)),
1133         },
1134         [ITEM_SCTP_DST] = {
1135                 .name = "dst",
1136                 .help = "SCTP destination port",
1137                 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
1138                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
1139                                              hdr.dst_port)),
1140         },
1141         [ITEM_VXLAN] = {
1142                 .name = "vxlan",
1143                 .help = "match VXLAN header",
1144                 .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
1145                 .next = NEXT(item_vxlan),
1146                 .call = parse_vc,
1147         },
1148         [ITEM_VXLAN_VNI] = {
1149                 .name = "vni",
1150                 .help = "VXLAN identifier",
1151                 .next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED), item_param),
1152                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
1153         },
1154         /* Validate/create actions. */
1155         [ACTIONS] = {
1156                 .name = "actions",
1157                 .help = "submit a list of associated actions",
1158                 .next = NEXT(next_action),
1159                 .call = parse_vc,
1160         },
1161         [ACTION_NEXT] = {
1162                 .name = "/",
1163                 .help = "specify next action",
1164                 .next = NEXT(next_action),
1165         },
1166         [ACTION_END] = {
1167                 .name = "end",
1168                 .help = "end list of actions",
1169                 .priv = PRIV_ACTION(END, 0),
1170                 .call = parse_vc,
1171         },
1172         [ACTION_VOID] = {
1173                 .name = "void",
1174                 .help = "no-op action",
1175                 .priv = PRIV_ACTION(VOID, 0),
1176                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
1177                 .call = parse_vc,
1178         },
1179         [ACTION_PASSTHRU] = {
1180                 .name = "passthru",
1181                 .help = "let subsequent rule process matched packets",
1182                 .priv = PRIV_ACTION(PASSTHRU, 0),
1183                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
1184                 .call = parse_vc,
1185         },
1186         [ACTION_MARK] = {
1187                 .name = "mark",
1188                 .help = "attach 32 bit value to packets",
1189                 .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
1190                 .next = NEXT(action_mark),
1191                 .call = parse_vc,
1192         },
1193         [ACTION_MARK_ID] = {
1194                 .name = "id",
1195                 .help = "32 bit value to return with packets",
1196                 .next = NEXT(action_mark, NEXT_ENTRY(UNSIGNED)),
1197                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
1198                 .call = parse_vc_conf,
1199         },
1200         [ACTION_FLAG] = {
1201                 .name = "flag",
1202                 .help = "flag packets",
1203                 .priv = PRIV_ACTION(FLAG, 0),
1204                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
1205                 .call = parse_vc,
1206         },
1207         [ACTION_QUEUE] = {
1208                 .name = "queue",
1209                 .help = "assign packets to a given queue index",
1210                 .priv = PRIV_ACTION(QUEUE,
1211                                     sizeof(struct rte_flow_action_queue)),
1212                 .next = NEXT(action_queue),
1213                 .call = parse_vc,
1214         },
1215         [ACTION_QUEUE_INDEX] = {
1216                 .name = "index",
1217                 .help = "queue index to use",
1218                 .next = NEXT(action_queue, NEXT_ENTRY(UNSIGNED)),
1219                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
1220                 .call = parse_vc_conf,
1221         },
1222         [ACTION_DROP] = {
1223                 .name = "drop",
1224                 .help = "drop packets (note: passthru has priority)",
1225                 .priv = PRIV_ACTION(DROP, 0),
1226                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
1227                 .call = parse_vc,
1228         },
1229         [ACTION_COUNT] = {
1230                 .name = "count",
1231                 .help = "enable counters for this rule",
1232                 .priv = PRIV_ACTION(COUNT, 0),
1233                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
1234                 .call = parse_vc,
1235         },
1236         [ACTION_DUP] = {
1237                 .name = "dup",
1238                 .help = "duplicate packets to a given queue index",
1239                 .priv = PRIV_ACTION(DUP, sizeof(struct rte_flow_action_dup)),
1240                 .next = NEXT(action_dup),
1241                 .call = parse_vc,
1242         },
1243         [ACTION_DUP_INDEX] = {
1244                 .name = "index",
1245                 .help = "queue index to duplicate packets to",
1246                 .next = NEXT(action_dup, NEXT_ENTRY(UNSIGNED)),
1247                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_dup, index)),
1248                 .call = parse_vc_conf,
1249         },
1250         [ACTION_RSS] = {
1251                 .name = "rss",
1252                 .help = "spread packets among several queues",
1253                 .priv = PRIV_ACTION(RSS, ACTION_RSS_SIZE),
1254                 .next = NEXT(action_rss),
1255                 .call = parse_vc,
1256         },
1257         [ACTION_RSS_QUEUES] = {
1258                 .name = "queues",
1259                 .help = "queue indices to use",
1260                 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
1261                 .call = parse_vc_conf,
1262         },
1263         [ACTION_RSS_QUEUE] = {
1264                 .name = "{queue}",
1265                 .help = "queue index",
1266                 .call = parse_vc_action_rss_queue,
1267                 .comp = comp_vc_action_rss_queue,
1268         },
1269         [ACTION_PF] = {
1270                 .name = "pf",
1271                 .help = "redirect packets to physical device function",
1272                 .priv = PRIV_ACTION(PF, 0),
1273                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
1274                 .call = parse_vc,
1275         },
1276         [ACTION_VF] = {
1277                 .name = "vf",
1278                 .help = "redirect packets to virtual device function",
1279                 .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
1280                 .next = NEXT(action_vf),
1281                 .call = parse_vc,
1282         },
1283         [ACTION_VF_ORIGINAL] = {
1284                 .name = "original",
1285                 .help = "use original VF ID if possible",
1286                 .next = NEXT(action_vf, NEXT_ENTRY(BOOLEAN)),
1287                 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
1288                                            original, 1)),
1289                 .call = parse_vc_conf,
1290         },
1291         [ACTION_VF_ID] = {
1292                 .name = "id",
1293                 .help = "VF ID to redirect packets to",
1294                 .next = NEXT(action_vf, NEXT_ENTRY(UNSIGNED)),
1295                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
1296                 .call = parse_vc_conf,
1297         },
1298 };
1299
1300 /** Remove and return last entry from argument stack. */
1301 static const struct arg *
1302 pop_args(struct context *ctx)
1303 {
1304         return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
1305 }
1306
1307 /** Add entry on top of the argument stack. */
1308 static int
1309 push_args(struct context *ctx, const struct arg *arg)
1310 {
1311         if (ctx->args_num == CTX_STACK_SIZE)
1312                 return -1;
1313         ctx->args[ctx->args_num++] = arg;
1314         return 0;
1315 }
1316
1317 /** Spread value into buffer according to bit-mask. */
1318 static size_t
1319 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
1320 {
1321         uint32_t i = arg->size;
1322         uint32_t end = 0;
1323         int sub = 1;
1324         int add = 0;
1325         size_t len = 0;
1326
1327         if (!arg->mask)
1328                 return 0;
1329 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1330         if (!arg->hton) {
1331                 i = 0;
1332                 end = arg->size;
1333                 sub = 0;
1334                 add = 1;
1335         }
1336 #endif
1337         while (i != end) {
1338                 unsigned int shift = 0;
1339                 uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
1340
1341                 for (shift = 0; arg->mask[i] >> shift; ++shift) {
1342                         if (!(arg->mask[i] & (1 << shift)))
1343                                 continue;
1344                         ++len;
1345                         if (!dst)
1346                                 continue;
1347                         *buf &= ~(1 << shift);
1348                         *buf |= (val & 1) << shift;
1349                         val >>= 1;
1350                 }
1351                 i += add;
1352         }
1353         return len;
1354 }
1355
1356 /**
1357  * Parse a prefix length and generate a bit-mask.
1358  *
1359  * Last argument (ctx->args) is retrieved to determine mask size, storage
1360  * location and whether the result must use network byte ordering.
1361  */
1362 static int
1363 parse_prefix(struct context *ctx, const struct token *token,
1364              const char *str, unsigned int len,
1365              void *buf, unsigned int size)
1366 {
1367         const struct arg *arg = pop_args(ctx);
1368         static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
1369         char *end;
1370         uintmax_t u;
1371         unsigned int bytes;
1372         unsigned int extra;
1373
1374         (void)token;
1375         /* Argument is expected. */
1376         if (!arg)
1377                 return -1;
1378         errno = 0;
1379         u = strtoumax(str, &end, 0);
1380         if (errno || (size_t)(end - str) != len)
1381                 goto error;
1382         if (arg->mask) {
1383                 uintmax_t v = 0;
1384
1385                 extra = arg_entry_bf_fill(NULL, 0, arg);
1386                 if (u > extra)
1387                         goto error;
1388                 if (!ctx->object)
1389                         return len;
1390                 extra -= u;
1391                 while (u--)
1392                         (v <<= 1, v |= 1);
1393                 v <<= extra;
1394                 if (!arg_entry_bf_fill(ctx->object, v, arg) ||
1395                     !arg_entry_bf_fill(ctx->objmask, -1, arg))
1396                         goto error;
1397                 return len;
1398         }
1399         bytes = u / 8;
1400         extra = u % 8;
1401         size = arg->size;
1402         if (bytes > size || bytes + !!extra > size)
1403                 goto error;
1404         if (!ctx->object)
1405                 return len;
1406         buf = (uint8_t *)ctx->object + arg->offset;
1407 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1408         if (!arg->hton) {
1409                 memset((uint8_t *)buf + size - bytes, 0xff, bytes);
1410                 memset(buf, 0x00, size - bytes);
1411                 if (extra)
1412                         ((uint8_t *)buf)[size - bytes - 1] = conv[extra];
1413         } else
1414 #endif
1415         {
1416                 memset(buf, 0xff, bytes);
1417                 memset((uint8_t *)buf + bytes, 0x00, size - bytes);
1418                 if (extra)
1419                         ((uint8_t *)buf)[bytes] = conv[extra];
1420         }
1421         if (ctx->objmask)
1422                 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
1423         return len;
1424 error:
1425         push_args(ctx, arg);
1426         return -1;
1427 }
1428
1429 /** Default parsing function for token name matching. */
1430 static int
1431 parse_default(struct context *ctx, const struct token *token,
1432               const char *str, unsigned int len,
1433               void *buf, unsigned int size)
1434 {
1435         (void)ctx;
1436         (void)buf;
1437         (void)size;
1438         if (strncmp(str, token->name, len))
1439                 return -1;
1440         return len;
1441 }
1442
1443 /** Parse flow command, initialize output buffer for subsequent tokens. */
1444 static int
1445 parse_init(struct context *ctx, const struct token *token,
1446            const char *str, unsigned int len,
1447            void *buf, unsigned int size)
1448 {
1449         struct buffer *out = buf;
1450
1451         /* Token name must match. */
1452         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
1453                 return -1;
1454         /* Nothing else to do if there is no buffer. */
1455         if (!out)
1456                 return len;
1457         /* Make sure buffer is large enough. */
1458         if (size < sizeof(*out))
1459                 return -1;
1460         /* Initialize buffer. */
1461         memset(out, 0x00, sizeof(*out));
1462         memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
1463         ctx->objdata = 0;
1464         ctx->object = out;
1465         ctx->objmask = NULL;
1466         return len;
1467 }
1468
1469 /** Parse tokens for validate/create commands. */
1470 static int
1471 parse_vc(struct context *ctx, const struct token *token,
1472          const char *str, unsigned int len,
1473          void *buf, unsigned int size)
1474 {
1475         struct buffer *out = buf;
1476         uint8_t *data;
1477         uint32_t data_size;
1478
1479         /* Token name must match. */
1480         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
1481                 return -1;
1482         /* Nothing else to do if there is no buffer. */
1483         if (!out)
1484                 return len;
1485         if (!out->command) {
1486                 if (ctx->curr != VALIDATE && ctx->curr != CREATE)
1487                         return -1;
1488                 if (sizeof(*out) > size)
1489                         return -1;
1490                 out->command = ctx->curr;
1491                 ctx->objdata = 0;
1492                 ctx->object = out;
1493                 ctx->objmask = NULL;
1494                 out->args.vc.data = (uint8_t *)out + size;
1495                 return len;
1496         }
1497         ctx->objdata = 0;
1498         ctx->object = &out->args.vc.attr;
1499         ctx->objmask = NULL;
1500         switch (ctx->curr) {
1501         case GROUP:
1502         case PRIORITY:
1503                 return len;
1504         case INGRESS:
1505                 out->args.vc.attr.ingress = 1;
1506                 return len;
1507         case EGRESS:
1508                 out->args.vc.attr.egress = 1;
1509                 return len;
1510         case PATTERN:
1511                 out->args.vc.pattern =
1512                         (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
1513                                                sizeof(double));
1514                 ctx->object = out->args.vc.pattern;
1515                 ctx->objmask = NULL;
1516                 return len;
1517         case ACTIONS:
1518                 out->args.vc.actions =
1519                         (void *)RTE_ALIGN_CEIL((uintptr_t)
1520                                                (out->args.vc.pattern +
1521                                                 out->args.vc.pattern_n),
1522                                                sizeof(double));
1523                 ctx->object = out->args.vc.actions;
1524                 ctx->objmask = NULL;
1525                 return len;
1526         default:
1527                 if (!token->priv)
1528                         return -1;
1529                 break;
1530         }
1531         if (!out->args.vc.actions) {
1532                 const struct parse_item_priv *priv = token->priv;
1533                 struct rte_flow_item *item =
1534                         out->args.vc.pattern + out->args.vc.pattern_n;
1535
1536                 data_size = priv->size * 3; /* spec, last, mask */
1537                 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
1538                                                (out->args.vc.data - data_size),
1539                                                sizeof(double));
1540                 if ((uint8_t *)item + sizeof(*item) > data)
1541                         return -1;
1542                 *item = (struct rte_flow_item){
1543                         .type = priv->type,
1544                 };
1545                 ++out->args.vc.pattern_n;
1546                 ctx->object = item;
1547                 ctx->objmask = NULL;
1548         } else {
1549                 const struct parse_action_priv *priv = token->priv;
1550                 struct rte_flow_action *action =
1551                         out->args.vc.actions + out->args.vc.actions_n;
1552
1553                 data_size = priv->size; /* configuration */
1554                 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
1555                                                (out->args.vc.data - data_size),
1556                                                sizeof(double));
1557                 if ((uint8_t *)action + sizeof(*action) > data)
1558                         return -1;
1559                 *action = (struct rte_flow_action){
1560                         .type = priv->type,
1561                 };
1562                 ++out->args.vc.actions_n;
1563                 ctx->object = action;
1564                 ctx->objmask = NULL;
1565         }
1566         memset(data, 0, data_size);
1567         out->args.vc.data = data;
1568         ctx->objdata = data_size;
1569         return len;
1570 }
1571
1572 /** Parse pattern item parameter type. */
1573 static int
1574 parse_vc_spec(struct context *ctx, const struct token *token,
1575               const char *str, unsigned int len,
1576               void *buf, unsigned int size)
1577 {
1578         struct buffer *out = buf;
1579         struct rte_flow_item *item;
1580         uint32_t data_size;
1581         int index;
1582         int objmask = 0;
1583
1584         (void)size;
1585         /* Token name must match. */
1586         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
1587                 return -1;
1588         /* Parse parameter types. */
1589         switch (ctx->curr) {
1590         case ITEM_PARAM_IS:
1591                 index = 0;
1592                 objmask = 1;
1593                 break;
1594         case ITEM_PARAM_SPEC:
1595                 index = 0;
1596                 break;
1597         case ITEM_PARAM_LAST:
1598                 index = 1;
1599                 break;
1600         case ITEM_PARAM_PREFIX:
1601                 /* Modify next token to expect a prefix. */
1602                 if (ctx->next_num < 2)
1603                         return -1;
1604                 ctx->next[ctx->next_num - 2] = NEXT_ENTRY(PREFIX);
1605                 /* Fall through. */
1606         case ITEM_PARAM_MASK:
1607                 index = 2;
1608                 break;
1609         default:
1610                 return -1;
1611         }
1612         /* Nothing else to do if there is no buffer. */
1613         if (!out)
1614                 return len;
1615         if (!out->args.vc.pattern_n)
1616                 return -1;
1617         item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
1618         data_size = ctx->objdata / 3; /* spec, last, mask */
1619         /* Point to selected object. */
1620         ctx->object = out->args.vc.data + (data_size * index);
1621         if (objmask) {
1622                 ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
1623                 item->mask = ctx->objmask;
1624         } else
1625                 ctx->objmask = NULL;
1626         /* Update relevant item pointer. */
1627         *((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
1628                 ctx->object;
1629         return len;
1630 }
1631
1632 /** Parse action configuration field. */
1633 static int
1634 parse_vc_conf(struct context *ctx, const struct token *token,
1635               const char *str, unsigned int len,
1636               void *buf, unsigned int size)
1637 {
1638         struct buffer *out = buf;
1639         struct rte_flow_action *action;
1640
1641         (void)size;
1642         /* Token name must match. */
1643         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
1644                 return -1;
1645         /* Nothing else to do if there is no buffer. */
1646         if (!out)
1647                 return len;
1648         if (!out->args.vc.actions_n)
1649                 return -1;
1650         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
1651         /* Point to selected object. */
1652         ctx->object = out->args.vc.data;
1653         ctx->objmask = NULL;
1654         /* Update configuration pointer. */
1655         action->conf = ctx->object;
1656         return len;
1657 }
1658
1659 /**
1660  * Parse queue field for RSS action.
1661  *
1662  * Valid tokens are queue indices and the "end" token.
1663  */
1664 static int
1665 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
1666                           const char *str, unsigned int len,
1667                           void *buf, unsigned int size)
1668 {
1669         static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
1670         int ret;
1671         int i;
1672
1673         (void)token;
1674         (void)buf;
1675         (void)size;
1676         if (ctx->curr != ACTION_RSS_QUEUE)
1677                 return -1;
1678         i = ctx->objdata >> 16;
1679         if (!strncmp(str, "end", len)) {
1680                 ctx->objdata &= 0xffff;
1681                 return len;
1682         }
1683         if (i >= ACTION_RSS_NUM)
1684                 return -1;
1685         if (push_args(ctx, ARGS_ENTRY(struct rte_flow_action_rss, queue[i])))
1686                 return -1;
1687         ret = parse_int(ctx, token, str, len, NULL, 0);
1688         if (ret < 0) {
1689                 pop_args(ctx);
1690                 return -1;
1691         }
1692         ++i;
1693         ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
1694         /* Repeat token. */
1695         if (ctx->next_num == RTE_DIM(ctx->next))
1696                 return -1;
1697         ctx->next[ctx->next_num++] = next;
1698         if (!ctx->object)
1699                 return len;
1700         ((struct rte_flow_action_rss *)ctx->object)->num = i;
1701         return len;
1702 }
1703
1704 /** Parse tokens for destroy command. */
1705 static int
1706 parse_destroy(struct context *ctx, const struct token *token,
1707               const char *str, unsigned int len,
1708               void *buf, unsigned int size)
1709 {
1710         struct buffer *out = buf;
1711
1712         /* Token name must match. */
1713         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
1714                 return -1;
1715         /* Nothing else to do if there is no buffer. */
1716         if (!out)
1717                 return len;
1718         if (!out->command) {
1719                 if (ctx->curr != DESTROY)
1720                         return -1;
1721                 if (sizeof(*out) > size)
1722                         return -1;
1723                 out->command = ctx->curr;
1724                 ctx->objdata = 0;
1725                 ctx->object = out;
1726                 ctx->objmask = NULL;
1727                 out->args.destroy.rule =
1728                         (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
1729                                                sizeof(double));
1730                 return len;
1731         }
1732         if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
1733              sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
1734                 return -1;
1735         ctx->objdata = 0;
1736         ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
1737         ctx->objmask = NULL;
1738         return len;
1739 }
1740
1741 /** Parse tokens for flush command. */
1742 static int
1743 parse_flush(struct context *ctx, const struct token *token,
1744             const char *str, unsigned int len,
1745             void *buf, unsigned int size)
1746 {
1747         struct buffer *out = buf;
1748
1749         /* Token name must match. */
1750         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
1751                 return -1;
1752         /* Nothing else to do if there is no buffer. */
1753         if (!out)
1754                 return len;
1755         if (!out->command) {
1756                 if (ctx->curr != FLUSH)
1757                         return -1;
1758                 if (sizeof(*out) > size)
1759                         return -1;
1760                 out->command = ctx->curr;
1761                 ctx->objdata = 0;
1762                 ctx->object = out;
1763                 ctx->objmask = NULL;
1764         }
1765         return len;
1766 }
1767
1768 /** Parse tokens for query command. */
1769 static int
1770 parse_query(struct context *ctx, const struct token *token,
1771             const char *str, unsigned int len,
1772             void *buf, unsigned int size)
1773 {
1774         struct buffer *out = buf;
1775
1776         /* Token name must match. */
1777         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
1778                 return -1;
1779         /* Nothing else to do if there is no buffer. */
1780         if (!out)
1781                 return len;
1782         if (!out->command) {
1783                 if (ctx->curr != QUERY)
1784                         return -1;
1785                 if (sizeof(*out) > size)
1786                         return -1;
1787                 out->command = ctx->curr;
1788                 ctx->objdata = 0;
1789                 ctx->object = out;
1790                 ctx->objmask = NULL;
1791         }
1792         return len;
1793 }
1794
1795 /** Parse action names. */
1796 static int
1797 parse_action(struct context *ctx, const struct token *token,
1798              const char *str, unsigned int len,
1799              void *buf, unsigned int size)
1800 {
1801         struct buffer *out = buf;
1802         const struct arg *arg = pop_args(ctx);
1803         unsigned int i;
1804
1805         (void)size;
1806         /* Argument is expected. */
1807         if (!arg)
1808                 return -1;
1809         /* Parse action name. */
1810         for (i = 0; next_action[i]; ++i) {
1811                 const struct parse_action_priv *priv;
1812
1813                 token = &token_list[next_action[i]];
1814                 if (strncmp(token->name, str, len))
1815                         continue;
1816                 priv = token->priv;
1817                 if (!priv)
1818                         goto error;
1819                 if (out)
1820                         memcpy((uint8_t *)ctx->object + arg->offset,
1821                                &priv->type,
1822                                arg->size);
1823                 return len;
1824         }
1825 error:
1826         push_args(ctx, arg);
1827         return -1;
1828 }
1829
1830 /** Parse tokens for list command. */
1831 static int
1832 parse_list(struct context *ctx, const struct token *token,
1833            const char *str, unsigned int len,
1834            void *buf, unsigned int size)
1835 {
1836         struct buffer *out = buf;
1837
1838         /* Token name must match. */
1839         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
1840                 return -1;
1841         /* Nothing else to do if there is no buffer. */
1842         if (!out)
1843                 return len;
1844         if (!out->command) {
1845                 if (ctx->curr != LIST)
1846                         return -1;
1847                 if (sizeof(*out) > size)
1848                         return -1;
1849                 out->command = ctx->curr;
1850                 ctx->objdata = 0;
1851                 ctx->object = out;
1852                 ctx->objmask = NULL;
1853                 out->args.list.group =
1854                         (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
1855                                                sizeof(double));
1856                 return len;
1857         }
1858         if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
1859              sizeof(*out->args.list.group)) > (uint8_t *)out + size)
1860                 return -1;
1861         ctx->objdata = 0;
1862         ctx->object = out->args.list.group + out->args.list.group_n++;
1863         ctx->objmask = NULL;
1864         return len;
1865 }
1866
1867 /**
1868  * Parse signed/unsigned integers 8 to 64-bit long.
1869  *
1870  * Last argument (ctx->args) is retrieved to determine integer type and
1871  * storage location.
1872  */
1873 static int
1874 parse_int(struct context *ctx, const struct token *token,
1875           const char *str, unsigned int len,
1876           void *buf, unsigned int size)
1877 {
1878         const struct arg *arg = pop_args(ctx);
1879         uintmax_t u;
1880         char *end;
1881
1882         (void)token;
1883         /* Argument is expected. */
1884         if (!arg)
1885                 return -1;
1886         errno = 0;
1887         u = arg->sign ?
1888                 (uintmax_t)strtoimax(str, &end, 0) :
1889                 strtoumax(str, &end, 0);
1890         if (errno || (size_t)(end - str) != len)
1891                 goto error;
1892         if (!ctx->object)
1893                 return len;
1894         if (arg->mask) {
1895                 if (!arg_entry_bf_fill(ctx->object, u, arg) ||
1896                     !arg_entry_bf_fill(ctx->objmask, -1, arg))
1897                         goto error;
1898                 return len;
1899         }
1900         buf = (uint8_t *)ctx->object + arg->offset;
1901         size = arg->size;
1902 objmask:
1903         switch (size) {
1904         case sizeof(uint8_t):
1905                 *(uint8_t *)buf = u;
1906                 break;
1907         case sizeof(uint16_t):
1908                 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
1909                 break;
1910         case sizeof(uint8_t [3]):
1911 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1912                 if (!arg->hton) {
1913                         ((uint8_t *)buf)[0] = u;
1914                         ((uint8_t *)buf)[1] = u >> 8;
1915                         ((uint8_t *)buf)[2] = u >> 16;
1916                         break;
1917                 }
1918 #endif
1919                 ((uint8_t *)buf)[0] = u >> 16;
1920                 ((uint8_t *)buf)[1] = u >> 8;
1921                 ((uint8_t *)buf)[2] = u;
1922                 break;
1923         case sizeof(uint32_t):
1924                 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
1925                 break;
1926         case sizeof(uint64_t):
1927                 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
1928                 break;
1929         default:
1930                 goto error;
1931         }
1932         if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
1933                 u = -1;
1934                 buf = (uint8_t *)ctx->objmask + arg->offset;
1935                 goto objmask;
1936         }
1937         return len;
1938 error:
1939         push_args(ctx, arg);
1940         return -1;
1941 }
1942
1943 /**
1944  * Parse a string.
1945  *
1946  * Two arguments (ctx->args) are retrieved from the stack to store data and
1947  * its length (in that order).
1948  */
1949 static int
1950 parse_string(struct context *ctx, const struct token *token,
1951              const char *str, unsigned int len,
1952              void *buf, unsigned int size)
1953 {
1954         const struct arg *arg_data = pop_args(ctx);
1955         const struct arg *arg_len = pop_args(ctx);
1956         char tmp[16]; /* Ought to be enough. */
1957         int ret;
1958
1959         /* Arguments are expected. */
1960         if (!arg_data)
1961                 return -1;
1962         if (!arg_len) {
1963                 push_args(ctx, arg_data);
1964                 return -1;
1965         }
1966         size = arg_data->size;
1967         /* Bit-mask fill is not supported. */
1968         if (arg_data->mask || size < len)
1969                 goto error;
1970         if (!ctx->object)
1971                 return len;
1972         /* Let parse_int() fill length information first. */
1973         ret = snprintf(tmp, sizeof(tmp), "%u", len);
1974         if (ret < 0)
1975                 goto error;
1976         push_args(ctx, arg_len);
1977         ret = parse_int(ctx, token, tmp, ret, NULL, 0);
1978         if (ret < 0) {
1979                 pop_args(ctx);
1980                 goto error;
1981         }
1982         buf = (uint8_t *)ctx->object + arg_data->offset;
1983         /* Output buffer is not necessarily NUL-terminated. */
1984         memcpy(buf, str, len);
1985         memset((uint8_t *)buf + len, 0x55, size - len);
1986         if (ctx->objmask)
1987                 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
1988         return len;
1989 error:
1990         push_args(ctx, arg_len);
1991         push_args(ctx, arg_data);
1992         return -1;
1993 }
1994
1995 /**
1996  * Parse a MAC address.
1997  *
1998  * Last argument (ctx->args) is retrieved to determine storage size and
1999  * location.
2000  */
2001 static int
2002 parse_mac_addr(struct context *ctx, const struct token *token,
2003                const char *str, unsigned int len,
2004                void *buf, unsigned int size)
2005 {
2006         const struct arg *arg = pop_args(ctx);
2007         struct ether_addr tmp;
2008         int ret;
2009
2010         (void)token;
2011         /* Argument is expected. */
2012         if (!arg)
2013                 return -1;
2014         size = arg->size;
2015         /* Bit-mask fill is not supported. */
2016         if (arg->mask || size != sizeof(tmp))
2017                 goto error;
2018         ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
2019         if (ret < 0 || (unsigned int)ret != len)
2020                 goto error;
2021         if (!ctx->object)
2022                 return len;
2023         buf = (uint8_t *)ctx->object + arg->offset;
2024         memcpy(buf, &tmp, size);
2025         if (ctx->objmask)
2026                 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
2027         return len;
2028 error:
2029         push_args(ctx, arg);
2030         return -1;
2031 }
2032
2033 /**
2034  * Parse an IPv4 address.
2035  *
2036  * Last argument (ctx->args) is retrieved to determine storage size and
2037  * location.
2038  */
2039 static int
2040 parse_ipv4_addr(struct context *ctx, const struct token *token,
2041                 const char *str, unsigned int len,
2042                 void *buf, unsigned int size)
2043 {
2044         const struct arg *arg = pop_args(ctx);
2045         char str2[len + 1];
2046         struct in_addr tmp;
2047         int ret;
2048
2049         /* Argument is expected. */
2050         if (!arg)
2051                 return -1;
2052         size = arg->size;
2053         /* Bit-mask fill is not supported. */
2054         if (arg->mask || size != sizeof(tmp))
2055                 goto error;
2056         /* Only network endian is supported. */
2057         if (!arg->hton)
2058                 goto error;
2059         memcpy(str2, str, len);
2060         str2[len] = '\0';
2061         ret = inet_pton(AF_INET, str2, &tmp);
2062         if (ret != 1) {
2063                 /* Attempt integer parsing. */
2064                 push_args(ctx, arg);
2065                 return parse_int(ctx, token, str, len, buf, size);
2066         }
2067         if (!ctx->object)
2068                 return len;
2069         buf = (uint8_t *)ctx->object + arg->offset;
2070         memcpy(buf, &tmp, size);
2071         if (ctx->objmask)
2072                 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
2073         return len;
2074 error:
2075         push_args(ctx, arg);
2076         return -1;
2077 }
2078
2079 /**
2080  * Parse an IPv6 address.
2081  *
2082  * Last argument (ctx->args) is retrieved to determine storage size and
2083  * location.
2084  */
2085 static int
2086 parse_ipv6_addr(struct context *ctx, const struct token *token,
2087                 const char *str, unsigned int len,
2088                 void *buf, unsigned int size)
2089 {
2090         const struct arg *arg = pop_args(ctx);
2091         char str2[len + 1];
2092         struct in6_addr tmp;
2093         int ret;
2094
2095         (void)token;
2096         /* Argument is expected. */
2097         if (!arg)
2098                 return -1;
2099         size = arg->size;
2100         /* Bit-mask fill is not supported. */
2101         if (arg->mask || size != sizeof(tmp))
2102                 goto error;
2103         /* Only network endian is supported. */
2104         if (!arg->hton)
2105                 goto error;
2106         memcpy(str2, str, len);
2107         str2[len] = '\0';
2108         ret = inet_pton(AF_INET6, str2, &tmp);
2109         if (ret != 1)
2110                 goto error;
2111         if (!ctx->object)
2112                 return len;
2113         buf = (uint8_t *)ctx->object + arg->offset;
2114         memcpy(buf, &tmp, size);
2115         if (ctx->objmask)
2116                 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
2117         return len;
2118 error:
2119         push_args(ctx, arg);
2120         return -1;
2121 }
2122
2123 /** Boolean values (even indices stand for false). */
2124 static const char *const boolean_name[] = {
2125         "0", "1",
2126         "false", "true",
2127         "no", "yes",
2128         "N", "Y",
2129         NULL,
2130 };
2131
2132 /**
2133  * Parse a boolean value.
2134  *
2135  * Last argument (ctx->args) is retrieved to determine storage size and
2136  * location.
2137  */
2138 static int
2139 parse_boolean(struct context *ctx, const struct token *token,
2140               const char *str, unsigned int len,
2141               void *buf, unsigned int size)
2142 {
2143         const struct arg *arg = pop_args(ctx);
2144         unsigned int i;
2145         int ret;
2146
2147         /* Argument is expected. */
2148         if (!arg)
2149                 return -1;
2150         for (i = 0; boolean_name[i]; ++i)
2151                 if (!strncmp(str, boolean_name[i], len))
2152                         break;
2153         /* Process token as integer. */
2154         if (boolean_name[i])
2155                 str = i & 1 ? "1" : "0";
2156         push_args(ctx, arg);
2157         ret = parse_int(ctx, token, str, strlen(str), buf, size);
2158         return ret > 0 ? (int)len : ret;
2159 }
2160
2161 /** Parse port and update context. */
2162 static int
2163 parse_port(struct context *ctx, const struct token *token,
2164            const char *str, unsigned int len,
2165            void *buf, unsigned int size)
2166 {
2167         struct buffer *out = &(struct buffer){ .port = 0 };
2168         int ret;
2169
2170         if (buf)
2171                 out = buf;
2172         else {
2173                 ctx->objdata = 0;
2174                 ctx->object = out;
2175                 ctx->objmask = NULL;
2176                 size = sizeof(*out);
2177         }
2178         ret = parse_int(ctx, token, str, len, out, size);
2179         if (ret >= 0)
2180                 ctx->port = out->port;
2181         if (!buf)
2182                 ctx->object = NULL;
2183         return ret;
2184 }
2185
2186 /** No completion. */
2187 static int
2188 comp_none(struct context *ctx, const struct token *token,
2189           unsigned int ent, char *buf, unsigned int size)
2190 {
2191         (void)ctx;
2192         (void)token;
2193         (void)ent;
2194         (void)buf;
2195         (void)size;
2196         return 0;
2197 }
2198
2199 /** Complete boolean values. */
2200 static int
2201 comp_boolean(struct context *ctx, const struct token *token,
2202              unsigned int ent, char *buf, unsigned int size)
2203 {
2204         unsigned int i;
2205
2206         (void)ctx;
2207         (void)token;
2208         for (i = 0; boolean_name[i]; ++i)
2209                 if (buf && i == ent)
2210                         return snprintf(buf, size, "%s", boolean_name[i]);
2211         if (buf)
2212                 return -1;
2213         return i;
2214 }
2215
2216 /** Complete action names. */
2217 static int
2218 comp_action(struct context *ctx, const struct token *token,
2219             unsigned int ent, char *buf, unsigned int size)
2220 {
2221         unsigned int i;
2222
2223         (void)ctx;
2224         (void)token;
2225         for (i = 0; next_action[i]; ++i)
2226                 if (buf && i == ent)
2227                         return snprintf(buf, size, "%s",
2228                                         token_list[next_action[i]].name);
2229         if (buf)
2230                 return -1;
2231         return i;
2232 }
2233
2234 /** Complete available ports. */
2235 static int
2236 comp_port(struct context *ctx, const struct token *token,
2237           unsigned int ent, char *buf, unsigned int size)
2238 {
2239         unsigned int i = 0;
2240         portid_t p;
2241
2242         (void)ctx;
2243         (void)token;
2244         FOREACH_PORT(p, ports) {
2245                 if (buf && i == ent)
2246                         return snprintf(buf, size, "%u", p);
2247                 ++i;
2248         }
2249         if (buf)
2250                 return -1;
2251         return i;
2252 }
2253
2254 /** Complete available rule IDs. */
2255 static int
2256 comp_rule_id(struct context *ctx, const struct token *token,
2257              unsigned int ent, char *buf, unsigned int size)
2258 {
2259         unsigned int i = 0;
2260         struct rte_port *port;
2261         struct port_flow *pf;
2262
2263         (void)token;
2264         if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
2265             ctx->port == (uint16_t)RTE_PORT_ALL)
2266                 return -1;
2267         port = &ports[ctx->port];
2268         for (pf = port->flow_list; pf != NULL; pf = pf->next) {
2269                 if (buf && i == ent)
2270                         return snprintf(buf, size, "%u", pf->id);
2271                 ++i;
2272         }
2273         if (buf)
2274                 return -1;
2275         return i;
2276 }
2277
2278 /** Complete queue field for RSS action. */
2279 static int
2280 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
2281                          unsigned int ent, char *buf, unsigned int size)
2282 {
2283         static const char *const str[] = { "", "end", NULL };
2284         unsigned int i;
2285
2286         (void)ctx;
2287         (void)token;
2288         for (i = 0; str[i] != NULL; ++i)
2289                 if (buf && i == ent)
2290                         return snprintf(buf, size, "%s", str[i]);
2291         if (buf)
2292                 return -1;
2293         return i;
2294 }
2295
2296 /** Internal context. */
2297 static struct context cmd_flow_context;
2298
2299 /** Global parser instance (cmdline API). */
2300 cmdline_parse_inst_t cmd_flow;
2301
2302 /** Initialize context. */
2303 static void
2304 cmd_flow_context_init(struct context *ctx)
2305 {
2306         /* A full memset() is not necessary. */
2307         ctx->curr = ZERO;
2308         ctx->prev = ZERO;
2309         ctx->next_num = 0;
2310         ctx->args_num = 0;
2311         ctx->reparse = 0;
2312         ctx->eol = 0;
2313         ctx->last = 0;
2314         ctx->port = 0;
2315         ctx->objdata = 0;
2316         ctx->object = NULL;
2317         ctx->objmask = NULL;
2318 }
2319
2320 /** Parse a token (cmdline API). */
2321 static int
2322 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
2323                unsigned int size)
2324 {
2325         struct context *ctx = &cmd_flow_context;
2326         const struct token *token;
2327         const enum index *list;
2328         int len;
2329         int i;
2330
2331         (void)hdr;
2332         /* Restart as requested. */
2333         if (ctx->reparse)
2334                 cmd_flow_context_init(ctx);
2335         token = &token_list[ctx->curr];
2336         /* Check argument length. */
2337         ctx->eol = 0;
2338         ctx->last = 1;
2339         for (len = 0; src[len]; ++len)
2340                 if (src[len] == '#' || isspace(src[len]))
2341                         break;
2342         if (!len)
2343                 return -1;
2344         /* Last argument and EOL detection. */
2345         for (i = len; src[i]; ++i)
2346                 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
2347                         break;
2348                 else if (!isspace(src[i])) {
2349                         ctx->last = 0;
2350                         break;
2351                 }
2352         for (; src[i]; ++i)
2353                 if (src[i] == '\r' || src[i] == '\n') {
2354                         ctx->eol = 1;
2355                         break;
2356                 }
2357         /* Initialize context if necessary. */
2358         if (!ctx->next_num) {
2359                 if (!token->next)
2360                         return 0;
2361                 ctx->next[ctx->next_num++] = token->next[0];
2362         }
2363         /* Process argument through candidates. */
2364         ctx->prev = ctx->curr;
2365         list = ctx->next[ctx->next_num - 1];
2366         for (i = 0; list[i]; ++i) {
2367                 const struct token *next = &token_list[list[i]];
2368                 int tmp;
2369
2370                 ctx->curr = list[i];
2371                 if (next->call)
2372                         tmp = next->call(ctx, next, src, len, result, size);
2373                 else
2374                         tmp = parse_default(ctx, next, src, len, result, size);
2375                 if (tmp == -1 || tmp != len)
2376                         continue;
2377                 token = next;
2378                 break;
2379         }
2380         if (!list[i])
2381                 return -1;
2382         --ctx->next_num;
2383         /* Push subsequent tokens if any. */
2384         if (token->next)
2385                 for (i = 0; token->next[i]; ++i) {
2386                         if (ctx->next_num == RTE_DIM(ctx->next))
2387                                 return -1;
2388                         ctx->next[ctx->next_num++] = token->next[i];
2389                 }
2390         /* Push arguments if any. */
2391         if (token->args)
2392                 for (i = 0; token->args[i]; ++i) {
2393                         if (ctx->args_num == RTE_DIM(ctx->args))
2394                                 return -1;
2395                         ctx->args[ctx->args_num++] = token->args[i];
2396                 }
2397         return len;
2398 }
2399
2400 /** Return number of completion entries (cmdline API). */
2401 static int
2402 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
2403 {
2404         struct context *ctx = &cmd_flow_context;
2405         const struct token *token = &token_list[ctx->curr];
2406         const enum index *list;
2407         int i;
2408
2409         (void)hdr;
2410         /* Tell cmd_flow_parse() that context must be reinitialized. */
2411         ctx->reparse = 1;
2412         /* Count number of tokens in current list. */
2413         if (ctx->next_num)
2414                 list = ctx->next[ctx->next_num - 1];
2415         else
2416                 list = token->next[0];
2417         for (i = 0; list[i]; ++i)
2418                 ;
2419         if (!i)
2420                 return 0;
2421         /*
2422          * If there is a single token, use its completion callback, otherwise
2423          * return the number of entries.
2424          */
2425         token = &token_list[list[0]];
2426         if (i == 1 && token->comp) {
2427                 /* Save index for cmd_flow_get_help(). */
2428                 ctx->prev = list[0];
2429                 return token->comp(ctx, token, 0, NULL, 0);
2430         }
2431         return i;
2432 }
2433
2434 /** Return a completion entry (cmdline API). */
2435 static int
2436 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
2437                           char *dst, unsigned int size)
2438 {
2439         struct context *ctx = &cmd_flow_context;
2440         const struct token *token = &token_list[ctx->curr];
2441         const enum index *list;
2442         int i;
2443
2444         (void)hdr;
2445         /* Tell cmd_flow_parse() that context must be reinitialized. */
2446         ctx->reparse = 1;
2447         /* Count number of tokens in current list. */
2448         if (ctx->next_num)
2449                 list = ctx->next[ctx->next_num - 1];
2450         else
2451                 list = token->next[0];
2452         for (i = 0; list[i]; ++i)
2453                 ;
2454         if (!i)
2455                 return -1;
2456         /* If there is a single token, use its completion callback. */
2457         token = &token_list[list[0]];
2458         if (i == 1 && token->comp) {
2459                 /* Save index for cmd_flow_get_help(). */
2460                 ctx->prev = list[0];
2461                 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
2462         }
2463         /* Otherwise make sure the index is valid and use defaults. */
2464         if (index >= i)
2465                 return -1;
2466         token = &token_list[list[index]];
2467         snprintf(dst, size, "%s", token->name);
2468         /* Save index for cmd_flow_get_help(). */
2469         ctx->prev = list[index];
2470         return 0;
2471 }
2472
2473 /** Populate help strings for current token (cmdline API). */
2474 static int
2475 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
2476 {
2477         struct context *ctx = &cmd_flow_context;
2478         const struct token *token = &token_list[ctx->prev];
2479
2480         (void)hdr;
2481         /* Tell cmd_flow_parse() that context must be reinitialized. */
2482         ctx->reparse = 1;
2483         if (!size)
2484                 return -1;
2485         /* Set token type and update global help with details. */
2486         snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
2487         if (token->help)
2488                 cmd_flow.help_str = token->help;
2489         else
2490                 cmd_flow.help_str = token->name;
2491         return 0;
2492 }
2493
2494 /** Token definition template (cmdline API). */
2495 static struct cmdline_token_hdr cmd_flow_token_hdr = {
2496         .ops = &(struct cmdline_token_ops){
2497                 .parse = cmd_flow_parse,
2498                 .complete_get_nb = cmd_flow_complete_get_nb,
2499                 .complete_get_elt = cmd_flow_complete_get_elt,
2500                 .get_help = cmd_flow_get_help,
2501         },
2502         .offset = 0,
2503 };
2504
2505 /** Populate the next dynamic token. */
2506 static void
2507 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
2508              cmdline_parse_token_hdr_t *(*hdrs)[])
2509 {
2510         struct context *ctx = &cmd_flow_context;
2511
2512         /* Always reinitialize context before requesting the first token. */
2513         if (!(hdr - *hdrs))
2514                 cmd_flow_context_init(ctx);
2515         /* Return NULL when no more tokens are expected. */
2516         if (!ctx->next_num && ctx->curr) {
2517                 *hdr = NULL;
2518                 return;
2519         }
2520         /* Determine if command should end here. */
2521         if (ctx->eol && ctx->last && ctx->next_num) {
2522                 const enum index *list = ctx->next[ctx->next_num - 1];
2523                 int i;
2524
2525                 for (i = 0; list[i]; ++i) {
2526                         if (list[i] != END)
2527                                 continue;
2528                         *hdr = NULL;
2529                         return;
2530                 }
2531         }
2532         *hdr = &cmd_flow_token_hdr;
2533 }
2534
2535 /** Dispatch parsed buffer to function calls. */
2536 static void
2537 cmd_flow_parsed(const struct buffer *in)
2538 {
2539         switch (in->command) {
2540         case VALIDATE:
2541                 port_flow_validate(in->port, &in->args.vc.attr,
2542                                    in->args.vc.pattern, in->args.vc.actions);
2543                 break;
2544         case CREATE:
2545                 port_flow_create(in->port, &in->args.vc.attr,
2546                                  in->args.vc.pattern, in->args.vc.actions);
2547                 break;
2548         case DESTROY:
2549                 port_flow_destroy(in->port, in->args.destroy.rule_n,
2550                                   in->args.destroy.rule);
2551                 break;
2552         case FLUSH:
2553                 port_flow_flush(in->port);
2554                 break;
2555         case QUERY:
2556                 port_flow_query(in->port, in->args.query.rule,
2557                                 in->args.query.action);
2558                 break;
2559         case LIST:
2560                 port_flow_list(in->port, in->args.list.group_n,
2561                                in->args.list.group);
2562                 break;
2563         default:
2564                 break;
2565         }
2566 }
2567
2568 /** Token generator and output processing callback (cmdline API). */
2569 static void
2570 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
2571 {
2572         if (cl == NULL)
2573                 cmd_flow_tok(arg0, arg2);
2574         else
2575                 cmd_flow_parsed(arg0);
2576 }
2577
2578 /** Global parser instance (cmdline API). */
2579 cmdline_parse_inst_t cmd_flow = {
2580         .f = cmd_flow_cb,
2581         .data = NULL, /**< Unused. */
2582         .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
2583         .tokens = {
2584                 NULL,
2585         }, /**< Tokens are returned by cmd_flow_tok(). */
2586 };