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