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