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