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