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