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