app/testpmd: add MPLSoUDP encapsulation
[dpdk.git] / app / test-pmd / cmdline_flow.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2016 6WIND S.A.
3  * Copyright 2016 Mellanox Technologies, Ltd
4  */
5
6 #include <stddef.h>
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <inttypes.h>
10 #include <errno.h>
11 #include <ctype.h>
12 #include <string.h>
13 #include <arpa/inet.h>
14 #include <sys/socket.h>
15
16 #include <rte_common.h>
17 #include <rte_eth_ctrl.h>
18 #include <rte_ethdev.h>
19 #include <rte_byteorder.h>
20 #include <cmdline_parse.h>
21 #include <cmdline_parse_etheraddr.h>
22 #include <rte_flow.h>
23
24 #include "testpmd.h"
25
26 /** Parser token indices. */
27 enum index {
28         /* Special tokens. */
29         ZERO = 0,
30         END,
31
32         /* Common tokens. */
33         INTEGER,
34         UNSIGNED,
35         PREFIX,
36         BOOLEAN,
37         STRING,
38         MAC_ADDR,
39         IPV4_ADDR,
40         IPV6_ADDR,
41         RULE_ID,
42         PORT_ID,
43         GROUP_ID,
44         PRIORITY_LEVEL,
45
46         /* Top-level command. */
47         FLOW,
48
49         /* Sub-level commands. */
50         VALIDATE,
51         CREATE,
52         DESTROY,
53         FLUSH,
54         QUERY,
55         LIST,
56         ISOLATE,
57
58         /* Destroy arguments. */
59         DESTROY_RULE,
60
61         /* Query arguments. */
62         QUERY_ACTION,
63
64         /* List arguments. */
65         LIST_GROUP,
66
67         /* Validate/create arguments. */
68         GROUP,
69         PRIORITY,
70         INGRESS,
71         EGRESS,
72         TRANSFER,
73
74         /* Validate/create pattern. */
75         PATTERN,
76         ITEM_PARAM_IS,
77         ITEM_PARAM_SPEC,
78         ITEM_PARAM_LAST,
79         ITEM_PARAM_MASK,
80         ITEM_PARAM_PREFIX,
81         ITEM_NEXT,
82         ITEM_END,
83         ITEM_VOID,
84         ITEM_INVERT,
85         ITEM_ANY,
86         ITEM_ANY_NUM,
87         ITEM_PF,
88         ITEM_VF,
89         ITEM_VF_ID,
90         ITEM_PHY_PORT,
91         ITEM_PHY_PORT_INDEX,
92         ITEM_PORT_ID,
93         ITEM_PORT_ID_ID,
94         ITEM_MARK,
95         ITEM_MARK_ID,
96         ITEM_RAW,
97         ITEM_RAW_RELATIVE,
98         ITEM_RAW_SEARCH,
99         ITEM_RAW_OFFSET,
100         ITEM_RAW_LIMIT,
101         ITEM_RAW_PATTERN,
102         ITEM_ETH,
103         ITEM_ETH_DST,
104         ITEM_ETH_SRC,
105         ITEM_ETH_TYPE,
106         ITEM_VLAN,
107         ITEM_VLAN_TCI,
108         ITEM_VLAN_PCP,
109         ITEM_VLAN_DEI,
110         ITEM_VLAN_VID,
111         ITEM_VLAN_INNER_TYPE,
112         ITEM_IPV4,
113         ITEM_IPV4_TOS,
114         ITEM_IPV4_TTL,
115         ITEM_IPV4_PROTO,
116         ITEM_IPV4_SRC,
117         ITEM_IPV4_DST,
118         ITEM_IPV6,
119         ITEM_IPV6_TC,
120         ITEM_IPV6_FLOW,
121         ITEM_IPV6_PROTO,
122         ITEM_IPV6_HOP,
123         ITEM_IPV6_SRC,
124         ITEM_IPV6_DST,
125         ITEM_ICMP,
126         ITEM_ICMP_TYPE,
127         ITEM_ICMP_CODE,
128         ITEM_UDP,
129         ITEM_UDP_SRC,
130         ITEM_UDP_DST,
131         ITEM_TCP,
132         ITEM_TCP_SRC,
133         ITEM_TCP_DST,
134         ITEM_TCP_FLAGS,
135         ITEM_SCTP,
136         ITEM_SCTP_SRC,
137         ITEM_SCTP_DST,
138         ITEM_SCTP_TAG,
139         ITEM_SCTP_CKSUM,
140         ITEM_VXLAN,
141         ITEM_VXLAN_VNI,
142         ITEM_E_TAG,
143         ITEM_E_TAG_GRP_ECID_B,
144         ITEM_NVGRE,
145         ITEM_NVGRE_TNI,
146         ITEM_MPLS,
147         ITEM_MPLS_LABEL,
148         ITEM_GRE,
149         ITEM_GRE_PROTO,
150         ITEM_FUZZY,
151         ITEM_FUZZY_THRESH,
152         ITEM_GTP,
153         ITEM_GTP_TEID,
154         ITEM_GTPC,
155         ITEM_GTPU,
156         ITEM_GENEVE,
157         ITEM_GENEVE_VNI,
158         ITEM_GENEVE_PROTO,
159         ITEM_VXLAN_GPE,
160         ITEM_VXLAN_GPE_VNI,
161         ITEM_ARP_ETH_IPV4,
162         ITEM_ARP_ETH_IPV4_SHA,
163         ITEM_ARP_ETH_IPV4_SPA,
164         ITEM_ARP_ETH_IPV4_THA,
165         ITEM_ARP_ETH_IPV4_TPA,
166         ITEM_IPV6_EXT,
167         ITEM_IPV6_EXT_NEXT_HDR,
168         ITEM_ICMP6,
169         ITEM_ICMP6_TYPE,
170         ITEM_ICMP6_CODE,
171         ITEM_ICMP6_ND_NS,
172         ITEM_ICMP6_ND_NS_TARGET_ADDR,
173         ITEM_ICMP6_ND_NA,
174         ITEM_ICMP6_ND_NA_TARGET_ADDR,
175         ITEM_ICMP6_ND_OPT,
176         ITEM_ICMP6_ND_OPT_TYPE,
177         ITEM_ICMP6_ND_OPT_SLA_ETH,
178         ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
179         ITEM_ICMP6_ND_OPT_TLA_ETH,
180         ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
181         ITEM_META,
182         ITEM_META_DATA,
183
184         /* Validate/create actions. */
185         ACTIONS,
186         ACTION_NEXT,
187         ACTION_END,
188         ACTION_VOID,
189         ACTION_PASSTHRU,
190         ACTION_JUMP,
191         ACTION_JUMP_GROUP,
192         ACTION_MARK,
193         ACTION_MARK_ID,
194         ACTION_FLAG,
195         ACTION_QUEUE,
196         ACTION_QUEUE_INDEX,
197         ACTION_DROP,
198         ACTION_COUNT,
199         ACTION_COUNT_SHARED,
200         ACTION_COUNT_ID,
201         ACTION_RSS,
202         ACTION_RSS_FUNC,
203         ACTION_RSS_LEVEL,
204         ACTION_RSS_FUNC_DEFAULT,
205         ACTION_RSS_FUNC_TOEPLITZ,
206         ACTION_RSS_FUNC_SIMPLE_XOR,
207         ACTION_RSS_TYPES,
208         ACTION_RSS_TYPE,
209         ACTION_RSS_KEY,
210         ACTION_RSS_KEY_LEN,
211         ACTION_RSS_QUEUES,
212         ACTION_RSS_QUEUE,
213         ACTION_PF,
214         ACTION_VF,
215         ACTION_VF_ORIGINAL,
216         ACTION_VF_ID,
217         ACTION_PHY_PORT,
218         ACTION_PHY_PORT_ORIGINAL,
219         ACTION_PHY_PORT_INDEX,
220         ACTION_PORT_ID,
221         ACTION_PORT_ID_ORIGINAL,
222         ACTION_PORT_ID_ID,
223         ACTION_METER,
224         ACTION_METER_ID,
225         ACTION_OF_SET_MPLS_TTL,
226         ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
227         ACTION_OF_DEC_MPLS_TTL,
228         ACTION_OF_SET_NW_TTL,
229         ACTION_OF_SET_NW_TTL_NW_TTL,
230         ACTION_OF_DEC_NW_TTL,
231         ACTION_OF_COPY_TTL_OUT,
232         ACTION_OF_COPY_TTL_IN,
233         ACTION_OF_POP_VLAN,
234         ACTION_OF_PUSH_VLAN,
235         ACTION_OF_PUSH_VLAN_ETHERTYPE,
236         ACTION_OF_SET_VLAN_VID,
237         ACTION_OF_SET_VLAN_VID_VLAN_VID,
238         ACTION_OF_SET_VLAN_PCP,
239         ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
240         ACTION_OF_POP_MPLS,
241         ACTION_OF_POP_MPLS_ETHERTYPE,
242         ACTION_OF_PUSH_MPLS,
243         ACTION_OF_PUSH_MPLS_ETHERTYPE,
244         ACTION_VXLAN_ENCAP,
245         ACTION_VXLAN_DECAP,
246         ACTION_NVGRE_ENCAP,
247         ACTION_NVGRE_DECAP,
248         ACTION_L2_ENCAP,
249         ACTION_L2_DECAP,
250         ACTION_MPLSOUDP_ENCAP,
251         ACTION_MPLSOUDP_DECAP,
252         ACTION_SET_IPV4_SRC,
253         ACTION_SET_IPV4_SRC_IPV4_SRC,
254         ACTION_SET_IPV4_DST,
255         ACTION_SET_IPV4_DST_IPV4_DST,
256         ACTION_SET_IPV6_SRC,
257         ACTION_SET_IPV6_SRC_IPV6_SRC,
258         ACTION_SET_IPV6_DST,
259         ACTION_SET_IPV6_DST_IPV6_DST,
260         ACTION_SET_TP_SRC,
261         ACTION_SET_TP_SRC_TP_SRC,
262         ACTION_SET_TP_DST,
263         ACTION_SET_TP_DST_TP_DST,
264         ACTION_MAC_SWAP,
265         ACTION_DEC_TTL,
266         ACTION_SET_TTL,
267         ACTION_SET_TTL_TTL,
268         ACTION_SET_MAC_SRC,
269         ACTION_SET_MAC_SRC_MAC_SRC,
270         ACTION_SET_MAC_DST,
271         ACTION_SET_MAC_DST_MAC_DST,
272 };
273
274 /** Maximum size for pattern in struct rte_flow_item_raw. */
275 #define ITEM_RAW_PATTERN_SIZE 40
276
277 /** Storage size for struct rte_flow_item_raw including pattern. */
278 #define ITEM_RAW_SIZE \
279         (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
280
281 /** Maximum number of queue indices in struct rte_flow_action_rss. */
282 #define ACTION_RSS_QUEUE_NUM 32
283
284 /** Storage for struct rte_flow_action_rss including external data. */
285 struct action_rss_data {
286         struct rte_flow_action_rss conf;
287         uint8_t key[RSS_HASH_KEY_LENGTH];
288         uint16_t queue[ACTION_RSS_QUEUE_NUM];
289 };
290
291 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
292 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
293
294 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
295 struct action_vxlan_encap_data {
296         struct rte_flow_action_vxlan_encap conf;
297         struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
298         struct rte_flow_item_eth item_eth;
299         struct rte_flow_item_vlan item_vlan;
300         union {
301                 struct rte_flow_item_ipv4 item_ipv4;
302                 struct rte_flow_item_ipv6 item_ipv6;
303         };
304         struct rte_flow_item_udp item_udp;
305         struct rte_flow_item_vxlan item_vxlan;
306 };
307
308 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
309 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
310
311 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
312 struct action_nvgre_encap_data {
313         struct rte_flow_action_nvgre_encap conf;
314         struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
315         struct rte_flow_item_eth item_eth;
316         struct rte_flow_item_vlan item_vlan;
317         union {
318                 struct rte_flow_item_ipv4 item_ipv4;
319                 struct rte_flow_item_ipv6 item_ipv6;
320         };
321         struct rte_flow_item_nvgre item_nvgre;
322 };
323
324 /** Maximum data size in struct rte_flow_action_raw_encap. */
325 #define ACTION_RAW_ENCAP_MAX_DATA 128
326
327 /** Storage for struct rte_flow_action_raw_encap including external data. */
328 struct action_raw_encap_data {
329         struct rte_flow_action_raw_encap conf;
330         uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
331         uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
332 };
333
334 /** Storage for struct rte_flow_action_raw_decap including external data. */
335 struct action_raw_decap_data {
336         struct rte_flow_action_raw_decap conf;
337         uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
338 };
339
340 /** Maximum number of subsequent tokens and arguments on the stack. */
341 #define CTX_STACK_SIZE 16
342
343 /** Parser context. */
344 struct context {
345         /** Stack of subsequent token lists to process. */
346         const enum index *next[CTX_STACK_SIZE];
347         /** Arguments for stacked tokens. */
348         const void *args[CTX_STACK_SIZE];
349         enum index curr; /**< Current token index. */
350         enum index prev; /**< Index of the last token seen. */
351         int next_num; /**< Number of entries in next[]. */
352         int args_num; /**< Number of entries in args[]. */
353         uint32_t eol:1; /**< EOL has been detected. */
354         uint32_t last:1; /**< No more arguments. */
355         portid_t port; /**< Current port ID (for completions). */
356         uint32_t objdata; /**< Object-specific data. */
357         void *object; /**< Address of current object for relative offsets. */
358         void *objmask; /**< Object a full mask must be written to. */
359 };
360
361 /** Token argument. */
362 struct arg {
363         uint32_t hton:1; /**< Use network byte ordering. */
364         uint32_t sign:1; /**< Value is signed. */
365         uint32_t bounded:1; /**< Value is bounded. */
366         uintmax_t min; /**< Minimum value if bounded. */
367         uintmax_t max; /**< Maximum value if bounded. */
368         uint32_t offset; /**< Relative offset from ctx->object. */
369         uint32_t size; /**< Field size. */
370         const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
371 };
372
373 /** Parser token definition. */
374 struct token {
375         /** Type displayed during completion (defaults to "TOKEN"). */
376         const char *type;
377         /** Help displayed during completion (defaults to token name). */
378         const char *help;
379         /** Private data used by parser functions. */
380         const void *priv;
381         /**
382          * Lists of subsequent tokens to push on the stack. Each call to the
383          * parser consumes the last entry of that stack.
384          */
385         const enum index *const *next;
386         /** Arguments stack for subsequent tokens that need them. */
387         const struct arg *const *args;
388         /**
389          * Token-processing callback, returns -1 in case of error, the
390          * length of the matched string otherwise. If NULL, attempts to
391          * match the token name.
392          *
393          * If buf is not NULL, the result should be stored in it according
394          * to context. An error is returned if not large enough.
395          */
396         int (*call)(struct context *ctx, const struct token *token,
397                     const char *str, unsigned int len,
398                     void *buf, unsigned int size);
399         /**
400          * Callback that provides possible values for this token, used for
401          * completion. Returns -1 in case of error, the number of possible
402          * values otherwise. If NULL, the token name is used.
403          *
404          * If buf is not NULL, entry index ent is written to buf and the
405          * full length of the entry is returned (same behavior as
406          * snprintf()).
407          */
408         int (*comp)(struct context *ctx, const struct token *token,
409                     unsigned int ent, char *buf, unsigned int size);
410         /** Mandatory token name, no default value. */
411         const char *name;
412 };
413
414 /** Static initializer for the next field. */
415 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
416
417 /** Static initializer for a NEXT() entry. */
418 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
419
420 /** Static initializer for the args field. */
421 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
422
423 /** Static initializer for ARGS() to target a field. */
424 #define ARGS_ENTRY(s, f) \
425         (&(const struct arg){ \
426                 .offset = offsetof(s, f), \
427                 .size = sizeof(((s *)0)->f), \
428         })
429
430 /** Static initializer for ARGS() to target a bit-field. */
431 #define ARGS_ENTRY_BF(s, f, b) \
432         (&(const struct arg){ \
433                 .size = sizeof(s), \
434                 .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
435         })
436
437 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
438 #define ARGS_ENTRY_MASK(s, f, m) \
439         (&(const struct arg){ \
440                 .offset = offsetof(s, f), \
441                 .size = sizeof(((s *)0)->f), \
442                 .mask = (const void *)(m), \
443         })
444
445 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
446 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
447         (&(const struct arg){ \
448                 .hton = 1, \
449                 .offset = offsetof(s, f), \
450                 .size = sizeof(((s *)0)->f), \
451                 .mask = (const void *)(m), \
452         })
453
454 /** Static initializer for ARGS() to target a pointer. */
455 #define ARGS_ENTRY_PTR(s, f) \
456         (&(const struct arg){ \
457                 .size = sizeof(*((s *)0)->f), \
458         })
459
460 /** Static initializer for ARGS() with arbitrary offset and size. */
461 #define ARGS_ENTRY_ARB(o, s) \
462         (&(const struct arg){ \
463                 .offset = (o), \
464                 .size = (s), \
465         })
466
467 /** Same as ARGS_ENTRY_ARB() with bounded values. */
468 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
469         (&(const struct arg){ \
470                 .bounded = 1, \
471                 .min = (i), \
472                 .max = (a), \
473                 .offset = (o), \
474                 .size = (s), \
475         })
476
477 /** Same as ARGS_ENTRY() using network byte ordering. */
478 #define ARGS_ENTRY_HTON(s, f) \
479         (&(const struct arg){ \
480                 .hton = 1, \
481                 .offset = offsetof(s, f), \
482                 .size = sizeof(((s *)0)->f), \
483         })
484
485 /** Parser output buffer layout expected by cmd_flow_parsed(). */
486 struct buffer {
487         enum index command; /**< Flow command. */
488         portid_t port; /**< Affected port ID. */
489         union {
490                 struct {
491                         struct rte_flow_attr attr;
492                         struct rte_flow_item *pattern;
493                         struct rte_flow_action *actions;
494                         uint32_t pattern_n;
495                         uint32_t actions_n;
496                         uint8_t *data;
497                 } vc; /**< Validate/create arguments. */
498                 struct {
499                         uint32_t *rule;
500                         uint32_t rule_n;
501                 } destroy; /**< Destroy arguments. */
502                 struct {
503                         uint32_t rule;
504                         struct rte_flow_action action;
505                 } query; /**< Query arguments. */
506                 struct {
507                         uint32_t *group;
508                         uint32_t group_n;
509                 } list; /**< List arguments. */
510                 struct {
511                         int set;
512                 } isolate; /**< Isolated mode arguments. */
513         } args; /**< Command arguments. */
514 };
515
516 /** Private data for pattern items. */
517 struct parse_item_priv {
518         enum rte_flow_item_type type; /**< Item type. */
519         uint32_t size; /**< Size of item specification structure. */
520 };
521
522 #define PRIV_ITEM(t, s) \
523         (&(const struct parse_item_priv){ \
524                 .type = RTE_FLOW_ITEM_TYPE_ ## t, \
525                 .size = s, \
526         })
527
528 /** Private data for actions. */
529 struct parse_action_priv {
530         enum rte_flow_action_type type; /**< Action type. */
531         uint32_t size; /**< Size of action configuration structure. */
532 };
533
534 #define PRIV_ACTION(t, s) \
535         (&(const struct parse_action_priv){ \
536                 .type = RTE_FLOW_ACTION_TYPE_ ## t, \
537                 .size = s, \
538         })
539
540 static const enum index next_vc_attr[] = {
541         GROUP,
542         PRIORITY,
543         INGRESS,
544         EGRESS,
545         TRANSFER,
546         PATTERN,
547         ZERO,
548 };
549
550 static const enum index next_destroy_attr[] = {
551         DESTROY_RULE,
552         END,
553         ZERO,
554 };
555
556 static const enum index next_list_attr[] = {
557         LIST_GROUP,
558         END,
559         ZERO,
560 };
561
562 static const enum index item_param[] = {
563         ITEM_PARAM_IS,
564         ITEM_PARAM_SPEC,
565         ITEM_PARAM_LAST,
566         ITEM_PARAM_MASK,
567         ITEM_PARAM_PREFIX,
568         ZERO,
569 };
570
571 static const enum index item_param_is[] = {
572         ITEM_PARAM_IS,
573         ZERO,
574 };
575
576 static const enum index next_item[] = {
577         ITEM_END,
578         ITEM_VOID,
579         ITEM_INVERT,
580         ITEM_ANY,
581         ITEM_PF,
582         ITEM_VF,
583         ITEM_PHY_PORT,
584         ITEM_PORT_ID,
585         ITEM_MARK,
586         ITEM_RAW,
587         ITEM_ETH,
588         ITEM_VLAN,
589         ITEM_IPV4,
590         ITEM_IPV6,
591         ITEM_ICMP,
592         ITEM_UDP,
593         ITEM_TCP,
594         ITEM_SCTP,
595         ITEM_VXLAN,
596         ITEM_E_TAG,
597         ITEM_NVGRE,
598         ITEM_MPLS,
599         ITEM_GRE,
600         ITEM_FUZZY,
601         ITEM_GTP,
602         ITEM_GTPC,
603         ITEM_GTPU,
604         ITEM_GENEVE,
605         ITEM_VXLAN_GPE,
606         ITEM_ARP_ETH_IPV4,
607         ITEM_IPV6_EXT,
608         ITEM_ICMP6,
609         ITEM_ICMP6_ND_NS,
610         ITEM_ICMP6_ND_NA,
611         ITEM_ICMP6_ND_OPT,
612         ITEM_ICMP6_ND_OPT_SLA_ETH,
613         ITEM_ICMP6_ND_OPT_TLA_ETH,
614         ITEM_META,
615         ZERO,
616 };
617
618 static const enum index item_fuzzy[] = {
619         ITEM_FUZZY_THRESH,
620         ITEM_NEXT,
621         ZERO,
622 };
623
624 static const enum index item_any[] = {
625         ITEM_ANY_NUM,
626         ITEM_NEXT,
627         ZERO,
628 };
629
630 static const enum index item_vf[] = {
631         ITEM_VF_ID,
632         ITEM_NEXT,
633         ZERO,
634 };
635
636 static const enum index item_phy_port[] = {
637         ITEM_PHY_PORT_INDEX,
638         ITEM_NEXT,
639         ZERO,
640 };
641
642 static const enum index item_port_id[] = {
643         ITEM_PORT_ID_ID,
644         ITEM_NEXT,
645         ZERO,
646 };
647
648 static const enum index item_mark[] = {
649         ITEM_MARK_ID,
650         ITEM_NEXT,
651         ZERO,
652 };
653
654 static const enum index item_raw[] = {
655         ITEM_RAW_RELATIVE,
656         ITEM_RAW_SEARCH,
657         ITEM_RAW_OFFSET,
658         ITEM_RAW_LIMIT,
659         ITEM_RAW_PATTERN,
660         ITEM_NEXT,
661         ZERO,
662 };
663
664 static const enum index item_eth[] = {
665         ITEM_ETH_DST,
666         ITEM_ETH_SRC,
667         ITEM_ETH_TYPE,
668         ITEM_NEXT,
669         ZERO,
670 };
671
672 static const enum index item_vlan[] = {
673         ITEM_VLAN_TCI,
674         ITEM_VLAN_PCP,
675         ITEM_VLAN_DEI,
676         ITEM_VLAN_VID,
677         ITEM_VLAN_INNER_TYPE,
678         ITEM_NEXT,
679         ZERO,
680 };
681
682 static const enum index item_ipv4[] = {
683         ITEM_IPV4_TOS,
684         ITEM_IPV4_TTL,
685         ITEM_IPV4_PROTO,
686         ITEM_IPV4_SRC,
687         ITEM_IPV4_DST,
688         ITEM_NEXT,
689         ZERO,
690 };
691
692 static const enum index item_ipv6[] = {
693         ITEM_IPV6_TC,
694         ITEM_IPV6_FLOW,
695         ITEM_IPV6_PROTO,
696         ITEM_IPV6_HOP,
697         ITEM_IPV6_SRC,
698         ITEM_IPV6_DST,
699         ITEM_NEXT,
700         ZERO,
701 };
702
703 static const enum index item_icmp[] = {
704         ITEM_ICMP_TYPE,
705         ITEM_ICMP_CODE,
706         ITEM_NEXT,
707         ZERO,
708 };
709
710 static const enum index item_udp[] = {
711         ITEM_UDP_SRC,
712         ITEM_UDP_DST,
713         ITEM_NEXT,
714         ZERO,
715 };
716
717 static const enum index item_tcp[] = {
718         ITEM_TCP_SRC,
719         ITEM_TCP_DST,
720         ITEM_TCP_FLAGS,
721         ITEM_NEXT,
722         ZERO,
723 };
724
725 static const enum index item_sctp[] = {
726         ITEM_SCTP_SRC,
727         ITEM_SCTP_DST,
728         ITEM_SCTP_TAG,
729         ITEM_SCTP_CKSUM,
730         ITEM_NEXT,
731         ZERO,
732 };
733
734 static const enum index item_vxlan[] = {
735         ITEM_VXLAN_VNI,
736         ITEM_NEXT,
737         ZERO,
738 };
739
740 static const enum index item_e_tag[] = {
741         ITEM_E_TAG_GRP_ECID_B,
742         ITEM_NEXT,
743         ZERO,
744 };
745
746 static const enum index item_nvgre[] = {
747         ITEM_NVGRE_TNI,
748         ITEM_NEXT,
749         ZERO,
750 };
751
752 static const enum index item_mpls[] = {
753         ITEM_MPLS_LABEL,
754         ITEM_NEXT,
755         ZERO,
756 };
757
758 static const enum index item_gre[] = {
759         ITEM_GRE_PROTO,
760         ITEM_NEXT,
761         ZERO,
762 };
763
764 static const enum index item_gtp[] = {
765         ITEM_GTP_TEID,
766         ITEM_NEXT,
767         ZERO,
768 };
769
770 static const enum index item_geneve[] = {
771         ITEM_GENEVE_VNI,
772         ITEM_GENEVE_PROTO,
773         ITEM_NEXT,
774         ZERO,
775 };
776
777 static const enum index item_vxlan_gpe[] = {
778         ITEM_VXLAN_GPE_VNI,
779         ITEM_NEXT,
780         ZERO,
781 };
782
783 static const enum index item_arp_eth_ipv4[] = {
784         ITEM_ARP_ETH_IPV4_SHA,
785         ITEM_ARP_ETH_IPV4_SPA,
786         ITEM_ARP_ETH_IPV4_THA,
787         ITEM_ARP_ETH_IPV4_TPA,
788         ITEM_NEXT,
789         ZERO,
790 };
791
792 static const enum index item_ipv6_ext[] = {
793         ITEM_IPV6_EXT_NEXT_HDR,
794         ITEM_NEXT,
795         ZERO,
796 };
797
798 static const enum index item_icmp6[] = {
799         ITEM_ICMP6_TYPE,
800         ITEM_ICMP6_CODE,
801         ITEM_NEXT,
802         ZERO,
803 };
804
805 static const enum index item_icmp6_nd_ns[] = {
806         ITEM_ICMP6_ND_NS_TARGET_ADDR,
807         ITEM_NEXT,
808         ZERO,
809 };
810
811 static const enum index item_icmp6_nd_na[] = {
812         ITEM_ICMP6_ND_NA_TARGET_ADDR,
813         ITEM_NEXT,
814         ZERO,
815 };
816
817 static const enum index item_icmp6_nd_opt[] = {
818         ITEM_ICMP6_ND_OPT_TYPE,
819         ITEM_NEXT,
820         ZERO,
821 };
822
823 static const enum index item_icmp6_nd_opt_sla_eth[] = {
824         ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
825         ITEM_NEXT,
826         ZERO,
827 };
828
829 static const enum index item_icmp6_nd_opt_tla_eth[] = {
830         ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
831         ITEM_NEXT,
832         ZERO,
833 };
834
835 static const enum index item_meta[] = {
836         ITEM_META_DATA,
837         ITEM_NEXT,
838         ZERO,
839 };
840
841 static const enum index next_action[] = {
842         ACTION_END,
843         ACTION_VOID,
844         ACTION_PASSTHRU,
845         ACTION_JUMP,
846         ACTION_MARK,
847         ACTION_FLAG,
848         ACTION_QUEUE,
849         ACTION_DROP,
850         ACTION_COUNT,
851         ACTION_RSS,
852         ACTION_PF,
853         ACTION_VF,
854         ACTION_PHY_PORT,
855         ACTION_PORT_ID,
856         ACTION_METER,
857         ACTION_OF_SET_MPLS_TTL,
858         ACTION_OF_DEC_MPLS_TTL,
859         ACTION_OF_SET_NW_TTL,
860         ACTION_OF_DEC_NW_TTL,
861         ACTION_OF_COPY_TTL_OUT,
862         ACTION_OF_COPY_TTL_IN,
863         ACTION_OF_POP_VLAN,
864         ACTION_OF_PUSH_VLAN,
865         ACTION_OF_SET_VLAN_VID,
866         ACTION_OF_SET_VLAN_PCP,
867         ACTION_OF_POP_MPLS,
868         ACTION_OF_PUSH_MPLS,
869         ACTION_VXLAN_ENCAP,
870         ACTION_VXLAN_DECAP,
871         ACTION_NVGRE_ENCAP,
872         ACTION_NVGRE_DECAP,
873         ACTION_L2_ENCAP,
874         ACTION_L2_DECAP,
875         ACTION_MPLSOUDP_ENCAP,
876         ACTION_MPLSOUDP_DECAP,
877         ACTION_SET_IPV4_SRC,
878         ACTION_SET_IPV4_DST,
879         ACTION_SET_IPV6_SRC,
880         ACTION_SET_IPV6_DST,
881         ACTION_SET_TP_SRC,
882         ACTION_SET_TP_DST,
883         ACTION_MAC_SWAP,
884         ACTION_DEC_TTL,
885         ACTION_SET_TTL,
886         ACTION_SET_MAC_SRC,
887         ACTION_SET_MAC_DST,
888         ZERO,
889 };
890
891 static const enum index action_mark[] = {
892         ACTION_MARK_ID,
893         ACTION_NEXT,
894         ZERO,
895 };
896
897 static const enum index action_queue[] = {
898         ACTION_QUEUE_INDEX,
899         ACTION_NEXT,
900         ZERO,
901 };
902
903 static const enum index action_count[] = {
904         ACTION_COUNT_ID,
905         ACTION_COUNT_SHARED,
906         ACTION_NEXT,
907         ZERO,
908 };
909
910 static const enum index action_rss[] = {
911         ACTION_RSS_FUNC,
912         ACTION_RSS_LEVEL,
913         ACTION_RSS_TYPES,
914         ACTION_RSS_KEY,
915         ACTION_RSS_KEY_LEN,
916         ACTION_RSS_QUEUES,
917         ACTION_NEXT,
918         ZERO,
919 };
920
921 static const enum index action_vf[] = {
922         ACTION_VF_ORIGINAL,
923         ACTION_VF_ID,
924         ACTION_NEXT,
925         ZERO,
926 };
927
928 static const enum index action_phy_port[] = {
929         ACTION_PHY_PORT_ORIGINAL,
930         ACTION_PHY_PORT_INDEX,
931         ACTION_NEXT,
932         ZERO,
933 };
934
935 static const enum index action_port_id[] = {
936         ACTION_PORT_ID_ORIGINAL,
937         ACTION_PORT_ID_ID,
938         ACTION_NEXT,
939         ZERO,
940 };
941
942 static const enum index action_meter[] = {
943         ACTION_METER_ID,
944         ACTION_NEXT,
945         ZERO,
946 };
947
948 static const enum index action_of_set_mpls_ttl[] = {
949         ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
950         ACTION_NEXT,
951         ZERO,
952 };
953
954 static const enum index action_of_set_nw_ttl[] = {
955         ACTION_OF_SET_NW_TTL_NW_TTL,
956         ACTION_NEXT,
957         ZERO,
958 };
959
960 static const enum index action_of_push_vlan[] = {
961         ACTION_OF_PUSH_VLAN_ETHERTYPE,
962         ACTION_NEXT,
963         ZERO,
964 };
965
966 static const enum index action_of_set_vlan_vid[] = {
967         ACTION_OF_SET_VLAN_VID_VLAN_VID,
968         ACTION_NEXT,
969         ZERO,
970 };
971
972 static const enum index action_of_set_vlan_pcp[] = {
973         ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
974         ACTION_NEXT,
975         ZERO,
976 };
977
978 static const enum index action_of_pop_mpls[] = {
979         ACTION_OF_POP_MPLS_ETHERTYPE,
980         ACTION_NEXT,
981         ZERO,
982 };
983
984 static const enum index action_of_push_mpls[] = {
985         ACTION_OF_PUSH_MPLS_ETHERTYPE,
986         ACTION_NEXT,
987         ZERO,
988 };
989
990 static const enum index action_set_ipv4_src[] = {
991         ACTION_SET_IPV4_SRC_IPV4_SRC,
992         ACTION_NEXT,
993         ZERO,
994 };
995
996 static const enum index action_set_mac_src[] = {
997         ACTION_SET_MAC_SRC_MAC_SRC,
998         ACTION_NEXT,
999         ZERO,
1000 };
1001
1002 static const enum index action_set_ipv4_dst[] = {
1003         ACTION_SET_IPV4_DST_IPV4_DST,
1004         ACTION_NEXT,
1005         ZERO,
1006 };
1007
1008 static const enum index action_set_ipv6_src[] = {
1009         ACTION_SET_IPV6_SRC_IPV6_SRC,
1010         ACTION_NEXT,
1011         ZERO,
1012 };
1013
1014 static const enum index action_set_ipv6_dst[] = {
1015         ACTION_SET_IPV6_DST_IPV6_DST,
1016         ACTION_NEXT,
1017         ZERO,
1018 };
1019
1020 static const enum index action_set_tp_src[] = {
1021         ACTION_SET_TP_SRC_TP_SRC,
1022         ACTION_NEXT,
1023         ZERO,
1024 };
1025
1026 static const enum index action_set_tp_dst[] = {
1027         ACTION_SET_TP_DST_TP_DST,
1028         ACTION_NEXT,
1029         ZERO,
1030 };
1031
1032 static const enum index action_set_ttl[] = {
1033         ACTION_SET_TTL_TTL,
1034         ACTION_NEXT,
1035         ZERO,
1036 };
1037
1038 static const enum index action_jump[] = {
1039         ACTION_JUMP_GROUP,
1040         ACTION_NEXT,
1041         ZERO,
1042 };
1043
1044 static const enum index action_set_mac_dst[] = {
1045         ACTION_SET_MAC_DST_MAC_DST,
1046         ACTION_NEXT,
1047         ZERO,
1048 };
1049
1050 static int parse_init(struct context *, const struct token *,
1051                       const char *, unsigned int,
1052                       void *, unsigned int);
1053 static int parse_vc(struct context *, const struct token *,
1054                     const char *, unsigned int,
1055                     void *, unsigned int);
1056 static int parse_vc_spec(struct context *, const struct token *,
1057                          const char *, unsigned int, void *, unsigned int);
1058 static int parse_vc_conf(struct context *, const struct token *,
1059                          const char *, unsigned int, void *, unsigned int);
1060 static int parse_vc_action_rss(struct context *, const struct token *,
1061                                const char *, unsigned int, void *,
1062                                unsigned int);
1063 static int parse_vc_action_rss_func(struct context *, const struct token *,
1064                                     const char *, unsigned int, void *,
1065                                     unsigned int);
1066 static int parse_vc_action_rss_type(struct context *, const struct token *,
1067                                     const char *, unsigned int, void *,
1068                                     unsigned int);
1069 static int parse_vc_action_rss_queue(struct context *, const struct token *,
1070                                      const char *, unsigned int, void *,
1071                                      unsigned int);
1072 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
1073                                        const char *, unsigned int, void *,
1074                                        unsigned int);
1075 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
1076                                        const char *, unsigned int, void *,
1077                                        unsigned int);
1078 static int parse_vc_action_l2_encap(struct context *, const struct token *,
1079                                     const char *, unsigned int, void *,
1080                                     unsigned int);
1081 static int parse_vc_action_l2_decap(struct context *, const struct token *,
1082                                     const char *, unsigned int, void *,
1083                                     unsigned int);
1084 static int parse_vc_action_mplsoudp_encap(struct context *,
1085                                           const struct token *, const char *,
1086                                           unsigned int, void *, unsigned int);
1087 static int parse_vc_action_mplsoudp_decap(struct context *,
1088                                           const struct token *, const char *,
1089                                           unsigned int, void *, unsigned int);
1090 static int parse_destroy(struct context *, const struct token *,
1091                          const char *, unsigned int,
1092                          void *, unsigned int);
1093 static int parse_flush(struct context *, const struct token *,
1094                        const char *, unsigned int,
1095                        void *, unsigned int);
1096 static int parse_query(struct context *, const struct token *,
1097                        const char *, unsigned int,
1098                        void *, unsigned int);
1099 static int parse_action(struct context *, const struct token *,
1100                         const char *, unsigned int,
1101                         void *, unsigned int);
1102 static int parse_list(struct context *, const struct token *,
1103                       const char *, unsigned int,
1104                       void *, unsigned int);
1105 static int parse_isolate(struct context *, const struct token *,
1106                          const char *, unsigned int,
1107                          void *, unsigned int);
1108 static int parse_int(struct context *, const struct token *,
1109                      const char *, unsigned int,
1110                      void *, unsigned int);
1111 static int parse_prefix(struct context *, const struct token *,
1112                         const char *, unsigned int,
1113                         void *, unsigned int);
1114 static int parse_boolean(struct context *, const struct token *,
1115                          const char *, unsigned int,
1116                          void *, unsigned int);
1117 static int parse_string(struct context *, const struct token *,
1118                         const char *, unsigned int,
1119                         void *, unsigned int);
1120 static int parse_mac_addr(struct context *, const struct token *,
1121                           const char *, unsigned int,
1122                           void *, unsigned int);
1123 static int parse_ipv4_addr(struct context *, const struct token *,
1124                            const char *, unsigned int,
1125                            void *, unsigned int);
1126 static int parse_ipv6_addr(struct context *, const struct token *,
1127                            const char *, unsigned int,
1128                            void *, unsigned int);
1129 static int parse_port(struct context *, const struct token *,
1130                       const char *, unsigned int,
1131                       void *, unsigned int);
1132 static int comp_none(struct context *, const struct token *,
1133                      unsigned int, char *, unsigned int);
1134 static int comp_boolean(struct context *, const struct token *,
1135                         unsigned int, char *, unsigned int);
1136 static int comp_action(struct context *, const struct token *,
1137                        unsigned int, char *, unsigned int);
1138 static int comp_port(struct context *, const struct token *,
1139                      unsigned int, char *, unsigned int);
1140 static int comp_rule_id(struct context *, const struct token *,
1141                         unsigned int, char *, unsigned int);
1142 static int comp_vc_action_rss_type(struct context *, const struct token *,
1143                                    unsigned int, char *, unsigned int);
1144 static int comp_vc_action_rss_queue(struct context *, const struct token *,
1145                                     unsigned int, char *, unsigned int);
1146
1147 /** Token definitions. */
1148 static const struct token token_list[] = {
1149         /* Special tokens. */
1150         [ZERO] = {
1151                 .name = "ZERO",
1152                 .help = "null entry, abused as the entry point",
1153                 .next = NEXT(NEXT_ENTRY(FLOW)),
1154         },
1155         [END] = {
1156                 .name = "",
1157                 .type = "RETURN",
1158                 .help = "command may end here",
1159         },
1160         /* Common tokens. */
1161         [INTEGER] = {
1162                 .name = "{int}",
1163                 .type = "INTEGER",
1164                 .help = "integer value",
1165                 .call = parse_int,
1166                 .comp = comp_none,
1167         },
1168         [UNSIGNED] = {
1169                 .name = "{unsigned}",
1170                 .type = "UNSIGNED",
1171                 .help = "unsigned integer value",
1172                 .call = parse_int,
1173                 .comp = comp_none,
1174         },
1175         [PREFIX] = {
1176                 .name = "{prefix}",
1177                 .type = "PREFIX",
1178                 .help = "prefix length for bit-mask",
1179                 .call = parse_prefix,
1180                 .comp = comp_none,
1181         },
1182         [BOOLEAN] = {
1183                 .name = "{boolean}",
1184                 .type = "BOOLEAN",
1185                 .help = "any boolean value",
1186                 .call = parse_boolean,
1187                 .comp = comp_boolean,
1188         },
1189         [STRING] = {
1190                 .name = "{string}",
1191                 .type = "STRING",
1192                 .help = "fixed string",
1193                 .call = parse_string,
1194                 .comp = comp_none,
1195         },
1196         [MAC_ADDR] = {
1197                 .name = "{MAC address}",
1198                 .type = "MAC-48",
1199                 .help = "standard MAC address notation",
1200                 .call = parse_mac_addr,
1201                 .comp = comp_none,
1202         },
1203         [IPV4_ADDR] = {
1204                 .name = "{IPv4 address}",
1205                 .type = "IPV4 ADDRESS",
1206                 .help = "standard IPv4 address notation",
1207                 .call = parse_ipv4_addr,
1208                 .comp = comp_none,
1209         },
1210         [IPV6_ADDR] = {
1211                 .name = "{IPv6 address}",
1212                 .type = "IPV6 ADDRESS",
1213                 .help = "standard IPv6 address notation",
1214                 .call = parse_ipv6_addr,
1215                 .comp = comp_none,
1216         },
1217         [RULE_ID] = {
1218                 .name = "{rule id}",
1219                 .type = "RULE ID",
1220                 .help = "rule identifier",
1221                 .call = parse_int,
1222                 .comp = comp_rule_id,
1223         },
1224         [PORT_ID] = {
1225                 .name = "{port_id}",
1226                 .type = "PORT ID",
1227                 .help = "port identifier",
1228                 .call = parse_port,
1229                 .comp = comp_port,
1230         },
1231         [GROUP_ID] = {
1232                 .name = "{group_id}",
1233                 .type = "GROUP ID",
1234                 .help = "group identifier",
1235                 .call = parse_int,
1236                 .comp = comp_none,
1237         },
1238         [PRIORITY_LEVEL] = {
1239                 .name = "{level}",
1240                 .type = "PRIORITY",
1241                 .help = "priority level",
1242                 .call = parse_int,
1243                 .comp = comp_none,
1244         },
1245         /* Top-level command. */
1246         [FLOW] = {
1247                 .name = "flow",
1248                 .type = "{command} {port_id} [{arg} [...]]",
1249                 .help = "manage ingress/egress flow rules",
1250                 .next = NEXT(NEXT_ENTRY
1251                              (VALIDATE,
1252                               CREATE,
1253                               DESTROY,
1254                               FLUSH,
1255                               LIST,
1256                               QUERY,
1257                               ISOLATE)),
1258                 .call = parse_init,
1259         },
1260         /* Sub-level commands. */
1261         [VALIDATE] = {
1262                 .name = "validate",
1263                 .help = "check whether a flow rule can be created",
1264                 .next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
1265                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
1266                 .call = parse_vc,
1267         },
1268         [CREATE] = {
1269                 .name = "create",
1270                 .help = "create a flow rule",
1271                 .next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
1272                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
1273                 .call = parse_vc,
1274         },
1275         [DESTROY] = {
1276                 .name = "destroy",
1277                 .help = "destroy specific flow rules",
1278                 .next = NEXT(NEXT_ENTRY(DESTROY_RULE), NEXT_ENTRY(PORT_ID)),
1279                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
1280                 .call = parse_destroy,
1281         },
1282         [FLUSH] = {
1283                 .name = "flush",
1284                 .help = "destroy all flow rules",
1285                 .next = NEXT(NEXT_ENTRY(PORT_ID)),
1286                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
1287                 .call = parse_flush,
1288         },
1289         [QUERY] = {
1290                 .name = "query",
1291                 .help = "query an existing flow rule",
1292                 .next = NEXT(NEXT_ENTRY(QUERY_ACTION),
1293                              NEXT_ENTRY(RULE_ID),
1294                              NEXT_ENTRY(PORT_ID)),
1295                 .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
1296                              ARGS_ENTRY(struct buffer, args.query.rule),
1297                              ARGS_ENTRY(struct buffer, port)),
1298                 .call = parse_query,
1299         },
1300         [LIST] = {
1301                 .name = "list",
1302                 .help = "list existing flow rules",
1303                 .next = NEXT(next_list_attr, NEXT_ENTRY(PORT_ID)),
1304                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
1305                 .call = parse_list,
1306         },
1307         [ISOLATE] = {
1308                 .name = "isolate",
1309                 .help = "restrict ingress traffic to the defined flow rules",
1310                 .next = NEXT(NEXT_ENTRY(BOOLEAN),
1311                              NEXT_ENTRY(PORT_ID)),
1312                 .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
1313                              ARGS_ENTRY(struct buffer, port)),
1314                 .call = parse_isolate,
1315         },
1316         /* Destroy arguments. */
1317         [DESTROY_RULE] = {
1318                 .name = "rule",
1319                 .help = "specify a rule identifier",
1320                 .next = NEXT(next_destroy_attr, NEXT_ENTRY(RULE_ID)),
1321                 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
1322                 .call = parse_destroy,
1323         },
1324         /* Query arguments. */
1325         [QUERY_ACTION] = {
1326                 .name = "{action}",
1327                 .type = "ACTION",
1328                 .help = "action to query, must be part of the rule",
1329                 .call = parse_action,
1330                 .comp = comp_action,
1331         },
1332         /* List arguments. */
1333         [LIST_GROUP] = {
1334                 .name = "group",
1335                 .help = "specify a group",
1336                 .next = NEXT(next_list_attr, NEXT_ENTRY(GROUP_ID)),
1337                 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
1338                 .call = parse_list,
1339         },
1340         /* Validate/create attributes. */
1341         [GROUP] = {
1342                 .name = "group",
1343                 .help = "specify a group",
1344                 .next = NEXT(next_vc_attr, NEXT_ENTRY(GROUP_ID)),
1345                 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
1346                 .call = parse_vc,
1347         },
1348         [PRIORITY] = {
1349                 .name = "priority",
1350                 .help = "specify a priority level",
1351                 .next = NEXT(next_vc_attr, NEXT_ENTRY(PRIORITY_LEVEL)),
1352                 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
1353                 .call = parse_vc,
1354         },
1355         [INGRESS] = {
1356                 .name = "ingress",
1357                 .help = "affect rule to ingress",
1358                 .next = NEXT(next_vc_attr),
1359                 .call = parse_vc,
1360         },
1361         [EGRESS] = {
1362                 .name = "egress",
1363                 .help = "affect rule to egress",
1364                 .next = NEXT(next_vc_attr),
1365                 .call = parse_vc,
1366         },
1367         [TRANSFER] = {
1368                 .name = "transfer",
1369                 .help = "apply rule directly to endpoints found in pattern",
1370                 .next = NEXT(next_vc_attr),
1371                 .call = parse_vc,
1372         },
1373         /* Validate/create pattern. */
1374         [PATTERN] = {
1375                 .name = "pattern",
1376                 .help = "submit a list of pattern items",
1377                 .next = NEXT(next_item),
1378                 .call = parse_vc,
1379         },
1380         [ITEM_PARAM_IS] = {
1381                 .name = "is",
1382                 .help = "match value perfectly (with full bit-mask)",
1383                 .call = parse_vc_spec,
1384         },
1385         [ITEM_PARAM_SPEC] = {
1386                 .name = "spec",
1387                 .help = "match value according to configured bit-mask",
1388                 .call = parse_vc_spec,
1389         },
1390         [ITEM_PARAM_LAST] = {
1391                 .name = "last",
1392                 .help = "specify upper bound to establish a range",
1393                 .call = parse_vc_spec,
1394         },
1395         [ITEM_PARAM_MASK] = {
1396                 .name = "mask",
1397                 .help = "specify bit-mask with relevant bits set to one",
1398                 .call = parse_vc_spec,
1399         },
1400         [ITEM_PARAM_PREFIX] = {
1401                 .name = "prefix",
1402                 .help = "generate bit-mask from a prefix length",
1403                 .call = parse_vc_spec,
1404         },
1405         [ITEM_NEXT] = {
1406                 .name = "/",
1407                 .help = "specify next pattern item",
1408                 .next = NEXT(next_item),
1409         },
1410         [ITEM_END] = {
1411                 .name = "end",
1412                 .help = "end list of pattern items",
1413                 .priv = PRIV_ITEM(END, 0),
1414                 .next = NEXT(NEXT_ENTRY(ACTIONS)),
1415                 .call = parse_vc,
1416         },
1417         [ITEM_VOID] = {
1418                 .name = "void",
1419                 .help = "no-op pattern item",
1420                 .priv = PRIV_ITEM(VOID, 0),
1421                 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
1422                 .call = parse_vc,
1423         },
1424         [ITEM_INVERT] = {
1425                 .name = "invert",
1426                 .help = "perform actions when pattern does not match",
1427                 .priv = PRIV_ITEM(INVERT, 0),
1428                 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
1429                 .call = parse_vc,
1430         },
1431         [ITEM_ANY] = {
1432                 .name = "any",
1433                 .help = "match any protocol for the current layer",
1434                 .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
1435                 .next = NEXT(item_any),
1436                 .call = parse_vc,
1437         },
1438         [ITEM_ANY_NUM] = {
1439                 .name = "num",
1440                 .help = "number of layers covered",
1441                 .next = NEXT(item_any, NEXT_ENTRY(UNSIGNED), item_param),
1442                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
1443         },
1444         [ITEM_PF] = {
1445                 .name = "pf",
1446                 .help = "match traffic from/to the physical function",
1447                 .priv = PRIV_ITEM(PF, 0),
1448                 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
1449                 .call = parse_vc,
1450         },
1451         [ITEM_VF] = {
1452                 .name = "vf",
1453                 .help = "match traffic from/to a virtual function ID",
1454                 .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
1455                 .next = NEXT(item_vf),
1456                 .call = parse_vc,
1457         },
1458         [ITEM_VF_ID] = {
1459                 .name = "id",
1460                 .help = "VF ID",
1461                 .next = NEXT(item_vf, NEXT_ENTRY(UNSIGNED), item_param),
1462                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
1463         },
1464         [ITEM_PHY_PORT] = {
1465                 .name = "phy_port",
1466                 .help = "match traffic from/to a specific physical port",
1467                 .priv = PRIV_ITEM(PHY_PORT,
1468                                   sizeof(struct rte_flow_item_phy_port)),
1469                 .next = NEXT(item_phy_port),
1470                 .call = parse_vc,
1471         },
1472         [ITEM_PHY_PORT_INDEX] = {
1473                 .name = "index",
1474                 .help = "physical port index",
1475                 .next = NEXT(item_phy_port, NEXT_ENTRY(UNSIGNED), item_param),
1476                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)),
1477         },
1478         [ITEM_PORT_ID] = {
1479                 .name = "port_id",
1480                 .help = "match traffic from/to a given DPDK port ID",
1481                 .priv = PRIV_ITEM(PORT_ID,
1482                                   sizeof(struct rte_flow_item_port_id)),
1483                 .next = NEXT(item_port_id),
1484                 .call = parse_vc,
1485         },
1486         [ITEM_PORT_ID_ID] = {
1487                 .name = "id",
1488                 .help = "DPDK port ID",
1489                 .next = NEXT(item_port_id, NEXT_ENTRY(UNSIGNED), item_param),
1490                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
1491         },
1492         [ITEM_MARK] = {
1493                 .name = "mark",
1494                 .help = "match traffic against value set in previously matched rule",
1495                 .priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
1496                 .next = NEXT(item_mark),
1497                 .call = parse_vc,
1498         },
1499         [ITEM_MARK_ID] = {
1500                 .name = "id",
1501                 .help = "Integer value to match against",
1502                 .next = NEXT(item_mark, NEXT_ENTRY(UNSIGNED), item_param),
1503                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
1504         },
1505         [ITEM_RAW] = {
1506                 .name = "raw",
1507                 .help = "match an arbitrary byte string",
1508                 .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
1509                 .next = NEXT(item_raw),
1510                 .call = parse_vc,
1511         },
1512         [ITEM_RAW_RELATIVE] = {
1513                 .name = "relative",
1514                 .help = "look for pattern after the previous item",
1515                 .next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
1516                 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
1517                                            relative, 1)),
1518         },
1519         [ITEM_RAW_SEARCH] = {
1520                 .name = "search",
1521                 .help = "search pattern from offset (see also limit)",
1522                 .next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
1523                 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
1524                                            search, 1)),
1525         },
1526         [ITEM_RAW_OFFSET] = {
1527                 .name = "offset",
1528                 .help = "absolute or relative offset for pattern",
1529                 .next = NEXT(item_raw, NEXT_ENTRY(INTEGER), item_param),
1530                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
1531         },
1532         [ITEM_RAW_LIMIT] = {
1533                 .name = "limit",
1534                 .help = "search area limit for start of pattern",
1535                 .next = NEXT(item_raw, NEXT_ENTRY(UNSIGNED), item_param),
1536                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
1537         },
1538         [ITEM_RAW_PATTERN] = {
1539                 .name = "pattern",
1540                 .help = "byte string to look for",
1541                 .next = NEXT(item_raw,
1542                              NEXT_ENTRY(STRING),
1543                              NEXT_ENTRY(ITEM_PARAM_IS,
1544                                         ITEM_PARAM_SPEC,
1545                                         ITEM_PARAM_MASK)),
1546                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
1547                              ARGS_ENTRY(struct rte_flow_item_raw, length),
1548                              ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
1549                                             ITEM_RAW_PATTERN_SIZE)),
1550         },
1551         [ITEM_ETH] = {
1552                 .name = "eth",
1553                 .help = "match Ethernet header",
1554                 .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
1555                 .next = NEXT(item_eth),
1556                 .call = parse_vc,
1557         },
1558         [ITEM_ETH_DST] = {
1559                 .name = "dst",
1560                 .help = "destination MAC",
1561                 .next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
1562                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
1563         },
1564         [ITEM_ETH_SRC] = {
1565                 .name = "src",
1566                 .help = "source MAC",
1567                 .next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
1568                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
1569         },
1570         [ITEM_ETH_TYPE] = {
1571                 .name = "type",
1572                 .help = "EtherType",
1573                 .next = NEXT(item_eth, NEXT_ENTRY(UNSIGNED), item_param),
1574                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
1575         },
1576         [ITEM_VLAN] = {
1577                 .name = "vlan",
1578                 .help = "match 802.1Q/ad VLAN tag",
1579                 .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
1580                 .next = NEXT(item_vlan),
1581                 .call = parse_vc,
1582         },
1583         [ITEM_VLAN_TCI] = {
1584                 .name = "tci",
1585                 .help = "tag control information",
1586                 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1587                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
1588         },
1589         [ITEM_VLAN_PCP] = {
1590                 .name = "pcp",
1591                 .help = "priority code point",
1592                 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1593                 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
1594                                                   tci, "\xe0\x00")),
1595         },
1596         [ITEM_VLAN_DEI] = {
1597                 .name = "dei",
1598                 .help = "drop eligible indicator",
1599                 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1600                 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
1601                                                   tci, "\x10\x00")),
1602         },
1603         [ITEM_VLAN_VID] = {
1604                 .name = "vid",
1605                 .help = "VLAN identifier",
1606                 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1607                 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
1608                                                   tci, "\x0f\xff")),
1609         },
1610         [ITEM_VLAN_INNER_TYPE] = {
1611                 .name = "inner_type",
1612                 .help = "inner EtherType",
1613                 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1614                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
1615                                              inner_type)),
1616         },
1617         [ITEM_IPV4] = {
1618                 .name = "ipv4",
1619                 .help = "match IPv4 header",
1620                 .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
1621                 .next = NEXT(item_ipv4),
1622                 .call = parse_vc,
1623         },
1624         [ITEM_IPV4_TOS] = {
1625                 .name = "tos",
1626                 .help = "type of service",
1627                 .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
1628                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1629                                              hdr.type_of_service)),
1630         },
1631         [ITEM_IPV4_TTL] = {
1632                 .name = "ttl",
1633                 .help = "time to live",
1634                 .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
1635                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1636                                              hdr.time_to_live)),
1637         },
1638         [ITEM_IPV4_PROTO] = {
1639                 .name = "proto",
1640                 .help = "next protocol ID",
1641                 .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
1642                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1643                                              hdr.next_proto_id)),
1644         },
1645         [ITEM_IPV4_SRC] = {
1646                 .name = "src",
1647                 .help = "source address",
1648                 .next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
1649                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1650                                              hdr.src_addr)),
1651         },
1652         [ITEM_IPV4_DST] = {
1653                 .name = "dst",
1654                 .help = "destination address",
1655                 .next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
1656                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1657                                              hdr.dst_addr)),
1658         },
1659         [ITEM_IPV6] = {
1660                 .name = "ipv6",
1661                 .help = "match IPv6 header",
1662                 .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
1663                 .next = NEXT(item_ipv6),
1664                 .call = parse_vc,
1665         },
1666         [ITEM_IPV6_TC] = {
1667                 .name = "tc",
1668                 .help = "traffic class",
1669                 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
1670                 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
1671                                                   hdr.vtc_flow,
1672                                                   "\x0f\xf0\x00\x00")),
1673         },
1674         [ITEM_IPV6_FLOW] = {
1675                 .name = "flow",
1676                 .help = "flow label",
1677                 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
1678                 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
1679                                                   hdr.vtc_flow,
1680                                                   "\x00\x0f\xff\xff")),
1681         },
1682         [ITEM_IPV6_PROTO] = {
1683                 .name = "proto",
1684                 .help = "protocol (next header)",
1685                 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
1686                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
1687                                              hdr.proto)),
1688         },
1689         [ITEM_IPV6_HOP] = {
1690                 .name = "hop",
1691                 .help = "hop limit",
1692                 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
1693                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
1694                                              hdr.hop_limits)),
1695         },
1696         [ITEM_IPV6_SRC] = {
1697                 .name = "src",
1698                 .help = "source address",
1699                 .next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
1700                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
1701                                              hdr.src_addr)),
1702         },
1703         [ITEM_IPV6_DST] = {
1704                 .name = "dst",
1705                 .help = "destination address",
1706                 .next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
1707                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
1708                                              hdr.dst_addr)),
1709         },
1710         [ITEM_ICMP] = {
1711                 .name = "icmp",
1712                 .help = "match ICMP header",
1713                 .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
1714                 .next = NEXT(item_icmp),
1715                 .call = parse_vc,
1716         },
1717         [ITEM_ICMP_TYPE] = {
1718                 .name = "type",
1719                 .help = "ICMP packet type",
1720                 .next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
1721                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
1722                                              hdr.icmp_type)),
1723         },
1724         [ITEM_ICMP_CODE] = {
1725                 .name = "code",
1726                 .help = "ICMP packet code",
1727                 .next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
1728                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
1729                                              hdr.icmp_code)),
1730         },
1731         [ITEM_UDP] = {
1732                 .name = "udp",
1733                 .help = "match UDP header",
1734                 .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
1735                 .next = NEXT(item_udp),
1736                 .call = parse_vc,
1737         },
1738         [ITEM_UDP_SRC] = {
1739                 .name = "src",
1740                 .help = "UDP source port",
1741                 .next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
1742                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
1743                                              hdr.src_port)),
1744         },
1745         [ITEM_UDP_DST] = {
1746                 .name = "dst",
1747                 .help = "UDP destination port",
1748                 .next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
1749                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
1750                                              hdr.dst_port)),
1751         },
1752         [ITEM_TCP] = {
1753                 .name = "tcp",
1754                 .help = "match TCP header",
1755                 .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
1756                 .next = NEXT(item_tcp),
1757                 .call = parse_vc,
1758         },
1759         [ITEM_TCP_SRC] = {
1760                 .name = "src",
1761                 .help = "TCP source port",
1762                 .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
1763                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
1764                                              hdr.src_port)),
1765         },
1766         [ITEM_TCP_DST] = {
1767                 .name = "dst",
1768                 .help = "TCP destination port",
1769                 .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
1770                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
1771                                              hdr.dst_port)),
1772         },
1773         [ITEM_TCP_FLAGS] = {
1774                 .name = "flags",
1775                 .help = "TCP flags",
1776                 .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
1777                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
1778                                              hdr.tcp_flags)),
1779         },
1780         [ITEM_SCTP] = {
1781                 .name = "sctp",
1782                 .help = "match SCTP header",
1783                 .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
1784                 .next = NEXT(item_sctp),
1785                 .call = parse_vc,
1786         },
1787         [ITEM_SCTP_SRC] = {
1788                 .name = "src",
1789                 .help = "SCTP source port",
1790                 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
1791                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
1792                                              hdr.src_port)),
1793         },
1794         [ITEM_SCTP_DST] = {
1795                 .name = "dst",
1796                 .help = "SCTP destination port",
1797                 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
1798                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
1799                                              hdr.dst_port)),
1800         },
1801         [ITEM_SCTP_TAG] = {
1802                 .name = "tag",
1803                 .help = "validation tag",
1804                 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
1805                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
1806                                              hdr.tag)),
1807         },
1808         [ITEM_SCTP_CKSUM] = {
1809                 .name = "cksum",
1810                 .help = "checksum",
1811                 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
1812                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
1813                                              hdr.cksum)),
1814         },
1815         [ITEM_VXLAN] = {
1816                 .name = "vxlan",
1817                 .help = "match VXLAN header",
1818                 .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
1819                 .next = NEXT(item_vxlan),
1820                 .call = parse_vc,
1821         },
1822         [ITEM_VXLAN_VNI] = {
1823                 .name = "vni",
1824                 .help = "VXLAN identifier",
1825                 .next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED), item_param),
1826                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
1827         },
1828         [ITEM_E_TAG] = {
1829                 .name = "e_tag",
1830                 .help = "match E-Tag header",
1831                 .priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
1832                 .next = NEXT(item_e_tag),
1833                 .call = parse_vc,
1834         },
1835         [ITEM_E_TAG_GRP_ECID_B] = {
1836                 .name = "grp_ecid_b",
1837                 .help = "GRP and E-CID base",
1838                 .next = NEXT(item_e_tag, NEXT_ENTRY(UNSIGNED), item_param),
1839                 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
1840                                                   rsvd_grp_ecid_b,
1841                                                   "\x3f\xff")),
1842         },
1843         [ITEM_NVGRE] = {
1844                 .name = "nvgre",
1845                 .help = "match NVGRE header",
1846                 .priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
1847                 .next = NEXT(item_nvgre),
1848                 .call = parse_vc,
1849         },
1850         [ITEM_NVGRE_TNI] = {
1851                 .name = "tni",
1852                 .help = "virtual subnet ID",
1853                 .next = NEXT(item_nvgre, NEXT_ENTRY(UNSIGNED), item_param),
1854                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
1855         },
1856         [ITEM_MPLS] = {
1857                 .name = "mpls",
1858                 .help = "match MPLS header",
1859                 .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
1860                 .next = NEXT(item_mpls),
1861                 .call = parse_vc,
1862         },
1863         [ITEM_MPLS_LABEL] = {
1864                 .name = "label",
1865                 .help = "MPLS label",
1866                 .next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
1867                 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
1868                                                   label_tc_s,
1869                                                   "\xff\xff\xf0")),
1870         },
1871         [ITEM_GRE] = {
1872                 .name = "gre",
1873                 .help = "match GRE header",
1874                 .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
1875                 .next = NEXT(item_gre),
1876                 .call = parse_vc,
1877         },
1878         [ITEM_GRE_PROTO] = {
1879                 .name = "protocol",
1880                 .help = "GRE protocol type",
1881                 .next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
1882                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
1883                                              protocol)),
1884         },
1885         [ITEM_FUZZY] = {
1886                 .name = "fuzzy",
1887                 .help = "fuzzy pattern match, expect faster than default",
1888                 .priv = PRIV_ITEM(FUZZY,
1889                                 sizeof(struct rte_flow_item_fuzzy)),
1890                 .next = NEXT(item_fuzzy),
1891                 .call = parse_vc,
1892         },
1893         [ITEM_FUZZY_THRESH] = {
1894                 .name = "thresh",
1895                 .help = "match accuracy threshold",
1896                 .next = NEXT(item_fuzzy, NEXT_ENTRY(UNSIGNED), item_param),
1897                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
1898                                         thresh)),
1899         },
1900         [ITEM_GTP] = {
1901                 .name = "gtp",
1902                 .help = "match GTP header",
1903                 .priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
1904                 .next = NEXT(item_gtp),
1905                 .call = parse_vc,
1906         },
1907         [ITEM_GTP_TEID] = {
1908                 .name = "teid",
1909                 .help = "tunnel endpoint identifier",
1910                 .next = NEXT(item_gtp, NEXT_ENTRY(UNSIGNED), item_param),
1911                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
1912         },
1913         [ITEM_GTPC] = {
1914                 .name = "gtpc",
1915                 .help = "match GTP header",
1916                 .priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
1917                 .next = NEXT(item_gtp),
1918                 .call = parse_vc,
1919         },
1920         [ITEM_GTPU] = {
1921                 .name = "gtpu",
1922                 .help = "match GTP header",
1923                 .priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
1924                 .next = NEXT(item_gtp),
1925                 .call = parse_vc,
1926         },
1927         [ITEM_GENEVE] = {
1928                 .name = "geneve",
1929                 .help = "match GENEVE header",
1930                 .priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
1931                 .next = NEXT(item_geneve),
1932                 .call = parse_vc,
1933         },
1934         [ITEM_GENEVE_VNI] = {
1935                 .name = "vni",
1936                 .help = "virtual network identifier",
1937                 .next = NEXT(item_geneve, NEXT_ENTRY(UNSIGNED), item_param),
1938                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
1939         },
1940         [ITEM_GENEVE_PROTO] = {
1941                 .name = "protocol",
1942                 .help = "GENEVE protocol type",
1943                 .next = NEXT(item_geneve, NEXT_ENTRY(UNSIGNED), item_param),
1944                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
1945                                              protocol)),
1946         },
1947         [ITEM_VXLAN_GPE] = {
1948                 .name = "vxlan-gpe",
1949                 .help = "match VXLAN-GPE header",
1950                 .priv = PRIV_ITEM(VXLAN_GPE,
1951                                   sizeof(struct rte_flow_item_vxlan_gpe)),
1952                 .next = NEXT(item_vxlan_gpe),
1953                 .call = parse_vc,
1954         },
1955         [ITEM_VXLAN_GPE_VNI] = {
1956                 .name = "vni",
1957                 .help = "VXLAN-GPE identifier",
1958                 .next = NEXT(item_vxlan_gpe, NEXT_ENTRY(UNSIGNED), item_param),
1959                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
1960                                              vni)),
1961         },
1962         [ITEM_ARP_ETH_IPV4] = {
1963                 .name = "arp_eth_ipv4",
1964                 .help = "match ARP header for Ethernet/IPv4",
1965                 .priv = PRIV_ITEM(ARP_ETH_IPV4,
1966                                   sizeof(struct rte_flow_item_arp_eth_ipv4)),
1967                 .next = NEXT(item_arp_eth_ipv4),
1968                 .call = parse_vc,
1969         },
1970         [ITEM_ARP_ETH_IPV4_SHA] = {
1971                 .name = "sha",
1972                 .help = "sender hardware address",
1973                 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(MAC_ADDR),
1974                              item_param),
1975                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
1976                                              sha)),
1977         },
1978         [ITEM_ARP_ETH_IPV4_SPA] = {
1979                 .name = "spa",
1980                 .help = "sender IPv4 address",
1981                 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(IPV4_ADDR),
1982                              item_param),
1983                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
1984                                              spa)),
1985         },
1986         [ITEM_ARP_ETH_IPV4_THA] = {
1987                 .name = "tha",
1988                 .help = "target hardware address",
1989                 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(MAC_ADDR),
1990                              item_param),
1991                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
1992                                              tha)),
1993         },
1994         [ITEM_ARP_ETH_IPV4_TPA] = {
1995                 .name = "tpa",
1996                 .help = "target IPv4 address",
1997                 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(IPV4_ADDR),
1998                              item_param),
1999                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
2000                                              tpa)),
2001         },
2002         [ITEM_IPV6_EXT] = {
2003                 .name = "ipv6_ext",
2004                 .help = "match presence of any IPv6 extension header",
2005                 .priv = PRIV_ITEM(IPV6_EXT,
2006                                   sizeof(struct rte_flow_item_ipv6_ext)),
2007                 .next = NEXT(item_ipv6_ext),
2008                 .call = parse_vc,
2009         },
2010         [ITEM_IPV6_EXT_NEXT_HDR] = {
2011                 .name = "next_hdr",
2012                 .help = "next header",
2013                 .next = NEXT(item_ipv6_ext, NEXT_ENTRY(UNSIGNED), item_param),
2014                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
2015                                              next_hdr)),
2016         },
2017         [ITEM_ICMP6] = {
2018                 .name = "icmp6",
2019                 .help = "match any ICMPv6 header",
2020                 .priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
2021                 .next = NEXT(item_icmp6),
2022                 .call = parse_vc,
2023         },
2024         [ITEM_ICMP6_TYPE] = {
2025                 .name = "type",
2026                 .help = "ICMPv6 type",
2027                 .next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
2028                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
2029                                              type)),
2030         },
2031         [ITEM_ICMP6_CODE] = {
2032                 .name = "code",
2033                 .help = "ICMPv6 code",
2034                 .next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
2035                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
2036                                              code)),
2037         },
2038         [ITEM_ICMP6_ND_NS] = {
2039                 .name = "icmp6_nd_ns",
2040                 .help = "match ICMPv6 neighbor discovery solicitation",
2041                 .priv = PRIV_ITEM(ICMP6_ND_NS,
2042                                   sizeof(struct rte_flow_item_icmp6_nd_ns)),
2043                 .next = NEXT(item_icmp6_nd_ns),
2044                 .call = parse_vc,
2045         },
2046         [ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
2047                 .name = "target_addr",
2048                 .help = "target address",
2049                 .next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(IPV6_ADDR),
2050                              item_param),
2051                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
2052                                              target_addr)),
2053         },
2054         [ITEM_ICMP6_ND_NA] = {
2055                 .name = "icmp6_nd_na",
2056                 .help = "match ICMPv6 neighbor discovery advertisement",
2057                 .priv = PRIV_ITEM(ICMP6_ND_NA,
2058                                   sizeof(struct rte_flow_item_icmp6_nd_na)),
2059                 .next = NEXT(item_icmp6_nd_na),
2060                 .call = parse_vc,
2061         },
2062         [ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
2063                 .name = "target_addr",
2064                 .help = "target address",
2065                 .next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(IPV6_ADDR),
2066                              item_param),
2067                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
2068                                              target_addr)),
2069         },
2070         [ITEM_ICMP6_ND_OPT] = {
2071                 .name = "icmp6_nd_opt",
2072                 .help = "match presence of any ICMPv6 neighbor discovery"
2073                         " option",
2074                 .priv = PRIV_ITEM(ICMP6_ND_OPT,
2075                                   sizeof(struct rte_flow_item_icmp6_nd_opt)),
2076                 .next = NEXT(item_icmp6_nd_opt),
2077                 .call = parse_vc,
2078         },
2079         [ITEM_ICMP6_ND_OPT_TYPE] = {
2080                 .name = "type",
2081                 .help = "ND option type",
2082                 .next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(UNSIGNED),
2083                              item_param),
2084                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
2085                                              type)),
2086         },
2087         [ITEM_ICMP6_ND_OPT_SLA_ETH] = {
2088                 .name = "icmp6_nd_opt_sla_eth",
2089                 .help = "match ICMPv6 neighbor discovery source Ethernet"
2090                         " link-layer address option",
2091                 .priv = PRIV_ITEM
2092                         (ICMP6_ND_OPT_SLA_ETH,
2093                          sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
2094                 .next = NEXT(item_icmp6_nd_opt_sla_eth),
2095                 .call = parse_vc,
2096         },
2097         [ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
2098                 .name = "sla",
2099                 .help = "source Ethernet LLA",
2100                 .next = NEXT(item_icmp6_nd_opt_sla_eth, NEXT_ENTRY(MAC_ADDR),
2101                              item_param),
2102                 .args = ARGS(ARGS_ENTRY_HTON
2103                              (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
2104         },
2105         [ITEM_ICMP6_ND_OPT_TLA_ETH] = {
2106                 .name = "icmp6_nd_opt_tla_eth",
2107                 .help = "match ICMPv6 neighbor discovery target Ethernet"
2108                         " link-layer address option",
2109                 .priv = PRIV_ITEM
2110                         (ICMP6_ND_OPT_TLA_ETH,
2111                          sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
2112                 .next = NEXT(item_icmp6_nd_opt_tla_eth),
2113                 .call = parse_vc,
2114         },
2115         [ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
2116                 .name = "tla",
2117                 .help = "target Ethernet LLA",
2118                 .next = NEXT(item_icmp6_nd_opt_tla_eth, NEXT_ENTRY(MAC_ADDR),
2119                              item_param),
2120                 .args = ARGS(ARGS_ENTRY_HTON
2121                              (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
2122         },
2123         [ITEM_META] = {
2124                 .name = "meta",
2125                 .help = "match metadata header",
2126                 .priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
2127                 .next = NEXT(item_meta),
2128                 .call = parse_vc,
2129         },
2130         [ITEM_META_DATA] = {
2131                 .name = "data",
2132                 .help = "metadata value",
2133                 .next = NEXT(item_meta, NEXT_ENTRY(UNSIGNED), item_param_is),
2134                 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_meta,
2135                                                   data, "\xff\xff\xff\xff")),
2136         },
2137
2138         /* Validate/create actions. */
2139         [ACTIONS] = {
2140                 .name = "actions",
2141                 .help = "submit a list of associated actions",
2142                 .next = NEXT(next_action),
2143                 .call = parse_vc,
2144         },
2145         [ACTION_NEXT] = {
2146                 .name = "/",
2147                 .help = "specify next action",
2148                 .next = NEXT(next_action),
2149         },
2150         [ACTION_END] = {
2151                 .name = "end",
2152                 .help = "end list of actions",
2153                 .priv = PRIV_ACTION(END, 0),
2154                 .call = parse_vc,
2155         },
2156         [ACTION_VOID] = {
2157                 .name = "void",
2158                 .help = "no-op action",
2159                 .priv = PRIV_ACTION(VOID, 0),
2160                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2161                 .call = parse_vc,
2162         },
2163         [ACTION_PASSTHRU] = {
2164                 .name = "passthru",
2165                 .help = "let subsequent rule process matched packets",
2166                 .priv = PRIV_ACTION(PASSTHRU, 0),
2167                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2168                 .call = parse_vc,
2169         },
2170         [ACTION_JUMP] = {
2171                 .name = "jump",
2172                 .help = "redirect traffic to a given group",
2173                 .priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
2174                 .next = NEXT(action_jump),
2175                 .call = parse_vc,
2176         },
2177         [ACTION_JUMP_GROUP] = {
2178                 .name = "group",
2179                 .help = "group to redirect traffic to",
2180                 .next = NEXT(action_jump, NEXT_ENTRY(UNSIGNED)),
2181                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
2182                 .call = parse_vc_conf,
2183         },
2184         [ACTION_MARK] = {
2185                 .name = "mark",
2186                 .help = "attach 32 bit value to packets",
2187                 .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
2188                 .next = NEXT(action_mark),
2189                 .call = parse_vc,
2190         },
2191         [ACTION_MARK_ID] = {
2192                 .name = "id",
2193                 .help = "32 bit value to return with packets",
2194                 .next = NEXT(action_mark, NEXT_ENTRY(UNSIGNED)),
2195                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
2196                 .call = parse_vc_conf,
2197         },
2198         [ACTION_FLAG] = {
2199                 .name = "flag",
2200                 .help = "flag packets",
2201                 .priv = PRIV_ACTION(FLAG, 0),
2202                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2203                 .call = parse_vc,
2204         },
2205         [ACTION_QUEUE] = {
2206                 .name = "queue",
2207                 .help = "assign packets to a given queue index",
2208                 .priv = PRIV_ACTION(QUEUE,
2209                                     sizeof(struct rte_flow_action_queue)),
2210                 .next = NEXT(action_queue),
2211                 .call = parse_vc,
2212         },
2213         [ACTION_QUEUE_INDEX] = {
2214                 .name = "index",
2215                 .help = "queue index to use",
2216                 .next = NEXT(action_queue, NEXT_ENTRY(UNSIGNED)),
2217                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
2218                 .call = parse_vc_conf,
2219         },
2220         [ACTION_DROP] = {
2221                 .name = "drop",
2222                 .help = "drop packets (note: passthru has priority)",
2223                 .priv = PRIV_ACTION(DROP, 0),
2224                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2225                 .call = parse_vc,
2226         },
2227         [ACTION_COUNT] = {
2228                 .name = "count",
2229                 .help = "enable counters for this rule",
2230                 .priv = PRIV_ACTION(COUNT,
2231                                     sizeof(struct rte_flow_action_count)),
2232                 .next = NEXT(action_count),
2233                 .call = parse_vc,
2234         },
2235         [ACTION_COUNT_ID] = {
2236                 .name = "identifier",
2237                 .help = "counter identifier to use",
2238                 .next = NEXT(action_count, NEXT_ENTRY(UNSIGNED)),
2239                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
2240                 .call = parse_vc_conf,
2241         },
2242         [ACTION_COUNT_SHARED] = {
2243                 .name = "shared",
2244                 .help = "shared counter",
2245                 .next = NEXT(action_count, NEXT_ENTRY(BOOLEAN)),
2246                 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_count,
2247                                            shared, 1)),
2248                 .call = parse_vc_conf,
2249         },
2250         [ACTION_RSS] = {
2251                 .name = "rss",
2252                 .help = "spread packets among several queues",
2253                 .priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
2254                 .next = NEXT(action_rss),
2255                 .call = parse_vc_action_rss,
2256         },
2257         [ACTION_RSS_FUNC] = {
2258                 .name = "func",
2259                 .help = "RSS hash function to apply",
2260                 .next = NEXT(action_rss,
2261                              NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
2262                                         ACTION_RSS_FUNC_TOEPLITZ,
2263                                         ACTION_RSS_FUNC_SIMPLE_XOR)),
2264         },
2265         [ACTION_RSS_FUNC_DEFAULT] = {
2266                 .name = "default",
2267                 .help = "default hash function",
2268                 .call = parse_vc_action_rss_func,
2269         },
2270         [ACTION_RSS_FUNC_TOEPLITZ] = {
2271                 .name = "toeplitz",
2272                 .help = "Toeplitz hash function",
2273                 .call = parse_vc_action_rss_func,
2274         },
2275         [ACTION_RSS_FUNC_SIMPLE_XOR] = {
2276                 .name = "simple_xor",
2277                 .help = "simple XOR hash function",
2278                 .call = parse_vc_action_rss_func,
2279         },
2280         [ACTION_RSS_LEVEL] = {
2281                 .name = "level",
2282                 .help = "encapsulation level for \"types\"",
2283                 .next = NEXT(action_rss, NEXT_ENTRY(UNSIGNED)),
2284                 .args = ARGS(ARGS_ENTRY_ARB
2285                              (offsetof(struct action_rss_data, conf) +
2286                               offsetof(struct rte_flow_action_rss, level),
2287                               sizeof(((struct rte_flow_action_rss *)0)->
2288                                      level))),
2289         },
2290         [ACTION_RSS_TYPES] = {
2291                 .name = "types",
2292                 .help = "specific RSS hash types",
2293                 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
2294         },
2295         [ACTION_RSS_TYPE] = {
2296                 .name = "{type}",
2297                 .help = "RSS hash type",
2298                 .call = parse_vc_action_rss_type,
2299                 .comp = comp_vc_action_rss_type,
2300         },
2301         [ACTION_RSS_KEY] = {
2302                 .name = "key",
2303                 .help = "RSS hash key",
2304                 .next = NEXT(action_rss, NEXT_ENTRY(STRING)),
2305                 .args = ARGS(ARGS_ENTRY_ARB(0, 0),
2306                              ARGS_ENTRY_ARB
2307                              (offsetof(struct action_rss_data, conf) +
2308                               offsetof(struct rte_flow_action_rss, key_len),
2309                               sizeof(((struct rte_flow_action_rss *)0)->
2310                                      key_len)),
2311                              ARGS_ENTRY(struct action_rss_data, key)),
2312         },
2313         [ACTION_RSS_KEY_LEN] = {
2314                 .name = "key_len",
2315                 .help = "RSS hash key length in bytes",
2316                 .next = NEXT(action_rss, NEXT_ENTRY(UNSIGNED)),
2317                 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
2318                              (offsetof(struct action_rss_data, conf) +
2319                               offsetof(struct rte_flow_action_rss, key_len),
2320                               sizeof(((struct rte_flow_action_rss *)0)->
2321                                      key_len),
2322                               0,
2323                               RSS_HASH_KEY_LENGTH)),
2324         },
2325         [ACTION_RSS_QUEUES] = {
2326                 .name = "queues",
2327                 .help = "queue indices to use",
2328                 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
2329                 .call = parse_vc_conf,
2330         },
2331         [ACTION_RSS_QUEUE] = {
2332                 .name = "{queue}",
2333                 .help = "queue index",
2334                 .call = parse_vc_action_rss_queue,
2335                 .comp = comp_vc_action_rss_queue,
2336         },
2337         [ACTION_PF] = {
2338                 .name = "pf",
2339                 .help = "direct traffic to physical function",
2340                 .priv = PRIV_ACTION(PF, 0),
2341                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2342                 .call = parse_vc,
2343         },
2344         [ACTION_VF] = {
2345                 .name = "vf",
2346                 .help = "direct traffic to a virtual function ID",
2347                 .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
2348                 .next = NEXT(action_vf),
2349                 .call = parse_vc,
2350         },
2351         [ACTION_VF_ORIGINAL] = {
2352                 .name = "original",
2353                 .help = "use original VF ID if possible",
2354                 .next = NEXT(action_vf, NEXT_ENTRY(BOOLEAN)),
2355                 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
2356                                            original, 1)),
2357                 .call = parse_vc_conf,
2358         },
2359         [ACTION_VF_ID] = {
2360                 .name = "id",
2361                 .help = "VF ID",
2362                 .next = NEXT(action_vf, NEXT_ENTRY(UNSIGNED)),
2363                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
2364                 .call = parse_vc_conf,
2365         },
2366         [ACTION_PHY_PORT] = {
2367                 .name = "phy_port",
2368                 .help = "direct packets to physical port index",
2369                 .priv = PRIV_ACTION(PHY_PORT,
2370                                     sizeof(struct rte_flow_action_phy_port)),
2371                 .next = NEXT(action_phy_port),
2372                 .call = parse_vc,
2373         },
2374         [ACTION_PHY_PORT_ORIGINAL] = {
2375                 .name = "original",
2376                 .help = "use original port index if possible",
2377                 .next = NEXT(action_phy_port, NEXT_ENTRY(BOOLEAN)),
2378                 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port,
2379                                            original, 1)),
2380                 .call = parse_vc_conf,
2381         },
2382         [ACTION_PHY_PORT_INDEX] = {
2383                 .name = "index",
2384                 .help = "physical port index",
2385                 .next = NEXT(action_phy_port, NEXT_ENTRY(UNSIGNED)),
2386                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port,
2387                                         index)),
2388                 .call = parse_vc_conf,
2389         },
2390         [ACTION_PORT_ID] = {
2391                 .name = "port_id",
2392                 .help = "direct matching traffic to a given DPDK port ID",
2393                 .priv = PRIV_ACTION(PORT_ID,
2394                                     sizeof(struct rte_flow_action_port_id)),
2395                 .next = NEXT(action_port_id),
2396                 .call = parse_vc,
2397         },
2398         [ACTION_PORT_ID_ORIGINAL] = {
2399                 .name = "original",
2400                 .help = "use original DPDK port ID if possible",
2401                 .next = NEXT(action_port_id, NEXT_ENTRY(BOOLEAN)),
2402                 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
2403                                            original, 1)),
2404                 .call = parse_vc_conf,
2405         },
2406         [ACTION_PORT_ID_ID] = {
2407                 .name = "id",
2408                 .help = "DPDK port ID",
2409                 .next = NEXT(action_port_id, NEXT_ENTRY(UNSIGNED)),
2410                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
2411                 .call = parse_vc_conf,
2412         },
2413         [ACTION_METER] = {
2414                 .name = "meter",
2415                 .help = "meter the directed packets at given id",
2416                 .priv = PRIV_ACTION(METER,
2417                                     sizeof(struct rte_flow_action_meter)),
2418                 .next = NEXT(action_meter),
2419                 .call = parse_vc,
2420         },
2421         [ACTION_METER_ID] = {
2422                 .name = "mtr_id",
2423                 .help = "meter id to use",
2424                 .next = NEXT(action_meter, NEXT_ENTRY(UNSIGNED)),
2425                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
2426                 .call = parse_vc_conf,
2427         },
2428         [ACTION_OF_SET_MPLS_TTL] = {
2429                 .name = "of_set_mpls_ttl",
2430                 .help = "OpenFlow's OFPAT_SET_MPLS_TTL",
2431                 .priv = PRIV_ACTION
2432                         (OF_SET_MPLS_TTL,
2433                          sizeof(struct rte_flow_action_of_set_mpls_ttl)),
2434                 .next = NEXT(action_of_set_mpls_ttl),
2435                 .call = parse_vc,
2436         },
2437         [ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = {
2438                 .name = "mpls_ttl",
2439                 .help = "MPLS TTL",
2440                 .next = NEXT(action_of_set_mpls_ttl, NEXT_ENTRY(UNSIGNED)),
2441                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl,
2442                                         mpls_ttl)),
2443                 .call = parse_vc_conf,
2444         },
2445         [ACTION_OF_DEC_MPLS_TTL] = {
2446                 .name = "of_dec_mpls_ttl",
2447                 .help = "OpenFlow's OFPAT_DEC_MPLS_TTL",
2448                 .priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0),
2449                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2450                 .call = parse_vc,
2451         },
2452         [ACTION_OF_SET_NW_TTL] = {
2453                 .name = "of_set_nw_ttl",
2454                 .help = "OpenFlow's OFPAT_SET_NW_TTL",
2455                 .priv = PRIV_ACTION
2456                         (OF_SET_NW_TTL,
2457                          sizeof(struct rte_flow_action_of_set_nw_ttl)),
2458                 .next = NEXT(action_of_set_nw_ttl),
2459                 .call = parse_vc,
2460         },
2461         [ACTION_OF_SET_NW_TTL_NW_TTL] = {
2462                 .name = "nw_ttl",
2463                 .help = "IP TTL",
2464                 .next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(UNSIGNED)),
2465                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl,
2466                                         nw_ttl)),
2467                 .call = parse_vc_conf,
2468         },
2469         [ACTION_OF_DEC_NW_TTL] = {
2470                 .name = "of_dec_nw_ttl",
2471                 .help = "OpenFlow's OFPAT_DEC_NW_TTL",
2472                 .priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
2473                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2474                 .call = parse_vc,
2475         },
2476         [ACTION_OF_COPY_TTL_OUT] = {
2477                 .name = "of_copy_ttl_out",
2478                 .help = "OpenFlow's OFPAT_COPY_TTL_OUT",
2479                 .priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0),
2480                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2481                 .call = parse_vc,
2482         },
2483         [ACTION_OF_COPY_TTL_IN] = {
2484                 .name = "of_copy_ttl_in",
2485                 .help = "OpenFlow's OFPAT_COPY_TTL_IN",
2486                 .priv = PRIV_ACTION(OF_COPY_TTL_IN, 0),
2487                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2488                 .call = parse_vc,
2489         },
2490         [ACTION_OF_POP_VLAN] = {
2491                 .name = "of_pop_vlan",
2492                 .help = "OpenFlow's OFPAT_POP_VLAN",
2493                 .priv = PRIV_ACTION(OF_POP_VLAN, 0),
2494                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2495                 .call = parse_vc,
2496         },
2497         [ACTION_OF_PUSH_VLAN] = {
2498                 .name = "of_push_vlan",
2499                 .help = "OpenFlow's OFPAT_PUSH_VLAN",
2500                 .priv = PRIV_ACTION
2501                         (OF_PUSH_VLAN,
2502                          sizeof(struct rte_flow_action_of_push_vlan)),
2503                 .next = NEXT(action_of_push_vlan),
2504                 .call = parse_vc,
2505         },
2506         [ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
2507                 .name = "ethertype",
2508                 .help = "EtherType",
2509                 .next = NEXT(action_of_push_vlan, NEXT_ENTRY(UNSIGNED)),
2510                 .args = ARGS(ARGS_ENTRY_HTON
2511                              (struct rte_flow_action_of_push_vlan,
2512                               ethertype)),
2513                 .call = parse_vc_conf,
2514         },
2515         [ACTION_OF_SET_VLAN_VID] = {
2516                 .name = "of_set_vlan_vid",
2517                 .help = "OpenFlow's OFPAT_SET_VLAN_VID",
2518                 .priv = PRIV_ACTION
2519                         (OF_SET_VLAN_VID,
2520                          sizeof(struct rte_flow_action_of_set_vlan_vid)),
2521                 .next = NEXT(action_of_set_vlan_vid),
2522                 .call = parse_vc,
2523         },
2524         [ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
2525                 .name = "vlan_vid",
2526                 .help = "VLAN id",
2527                 .next = NEXT(action_of_set_vlan_vid, NEXT_ENTRY(UNSIGNED)),
2528                 .args = ARGS(ARGS_ENTRY_HTON
2529                              (struct rte_flow_action_of_set_vlan_vid,
2530                               vlan_vid)),
2531                 .call = parse_vc_conf,
2532         },
2533         [ACTION_OF_SET_VLAN_PCP] = {
2534                 .name = "of_set_vlan_pcp",
2535                 .help = "OpenFlow's OFPAT_SET_VLAN_PCP",
2536                 .priv = PRIV_ACTION
2537                         (OF_SET_VLAN_PCP,
2538                          sizeof(struct rte_flow_action_of_set_vlan_pcp)),
2539                 .next = NEXT(action_of_set_vlan_pcp),
2540                 .call = parse_vc,
2541         },
2542         [ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
2543                 .name = "vlan_pcp",
2544                 .help = "VLAN priority",
2545                 .next = NEXT(action_of_set_vlan_pcp, NEXT_ENTRY(UNSIGNED)),
2546                 .args = ARGS(ARGS_ENTRY_HTON
2547                              (struct rte_flow_action_of_set_vlan_pcp,
2548                               vlan_pcp)),
2549                 .call = parse_vc_conf,
2550         },
2551         [ACTION_OF_POP_MPLS] = {
2552                 .name = "of_pop_mpls",
2553                 .help = "OpenFlow's OFPAT_POP_MPLS",
2554                 .priv = PRIV_ACTION(OF_POP_MPLS,
2555                                     sizeof(struct rte_flow_action_of_pop_mpls)),
2556                 .next = NEXT(action_of_pop_mpls),
2557                 .call = parse_vc,
2558         },
2559         [ACTION_OF_POP_MPLS_ETHERTYPE] = {
2560                 .name = "ethertype",
2561                 .help = "EtherType",
2562                 .next = NEXT(action_of_pop_mpls, NEXT_ENTRY(UNSIGNED)),
2563                 .args = ARGS(ARGS_ENTRY_HTON
2564                              (struct rte_flow_action_of_pop_mpls,
2565                               ethertype)),
2566                 .call = parse_vc_conf,
2567         },
2568         [ACTION_OF_PUSH_MPLS] = {
2569                 .name = "of_push_mpls",
2570                 .help = "OpenFlow's OFPAT_PUSH_MPLS",
2571                 .priv = PRIV_ACTION
2572                         (OF_PUSH_MPLS,
2573                          sizeof(struct rte_flow_action_of_push_mpls)),
2574                 .next = NEXT(action_of_push_mpls),
2575                 .call = parse_vc,
2576         },
2577         [ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
2578                 .name = "ethertype",
2579                 .help = "EtherType",
2580                 .next = NEXT(action_of_push_mpls, NEXT_ENTRY(UNSIGNED)),
2581                 .args = ARGS(ARGS_ENTRY_HTON
2582                              (struct rte_flow_action_of_push_mpls,
2583                               ethertype)),
2584                 .call = parse_vc_conf,
2585         },
2586         [ACTION_VXLAN_ENCAP] = {
2587                 .name = "vxlan_encap",
2588                 .help = "VXLAN encapsulation, uses configuration set by \"set"
2589                         " vxlan\"",
2590                 .priv = PRIV_ACTION(VXLAN_ENCAP,
2591                                     sizeof(struct action_vxlan_encap_data)),
2592                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2593                 .call = parse_vc_action_vxlan_encap,
2594         },
2595         [ACTION_VXLAN_DECAP] = {
2596                 .name = "vxlan_decap",
2597                 .help = "Performs a decapsulation action by stripping all"
2598                         " headers of the VXLAN tunnel network overlay from the"
2599                         " matched flow.",
2600                 .priv = PRIV_ACTION(VXLAN_DECAP, 0),
2601                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2602                 .call = parse_vc,
2603         },
2604         [ACTION_NVGRE_ENCAP] = {
2605                 .name = "nvgre_encap",
2606                 .help = "NVGRE encapsulation, uses configuration set by \"set"
2607                         " nvgre\"",
2608                 .priv = PRIV_ACTION(NVGRE_ENCAP,
2609                                     sizeof(struct action_nvgre_encap_data)),
2610                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2611                 .call = parse_vc_action_nvgre_encap,
2612         },
2613         [ACTION_NVGRE_DECAP] = {
2614                 .name = "nvgre_decap",
2615                 .help = "Performs a decapsulation action by stripping all"
2616                         " headers of the NVGRE tunnel network overlay from the"
2617                         " matched flow.",
2618                 .priv = PRIV_ACTION(NVGRE_DECAP, 0),
2619                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2620                 .call = parse_vc,
2621         },
2622         [ACTION_MPLSOUDP_ENCAP] = {
2623                 .name = "mplsoudp_encap",
2624                 .help = "mplsoudp encapsulation, uses configuration set by"
2625                         " \"set mplsoudp_encap\"",
2626                 .priv = PRIV_ACTION(RAW_ENCAP,
2627                                     sizeof(struct action_raw_encap_data)),
2628                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2629                 .call = parse_vc_action_mplsoudp_encap,
2630         },
2631         [ACTION_L2_ENCAP] = {
2632                 .name = "l2_encap",
2633                 .help = "l2 encapsulation, uses configuration set by"
2634                         " \"set l2_encp\"",
2635                 .priv = PRIV_ACTION(RAW_ENCAP,
2636                                     sizeof(struct action_raw_encap_data)),
2637                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2638                 .call = parse_vc_action_l2_encap,
2639         },
2640         [ACTION_L2_DECAP] = {
2641                 .name = "l2_decap",
2642                 .help = "l2 decap, uses configuration set by"
2643                         " \"set l2_decap\"",
2644                 .priv = PRIV_ACTION(RAW_DECAP,
2645                                     sizeof(struct action_raw_decap_data)),
2646                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2647                 .call = parse_vc_action_l2_decap,
2648         },
2649         [ACTION_MPLSOUDP_DECAP] = {
2650                 .name = "mplsoudp_decap",
2651                 .help = "mplsoudp decapsulation, uses configuration set by"
2652                         " \"set mplsoudp_decap\"",
2653                 .priv = PRIV_ACTION(RAW_DECAP,
2654                                     sizeof(struct action_raw_decap_data)),
2655                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2656                 .call = parse_vc_action_mplsoudp_decap,
2657         },
2658         [ACTION_SET_IPV4_SRC] = {
2659                 .name = "set_ipv4_src",
2660                 .help = "Set a new IPv4 source address in the outermost"
2661                         " IPv4 header",
2662                 .priv = PRIV_ACTION(SET_IPV4_SRC,
2663                         sizeof(struct rte_flow_action_set_ipv4)),
2664                 .next = NEXT(action_set_ipv4_src),
2665                 .call = parse_vc,
2666         },
2667         [ACTION_SET_IPV4_SRC_IPV4_SRC] = {
2668                 .name = "ipv4_addr",
2669                 .help = "new IPv4 source address to set",
2670                 .next = NEXT(action_set_ipv4_src, NEXT_ENTRY(IPV4_ADDR)),
2671                 .args = ARGS(ARGS_ENTRY_HTON
2672                         (struct rte_flow_action_set_ipv4, ipv4_addr)),
2673                 .call = parse_vc_conf,
2674         },
2675         [ACTION_SET_IPV4_DST] = {
2676                 .name = "set_ipv4_dst",
2677                 .help = "Set a new IPv4 destination address in the outermost"
2678                         " IPv4 header",
2679                 .priv = PRIV_ACTION(SET_IPV4_DST,
2680                         sizeof(struct rte_flow_action_set_ipv4)),
2681                 .next = NEXT(action_set_ipv4_dst),
2682                 .call = parse_vc,
2683         },
2684         [ACTION_SET_IPV4_DST_IPV4_DST] = {
2685                 .name = "ipv4_addr",
2686                 .help = "new IPv4 destination address to set",
2687                 .next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(IPV4_ADDR)),
2688                 .args = ARGS(ARGS_ENTRY_HTON
2689                         (struct rte_flow_action_set_ipv4, ipv4_addr)),
2690                 .call = parse_vc_conf,
2691         },
2692         [ACTION_SET_IPV6_SRC] = {
2693                 .name = "set_ipv6_src",
2694                 .help = "Set a new IPv6 source address in the outermost"
2695                         " IPv6 header",
2696                 .priv = PRIV_ACTION(SET_IPV6_SRC,
2697                         sizeof(struct rte_flow_action_set_ipv6)),
2698                 .next = NEXT(action_set_ipv6_src),
2699                 .call = parse_vc,
2700         },
2701         [ACTION_SET_IPV6_SRC_IPV6_SRC] = {
2702                 .name = "ipv6_addr",
2703                 .help = "new IPv6 source address to set",
2704                 .next = NEXT(action_set_ipv6_src, NEXT_ENTRY(IPV6_ADDR)),
2705                 .args = ARGS(ARGS_ENTRY_HTON
2706                         (struct rte_flow_action_set_ipv6, ipv6_addr)),
2707                 .call = parse_vc_conf,
2708         },
2709         [ACTION_SET_IPV6_DST] = {
2710                 .name = "set_ipv6_dst",
2711                 .help = "Set a new IPv6 destination address in the outermost"
2712                         " IPv6 header",
2713                 .priv = PRIV_ACTION(SET_IPV6_DST,
2714                         sizeof(struct rte_flow_action_set_ipv6)),
2715                 .next = NEXT(action_set_ipv6_dst),
2716                 .call = parse_vc,
2717         },
2718         [ACTION_SET_IPV6_DST_IPV6_DST] = {
2719                 .name = "ipv6_addr",
2720                 .help = "new IPv6 destination address to set",
2721                 .next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(IPV6_ADDR)),
2722                 .args = ARGS(ARGS_ENTRY_HTON
2723                         (struct rte_flow_action_set_ipv6, ipv6_addr)),
2724                 .call = parse_vc_conf,
2725         },
2726         [ACTION_SET_TP_SRC] = {
2727                 .name = "set_tp_src",
2728                 .help = "set a new source port number in the outermost"
2729                         " TCP/UDP header",
2730                 .priv = PRIV_ACTION(SET_TP_SRC,
2731                         sizeof(struct rte_flow_action_set_tp)),
2732                 .next = NEXT(action_set_tp_src),
2733                 .call = parse_vc,
2734         },
2735         [ACTION_SET_TP_SRC_TP_SRC] = {
2736                 .name = "port",
2737                 .help = "new source port number to set",
2738                 .next = NEXT(action_set_tp_src, NEXT_ENTRY(UNSIGNED)),
2739                 .args = ARGS(ARGS_ENTRY_HTON
2740                              (struct rte_flow_action_set_tp, port)),
2741                 .call = parse_vc_conf,
2742         },
2743         [ACTION_SET_TP_DST] = {
2744                 .name = "set_tp_dst",
2745                 .help = "set a new destination port number in the outermost"
2746                         " TCP/UDP header",
2747                 .priv = PRIV_ACTION(SET_TP_DST,
2748                         sizeof(struct rte_flow_action_set_tp)),
2749                 .next = NEXT(action_set_tp_dst),
2750                 .call = parse_vc,
2751         },
2752         [ACTION_SET_TP_DST_TP_DST] = {
2753                 .name = "port",
2754                 .help = "new destination port number to set",
2755                 .next = NEXT(action_set_tp_dst, NEXT_ENTRY(UNSIGNED)),
2756                 .args = ARGS(ARGS_ENTRY_HTON
2757                              (struct rte_flow_action_set_tp, port)),
2758                 .call = parse_vc_conf,
2759         },
2760         [ACTION_MAC_SWAP] = {
2761                 .name = "mac_swap",
2762                 .help = "Swap the source and destination MAC addresses"
2763                         " in the outermost Ethernet header",
2764                 .priv = PRIV_ACTION(MAC_SWAP, 0),
2765                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2766                 .call = parse_vc,
2767         },
2768         [ACTION_DEC_TTL] = {
2769                 .name = "dec_ttl",
2770                 .help = "decrease network TTL if available",
2771                 .priv = PRIV_ACTION(DEC_TTL, 0),
2772                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2773                 .call = parse_vc,
2774         },
2775         [ACTION_SET_TTL] = {
2776                 .name = "set_ttl",
2777                 .help = "set ttl value",
2778                 .priv = PRIV_ACTION(SET_TTL,
2779                         sizeof(struct rte_flow_action_set_ttl)),
2780                 .next = NEXT(action_set_ttl),
2781                 .call = parse_vc,
2782         },
2783         [ACTION_SET_TTL_TTL] = {
2784                 .name = "ttl_value",
2785                 .help = "new ttl value to set",
2786                 .next = NEXT(action_set_ttl, NEXT_ENTRY(UNSIGNED)),
2787                 .args = ARGS(ARGS_ENTRY_HTON
2788                              (struct rte_flow_action_set_ttl, ttl_value)),
2789                 .call = parse_vc_conf,
2790         },
2791         [ACTION_SET_MAC_SRC] = {
2792                 .name = "set_mac_src",
2793                 .help = "set source mac address",
2794                 .priv = PRIV_ACTION(SET_MAC_SRC,
2795                         sizeof(struct rte_flow_action_set_mac)),
2796                 .next = NEXT(action_set_mac_src),
2797                 .call = parse_vc,
2798         },
2799         [ACTION_SET_MAC_SRC_MAC_SRC] = {
2800                 .name = "mac_addr",
2801                 .help = "new source mac address",
2802                 .next = NEXT(action_set_mac_src, NEXT_ENTRY(MAC_ADDR)),
2803                 .args = ARGS(ARGS_ENTRY_HTON
2804                              (struct rte_flow_action_set_mac, mac_addr)),
2805                 .call = parse_vc_conf,
2806         },
2807         [ACTION_SET_MAC_DST] = {
2808                 .name = "set_mac_dst",
2809                 .help = "set destination mac address",
2810                 .priv = PRIV_ACTION(SET_MAC_DST,
2811                         sizeof(struct rte_flow_action_set_mac)),
2812                 .next = NEXT(action_set_mac_dst),
2813                 .call = parse_vc,
2814         },
2815         [ACTION_SET_MAC_DST_MAC_DST] = {
2816                 .name = "mac_addr",
2817                 .help = "new destination mac address to set",
2818                 .next = NEXT(action_set_mac_dst, NEXT_ENTRY(MAC_ADDR)),
2819                 .args = ARGS(ARGS_ENTRY_HTON
2820                              (struct rte_flow_action_set_mac, mac_addr)),
2821                 .call = parse_vc_conf,
2822         },
2823 };
2824
2825 /** Remove and return last entry from argument stack. */
2826 static const struct arg *
2827 pop_args(struct context *ctx)
2828 {
2829         return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
2830 }
2831
2832 /** Add entry on top of the argument stack. */
2833 static int
2834 push_args(struct context *ctx, const struct arg *arg)
2835 {
2836         if (ctx->args_num == CTX_STACK_SIZE)
2837                 return -1;
2838         ctx->args[ctx->args_num++] = arg;
2839         return 0;
2840 }
2841
2842 /** Spread value into buffer according to bit-mask. */
2843 static size_t
2844 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
2845 {
2846         uint32_t i = arg->size;
2847         uint32_t end = 0;
2848         int sub = 1;
2849         int add = 0;
2850         size_t len = 0;
2851
2852         if (!arg->mask)
2853                 return 0;
2854 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
2855         if (!arg->hton) {
2856                 i = 0;
2857                 end = arg->size;
2858                 sub = 0;
2859                 add = 1;
2860         }
2861 #endif
2862         while (i != end) {
2863                 unsigned int shift = 0;
2864                 uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
2865
2866                 for (shift = 0; arg->mask[i] >> shift; ++shift) {
2867                         if (!(arg->mask[i] & (1 << shift)))
2868                                 continue;
2869                         ++len;
2870                         if (!dst)
2871                                 continue;
2872                         *buf &= ~(1 << shift);
2873                         *buf |= (val & 1) << shift;
2874                         val >>= 1;
2875                 }
2876                 i += add;
2877         }
2878         return len;
2879 }
2880
2881 /** Compare a string with a partial one of a given length. */
2882 static int
2883 strcmp_partial(const char *full, const char *partial, size_t partial_len)
2884 {
2885         int r = strncmp(full, partial, partial_len);
2886
2887         if (r)
2888                 return r;
2889         if (strlen(full) <= partial_len)
2890                 return 0;
2891         return full[partial_len];
2892 }
2893
2894 /**
2895  * Parse a prefix length and generate a bit-mask.
2896  *
2897  * Last argument (ctx->args) is retrieved to determine mask size, storage
2898  * location and whether the result must use network byte ordering.
2899  */
2900 static int
2901 parse_prefix(struct context *ctx, const struct token *token,
2902              const char *str, unsigned int len,
2903              void *buf, unsigned int size)
2904 {
2905         const struct arg *arg = pop_args(ctx);
2906         static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
2907         char *end;
2908         uintmax_t u;
2909         unsigned int bytes;
2910         unsigned int extra;
2911
2912         (void)token;
2913         /* Argument is expected. */
2914         if (!arg)
2915                 return -1;
2916         errno = 0;
2917         u = strtoumax(str, &end, 0);
2918         if (errno || (size_t)(end - str) != len)
2919                 goto error;
2920         if (arg->mask) {
2921                 uintmax_t v = 0;
2922
2923                 extra = arg_entry_bf_fill(NULL, 0, arg);
2924                 if (u > extra)
2925                         goto error;
2926                 if (!ctx->object)
2927                         return len;
2928                 extra -= u;
2929                 while (u--)
2930                         (v <<= 1, v |= 1);
2931                 v <<= extra;
2932                 if (!arg_entry_bf_fill(ctx->object, v, arg) ||
2933                     !arg_entry_bf_fill(ctx->objmask, -1, arg))
2934                         goto error;
2935                 return len;
2936         }
2937         bytes = u / 8;
2938         extra = u % 8;
2939         size = arg->size;
2940         if (bytes > size || bytes + !!extra > size)
2941                 goto error;
2942         if (!ctx->object)
2943                 return len;
2944         buf = (uint8_t *)ctx->object + arg->offset;
2945 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
2946         if (!arg->hton) {
2947                 memset((uint8_t *)buf + size - bytes, 0xff, bytes);
2948                 memset(buf, 0x00, size - bytes);
2949                 if (extra)
2950                         ((uint8_t *)buf)[size - bytes - 1] = conv[extra];
2951         } else
2952 #endif
2953         {
2954                 memset(buf, 0xff, bytes);
2955                 memset((uint8_t *)buf + bytes, 0x00, size - bytes);
2956                 if (extra)
2957                         ((uint8_t *)buf)[bytes] = conv[extra];
2958         }
2959         if (ctx->objmask)
2960                 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
2961         return len;
2962 error:
2963         push_args(ctx, arg);
2964         return -1;
2965 }
2966
2967 /** Default parsing function for token name matching. */
2968 static int
2969 parse_default(struct context *ctx, const struct token *token,
2970               const char *str, unsigned int len,
2971               void *buf, unsigned int size)
2972 {
2973         (void)ctx;
2974         (void)buf;
2975         (void)size;
2976         if (strcmp_partial(token->name, str, len))
2977                 return -1;
2978         return len;
2979 }
2980
2981 /** Parse flow command, initialize output buffer for subsequent tokens. */
2982 static int
2983 parse_init(struct context *ctx, const struct token *token,
2984            const char *str, unsigned int len,
2985            void *buf, unsigned int size)
2986 {
2987         struct buffer *out = buf;
2988
2989         /* Token name must match. */
2990         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
2991                 return -1;
2992         /* Nothing else to do if there is no buffer. */
2993         if (!out)
2994                 return len;
2995         /* Make sure buffer is large enough. */
2996         if (size < sizeof(*out))
2997                 return -1;
2998         /* Initialize buffer. */
2999         memset(out, 0x00, sizeof(*out));
3000         memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
3001         ctx->objdata = 0;
3002         ctx->object = out;
3003         ctx->objmask = NULL;
3004         return len;
3005 }
3006
3007 /** Parse tokens for validate/create commands. */
3008 static int
3009 parse_vc(struct context *ctx, const struct token *token,
3010          const char *str, unsigned int len,
3011          void *buf, unsigned int size)
3012 {
3013         struct buffer *out = buf;
3014         uint8_t *data;
3015         uint32_t data_size;
3016
3017         /* Token name must match. */
3018         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3019                 return -1;
3020         /* Nothing else to do if there is no buffer. */
3021         if (!out)
3022                 return len;
3023         if (!out->command) {
3024                 if (ctx->curr != VALIDATE && ctx->curr != CREATE)
3025                         return -1;
3026                 if (sizeof(*out) > size)
3027                         return -1;
3028                 out->command = ctx->curr;
3029                 ctx->objdata = 0;
3030                 ctx->object = out;
3031                 ctx->objmask = NULL;
3032                 out->args.vc.data = (uint8_t *)out + size;
3033                 return len;
3034         }
3035         ctx->objdata = 0;
3036         ctx->object = &out->args.vc.attr;
3037         ctx->objmask = NULL;
3038         switch (ctx->curr) {
3039         case GROUP:
3040         case PRIORITY:
3041                 return len;
3042         case INGRESS:
3043                 out->args.vc.attr.ingress = 1;
3044                 return len;
3045         case EGRESS:
3046                 out->args.vc.attr.egress = 1;
3047                 return len;
3048         case TRANSFER:
3049                 out->args.vc.attr.transfer = 1;
3050                 return len;
3051         case PATTERN:
3052                 out->args.vc.pattern =
3053                         (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
3054                                                sizeof(double));
3055                 ctx->object = out->args.vc.pattern;
3056                 ctx->objmask = NULL;
3057                 return len;
3058         case ACTIONS:
3059                 out->args.vc.actions =
3060                         (void *)RTE_ALIGN_CEIL((uintptr_t)
3061                                                (out->args.vc.pattern +
3062                                                 out->args.vc.pattern_n),
3063                                                sizeof(double));
3064                 ctx->object = out->args.vc.actions;
3065                 ctx->objmask = NULL;
3066                 return len;
3067         default:
3068                 if (!token->priv)
3069                         return -1;
3070                 break;
3071         }
3072         if (!out->args.vc.actions) {
3073                 const struct parse_item_priv *priv = token->priv;
3074                 struct rte_flow_item *item =
3075                         out->args.vc.pattern + out->args.vc.pattern_n;
3076
3077                 data_size = priv->size * 3; /* spec, last, mask */
3078                 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
3079                                                (out->args.vc.data - data_size),
3080                                                sizeof(double));
3081                 if ((uint8_t *)item + sizeof(*item) > data)
3082                         return -1;
3083                 *item = (struct rte_flow_item){
3084                         .type = priv->type,
3085                 };
3086                 ++out->args.vc.pattern_n;
3087                 ctx->object = item;
3088                 ctx->objmask = NULL;
3089         } else {
3090                 const struct parse_action_priv *priv = token->priv;
3091                 struct rte_flow_action *action =
3092                         out->args.vc.actions + out->args.vc.actions_n;
3093
3094                 data_size = priv->size; /* configuration */
3095                 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
3096                                                (out->args.vc.data - data_size),
3097                                                sizeof(double));
3098                 if ((uint8_t *)action + sizeof(*action) > data)
3099                         return -1;
3100                 *action = (struct rte_flow_action){
3101                         .type = priv->type,
3102                         .conf = data_size ? data : NULL,
3103                 };
3104                 ++out->args.vc.actions_n;
3105                 ctx->object = action;
3106                 ctx->objmask = NULL;
3107         }
3108         memset(data, 0, data_size);
3109         out->args.vc.data = data;
3110         ctx->objdata = data_size;
3111         return len;
3112 }
3113
3114 /** Parse pattern item parameter type. */
3115 static int
3116 parse_vc_spec(struct context *ctx, const struct token *token,
3117               const char *str, unsigned int len,
3118               void *buf, unsigned int size)
3119 {
3120         struct buffer *out = buf;
3121         struct rte_flow_item *item;
3122         uint32_t data_size;
3123         int index;
3124         int objmask = 0;
3125
3126         (void)size;
3127         /* Token name must match. */
3128         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3129                 return -1;
3130         /* Parse parameter types. */
3131         switch (ctx->curr) {
3132                 static const enum index prefix[] = NEXT_ENTRY(PREFIX);
3133
3134         case ITEM_PARAM_IS:
3135                 index = 0;
3136                 objmask = 1;
3137                 break;
3138         case ITEM_PARAM_SPEC:
3139                 index = 0;
3140                 break;
3141         case ITEM_PARAM_LAST:
3142                 index = 1;
3143                 break;
3144         case ITEM_PARAM_PREFIX:
3145                 /* Modify next token to expect a prefix. */
3146                 if (ctx->next_num < 2)
3147                         return -1;
3148                 ctx->next[ctx->next_num - 2] = prefix;
3149                 /* Fall through. */
3150         case ITEM_PARAM_MASK:
3151                 index = 2;
3152                 break;
3153         default:
3154                 return -1;
3155         }
3156         /* Nothing else to do if there is no buffer. */
3157         if (!out)
3158                 return len;
3159         if (!out->args.vc.pattern_n)
3160                 return -1;
3161         item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
3162         data_size = ctx->objdata / 3; /* spec, last, mask */
3163         /* Point to selected object. */
3164         ctx->object = out->args.vc.data + (data_size * index);
3165         if (objmask) {
3166                 ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
3167                 item->mask = ctx->objmask;
3168         } else
3169                 ctx->objmask = NULL;
3170         /* Update relevant item pointer. */
3171         *((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
3172                 ctx->object;
3173         return len;
3174 }
3175
3176 /** Parse action configuration field. */
3177 static int
3178 parse_vc_conf(struct context *ctx, const struct token *token,
3179               const char *str, unsigned int len,
3180               void *buf, unsigned int size)
3181 {
3182         struct buffer *out = buf;
3183
3184         (void)size;
3185         /* Token name must match. */
3186         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3187                 return -1;
3188         /* Nothing else to do if there is no buffer. */
3189         if (!out)
3190                 return len;
3191         /* Point to selected object. */
3192         ctx->object = out->args.vc.data;
3193         ctx->objmask = NULL;
3194         return len;
3195 }
3196
3197 /** Parse RSS action. */
3198 static int
3199 parse_vc_action_rss(struct context *ctx, const struct token *token,
3200                     const char *str, unsigned int len,
3201                     void *buf, unsigned int size)
3202 {
3203         struct buffer *out = buf;
3204         struct rte_flow_action *action;
3205         struct action_rss_data *action_rss_data;
3206         unsigned int i;
3207         int ret;
3208
3209         ret = parse_vc(ctx, token, str, len, buf, size);
3210         if (ret < 0)
3211                 return ret;
3212         /* Nothing else to do if there is no buffer. */
3213         if (!out)
3214                 return ret;
3215         if (!out->args.vc.actions_n)
3216                 return -1;
3217         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3218         /* Point to selected object. */
3219         ctx->object = out->args.vc.data;
3220         ctx->objmask = NULL;
3221         /* Set up default configuration. */
3222         action_rss_data = ctx->object;
3223         *action_rss_data = (struct action_rss_data){
3224                 .conf = (struct rte_flow_action_rss){
3225                         .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
3226                         .level = 0,
3227                         .types = rss_hf,
3228                         .key_len = sizeof(action_rss_data->key),
3229                         .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
3230                         .key = action_rss_data->key,
3231                         .queue = action_rss_data->queue,
3232                 },
3233                 .key = "testpmd's default RSS hash key, "
3234                         "override it for better balancing",
3235                 .queue = { 0 },
3236         };
3237         for (i = 0; i < action_rss_data->conf.queue_num; ++i)
3238                 action_rss_data->queue[i] = i;
3239         if (!port_id_is_invalid(ctx->port, DISABLED_WARN) &&
3240             ctx->port != (portid_t)RTE_PORT_ALL) {
3241                 struct rte_eth_dev_info info;
3242
3243                 rte_eth_dev_info_get(ctx->port, &info);
3244                 action_rss_data->conf.key_len =
3245                         RTE_MIN(sizeof(action_rss_data->key),
3246                                 info.hash_key_size);
3247         }
3248         action->conf = &action_rss_data->conf;
3249         return ret;
3250 }
3251
3252 /**
3253  * Parse func field for RSS action.
3254  *
3255  * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
3256  * ACTION_RSS_FUNC_* index that called this function.
3257  */
3258 static int
3259 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
3260                          const char *str, unsigned int len,
3261                          void *buf, unsigned int size)
3262 {
3263         struct action_rss_data *action_rss_data;
3264         enum rte_eth_hash_function func;
3265
3266         (void)buf;
3267         (void)size;
3268         /* Token name must match. */
3269         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3270                 return -1;
3271         switch (ctx->curr) {
3272         case ACTION_RSS_FUNC_DEFAULT:
3273                 func = RTE_ETH_HASH_FUNCTION_DEFAULT;
3274                 break;
3275         case ACTION_RSS_FUNC_TOEPLITZ:
3276                 func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
3277                 break;
3278         case ACTION_RSS_FUNC_SIMPLE_XOR:
3279                 func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
3280                 break;
3281         default:
3282                 return -1;
3283         }
3284         if (!ctx->object)
3285                 return len;
3286         action_rss_data = ctx->object;
3287         action_rss_data->conf.func = func;
3288         return len;
3289 }
3290
3291 /**
3292  * Parse type field for RSS action.
3293  *
3294  * Valid tokens are type field names and the "end" token.
3295  */
3296 static int
3297 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
3298                           const char *str, unsigned int len,
3299                           void *buf, unsigned int size)
3300 {
3301         static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
3302         struct action_rss_data *action_rss_data;
3303         unsigned int i;
3304
3305         (void)token;
3306         (void)buf;
3307         (void)size;
3308         if (ctx->curr != ACTION_RSS_TYPE)
3309                 return -1;
3310         if (!(ctx->objdata >> 16) && ctx->object) {
3311                 action_rss_data = ctx->object;
3312                 action_rss_data->conf.types = 0;
3313         }
3314         if (!strcmp_partial("end", str, len)) {
3315                 ctx->objdata &= 0xffff;
3316                 return len;
3317         }
3318         for (i = 0; rss_type_table[i].str; ++i)
3319                 if (!strcmp_partial(rss_type_table[i].str, str, len))
3320                         break;
3321         if (!rss_type_table[i].str)
3322                 return -1;
3323         ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
3324         /* Repeat token. */
3325         if (ctx->next_num == RTE_DIM(ctx->next))
3326                 return -1;
3327         ctx->next[ctx->next_num++] = next;
3328         if (!ctx->object)
3329                 return len;
3330         action_rss_data = ctx->object;
3331         action_rss_data->conf.types |= rss_type_table[i].rss_type;
3332         return len;
3333 }
3334
3335 /**
3336  * Parse queue field for RSS action.
3337  *
3338  * Valid tokens are queue indices and the "end" token.
3339  */
3340 static int
3341 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
3342                           const char *str, unsigned int len,
3343                           void *buf, unsigned int size)
3344 {
3345         static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
3346         struct action_rss_data *action_rss_data;
3347         int ret;
3348         int i;
3349
3350         (void)token;
3351         (void)buf;
3352         (void)size;
3353         if (ctx->curr != ACTION_RSS_QUEUE)
3354                 return -1;
3355         i = ctx->objdata >> 16;
3356         if (!strcmp_partial("end", str, len)) {
3357                 ctx->objdata &= 0xffff;
3358                 goto end;
3359         }
3360         if (i >= ACTION_RSS_QUEUE_NUM)
3361                 return -1;
3362         if (push_args(ctx,
3363                       ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
3364                                      i * sizeof(action_rss_data->queue[i]),
3365                                      sizeof(action_rss_data->queue[i]))))
3366                 return -1;
3367         ret = parse_int(ctx, token, str, len, NULL, 0);
3368         if (ret < 0) {
3369                 pop_args(ctx);
3370                 return -1;
3371         }
3372         ++i;
3373         ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
3374         /* Repeat token. */
3375         if (ctx->next_num == RTE_DIM(ctx->next))
3376                 return -1;
3377         ctx->next[ctx->next_num++] = next;
3378 end:
3379         if (!ctx->object)
3380                 return len;
3381         action_rss_data = ctx->object;
3382         action_rss_data->conf.queue_num = i;
3383         action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
3384         return len;
3385 }
3386
3387 /** Parse VXLAN encap action. */
3388 static int
3389 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
3390                             const char *str, unsigned int len,
3391                             void *buf, unsigned int size)
3392 {
3393         struct buffer *out = buf;
3394         struct rte_flow_action *action;
3395         struct action_vxlan_encap_data *action_vxlan_encap_data;
3396         int ret;
3397
3398         ret = parse_vc(ctx, token, str, len, buf, size);
3399         if (ret < 0)
3400                 return ret;
3401         /* Nothing else to do if there is no buffer. */
3402         if (!out)
3403                 return ret;
3404         if (!out->args.vc.actions_n)
3405                 return -1;
3406         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3407         /* Point to selected object. */
3408         ctx->object = out->args.vc.data;
3409         ctx->objmask = NULL;
3410         /* Set up default configuration. */
3411         action_vxlan_encap_data = ctx->object;
3412         *action_vxlan_encap_data = (struct action_vxlan_encap_data){
3413                 .conf = (struct rte_flow_action_vxlan_encap){
3414                         .definition = action_vxlan_encap_data->items,
3415                 },
3416                 .items = {
3417                         {
3418                                 .type = RTE_FLOW_ITEM_TYPE_ETH,
3419                                 .spec = &action_vxlan_encap_data->item_eth,
3420                                 .mask = &rte_flow_item_eth_mask,
3421                         },
3422                         {
3423                                 .type = RTE_FLOW_ITEM_TYPE_VLAN,
3424                                 .spec = &action_vxlan_encap_data->item_vlan,
3425                                 .mask = &rte_flow_item_vlan_mask,
3426                         },
3427                         {
3428                                 .type = RTE_FLOW_ITEM_TYPE_IPV4,
3429                                 .spec = &action_vxlan_encap_data->item_ipv4,
3430                                 .mask = &rte_flow_item_ipv4_mask,
3431                         },
3432                         {
3433                                 .type = RTE_FLOW_ITEM_TYPE_UDP,
3434                                 .spec = &action_vxlan_encap_data->item_udp,
3435                                 .mask = &rte_flow_item_udp_mask,
3436                         },
3437                         {
3438                                 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
3439                                 .spec = &action_vxlan_encap_data->item_vxlan,
3440                                 .mask = &rte_flow_item_vxlan_mask,
3441                         },
3442                         {
3443                                 .type = RTE_FLOW_ITEM_TYPE_END,
3444                         },
3445                 },
3446                 .item_eth.type = 0,
3447                 .item_vlan = {
3448                         .tci = vxlan_encap_conf.vlan_tci,
3449                         .inner_type = 0,
3450                 },
3451                 .item_ipv4.hdr = {
3452                         .src_addr = vxlan_encap_conf.ipv4_src,
3453                         .dst_addr = vxlan_encap_conf.ipv4_dst,
3454                 },
3455                 .item_udp.hdr = {
3456                         .src_port = vxlan_encap_conf.udp_src,
3457                         .dst_port = vxlan_encap_conf.udp_dst,
3458                 },
3459                 .item_vxlan.flags = 0,
3460         };
3461         memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes,
3462                vxlan_encap_conf.eth_dst, ETHER_ADDR_LEN);
3463         memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
3464                vxlan_encap_conf.eth_src, ETHER_ADDR_LEN);
3465         if (!vxlan_encap_conf.select_ipv4) {
3466                 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
3467                        &vxlan_encap_conf.ipv6_src,
3468                        sizeof(vxlan_encap_conf.ipv6_src));
3469                 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
3470                        &vxlan_encap_conf.ipv6_dst,
3471                        sizeof(vxlan_encap_conf.ipv6_dst));
3472                 action_vxlan_encap_data->items[2] = (struct rte_flow_item){
3473                         .type = RTE_FLOW_ITEM_TYPE_IPV6,
3474                         .spec = &action_vxlan_encap_data->item_ipv6,
3475                         .mask = &rte_flow_item_ipv6_mask,
3476                 };
3477         }
3478         if (!vxlan_encap_conf.select_vlan)
3479                 action_vxlan_encap_data->items[1].type =
3480                         RTE_FLOW_ITEM_TYPE_VOID;
3481         memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
3482                RTE_DIM(vxlan_encap_conf.vni));
3483         action->conf = &action_vxlan_encap_data->conf;
3484         return ret;
3485 }
3486
3487 /** Parse NVGRE encap action. */
3488 static int
3489 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
3490                             const char *str, unsigned int len,
3491                             void *buf, unsigned int size)
3492 {
3493         struct buffer *out = buf;
3494         struct rte_flow_action *action;
3495         struct action_nvgre_encap_data *action_nvgre_encap_data;
3496         int ret;
3497
3498         ret = parse_vc(ctx, token, str, len, buf, size);
3499         if (ret < 0)
3500                 return ret;
3501         /* Nothing else to do if there is no buffer. */
3502         if (!out)
3503                 return ret;
3504         if (!out->args.vc.actions_n)
3505                 return -1;
3506         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3507         /* Point to selected object. */
3508         ctx->object = out->args.vc.data;
3509         ctx->objmask = NULL;
3510         /* Set up default configuration. */
3511         action_nvgre_encap_data = ctx->object;
3512         *action_nvgre_encap_data = (struct action_nvgre_encap_data){
3513                 .conf = (struct rte_flow_action_nvgre_encap){
3514                         .definition = action_nvgre_encap_data->items,
3515                 },
3516                 .items = {
3517                         {
3518                                 .type = RTE_FLOW_ITEM_TYPE_ETH,
3519                                 .spec = &action_nvgre_encap_data->item_eth,
3520                                 .mask = &rte_flow_item_eth_mask,
3521                         },
3522                         {
3523                                 .type = RTE_FLOW_ITEM_TYPE_VLAN,
3524                                 .spec = &action_nvgre_encap_data->item_vlan,
3525                                 .mask = &rte_flow_item_vlan_mask,
3526                         },
3527                         {
3528                                 .type = RTE_FLOW_ITEM_TYPE_IPV4,
3529                                 .spec = &action_nvgre_encap_data->item_ipv4,
3530                                 .mask = &rte_flow_item_ipv4_mask,
3531                         },
3532                         {
3533                                 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
3534                                 .spec = &action_nvgre_encap_data->item_nvgre,
3535                                 .mask = &rte_flow_item_nvgre_mask,
3536                         },
3537                         {
3538                                 .type = RTE_FLOW_ITEM_TYPE_END,
3539                         },
3540                 },
3541                 .item_eth.type = 0,
3542                 .item_vlan = {
3543                         .tci = nvgre_encap_conf.vlan_tci,
3544                         .inner_type = 0,
3545                 },
3546                 .item_ipv4.hdr = {
3547                        .src_addr = nvgre_encap_conf.ipv4_src,
3548                        .dst_addr = nvgre_encap_conf.ipv4_dst,
3549                 },
3550                 .item_nvgre.flow_id = 0,
3551         };
3552         memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
3553                nvgre_encap_conf.eth_dst, ETHER_ADDR_LEN);
3554         memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
3555                nvgre_encap_conf.eth_src, ETHER_ADDR_LEN);
3556         if (!nvgre_encap_conf.select_ipv4) {
3557                 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
3558                        &nvgre_encap_conf.ipv6_src,
3559                        sizeof(nvgre_encap_conf.ipv6_src));
3560                 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
3561                        &nvgre_encap_conf.ipv6_dst,
3562                        sizeof(nvgre_encap_conf.ipv6_dst));
3563                 action_nvgre_encap_data->items[2] = (struct rte_flow_item){
3564                         .type = RTE_FLOW_ITEM_TYPE_IPV6,
3565                         .spec = &action_nvgre_encap_data->item_ipv6,
3566                         .mask = &rte_flow_item_ipv6_mask,
3567                 };
3568         }
3569         if (!nvgre_encap_conf.select_vlan)
3570                 action_nvgre_encap_data->items[1].type =
3571                         RTE_FLOW_ITEM_TYPE_VOID;
3572         memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
3573                RTE_DIM(nvgre_encap_conf.tni));
3574         action->conf = &action_nvgre_encap_data->conf;
3575         return ret;
3576 }
3577
3578 /** Parse l2 encap action. */
3579 static int
3580 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
3581                          const char *str, unsigned int len,
3582                          void *buf, unsigned int size)
3583 {
3584         struct buffer *out = buf;
3585         struct rte_flow_action *action;
3586         struct action_raw_encap_data *action_encap_data;
3587         struct rte_flow_item_eth eth = { .type = 0, };
3588         struct rte_flow_item_vlan vlan = {
3589                 .tci = mplsoudp_encap_conf.vlan_tci,
3590                 .inner_type = 0,
3591         };
3592         uint8_t *header;
3593         int ret;
3594
3595         ret = parse_vc(ctx, token, str, len, buf, size);
3596         if (ret < 0)
3597                 return ret;
3598         /* Nothing else to do if there is no buffer. */
3599         if (!out)
3600                 return ret;
3601         if (!out->args.vc.actions_n)
3602                 return -1;
3603         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3604         /* Point to selected object. */
3605         ctx->object = out->args.vc.data;
3606         ctx->objmask = NULL;
3607         /* Copy the headers to the buffer. */
3608         action_encap_data = ctx->object;
3609         *action_encap_data = (struct action_raw_encap_data) {
3610                 .conf = (struct rte_flow_action_raw_encap){
3611                         .data = action_encap_data->data,
3612                 },
3613                 .data = {},
3614         };
3615         header = action_encap_data->data;
3616         if (l2_encap_conf.select_vlan)
3617                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
3618         else if (l2_encap_conf.select_ipv4)
3619                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3620         else
3621                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3622         memcpy(eth.dst.addr_bytes,
3623                l2_encap_conf.eth_dst, ETHER_ADDR_LEN);
3624         memcpy(eth.src.addr_bytes,
3625                l2_encap_conf.eth_src, ETHER_ADDR_LEN);
3626         memcpy(header, &eth, sizeof(eth));
3627         header += sizeof(eth);
3628         if (l2_encap_conf.select_vlan) {
3629                 if (l2_encap_conf.select_ipv4)
3630                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3631                 else
3632                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3633                 memcpy(header, &vlan, sizeof(vlan));
3634                 header += sizeof(vlan);
3635         }
3636         action_encap_data->conf.size = header -
3637                 action_encap_data->data;
3638         action->conf = &action_encap_data->conf;
3639         return ret;
3640 }
3641
3642 /** Parse l2 decap action. */
3643 static int
3644 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
3645                          const char *str, unsigned int len,
3646                          void *buf, unsigned int size)
3647 {
3648         struct buffer *out = buf;
3649         struct rte_flow_action *action;
3650         struct action_raw_decap_data *action_decap_data;
3651         struct rte_flow_item_eth eth = { .type = 0, };
3652         struct rte_flow_item_vlan vlan = {
3653                 .tci = mplsoudp_encap_conf.vlan_tci,
3654                 .inner_type = 0,
3655         };
3656         uint8_t *header;
3657         int ret;
3658
3659         ret = parse_vc(ctx, token, str, len, buf, size);
3660         if (ret < 0)
3661                 return ret;
3662         /* Nothing else to do if there is no buffer. */
3663         if (!out)
3664                 return ret;
3665         if (!out->args.vc.actions_n)
3666                 return -1;
3667         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3668         /* Point to selected object. */
3669         ctx->object = out->args.vc.data;
3670         ctx->objmask = NULL;
3671         /* Copy the headers to the buffer. */
3672         action_decap_data = ctx->object;
3673         *action_decap_data = (struct action_raw_decap_data) {
3674                 .conf = (struct rte_flow_action_raw_decap){
3675                         .data = action_decap_data->data,
3676                 },
3677                 .data = {},
3678         };
3679         header = action_decap_data->data;
3680         if (l2_decap_conf.select_vlan)
3681                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
3682         memcpy(header, &eth, sizeof(eth));
3683         header += sizeof(eth);
3684         if (l2_decap_conf.select_vlan) {
3685                 memcpy(header, &vlan, sizeof(vlan));
3686                 header += sizeof(vlan);
3687         }
3688         action_decap_data->conf.size = header -
3689                 action_decap_data->data;
3690         action->conf = &action_decap_data->conf;
3691         return ret;
3692 }
3693
3694 /** Parse MPLSOUDP encap action. */
3695 static int
3696 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
3697                                const char *str, unsigned int len,
3698                                void *buf, unsigned int size)
3699 {
3700         struct buffer *out = buf;
3701         struct rte_flow_action *action;
3702         struct action_raw_encap_data *action_encap_data;
3703         struct rte_flow_item_eth eth = { .type = 0, };
3704         struct rte_flow_item_vlan vlan = {
3705                 .tci = mplsoudp_encap_conf.vlan_tci,
3706                 .inner_type = 0,
3707         };
3708         struct rte_flow_item_ipv4 ipv4 = {
3709                 .hdr =  {
3710                         .src_addr = mplsoudp_encap_conf.ipv4_src,
3711                         .dst_addr = mplsoudp_encap_conf.ipv4_dst,
3712                         .next_proto_id = IPPROTO_UDP,
3713                 },
3714         };
3715         struct rte_flow_item_ipv6 ipv6 = {
3716                 .hdr =  {
3717                         .proto = IPPROTO_UDP,
3718                 },
3719         };
3720         struct rte_flow_item_udp udp = {
3721                 .hdr = {
3722                         .src_port = mplsoudp_encap_conf.udp_src,
3723                         .dst_port = mplsoudp_encap_conf.udp_dst,
3724                 },
3725         };
3726         struct rte_flow_item_mpls mpls;
3727         uint8_t *header;
3728         int ret;
3729
3730         ret = parse_vc(ctx, token, str, len, buf, size);
3731         if (ret < 0)
3732                 return ret;
3733         /* Nothing else to do if there is no buffer. */
3734         if (!out)
3735                 return ret;
3736         if (!out->args.vc.actions_n)
3737                 return -1;
3738         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3739         /* Point to selected object. */
3740         ctx->object = out->args.vc.data;
3741         ctx->objmask = NULL;
3742         /* Copy the headers to the buffer. */
3743         action_encap_data = ctx->object;
3744         *action_encap_data = (struct action_raw_encap_data) {
3745                 .conf = (struct rte_flow_action_raw_encap){
3746                         .data = action_encap_data->data,
3747                 },
3748                 .data = {},
3749                 .preserve = {},
3750         };
3751         header = action_encap_data->data;
3752         if (mplsoudp_encap_conf.select_vlan)
3753                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
3754         else if (mplsoudp_encap_conf.select_ipv4)
3755                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3756         else
3757                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3758         memcpy(eth.dst.addr_bytes,
3759                mplsoudp_encap_conf.eth_dst, ETHER_ADDR_LEN);
3760         memcpy(eth.src.addr_bytes,
3761                mplsoudp_encap_conf.eth_src, ETHER_ADDR_LEN);
3762         memcpy(header, &eth, sizeof(eth));
3763         header += sizeof(eth);
3764         if (mplsoudp_encap_conf.select_vlan) {
3765                 if (mplsoudp_encap_conf.select_ipv4)
3766                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3767                 else
3768                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3769                 memcpy(header, &vlan, sizeof(vlan));
3770                 header += sizeof(vlan);
3771         }
3772         if (mplsoudp_encap_conf.select_ipv4) {
3773                 memcpy(header, &ipv4, sizeof(ipv4));
3774                 header += sizeof(ipv4);
3775         } else {
3776                 memcpy(&ipv6.hdr.src_addr,
3777                        &mplsoudp_encap_conf.ipv6_src,
3778                        sizeof(mplsoudp_encap_conf.ipv6_src));
3779                 memcpy(&ipv6.hdr.dst_addr,
3780                        &mplsoudp_encap_conf.ipv6_dst,
3781                        sizeof(mplsoudp_encap_conf.ipv6_dst));
3782                 memcpy(header, &ipv6, sizeof(ipv6));
3783                 header += sizeof(ipv6);
3784         }
3785         memcpy(header, &udp, sizeof(udp));
3786         header += sizeof(udp);
3787         memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
3788                RTE_DIM(mplsoudp_encap_conf.label));
3789         memcpy(header, &mpls, sizeof(mpls));
3790         header += sizeof(mpls);
3791         action_encap_data->conf.size = header -
3792                 action_encap_data->data;
3793         action->conf = &action_encap_data->conf;
3794         return ret;
3795 }
3796
3797 /** Parse MPLSOUDP decap action. */
3798 static int
3799 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
3800                                const char *str, unsigned int len,
3801                                void *buf, unsigned int size)
3802 {
3803         struct buffer *out = buf;
3804         struct rte_flow_action *action;
3805         struct action_raw_decap_data *action_decap_data;
3806         struct rte_flow_item_eth eth = { .type = 0, };
3807         struct rte_flow_item_vlan vlan = {.tci = 0};
3808         struct rte_flow_item_ipv4 ipv4 = {
3809                 .hdr =  {
3810                         .next_proto_id = IPPROTO_UDP,
3811                 },
3812         };
3813         struct rte_flow_item_ipv6 ipv6 = {
3814                 .hdr =  {
3815                         .proto = IPPROTO_UDP,
3816                 },
3817         };
3818         struct rte_flow_item_udp udp = {
3819                 .hdr = {
3820                         .dst_port = rte_cpu_to_be_16(6635),
3821                 },
3822         };
3823         struct rte_flow_item_mpls mpls;
3824         uint8_t *header;
3825         int ret;
3826
3827         ret = parse_vc(ctx, token, str, len, buf, size);
3828         if (ret < 0)
3829                 return ret;
3830         /* Nothing else to do if there is no buffer. */
3831         if (!out)
3832                 return ret;
3833         if (!out->args.vc.actions_n)
3834                 return -1;
3835         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3836         /* Point to selected object. */
3837         ctx->object = out->args.vc.data;
3838         ctx->objmask = NULL;
3839         /* Copy the headers to the buffer. */
3840         action_decap_data = ctx->object;
3841         *action_decap_data = (struct action_raw_decap_data) {
3842                 .conf = (struct rte_flow_action_raw_decap){
3843                         .data = action_decap_data->data,
3844                 },
3845                 .data = {},
3846         };
3847         header = action_decap_data->data;
3848         if (mplsoudp_decap_conf.select_vlan)
3849                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
3850         else if (mplsoudp_encap_conf.select_ipv4)
3851                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3852         else
3853                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3854         memcpy(eth.dst.addr_bytes,
3855                mplsoudp_encap_conf.eth_dst, ETHER_ADDR_LEN);
3856         memcpy(eth.src.addr_bytes,
3857                mplsoudp_encap_conf.eth_src, ETHER_ADDR_LEN);
3858         memcpy(header, &eth, sizeof(eth));
3859         header += sizeof(eth);
3860         if (mplsoudp_encap_conf.select_vlan) {
3861                 if (mplsoudp_encap_conf.select_ipv4)
3862                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3863                 else
3864                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3865                 memcpy(header, &vlan, sizeof(vlan));
3866                 header += sizeof(vlan);
3867         }
3868         if (mplsoudp_encap_conf.select_ipv4) {
3869                 memcpy(header, &ipv4, sizeof(ipv4));
3870                 header += sizeof(ipv4);
3871         } else {
3872                 memcpy(header, &ipv6, sizeof(ipv6));
3873                 header += sizeof(ipv6);
3874         }
3875         memcpy(header, &udp, sizeof(udp));
3876         header += sizeof(udp);
3877         memset(&mpls, 0, sizeof(mpls));
3878         memcpy(header, &mpls, sizeof(mpls));
3879         header += sizeof(mpls);
3880         action_decap_data->conf.size = header -
3881                 action_decap_data->data;
3882         action->conf = &action_decap_data->conf;
3883         return ret;
3884 }
3885
3886 /** Parse tokens for destroy command. */
3887 static int
3888 parse_destroy(struct context *ctx, const struct token *token,
3889               const char *str, unsigned int len,
3890               void *buf, unsigned int size)
3891 {
3892         struct buffer *out = buf;
3893
3894         /* Token name must match. */
3895         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3896                 return -1;
3897         /* Nothing else to do if there is no buffer. */
3898         if (!out)
3899                 return len;
3900         if (!out->command) {
3901                 if (ctx->curr != DESTROY)
3902                         return -1;
3903                 if (sizeof(*out) > size)
3904                         return -1;
3905                 out->command = ctx->curr;
3906                 ctx->objdata = 0;
3907                 ctx->object = out;
3908                 ctx->objmask = NULL;
3909                 out->args.destroy.rule =
3910                         (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
3911                                                sizeof(double));
3912                 return len;
3913         }
3914         if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
3915              sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
3916                 return -1;
3917         ctx->objdata = 0;
3918         ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
3919         ctx->objmask = NULL;
3920         return len;
3921 }
3922
3923 /** Parse tokens for flush command. */
3924 static int
3925 parse_flush(struct context *ctx, const struct token *token,
3926             const char *str, unsigned int len,
3927             void *buf, unsigned int size)
3928 {
3929         struct buffer *out = buf;
3930
3931         /* Token name must match. */
3932         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3933                 return -1;
3934         /* Nothing else to do if there is no buffer. */
3935         if (!out)
3936                 return len;
3937         if (!out->command) {
3938                 if (ctx->curr != FLUSH)
3939                         return -1;
3940                 if (sizeof(*out) > size)
3941                         return -1;
3942                 out->command = ctx->curr;
3943                 ctx->objdata = 0;
3944                 ctx->object = out;
3945                 ctx->objmask = NULL;
3946         }
3947         return len;
3948 }
3949
3950 /** Parse tokens for query command. */
3951 static int
3952 parse_query(struct context *ctx, const struct token *token,
3953             const char *str, unsigned int len,
3954             void *buf, unsigned int size)
3955 {
3956         struct buffer *out = buf;
3957
3958         /* Token name must match. */
3959         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3960                 return -1;
3961         /* Nothing else to do if there is no buffer. */
3962         if (!out)
3963                 return len;
3964         if (!out->command) {
3965                 if (ctx->curr != QUERY)
3966                         return -1;
3967                 if (sizeof(*out) > size)
3968                         return -1;
3969                 out->command = ctx->curr;
3970                 ctx->objdata = 0;
3971                 ctx->object = out;
3972                 ctx->objmask = NULL;
3973         }
3974         return len;
3975 }
3976
3977 /** Parse action names. */
3978 static int
3979 parse_action(struct context *ctx, const struct token *token,
3980              const char *str, unsigned int len,
3981              void *buf, unsigned int size)
3982 {
3983         struct buffer *out = buf;
3984         const struct arg *arg = pop_args(ctx);
3985         unsigned int i;
3986
3987         (void)size;
3988         /* Argument is expected. */
3989         if (!arg)
3990                 return -1;
3991         /* Parse action name. */
3992         for (i = 0; next_action[i]; ++i) {
3993                 const struct parse_action_priv *priv;
3994
3995                 token = &token_list[next_action[i]];
3996                 if (strcmp_partial(token->name, str, len))
3997                         continue;
3998                 priv = token->priv;
3999                 if (!priv)
4000                         goto error;
4001                 if (out)
4002                         memcpy((uint8_t *)ctx->object + arg->offset,
4003                                &priv->type,
4004                                arg->size);
4005                 return len;
4006         }
4007 error:
4008         push_args(ctx, arg);
4009         return -1;
4010 }
4011
4012 /** Parse tokens for list command. */
4013 static int
4014 parse_list(struct context *ctx, const struct token *token,
4015            const char *str, unsigned int len,
4016            void *buf, unsigned int size)
4017 {
4018         struct buffer *out = buf;
4019
4020         /* Token name must match. */
4021         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4022                 return -1;
4023         /* Nothing else to do if there is no buffer. */
4024         if (!out)
4025                 return len;
4026         if (!out->command) {
4027                 if (ctx->curr != LIST)
4028                         return -1;
4029                 if (sizeof(*out) > size)
4030                         return -1;
4031                 out->command = ctx->curr;
4032                 ctx->objdata = 0;
4033                 ctx->object = out;
4034                 ctx->objmask = NULL;
4035                 out->args.list.group =
4036                         (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
4037                                                sizeof(double));
4038                 return len;
4039         }
4040         if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
4041              sizeof(*out->args.list.group)) > (uint8_t *)out + size)
4042                 return -1;
4043         ctx->objdata = 0;
4044         ctx->object = out->args.list.group + out->args.list.group_n++;
4045         ctx->objmask = NULL;
4046         return len;
4047 }
4048
4049 /** Parse tokens for isolate command. */
4050 static int
4051 parse_isolate(struct context *ctx, const struct token *token,
4052               const char *str, unsigned int len,
4053               void *buf, unsigned int size)
4054 {
4055         struct buffer *out = buf;
4056
4057         /* Token name must match. */
4058         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4059                 return -1;
4060         /* Nothing else to do if there is no buffer. */
4061         if (!out)
4062                 return len;
4063         if (!out->command) {
4064                 if (ctx->curr != ISOLATE)
4065                         return -1;
4066                 if (sizeof(*out) > size)
4067                         return -1;
4068                 out->command = ctx->curr;
4069                 ctx->objdata = 0;
4070                 ctx->object = out;
4071                 ctx->objmask = NULL;
4072         }
4073         return len;
4074 }
4075
4076 /**
4077  * Parse signed/unsigned integers 8 to 64-bit long.
4078  *
4079  * Last argument (ctx->args) is retrieved to determine integer type and
4080  * storage location.
4081  */
4082 static int
4083 parse_int(struct context *ctx, const struct token *token,
4084           const char *str, unsigned int len,
4085           void *buf, unsigned int size)
4086 {
4087         const struct arg *arg = pop_args(ctx);
4088         uintmax_t u;
4089         char *end;
4090
4091         (void)token;
4092         /* Argument is expected. */
4093         if (!arg)
4094                 return -1;
4095         errno = 0;
4096         u = arg->sign ?
4097                 (uintmax_t)strtoimax(str, &end, 0) :
4098                 strtoumax(str, &end, 0);
4099         if (errno || (size_t)(end - str) != len)
4100                 goto error;
4101         if (arg->bounded &&
4102             ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
4103                             (intmax_t)u > (intmax_t)arg->max)) ||
4104              (!arg->sign && (u < arg->min || u > arg->max))))
4105                 goto error;
4106         if (!ctx->object)
4107                 return len;
4108         if (arg->mask) {
4109                 if (!arg_entry_bf_fill(ctx->object, u, arg) ||
4110                     !arg_entry_bf_fill(ctx->objmask, -1, arg))
4111                         goto error;
4112                 return len;
4113         }
4114         buf = (uint8_t *)ctx->object + arg->offset;
4115         size = arg->size;
4116 objmask:
4117         switch (size) {
4118         case sizeof(uint8_t):
4119                 *(uint8_t *)buf = u;
4120                 break;
4121         case sizeof(uint16_t):
4122                 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
4123                 break;
4124         case sizeof(uint8_t [3]):
4125 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4126                 if (!arg->hton) {
4127                         ((uint8_t *)buf)[0] = u;
4128                         ((uint8_t *)buf)[1] = u >> 8;
4129                         ((uint8_t *)buf)[2] = u >> 16;
4130                         break;
4131                 }
4132 #endif
4133                 ((uint8_t *)buf)[0] = u >> 16;
4134                 ((uint8_t *)buf)[1] = u >> 8;
4135                 ((uint8_t *)buf)[2] = u;
4136                 break;
4137         case sizeof(uint32_t):
4138                 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
4139                 break;
4140         case sizeof(uint64_t):
4141                 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
4142                 break;
4143         default:
4144                 goto error;
4145         }
4146         if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
4147                 u = -1;
4148                 buf = (uint8_t *)ctx->objmask + arg->offset;
4149                 goto objmask;
4150         }
4151         return len;
4152 error:
4153         push_args(ctx, arg);
4154         return -1;
4155 }
4156
4157 /**
4158  * Parse a string.
4159  *
4160  * Three arguments (ctx->args) are retrieved from the stack to store data,
4161  * its actual length and address (in that order).
4162  */
4163 static int
4164 parse_string(struct context *ctx, const struct token *token,
4165              const char *str, unsigned int len,
4166              void *buf, unsigned int size)
4167 {
4168         const struct arg *arg_data = pop_args(ctx);
4169         const struct arg *arg_len = pop_args(ctx);
4170         const struct arg *arg_addr = pop_args(ctx);
4171         char tmp[16]; /* Ought to be enough. */
4172         int ret;
4173
4174         /* Arguments are expected. */
4175         if (!arg_data)
4176                 return -1;
4177         if (!arg_len) {
4178                 push_args(ctx, arg_data);
4179                 return -1;
4180         }
4181         if (!arg_addr) {
4182                 push_args(ctx, arg_len);
4183                 push_args(ctx, arg_data);
4184                 return -1;
4185         }
4186         size = arg_data->size;
4187         /* Bit-mask fill is not supported. */
4188         if (arg_data->mask || size < len)
4189                 goto error;
4190         if (!ctx->object)
4191                 return len;
4192         /* Let parse_int() fill length information first. */
4193         ret = snprintf(tmp, sizeof(tmp), "%u", len);
4194         if (ret < 0)
4195                 goto error;
4196         push_args(ctx, arg_len);
4197         ret = parse_int(ctx, token, tmp, ret, NULL, 0);
4198         if (ret < 0) {
4199                 pop_args(ctx);
4200                 goto error;
4201         }
4202         buf = (uint8_t *)ctx->object + arg_data->offset;
4203         /* Output buffer is not necessarily NUL-terminated. */
4204         memcpy(buf, str, len);
4205         memset((uint8_t *)buf + len, 0x00, size - len);
4206         if (ctx->objmask)
4207                 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
4208         /* Save address if requested. */
4209         if (arg_addr->size) {
4210                 memcpy((uint8_t *)ctx->object + arg_addr->offset,
4211                        (void *[]){
4212                         (uint8_t *)ctx->object + arg_data->offset
4213                        },
4214                        arg_addr->size);
4215                 if (ctx->objmask)
4216                         memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
4217                                (void *[]){
4218                                 (uint8_t *)ctx->objmask + arg_data->offset
4219                                },
4220                                arg_addr->size);
4221         }
4222         return len;
4223 error:
4224         push_args(ctx, arg_addr);
4225         push_args(ctx, arg_len);
4226         push_args(ctx, arg_data);
4227         return -1;
4228 }
4229
4230 /**
4231  * Parse a MAC address.
4232  *
4233  * Last argument (ctx->args) is retrieved to determine storage size and
4234  * location.
4235  */
4236 static int
4237 parse_mac_addr(struct context *ctx, const struct token *token,
4238                const char *str, unsigned int len,
4239                void *buf, unsigned int size)
4240 {
4241         const struct arg *arg = pop_args(ctx);
4242         struct ether_addr tmp;
4243         int ret;
4244
4245         (void)token;
4246         /* Argument is expected. */
4247         if (!arg)
4248                 return -1;
4249         size = arg->size;
4250         /* Bit-mask fill is not supported. */
4251         if (arg->mask || size != sizeof(tmp))
4252                 goto error;
4253         /* Only network endian is supported. */
4254         if (!arg->hton)
4255                 goto error;
4256         ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
4257         if (ret < 0 || (unsigned int)ret != len)
4258                 goto error;
4259         if (!ctx->object)
4260                 return len;
4261         buf = (uint8_t *)ctx->object + arg->offset;
4262         memcpy(buf, &tmp, size);
4263         if (ctx->objmask)
4264                 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
4265         return len;
4266 error:
4267         push_args(ctx, arg);
4268         return -1;
4269 }
4270
4271 /**
4272  * Parse an IPv4 address.
4273  *
4274  * Last argument (ctx->args) is retrieved to determine storage size and
4275  * location.
4276  */
4277 static int
4278 parse_ipv4_addr(struct context *ctx, const struct token *token,
4279                 const char *str, unsigned int len,
4280                 void *buf, unsigned int size)
4281 {
4282         const struct arg *arg = pop_args(ctx);
4283         char str2[len + 1];
4284         struct in_addr tmp;
4285         int ret;
4286
4287         /* Argument is expected. */
4288         if (!arg)
4289                 return -1;
4290         size = arg->size;
4291         /* Bit-mask fill is not supported. */
4292         if (arg->mask || size != sizeof(tmp))
4293                 goto error;
4294         /* Only network endian is supported. */
4295         if (!arg->hton)
4296                 goto error;
4297         memcpy(str2, str, len);
4298         str2[len] = '\0';
4299         ret = inet_pton(AF_INET, str2, &tmp);
4300         if (ret != 1) {
4301                 /* Attempt integer parsing. */
4302                 push_args(ctx, arg);
4303                 return parse_int(ctx, token, str, len, buf, size);
4304         }
4305         if (!ctx->object)
4306                 return len;
4307         buf = (uint8_t *)ctx->object + arg->offset;
4308         memcpy(buf, &tmp, size);
4309         if (ctx->objmask)
4310                 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
4311         return len;
4312 error:
4313         push_args(ctx, arg);
4314         return -1;
4315 }
4316
4317 /**
4318  * Parse an IPv6 address.
4319  *
4320  * Last argument (ctx->args) is retrieved to determine storage size and
4321  * location.
4322  */
4323 static int
4324 parse_ipv6_addr(struct context *ctx, const struct token *token,
4325                 const char *str, unsigned int len,
4326                 void *buf, unsigned int size)
4327 {
4328         const struct arg *arg = pop_args(ctx);
4329         char str2[len + 1];
4330         struct in6_addr tmp;
4331         int ret;
4332
4333         (void)token;
4334         /* Argument is expected. */
4335         if (!arg)
4336                 return -1;
4337         size = arg->size;
4338         /* Bit-mask fill is not supported. */
4339         if (arg->mask || size != sizeof(tmp))
4340                 goto error;
4341         /* Only network endian is supported. */
4342         if (!arg->hton)
4343                 goto error;
4344         memcpy(str2, str, len);
4345         str2[len] = '\0';
4346         ret = inet_pton(AF_INET6, str2, &tmp);
4347         if (ret != 1)
4348                 goto error;
4349         if (!ctx->object)
4350                 return len;
4351         buf = (uint8_t *)ctx->object + arg->offset;
4352         memcpy(buf, &tmp, size);
4353         if (ctx->objmask)
4354                 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
4355         return len;
4356 error:
4357         push_args(ctx, arg);
4358         return -1;
4359 }
4360
4361 /** Boolean values (even indices stand for false). */
4362 static const char *const boolean_name[] = {
4363         "0", "1",
4364         "false", "true",
4365         "no", "yes",
4366         "N", "Y",
4367         "off", "on",
4368         NULL,
4369 };
4370
4371 /**
4372  * Parse a boolean value.
4373  *
4374  * Last argument (ctx->args) is retrieved to determine storage size and
4375  * location.
4376  */
4377 static int
4378 parse_boolean(struct context *ctx, const struct token *token,
4379               const char *str, unsigned int len,
4380               void *buf, unsigned int size)
4381 {
4382         const struct arg *arg = pop_args(ctx);
4383         unsigned int i;
4384         int ret;
4385
4386         /* Argument is expected. */
4387         if (!arg)
4388                 return -1;
4389         for (i = 0; boolean_name[i]; ++i)
4390                 if (!strcmp_partial(boolean_name[i], str, len))
4391                         break;
4392         /* Process token as integer. */
4393         if (boolean_name[i])
4394                 str = i & 1 ? "1" : "0";
4395         push_args(ctx, arg);
4396         ret = parse_int(ctx, token, str, strlen(str), buf, size);
4397         return ret > 0 ? (int)len : ret;
4398 }
4399
4400 /** Parse port and update context. */
4401 static int
4402 parse_port(struct context *ctx, const struct token *token,
4403            const char *str, unsigned int len,
4404            void *buf, unsigned int size)
4405 {
4406         struct buffer *out = &(struct buffer){ .port = 0 };
4407         int ret;
4408
4409         if (buf)
4410                 out = buf;
4411         else {
4412                 ctx->objdata = 0;
4413                 ctx->object = out;
4414                 ctx->objmask = NULL;
4415                 size = sizeof(*out);
4416         }
4417         ret = parse_int(ctx, token, str, len, out, size);
4418         if (ret >= 0)
4419                 ctx->port = out->port;
4420         if (!buf)
4421                 ctx->object = NULL;
4422         return ret;
4423 }
4424
4425 /** No completion. */
4426 static int
4427 comp_none(struct context *ctx, const struct token *token,
4428           unsigned int ent, char *buf, unsigned int size)
4429 {
4430         (void)ctx;
4431         (void)token;
4432         (void)ent;
4433         (void)buf;
4434         (void)size;
4435         return 0;
4436 }
4437
4438 /** Complete boolean values. */
4439 static int
4440 comp_boolean(struct context *ctx, const struct token *token,
4441              unsigned int ent, char *buf, unsigned int size)
4442 {
4443         unsigned int i;
4444
4445         (void)ctx;
4446         (void)token;
4447         for (i = 0; boolean_name[i]; ++i)
4448                 if (buf && i == ent)
4449                         return snprintf(buf, size, "%s", boolean_name[i]);
4450         if (buf)
4451                 return -1;
4452         return i;
4453 }
4454
4455 /** Complete action names. */
4456 static int
4457 comp_action(struct context *ctx, const struct token *token,
4458             unsigned int ent, char *buf, unsigned int size)
4459 {
4460         unsigned int i;
4461
4462         (void)ctx;
4463         (void)token;
4464         for (i = 0; next_action[i]; ++i)
4465                 if (buf && i == ent)
4466                         return snprintf(buf, size, "%s",
4467                                         token_list[next_action[i]].name);
4468         if (buf)
4469                 return -1;
4470         return i;
4471 }
4472
4473 /** Complete available ports. */
4474 static int
4475 comp_port(struct context *ctx, const struct token *token,
4476           unsigned int ent, char *buf, unsigned int size)
4477 {
4478         unsigned int i = 0;
4479         portid_t p;
4480
4481         (void)ctx;
4482         (void)token;
4483         RTE_ETH_FOREACH_DEV(p) {
4484                 if (buf && i == ent)
4485                         return snprintf(buf, size, "%u", p);
4486                 ++i;
4487         }
4488         if (buf)
4489                 return -1;
4490         return i;
4491 }
4492
4493 /** Complete available rule IDs. */
4494 static int
4495 comp_rule_id(struct context *ctx, const struct token *token,
4496              unsigned int ent, char *buf, unsigned int size)
4497 {
4498         unsigned int i = 0;
4499         struct rte_port *port;
4500         struct port_flow *pf;
4501
4502         (void)token;
4503         if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
4504             ctx->port == (portid_t)RTE_PORT_ALL)
4505                 return -1;
4506         port = &ports[ctx->port];
4507         for (pf = port->flow_list; pf != NULL; pf = pf->next) {
4508                 if (buf && i == ent)
4509                         return snprintf(buf, size, "%u", pf->id);
4510                 ++i;
4511         }
4512         if (buf)
4513                 return -1;
4514         return i;
4515 }
4516
4517 /** Complete type field for RSS action. */
4518 static int
4519 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
4520                         unsigned int ent, char *buf, unsigned int size)
4521 {
4522         unsigned int i;
4523
4524         (void)ctx;
4525         (void)token;
4526         for (i = 0; rss_type_table[i].str; ++i)
4527                 ;
4528         if (!buf)
4529                 return i + 1;
4530         if (ent < i)
4531                 return snprintf(buf, size, "%s", rss_type_table[ent].str);
4532         if (ent == i)
4533                 return snprintf(buf, size, "end");
4534         return -1;
4535 }
4536
4537 /** Complete queue field for RSS action. */
4538 static int
4539 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
4540                          unsigned int ent, char *buf, unsigned int size)
4541 {
4542         (void)ctx;
4543         (void)token;
4544         if (!buf)
4545                 return nb_rxq + 1;
4546         if (ent < nb_rxq)
4547                 return snprintf(buf, size, "%u", ent);
4548         if (ent == nb_rxq)
4549                 return snprintf(buf, size, "end");
4550         return -1;
4551 }
4552
4553 /** Internal context. */
4554 static struct context cmd_flow_context;
4555
4556 /** Global parser instance (cmdline API). */
4557 cmdline_parse_inst_t cmd_flow;
4558
4559 /** Initialize context. */
4560 static void
4561 cmd_flow_context_init(struct context *ctx)
4562 {
4563         /* A full memset() is not necessary. */
4564         ctx->curr = ZERO;
4565         ctx->prev = ZERO;
4566         ctx->next_num = 0;
4567         ctx->args_num = 0;
4568         ctx->eol = 0;
4569         ctx->last = 0;
4570         ctx->port = 0;
4571         ctx->objdata = 0;
4572         ctx->object = NULL;
4573         ctx->objmask = NULL;
4574 }
4575
4576 /** Parse a token (cmdline API). */
4577 static int
4578 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
4579                unsigned int size)
4580 {
4581         struct context *ctx = &cmd_flow_context;
4582         const struct token *token;
4583         const enum index *list;
4584         int len;
4585         int i;
4586
4587         (void)hdr;
4588         token = &token_list[ctx->curr];
4589         /* Check argument length. */
4590         ctx->eol = 0;
4591         ctx->last = 1;
4592         for (len = 0; src[len]; ++len)
4593                 if (src[len] == '#' || isspace(src[len]))
4594                         break;
4595         if (!len)
4596                 return -1;
4597         /* Last argument and EOL detection. */
4598         for (i = len; src[i]; ++i)
4599                 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
4600                         break;
4601                 else if (!isspace(src[i])) {
4602                         ctx->last = 0;
4603                         break;
4604                 }
4605         for (; src[i]; ++i)
4606                 if (src[i] == '\r' || src[i] == '\n') {
4607                         ctx->eol = 1;
4608                         break;
4609                 }
4610         /* Initialize context if necessary. */
4611         if (!ctx->next_num) {
4612                 if (!token->next)
4613                         return 0;
4614                 ctx->next[ctx->next_num++] = token->next[0];
4615         }
4616         /* Process argument through candidates. */
4617         ctx->prev = ctx->curr;
4618         list = ctx->next[ctx->next_num - 1];
4619         for (i = 0; list[i]; ++i) {
4620                 const struct token *next = &token_list[list[i]];
4621                 int tmp;
4622
4623                 ctx->curr = list[i];
4624                 if (next->call)
4625                         tmp = next->call(ctx, next, src, len, result, size);
4626                 else
4627                         tmp = parse_default(ctx, next, src, len, result, size);
4628                 if (tmp == -1 || tmp != len)
4629                         continue;
4630                 token = next;
4631                 break;
4632         }
4633         if (!list[i])
4634                 return -1;
4635         --ctx->next_num;
4636         /* Push subsequent tokens if any. */
4637         if (token->next)
4638                 for (i = 0; token->next[i]; ++i) {
4639                         if (ctx->next_num == RTE_DIM(ctx->next))
4640                                 return -1;
4641                         ctx->next[ctx->next_num++] = token->next[i];
4642                 }
4643         /* Push arguments if any. */
4644         if (token->args)
4645                 for (i = 0; token->args[i]; ++i) {
4646                         if (ctx->args_num == RTE_DIM(ctx->args))
4647                                 return -1;
4648                         ctx->args[ctx->args_num++] = token->args[i];
4649                 }
4650         return len;
4651 }
4652
4653 /** Return number of completion entries (cmdline API). */
4654 static int
4655 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
4656 {
4657         struct context *ctx = &cmd_flow_context;
4658         const struct token *token = &token_list[ctx->curr];
4659         const enum index *list;
4660         int i;
4661
4662         (void)hdr;
4663         /* Count number of tokens in current list. */
4664         if (ctx->next_num)
4665                 list = ctx->next[ctx->next_num - 1];
4666         else
4667                 list = token->next[0];
4668         for (i = 0; list[i]; ++i)
4669                 ;
4670         if (!i)
4671                 return 0;
4672         /*
4673          * If there is a single token, use its completion callback, otherwise
4674          * return the number of entries.
4675          */
4676         token = &token_list[list[0]];
4677         if (i == 1 && token->comp) {
4678                 /* Save index for cmd_flow_get_help(). */
4679                 ctx->prev = list[0];
4680                 return token->comp(ctx, token, 0, NULL, 0);
4681         }
4682         return i;
4683 }
4684
4685 /** Return a completion entry (cmdline API). */
4686 static int
4687 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
4688                           char *dst, unsigned int size)
4689 {
4690         struct context *ctx = &cmd_flow_context;
4691         const struct token *token = &token_list[ctx->curr];
4692         const enum index *list;
4693         int i;
4694
4695         (void)hdr;
4696         /* Count number of tokens in current list. */
4697         if (ctx->next_num)
4698                 list = ctx->next[ctx->next_num - 1];
4699         else
4700                 list = token->next[0];
4701         for (i = 0; list[i]; ++i)
4702                 ;
4703         if (!i)
4704                 return -1;
4705         /* If there is a single token, use its completion callback. */
4706         token = &token_list[list[0]];
4707         if (i == 1 && token->comp) {
4708                 /* Save index for cmd_flow_get_help(). */
4709                 ctx->prev = list[0];
4710                 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
4711         }
4712         /* Otherwise make sure the index is valid and use defaults. */
4713         if (index >= i)
4714                 return -1;
4715         token = &token_list[list[index]];
4716         snprintf(dst, size, "%s", token->name);
4717         /* Save index for cmd_flow_get_help(). */
4718         ctx->prev = list[index];
4719         return 0;
4720 }
4721
4722 /** Populate help strings for current token (cmdline API). */
4723 static int
4724 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
4725 {
4726         struct context *ctx = &cmd_flow_context;
4727         const struct token *token = &token_list[ctx->prev];
4728
4729         (void)hdr;
4730         if (!size)
4731                 return -1;
4732         /* Set token type and update global help with details. */
4733         snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
4734         if (token->help)
4735                 cmd_flow.help_str = token->help;
4736         else
4737                 cmd_flow.help_str = token->name;
4738         return 0;
4739 }
4740
4741 /** Token definition template (cmdline API). */
4742 static struct cmdline_token_hdr cmd_flow_token_hdr = {
4743         .ops = &(struct cmdline_token_ops){
4744                 .parse = cmd_flow_parse,
4745                 .complete_get_nb = cmd_flow_complete_get_nb,
4746                 .complete_get_elt = cmd_flow_complete_get_elt,
4747                 .get_help = cmd_flow_get_help,
4748         },
4749         .offset = 0,
4750 };
4751
4752 /** Populate the next dynamic token. */
4753 static void
4754 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
4755              cmdline_parse_token_hdr_t **hdr_inst)
4756 {
4757         struct context *ctx = &cmd_flow_context;
4758
4759         /* Always reinitialize context before requesting the first token. */
4760         if (!(hdr_inst - cmd_flow.tokens))
4761                 cmd_flow_context_init(ctx);
4762         /* Return NULL when no more tokens are expected. */
4763         if (!ctx->next_num && ctx->curr) {
4764                 *hdr = NULL;
4765                 return;
4766         }
4767         /* Determine if command should end here. */
4768         if (ctx->eol && ctx->last && ctx->next_num) {
4769                 const enum index *list = ctx->next[ctx->next_num - 1];
4770                 int i;
4771
4772                 for (i = 0; list[i]; ++i) {
4773                         if (list[i] != END)
4774                                 continue;
4775                         *hdr = NULL;
4776                         return;
4777                 }
4778         }
4779         *hdr = &cmd_flow_token_hdr;
4780 }
4781
4782 /** Dispatch parsed buffer to function calls. */
4783 static void
4784 cmd_flow_parsed(const struct buffer *in)
4785 {
4786         switch (in->command) {
4787         case VALIDATE:
4788                 port_flow_validate(in->port, &in->args.vc.attr,
4789                                    in->args.vc.pattern, in->args.vc.actions);
4790                 break;
4791         case CREATE:
4792                 port_flow_create(in->port, &in->args.vc.attr,
4793                                  in->args.vc.pattern, in->args.vc.actions);
4794                 break;
4795         case DESTROY:
4796                 port_flow_destroy(in->port, in->args.destroy.rule_n,
4797                                   in->args.destroy.rule);
4798                 break;
4799         case FLUSH:
4800                 port_flow_flush(in->port);
4801                 break;
4802         case QUERY:
4803                 port_flow_query(in->port, in->args.query.rule,
4804                                 &in->args.query.action);
4805                 break;
4806         case LIST:
4807                 port_flow_list(in->port, in->args.list.group_n,
4808                                in->args.list.group);
4809                 break;
4810         case ISOLATE:
4811                 port_flow_isolate(in->port, in->args.isolate.set);
4812                 break;
4813         default:
4814                 break;
4815         }
4816 }
4817
4818 /** Token generator and output processing callback (cmdline API). */
4819 static void
4820 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
4821 {
4822         if (cl == NULL)
4823                 cmd_flow_tok(arg0, arg2);
4824         else
4825                 cmd_flow_parsed(arg0);
4826 }
4827
4828 /** Global parser instance (cmdline API). */
4829 cmdline_parse_inst_t cmd_flow = {
4830         .f = cmd_flow_cb,
4831         .data = NULL, /**< Unused. */
4832         .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
4833         .tokens = {
4834                 NULL,
4835         }, /**< Tokens are returned by cmd_flow_tok(). */
4836 };