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