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