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