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