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