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