New upstream version 18.11.2
[deb_dpdk.git] / app / test-pmd / cmdline_flow.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2016 6WIND S.A.
3  * Copyright 2016 Mellanox Technologies, Ltd
4  */
5
6 #include <stddef.h>
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <inttypes.h>
10 #include <errno.h>
11 #include <ctype.h>
12 #include <string.h>
13 #include <arpa/inet.h>
14 #include <sys/socket.h>
15
16 #include <rte_common.h>
17 #include <rte_eth_ctrl.h>
18 #include <rte_ethdev.h>
19 #include <rte_byteorder.h>
20 #include <cmdline_parse.h>
21 #include <cmdline_parse_etheraddr.h>
22 #include <rte_flow.h>
23
24 #include "testpmd.h"
25
26 /** Parser token indices. */
27 enum index {
28         /* Special tokens. */
29         ZERO = 0,
30         END,
31
32         /* Common tokens. */
33         INTEGER,
34         UNSIGNED,
35         PREFIX,
36         BOOLEAN,
37         STRING,
38         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, ETHER_ADDR_LEN);
3497         memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
3498                vxlan_encap_conf.eth_src, 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         memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
3516                RTE_DIM(vxlan_encap_conf.vni));
3517         action->conf = &action_vxlan_encap_data->conf;
3518         return ret;
3519 }
3520
3521 /** Parse NVGRE encap action. */
3522 static int
3523 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
3524                             const char *str, unsigned int len,
3525                             void *buf, unsigned int size)
3526 {
3527         struct buffer *out = buf;
3528         struct rte_flow_action *action;
3529         struct action_nvgre_encap_data *action_nvgre_encap_data;
3530         int ret;
3531
3532         ret = parse_vc(ctx, token, str, len, buf, size);
3533         if (ret < 0)
3534                 return ret;
3535         /* Nothing else to do if there is no buffer. */
3536         if (!out)
3537                 return ret;
3538         if (!out->args.vc.actions_n)
3539                 return -1;
3540         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3541         /* Point to selected object. */
3542         ctx->object = out->args.vc.data;
3543         ctx->objmask = NULL;
3544         /* Set up default configuration. */
3545         action_nvgre_encap_data = ctx->object;
3546         *action_nvgre_encap_data = (struct action_nvgre_encap_data){
3547                 .conf = (struct rte_flow_action_nvgre_encap){
3548                         .definition = action_nvgre_encap_data->items,
3549                 },
3550                 .items = {
3551                         {
3552                                 .type = RTE_FLOW_ITEM_TYPE_ETH,
3553                                 .spec = &action_nvgre_encap_data->item_eth,
3554                                 .mask = &rte_flow_item_eth_mask,
3555                         },
3556                         {
3557                                 .type = RTE_FLOW_ITEM_TYPE_VLAN,
3558                                 .spec = &action_nvgre_encap_data->item_vlan,
3559                                 .mask = &rte_flow_item_vlan_mask,
3560                         },
3561                         {
3562                                 .type = RTE_FLOW_ITEM_TYPE_IPV4,
3563                                 .spec = &action_nvgre_encap_data->item_ipv4,
3564                                 .mask = &rte_flow_item_ipv4_mask,
3565                         },
3566                         {
3567                                 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
3568                                 .spec = &action_nvgre_encap_data->item_nvgre,
3569                                 .mask = &rte_flow_item_nvgre_mask,
3570                         },
3571                         {
3572                                 .type = RTE_FLOW_ITEM_TYPE_END,
3573                         },
3574                 },
3575                 .item_eth.type = 0,
3576                 .item_vlan = {
3577                         .tci = nvgre_encap_conf.vlan_tci,
3578                         .inner_type = 0,
3579                 },
3580                 .item_ipv4.hdr = {
3581                        .src_addr = nvgre_encap_conf.ipv4_src,
3582                        .dst_addr = nvgre_encap_conf.ipv4_dst,
3583                 },
3584                 .item_nvgre.flow_id = 0,
3585         };
3586         memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
3587                nvgre_encap_conf.eth_dst, ETHER_ADDR_LEN);
3588         memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
3589                nvgre_encap_conf.eth_src, ETHER_ADDR_LEN);
3590         if (!nvgre_encap_conf.select_ipv4) {
3591                 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
3592                        &nvgre_encap_conf.ipv6_src,
3593                        sizeof(nvgre_encap_conf.ipv6_src));
3594                 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
3595                        &nvgre_encap_conf.ipv6_dst,
3596                        sizeof(nvgre_encap_conf.ipv6_dst));
3597                 action_nvgre_encap_data->items[2] = (struct rte_flow_item){
3598                         .type = RTE_FLOW_ITEM_TYPE_IPV6,
3599                         .spec = &action_nvgre_encap_data->item_ipv6,
3600                         .mask = &rte_flow_item_ipv6_mask,
3601                 };
3602         }
3603         if (!nvgre_encap_conf.select_vlan)
3604                 action_nvgre_encap_data->items[1].type =
3605                         RTE_FLOW_ITEM_TYPE_VOID;
3606         memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
3607                RTE_DIM(nvgre_encap_conf.tni));
3608         action->conf = &action_nvgre_encap_data->conf;
3609         return ret;
3610 }
3611
3612 /** Parse l2 encap action. */
3613 static int
3614 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
3615                          const char *str, unsigned int len,
3616                          void *buf, unsigned int size)
3617 {
3618         struct buffer *out = buf;
3619         struct rte_flow_action *action;
3620         struct action_raw_encap_data *action_encap_data;
3621         struct rte_flow_item_eth eth = { .type = 0, };
3622         struct rte_flow_item_vlan vlan = {
3623                 .tci = mplsoudp_encap_conf.vlan_tci,
3624                 .inner_type = 0,
3625         };
3626         uint8_t *header;
3627         int ret;
3628
3629         ret = parse_vc(ctx, token, str, len, buf, size);
3630         if (ret < 0)
3631                 return ret;
3632         /* Nothing else to do if there is no buffer. */
3633         if (!out)
3634                 return ret;
3635         if (!out->args.vc.actions_n)
3636                 return -1;
3637         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3638         /* Point to selected object. */
3639         ctx->object = out->args.vc.data;
3640         ctx->objmask = NULL;
3641         /* Copy the headers to the buffer. */
3642         action_encap_data = ctx->object;
3643         *action_encap_data = (struct action_raw_encap_data) {
3644                 .conf = (struct rte_flow_action_raw_encap){
3645                         .data = action_encap_data->data,
3646                 },
3647                 .data = {},
3648         };
3649         header = action_encap_data->data;
3650         if (l2_encap_conf.select_vlan)
3651                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
3652         else if (l2_encap_conf.select_ipv4)
3653                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3654         else
3655                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3656         memcpy(eth.dst.addr_bytes,
3657                l2_encap_conf.eth_dst, ETHER_ADDR_LEN);
3658         memcpy(eth.src.addr_bytes,
3659                l2_encap_conf.eth_src, ETHER_ADDR_LEN);
3660         memcpy(header, &eth, sizeof(eth));
3661         header += sizeof(eth);
3662         if (l2_encap_conf.select_vlan) {
3663                 if (l2_encap_conf.select_ipv4)
3664                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3665                 else
3666                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3667                 memcpy(header, &vlan, sizeof(vlan));
3668                 header += sizeof(vlan);
3669         }
3670         action_encap_data->conf.size = header -
3671                 action_encap_data->data;
3672         action->conf = &action_encap_data->conf;
3673         return ret;
3674 }
3675
3676 /** Parse l2 decap action. */
3677 static int
3678 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
3679                          const char *str, unsigned int len,
3680                          void *buf, unsigned int size)
3681 {
3682         struct buffer *out = buf;
3683         struct rte_flow_action *action;
3684         struct action_raw_decap_data *action_decap_data;
3685         struct rte_flow_item_eth eth = { .type = 0, };
3686         struct rte_flow_item_vlan vlan = {
3687                 .tci = mplsoudp_encap_conf.vlan_tci,
3688                 .inner_type = 0,
3689         };
3690         uint8_t *header;
3691         int ret;
3692
3693         ret = parse_vc(ctx, token, str, len, buf, size);
3694         if (ret < 0)
3695                 return ret;
3696         /* Nothing else to do if there is no buffer. */
3697         if (!out)
3698                 return ret;
3699         if (!out->args.vc.actions_n)
3700                 return -1;
3701         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3702         /* Point to selected object. */
3703         ctx->object = out->args.vc.data;
3704         ctx->objmask = NULL;
3705         /* Copy the headers to the buffer. */
3706         action_decap_data = ctx->object;
3707         *action_decap_data = (struct action_raw_decap_data) {
3708                 .conf = (struct rte_flow_action_raw_decap){
3709                         .data = action_decap_data->data,
3710                 },
3711                 .data = {},
3712         };
3713         header = action_decap_data->data;
3714         if (l2_decap_conf.select_vlan)
3715                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
3716         memcpy(header, &eth, sizeof(eth));
3717         header += sizeof(eth);
3718         if (l2_decap_conf.select_vlan) {
3719                 memcpy(header, &vlan, sizeof(vlan));
3720                 header += sizeof(vlan);
3721         }
3722         action_decap_data->conf.size = header -
3723                 action_decap_data->data;
3724         action->conf = &action_decap_data->conf;
3725         return ret;
3726 }
3727
3728 #define ETHER_TYPE_MPLS_UNICAST 0x8847
3729
3730 /** Parse MPLSOGRE encap action. */
3731 static int
3732 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
3733                                const char *str, unsigned int len,
3734                                void *buf, unsigned int size)
3735 {
3736         struct buffer *out = buf;
3737         struct rte_flow_action *action;
3738         struct action_raw_encap_data *action_encap_data;
3739         struct rte_flow_item_eth eth = { .type = 0, };
3740         struct rte_flow_item_vlan vlan = {
3741                 .tci = mplsogre_encap_conf.vlan_tci,
3742                 .inner_type = 0,
3743         };
3744         struct rte_flow_item_ipv4 ipv4 = {
3745                 .hdr =  {
3746                         .src_addr = mplsogre_encap_conf.ipv4_src,
3747                         .dst_addr = mplsogre_encap_conf.ipv4_dst,
3748                         .next_proto_id = IPPROTO_GRE,
3749                 },
3750         };
3751         struct rte_flow_item_ipv6 ipv6 = {
3752                 .hdr =  {
3753                         .proto = IPPROTO_GRE,
3754                 },
3755         };
3756         struct rte_flow_item_gre gre = {
3757                 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
3758         };
3759         struct rte_flow_item_mpls mpls;
3760         uint8_t *header;
3761         int ret;
3762
3763         ret = parse_vc(ctx, token, str, len, buf, size);
3764         if (ret < 0)
3765                 return ret;
3766         /* Nothing else to do if there is no buffer. */
3767         if (!out)
3768                 return ret;
3769         if (!out->args.vc.actions_n)
3770                 return -1;
3771         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3772         /* Point to selected object. */
3773         ctx->object = out->args.vc.data;
3774         ctx->objmask = NULL;
3775         /* Copy the headers to the buffer. */
3776         action_encap_data = ctx->object;
3777         *action_encap_data = (struct action_raw_encap_data) {
3778                 .conf = (struct rte_flow_action_raw_encap){
3779                         .data = action_encap_data->data,
3780                 },
3781                 .data = {},
3782                 .preserve = {},
3783         };
3784         header = action_encap_data->data;
3785         if (mplsogre_encap_conf.select_vlan)
3786                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
3787         else if (mplsogre_encap_conf.select_ipv4)
3788                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3789         else
3790                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3791         memcpy(eth.dst.addr_bytes,
3792                mplsogre_encap_conf.eth_dst, ETHER_ADDR_LEN);
3793         memcpy(eth.src.addr_bytes,
3794                mplsogre_encap_conf.eth_src, ETHER_ADDR_LEN);
3795         memcpy(header, &eth, sizeof(eth));
3796         header += sizeof(eth);
3797         if (mplsogre_encap_conf.select_vlan) {
3798                 if (mplsogre_encap_conf.select_ipv4)
3799                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3800                 else
3801                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3802                 memcpy(header, &vlan, sizeof(vlan));
3803                 header += sizeof(vlan);
3804         }
3805         if (mplsogre_encap_conf.select_ipv4) {
3806                 memcpy(header, &ipv4, sizeof(ipv4));
3807                 header += sizeof(ipv4);
3808         } else {
3809                 memcpy(&ipv6.hdr.src_addr,
3810                        &mplsogre_encap_conf.ipv6_src,
3811                        sizeof(mplsogre_encap_conf.ipv6_src));
3812                 memcpy(&ipv6.hdr.dst_addr,
3813                        &mplsogre_encap_conf.ipv6_dst,
3814                        sizeof(mplsogre_encap_conf.ipv6_dst));
3815                 memcpy(header, &ipv6, sizeof(ipv6));
3816                 header += sizeof(ipv6);
3817         }
3818         memcpy(header, &gre, sizeof(gre));
3819         header += sizeof(gre);
3820         memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
3821                RTE_DIM(mplsogre_encap_conf.label));
3822         mpls.label_tc_s[2] |= 0x1;
3823         memcpy(header, &mpls, sizeof(mpls));
3824         header += sizeof(mpls);
3825         action_encap_data->conf.size = header -
3826                 action_encap_data->data;
3827         action->conf = &action_encap_data->conf;
3828         return ret;
3829 }
3830
3831 /** Parse MPLSOGRE decap action. */
3832 static int
3833 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
3834                                const char *str, unsigned int len,
3835                                void *buf, unsigned int size)
3836 {
3837         struct buffer *out = buf;
3838         struct rte_flow_action *action;
3839         struct action_raw_decap_data *action_decap_data;
3840         struct rte_flow_item_eth eth = { .type = 0, };
3841         struct rte_flow_item_vlan vlan = {.tci = 0};
3842         struct rte_flow_item_ipv4 ipv4 = {
3843                 .hdr =  {
3844                         .next_proto_id = IPPROTO_GRE,
3845                 },
3846         };
3847         struct rte_flow_item_ipv6 ipv6 = {
3848                 .hdr =  {
3849                         .proto = IPPROTO_GRE,
3850                 },
3851         };
3852         struct rte_flow_item_gre gre = {
3853                 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
3854         };
3855         struct rte_flow_item_mpls mpls;
3856         uint8_t *header;
3857         int ret;
3858
3859         ret = parse_vc(ctx, token, str, len, buf, size);
3860         if (ret < 0)
3861                 return ret;
3862         /* Nothing else to do if there is no buffer. */
3863         if (!out)
3864                 return ret;
3865         if (!out->args.vc.actions_n)
3866                 return -1;
3867         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3868         /* Point to selected object. */
3869         ctx->object = out->args.vc.data;
3870         ctx->objmask = NULL;
3871         /* Copy the headers to the buffer. */
3872         action_decap_data = ctx->object;
3873         *action_decap_data = (struct action_raw_decap_data) {
3874                 .conf = (struct rte_flow_action_raw_decap){
3875                         .data = action_decap_data->data,
3876                 },
3877                 .data = {},
3878         };
3879         header = action_decap_data->data;
3880         if (mplsogre_decap_conf.select_vlan)
3881                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
3882         else if (mplsogre_encap_conf.select_ipv4)
3883                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3884         else
3885                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3886         memcpy(eth.dst.addr_bytes,
3887                mplsogre_encap_conf.eth_dst, ETHER_ADDR_LEN);
3888         memcpy(eth.src.addr_bytes,
3889                mplsogre_encap_conf.eth_src, ETHER_ADDR_LEN);
3890         memcpy(header, &eth, sizeof(eth));
3891         header += sizeof(eth);
3892         if (mplsogre_encap_conf.select_vlan) {
3893                 if (mplsogre_encap_conf.select_ipv4)
3894                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3895                 else
3896                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3897                 memcpy(header, &vlan, sizeof(vlan));
3898                 header += sizeof(vlan);
3899         }
3900         if (mplsogre_encap_conf.select_ipv4) {
3901                 memcpy(header, &ipv4, sizeof(ipv4));
3902                 header += sizeof(ipv4);
3903         } else {
3904                 memcpy(header, &ipv6, sizeof(ipv6));
3905                 header += sizeof(ipv6);
3906         }
3907         memcpy(header, &gre, sizeof(gre));
3908         header += sizeof(gre);
3909         memset(&mpls, 0, sizeof(mpls));
3910         memcpy(header, &mpls, sizeof(mpls));
3911         header += sizeof(mpls);
3912         action_decap_data->conf.size = header -
3913                 action_decap_data->data;
3914         action->conf = &action_decap_data->conf;
3915         return ret;
3916 }
3917
3918 /** Parse MPLSOUDP encap action. */
3919 static int
3920 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
3921                                const char *str, unsigned int len,
3922                                void *buf, unsigned int size)
3923 {
3924         struct buffer *out = buf;
3925         struct rte_flow_action *action;
3926         struct action_raw_encap_data *action_encap_data;
3927         struct rte_flow_item_eth eth = { .type = 0, };
3928         struct rte_flow_item_vlan vlan = {
3929                 .tci = mplsoudp_encap_conf.vlan_tci,
3930                 .inner_type = 0,
3931         };
3932         struct rte_flow_item_ipv4 ipv4 = {
3933                 .hdr =  {
3934                         .src_addr = mplsoudp_encap_conf.ipv4_src,
3935                         .dst_addr = mplsoudp_encap_conf.ipv4_dst,
3936                         .next_proto_id = IPPROTO_UDP,
3937                 },
3938         };
3939         struct rte_flow_item_ipv6 ipv6 = {
3940                 .hdr =  {
3941                         .proto = IPPROTO_UDP,
3942                 },
3943         };
3944         struct rte_flow_item_udp udp = {
3945                 .hdr = {
3946                         .src_port = mplsoudp_encap_conf.udp_src,
3947                         .dst_port = mplsoudp_encap_conf.udp_dst,
3948                 },
3949         };
3950         struct rte_flow_item_mpls mpls;
3951         uint8_t *header;
3952         int ret;
3953
3954         ret = parse_vc(ctx, token, str, len, buf, size);
3955         if (ret < 0)
3956                 return ret;
3957         /* Nothing else to do if there is no buffer. */
3958         if (!out)
3959                 return ret;
3960         if (!out->args.vc.actions_n)
3961                 return -1;
3962         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3963         /* Point to selected object. */
3964         ctx->object = out->args.vc.data;
3965         ctx->objmask = NULL;
3966         /* Copy the headers to the buffer. */
3967         action_encap_data = ctx->object;
3968         *action_encap_data = (struct action_raw_encap_data) {
3969                 .conf = (struct rte_flow_action_raw_encap){
3970                         .data = action_encap_data->data,
3971                 },
3972                 .data = {},
3973                 .preserve = {},
3974         };
3975         header = action_encap_data->data;
3976         if (mplsoudp_encap_conf.select_vlan)
3977                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
3978         else if (mplsoudp_encap_conf.select_ipv4)
3979                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3980         else
3981                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3982         memcpy(eth.dst.addr_bytes,
3983                mplsoudp_encap_conf.eth_dst, ETHER_ADDR_LEN);
3984         memcpy(eth.src.addr_bytes,
3985                mplsoudp_encap_conf.eth_src, ETHER_ADDR_LEN);
3986         memcpy(header, &eth, sizeof(eth));
3987         header += sizeof(eth);
3988         if (mplsoudp_encap_conf.select_vlan) {
3989                 if (mplsoudp_encap_conf.select_ipv4)
3990                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3991                 else
3992                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3993                 memcpy(header, &vlan, sizeof(vlan));
3994                 header += sizeof(vlan);
3995         }
3996         if (mplsoudp_encap_conf.select_ipv4) {
3997                 memcpy(header, &ipv4, sizeof(ipv4));
3998                 header += sizeof(ipv4);
3999         } else {
4000                 memcpy(&ipv6.hdr.src_addr,
4001                        &mplsoudp_encap_conf.ipv6_src,
4002                        sizeof(mplsoudp_encap_conf.ipv6_src));
4003                 memcpy(&ipv6.hdr.dst_addr,
4004                        &mplsoudp_encap_conf.ipv6_dst,
4005                        sizeof(mplsoudp_encap_conf.ipv6_dst));
4006                 memcpy(header, &ipv6, sizeof(ipv6));
4007                 header += sizeof(ipv6);
4008         }
4009         memcpy(header, &udp, sizeof(udp));
4010         header += sizeof(udp);
4011         memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
4012                RTE_DIM(mplsoudp_encap_conf.label));
4013         mpls.label_tc_s[2] |= 0x1;
4014         memcpy(header, &mpls, sizeof(mpls));
4015         header += sizeof(mpls);
4016         action_encap_data->conf.size = header -
4017                 action_encap_data->data;
4018         action->conf = &action_encap_data->conf;
4019         return ret;
4020 }
4021
4022 /** Parse MPLSOUDP decap action. */
4023 static int
4024 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
4025                                const char *str, unsigned int len,
4026                                void *buf, unsigned int size)
4027 {
4028         struct buffer *out = buf;
4029         struct rte_flow_action *action;
4030         struct action_raw_decap_data *action_decap_data;
4031         struct rte_flow_item_eth eth = { .type = 0, };
4032         struct rte_flow_item_vlan vlan = {.tci = 0};
4033         struct rte_flow_item_ipv4 ipv4 = {
4034                 .hdr =  {
4035                         .next_proto_id = IPPROTO_UDP,
4036                 },
4037         };
4038         struct rte_flow_item_ipv6 ipv6 = {
4039                 .hdr =  {
4040                         .proto = IPPROTO_UDP,
4041                 },
4042         };
4043         struct rte_flow_item_udp udp = {
4044                 .hdr = {
4045                         .dst_port = rte_cpu_to_be_16(6635),
4046                 },
4047         };
4048         struct rte_flow_item_mpls mpls;
4049         uint8_t *header;
4050         int ret;
4051
4052         ret = parse_vc(ctx, token, str, len, buf, size);
4053         if (ret < 0)
4054                 return ret;
4055         /* Nothing else to do if there is no buffer. */
4056         if (!out)
4057                 return ret;
4058         if (!out->args.vc.actions_n)
4059                 return -1;
4060         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4061         /* Point to selected object. */
4062         ctx->object = out->args.vc.data;
4063         ctx->objmask = NULL;
4064         /* Copy the headers to the buffer. */
4065         action_decap_data = ctx->object;
4066         *action_decap_data = (struct action_raw_decap_data) {
4067                 .conf = (struct rte_flow_action_raw_decap){
4068                         .data = action_decap_data->data,
4069                 },
4070                 .data = {},
4071         };
4072         header = action_decap_data->data;
4073         if (mplsoudp_decap_conf.select_vlan)
4074                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
4075         else if (mplsoudp_encap_conf.select_ipv4)
4076                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
4077         else
4078                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
4079         memcpy(eth.dst.addr_bytes,
4080                mplsoudp_encap_conf.eth_dst, ETHER_ADDR_LEN);
4081         memcpy(eth.src.addr_bytes,
4082                mplsoudp_encap_conf.eth_src, ETHER_ADDR_LEN);
4083         memcpy(header, &eth, sizeof(eth));
4084         header += sizeof(eth);
4085         if (mplsoudp_encap_conf.select_vlan) {
4086                 if (mplsoudp_encap_conf.select_ipv4)
4087                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
4088                 else
4089                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
4090                 memcpy(header, &vlan, sizeof(vlan));
4091                 header += sizeof(vlan);
4092         }
4093         if (mplsoudp_encap_conf.select_ipv4) {
4094                 memcpy(header, &ipv4, sizeof(ipv4));
4095                 header += sizeof(ipv4);
4096         } else {
4097                 memcpy(header, &ipv6, sizeof(ipv6));
4098                 header += sizeof(ipv6);
4099         }
4100         memcpy(header, &udp, sizeof(udp));
4101         header += sizeof(udp);
4102         memset(&mpls, 0, sizeof(mpls));
4103         memcpy(header, &mpls, sizeof(mpls));
4104         header += sizeof(mpls);
4105         action_decap_data->conf.size = header -
4106                 action_decap_data->data;
4107         action->conf = &action_decap_data->conf;
4108         return ret;
4109 }
4110
4111 /** Parse tokens for destroy command. */
4112 static int
4113 parse_destroy(struct context *ctx, const struct token *token,
4114               const char *str, unsigned int len,
4115               void *buf, unsigned int size)
4116 {
4117         struct buffer *out = buf;
4118
4119         /* Token name must match. */
4120         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4121                 return -1;
4122         /* Nothing else to do if there is no buffer. */
4123         if (!out)
4124                 return len;
4125         if (!out->command) {
4126                 if (ctx->curr != DESTROY)
4127                         return -1;
4128                 if (sizeof(*out) > size)
4129                         return -1;
4130                 out->command = ctx->curr;
4131                 ctx->objdata = 0;
4132                 ctx->object = out;
4133                 ctx->objmask = NULL;
4134                 out->args.destroy.rule =
4135                         (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
4136                                                sizeof(double));
4137                 return len;
4138         }
4139         if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
4140              sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
4141                 return -1;
4142         ctx->objdata = 0;
4143         ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
4144         ctx->objmask = NULL;
4145         return len;
4146 }
4147
4148 /** Parse tokens for flush command. */
4149 static int
4150 parse_flush(struct context *ctx, const struct token *token,
4151             const char *str, unsigned int len,
4152             void *buf, unsigned int size)
4153 {
4154         struct buffer *out = buf;
4155
4156         /* Token name must match. */
4157         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4158                 return -1;
4159         /* Nothing else to do if there is no buffer. */
4160         if (!out)
4161                 return len;
4162         if (!out->command) {
4163                 if (ctx->curr != FLUSH)
4164                         return -1;
4165                 if (sizeof(*out) > size)
4166                         return -1;
4167                 out->command = ctx->curr;
4168                 ctx->objdata = 0;
4169                 ctx->object = out;
4170                 ctx->objmask = NULL;
4171         }
4172         return len;
4173 }
4174
4175 /** Parse tokens for query command. */
4176 static int
4177 parse_query(struct context *ctx, const struct token *token,
4178             const char *str, unsigned int len,
4179             void *buf, unsigned int size)
4180 {
4181         struct buffer *out = buf;
4182
4183         /* Token name must match. */
4184         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4185                 return -1;
4186         /* Nothing else to do if there is no buffer. */
4187         if (!out)
4188                 return len;
4189         if (!out->command) {
4190                 if (ctx->curr != QUERY)
4191                         return -1;
4192                 if (sizeof(*out) > size)
4193                         return -1;
4194                 out->command = ctx->curr;
4195                 ctx->objdata = 0;
4196                 ctx->object = out;
4197                 ctx->objmask = NULL;
4198         }
4199         return len;
4200 }
4201
4202 /** Parse action names. */
4203 static int
4204 parse_action(struct context *ctx, const struct token *token,
4205              const char *str, unsigned int len,
4206              void *buf, unsigned int size)
4207 {
4208         struct buffer *out = buf;
4209         const struct arg *arg = pop_args(ctx);
4210         unsigned int i;
4211
4212         (void)size;
4213         /* Argument is expected. */
4214         if (!arg)
4215                 return -1;
4216         /* Parse action name. */
4217         for (i = 0; next_action[i]; ++i) {
4218                 const struct parse_action_priv *priv;
4219
4220                 token = &token_list[next_action[i]];
4221                 if (strcmp_partial(token->name, str, len))
4222                         continue;
4223                 priv = token->priv;
4224                 if (!priv)
4225                         goto error;
4226                 if (out)
4227                         memcpy((uint8_t *)ctx->object + arg->offset,
4228                                &priv->type,
4229                                arg->size);
4230                 return len;
4231         }
4232 error:
4233         push_args(ctx, arg);
4234         return -1;
4235 }
4236
4237 /** Parse tokens for list command. */
4238 static int
4239 parse_list(struct context *ctx, const struct token *token,
4240            const char *str, unsigned int len,
4241            void *buf, unsigned int size)
4242 {
4243         struct buffer *out = buf;
4244
4245         /* Token name must match. */
4246         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4247                 return -1;
4248         /* Nothing else to do if there is no buffer. */
4249         if (!out)
4250                 return len;
4251         if (!out->command) {
4252                 if (ctx->curr != LIST)
4253                         return -1;
4254                 if (sizeof(*out) > size)
4255                         return -1;
4256                 out->command = ctx->curr;
4257                 ctx->objdata = 0;
4258                 ctx->object = out;
4259                 ctx->objmask = NULL;
4260                 out->args.list.group =
4261                         (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
4262                                                sizeof(double));
4263                 return len;
4264         }
4265         if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
4266              sizeof(*out->args.list.group)) > (uint8_t *)out + size)
4267                 return -1;
4268         ctx->objdata = 0;
4269         ctx->object = out->args.list.group + out->args.list.group_n++;
4270         ctx->objmask = NULL;
4271         return len;
4272 }
4273
4274 /** Parse tokens for isolate command. */
4275 static int
4276 parse_isolate(struct context *ctx, const struct token *token,
4277               const char *str, unsigned int len,
4278               void *buf, unsigned int size)
4279 {
4280         struct buffer *out = buf;
4281
4282         /* Token name must match. */
4283         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4284                 return -1;
4285         /* Nothing else to do if there is no buffer. */
4286         if (!out)
4287                 return len;
4288         if (!out->command) {
4289                 if (ctx->curr != ISOLATE)
4290                         return -1;
4291                 if (sizeof(*out) > size)
4292                         return -1;
4293                 out->command = ctx->curr;
4294                 ctx->objdata = 0;
4295                 ctx->object = out;
4296                 ctx->objmask = NULL;
4297         }
4298         return len;
4299 }
4300
4301 /**
4302  * Parse signed/unsigned integers 8 to 64-bit long.
4303  *
4304  * Last argument (ctx->args) is retrieved to determine integer type and
4305  * storage location.
4306  */
4307 static int
4308 parse_int(struct context *ctx, const struct token *token,
4309           const char *str, unsigned int len,
4310           void *buf, unsigned int size)
4311 {
4312         const struct arg *arg = pop_args(ctx);
4313         uintmax_t u;
4314         char *end;
4315
4316         (void)token;
4317         /* Argument is expected. */
4318         if (!arg)
4319                 return -1;
4320         errno = 0;
4321         u = arg->sign ?
4322                 (uintmax_t)strtoimax(str, &end, 0) :
4323                 strtoumax(str, &end, 0);
4324         if (errno || (size_t)(end - str) != len)
4325                 goto error;
4326         if (arg->bounded &&
4327             ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
4328                             (intmax_t)u > (intmax_t)arg->max)) ||
4329              (!arg->sign && (u < arg->min || u > arg->max))))
4330                 goto error;
4331         if (!ctx->object)
4332                 return len;
4333         if (arg->mask) {
4334                 if (!arg_entry_bf_fill(ctx->object, u, arg) ||
4335                     !arg_entry_bf_fill(ctx->objmask, -1, arg))
4336                         goto error;
4337                 return len;
4338         }
4339         buf = (uint8_t *)ctx->object + arg->offset;
4340         size = arg->size;
4341 objmask:
4342         switch (size) {
4343         case sizeof(uint8_t):
4344                 *(uint8_t *)buf = u;
4345                 break;
4346         case sizeof(uint16_t):
4347                 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
4348                 break;
4349         case sizeof(uint8_t [3]):
4350 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4351                 if (!arg->hton) {
4352                         ((uint8_t *)buf)[0] = u;
4353                         ((uint8_t *)buf)[1] = u >> 8;
4354                         ((uint8_t *)buf)[2] = u >> 16;
4355                         break;
4356                 }
4357 #endif
4358                 ((uint8_t *)buf)[0] = u >> 16;
4359                 ((uint8_t *)buf)[1] = u >> 8;
4360                 ((uint8_t *)buf)[2] = u;
4361                 break;
4362         case sizeof(uint32_t):
4363                 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
4364                 break;
4365         case sizeof(uint64_t):
4366                 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
4367                 break;
4368         default:
4369                 goto error;
4370         }
4371         if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
4372                 u = -1;
4373                 buf = (uint8_t *)ctx->objmask + arg->offset;
4374                 goto objmask;
4375         }
4376         return len;
4377 error:
4378         push_args(ctx, arg);
4379         return -1;
4380 }
4381
4382 /**
4383  * Parse a string.
4384  *
4385  * Three arguments (ctx->args) are retrieved from the stack to store data,
4386  * its actual length and address (in that order).
4387  */
4388 static int
4389 parse_string(struct context *ctx, const struct token *token,
4390              const char *str, unsigned int len,
4391              void *buf, unsigned int size)
4392 {
4393         const struct arg *arg_data = pop_args(ctx);
4394         const struct arg *arg_len = pop_args(ctx);
4395         const struct arg *arg_addr = pop_args(ctx);
4396         char tmp[16]; /* Ought to be enough. */
4397         int ret;
4398
4399         /* Arguments are expected. */
4400         if (!arg_data)
4401                 return -1;
4402         if (!arg_len) {
4403                 push_args(ctx, arg_data);
4404                 return -1;
4405         }
4406         if (!arg_addr) {
4407                 push_args(ctx, arg_len);
4408                 push_args(ctx, arg_data);
4409                 return -1;
4410         }
4411         size = arg_data->size;
4412         /* Bit-mask fill is not supported. */
4413         if (arg_data->mask || size < len)
4414                 goto error;
4415         if (!ctx->object)
4416                 return len;
4417         /* Let parse_int() fill length information first. */
4418         ret = snprintf(tmp, sizeof(tmp), "%u", len);
4419         if (ret < 0)
4420                 goto error;
4421         push_args(ctx, arg_len);
4422         ret = parse_int(ctx, token, tmp, ret, NULL, 0);
4423         if (ret < 0) {
4424                 pop_args(ctx);
4425                 goto error;
4426         }
4427         buf = (uint8_t *)ctx->object + arg_data->offset;
4428         /* Output buffer is not necessarily NUL-terminated. */
4429         memcpy(buf, str, len);
4430         memset((uint8_t *)buf + len, 0x00, size - len);
4431         if (ctx->objmask)
4432                 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
4433         /* Save address if requested. */
4434         if (arg_addr->size) {
4435                 memcpy((uint8_t *)ctx->object + arg_addr->offset,
4436                        (void *[]){
4437                         (uint8_t *)ctx->object + arg_data->offset
4438                        },
4439                        arg_addr->size);
4440                 if (ctx->objmask)
4441                         memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
4442                                (void *[]){
4443                                 (uint8_t *)ctx->objmask + arg_data->offset
4444                                },
4445                                arg_addr->size);
4446         }
4447         return len;
4448 error:
4449         push_args(ctx, arg_addr);
4450         push_args(ctx, arg_len);
4451         push_args(ctx, arg_data);
4452         return -1;
4453 }
4454
4455 static int
4456 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
4457 {
4458         char *c = NULL;
4459         uint32_t i, len;
4460         char tmp[3];
4461
4462         /* Check input parameters */
4463         if ((src == NULL) ||
4464                 (dst == NULL) ||
4465                 (size == NULL) ||
4466                 (*size == 0))
4467                 return -1;
4468
4469         /* Convert chars to bytes */
4470         for (i = 0, len = 0; i < *size; i += 2) {
4471                 snprintf(tmp, 3, "%s", src + i);
4472                 dst[len++] = strtoul(tmp, &c, 16);
4473                 if (*c != 0) {
4474                         len--;
4475                         dst[len] = 0;
4476                         *size = len;
4477                         return -1;
4478                 }
4479         }
4480         dst[len] = 0;
4481         *size = len;
4482
4483         return 0;
4484 }
4485
4486 static int
4487 parse_hex(struct context *ctx, const struct token *token,
4488                 const char *str, unsigned int len,
4489                 void *buf, unsigned int size)
4490 {
4491         const struct arg *arg_data = pop_args(ctx);
4492         const struct arg *arg_len = pop_args(ctx);
4493         const struct arg *arg_addr = pop_args(ctx);
4494         char tmp[16]; /* Ought to be enough. */
4495         int ret;
4496         unsigned int hexlen = len;
4497         unsigned int length = 256;
4498         uint8_t hex_tmp[length];
4499
4500         /* Arguments are expected. */
4501         if (!arg_data)
4502                 return -1;
4503         if (!arg_len) {
4504                 push_args(ctx, arg_data);
4505                 return -1;
4506         }
4507         if (!arg_addr) {
4508                 push_args(ctx, arg_len);
4509                 push_args(ctx, arg_data);
4510                 return -1;
4511         }
4512         size = arg_data->size;
4513         /* Bit-mask fill is not supported. */
4514         if (arg_data->mask)
4515                 goto error;
4516         if (!ctx->object)
4517                 return len;
4518
4519         /* translate bytes string to array. */
4520         if (str[0] == '0' && ((str[1] == 'x') ||
4521                         (str[1] == 'X'))) {
4522                 str += 2;
4523                 hexlen -= 2;
4524         }
4525         if (hexlen > length)
4526                 return -1;
4527         ret = parse_hex_string(str, hex_tmp, &hexlen);
4528         if (ret < 0)
4529                 goto error;
4530         /* Let parse_int() fill length information first. */
4531         ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
4532         if (ret < 0)
4533                 goto error;
4534         push_args(ctx, arg_len);
4535         ret = parse_int(ctx, token, tmp, ret, NULL, 0);
4536         if (ret < 0) {
4537                 pop_args(ctx);
4538                 goto error;
4539         }
4540         buf = (uint8_t *)ctx->object + arg_data->offset;
4541         /* Output buffer is not necessarily NUL-terminated. */
4542         memcpy(buf, hex_tmp, hexlen);
4543         memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
4544         if (ctx->objmask)
4545                 memset((uint8_t *)ctx->objmask + arg_data->offset,
4546                                         0xff, hexlen);
4547         /* Save address if requested. */
4548         if (arg_addr->size) {
4549                 memcpy((uint8_t *)ctx->object + arg_addr->offset,
4550                        (void *[]){
4551                         (uint8_t *)ctx->object + arg_data->offset
4552                        },
4553                        arg_addr->size);
4554                 if (ctx->objmask)
4555                         memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
4556                                (void *[]){
4557                                 (uint8_t *)ctx->objmask + arg_data->offset
4558                                },
4559                                arg_addr->size);
4560         }
4561         return len;
4562 error:
4563         push_args(ctx, arg_addr);
4564         push_args(ctx, arg_len);
4565         push_args(ctx, arg_data);
4566         return -1;
4567
4568 }
4569
4570 /**
4571  * Parse a MAC address.
4572  *
4573  * Last argument (ctx->args) is retrieved to determine storage size and
4574  * location.
4575  */
4576 static int
4577 parse_mac_addr(struct context *ctx, const struct token *token,
4578                const char *str, unsigned int len,
4579                void *buf, unsigned int size)
4580 {
4581         const struct arg *arg = pop_args(ctx);
4582         struct ether_addr tmp;
4583         int ret;
4584
4585         (void)token;
4586         /* Argument is expected. */
4587         if (!arg)
4588                 return -1;
4589         size = arg->size;
4590         /* Bit-mask fill is not supported. */
4591         if (arg->mask || size != sizeof(tmp))
4592                 goto error;
4593         /* Only network endian is supported. */
4594         if (!arg->hton)
4595                 goto error;
4596         ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
4597         if (ret < 0 || (unsigned int)ret != len)
4598                 goto error;
4599         if (!ctx->object)
4600                 return len;
4601         buf = (uint8_t *)ctx->object + arg->offset;
4602         memcpy(buf, &tmp, size);
4603         if (ctx->objmask)
4604                 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
4605         return len;
4606 error:
4607         push_args(ctx, arg);
4608         return -1;
4609 }
4610
4611 /**
4612  * Parse an IPv4 address.
4613  *
4614  * Last argument (ctx->args) is retrieved to determine storage size and
4615  * location.
4616  */
4617 static int
4618 parse_ipv4_addr(struct context *ctx, const struct token *token,
4619                 const char *str, unsigned int len,
4620                 void *buf, unsigned int size)
4621 {
4622         const struct arg *arg = pop_args(ctx);
4623         char str2[len + 1];
4624         struct in_addr tmp;
4625         int ret;
4626
4627         /* Argument is expected. */
4628         if (!arg)
4629                 return -1;
4630         size = arg->size;
4631         /* Bit-mask fill is not supported. */
4632         if (arg->mask || size != sizeof(tmp))
4633                 goto error;
4634         /* Only network endian is supported. */
4635         if (!arg->hton)
4636                 goto error;
4637         memcpy(str2, str, len);
4638         str2[len] = '\0';
4639         ret = inet_pton(AF_INET, str2, &tmp);
4640         if (ret != 1) {
4641                 /* Attempt integer parsing. */
4642                 push_args(ctx, arg);
4643                 return parse_int(ctx, token, str, len, buf, size);
4644         }
4645         if (!ctx->object)
4646                 return len;
4647         buf = (uint8_t *)ctx->object + arg->offset;
4648         memcpy(buf, &tmp, size);
4649         if (ctx->objmask)
4650                 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
4651         return len;
4652 error:
4653         push_args(ctx, arg);
4654         return -1;
4655 }
4656
4657 /**
4658  * Parse an IPv6 address.
4659  *
4660  * Last argument (ctx->args) is retrieved to determine storage size and
4661  * location.
4662  */
4663 static int
4664 parse_ipv6_addr(struct context *ctx, const struct token *token,
4665                 const char *str, unsigned int len,
4666                 void *buf, unsigned int size)
4667 {
4668         const struct arg *arg = pop_args(ctx);
4669         char str2[len + 1];
4670         struct in6_addr tmp;
4671         int ret;
4672
4673         (void)token;
4674         /* Argument is expected. */
4675         if (!arg)
4676                 return -1;
4677         size = arg->size;
4678         /* Bit-mask fill is not supported. */
4679         if (arg->mask || size != sizeof(tmp))
4680                 goto error;
4681         /* Only network endian is supported. */
4682         if (!arg->hton)
4683                 goto error;
4684         memcpy(str2, str, len);
4685         str2[len] = '\0';
4686         ret = inet_pton(AF_INET6, str2, &tmp);
4687         if (ret != 1)
4688                 goto error;
4689         if (!ctx->object)
4690                 return len;
4691         buf = (uint8_t *)ctx->object + arg->offset;
4692         memcpy(buf, &tmp, size);
4693         if (ctx->objmask)
4694                 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
4695         return len;
4696 error:
4697         push_args(ctx, arg);
4698         return -1;
4699 }
4700
4701 /** Boolean values (even indices stand for false). */
4702 static const char *const boolean_name[] = {
4703         "0", "1",
4704         "false", "true",
4705         "no", "yes",
4706         "N", "Y",
4707         "off", "on",
4708         NULL,
4709 };
4710
4711 /**
4712  * Parse a boolean value.
4713  *
4714  * Last argument (ctx->args) is retrieved to determine storage size and
4715  * location.
4716  */
4717 static int
4718 parse_boolean(struct context *ctx, const struct token *token,
4719               const char *str, unsigned int len,
4720               void *buf, unsigned int size)
4721 {
4722         const struct arg *arg = pop_args(ctx);
4723         unsigned int i;
4724         int ret;
4725
4726         /* Argument is expected. */
4727         if (!arg)
4728                 return -1;
4729         for (i = 0; boolean_name[i]; ++i)
4730                 if (!strcmp_partial(boolean_name[i], str, len))
4731                         break;
4732         /* Process token as integer. */
4733         if (boolean_name[i])
4734                 str = i & 1 ? "1" : "0";
4735         push_args(ctx, arg);
4736         ret = parse_int(ctx, token, str, strlen(str), buf, size);
4737         return ret > 0 ? (int)len : ret;
4738 }
4739
4740 /** Parse port and update context. */
4741 static int
4742 parse_port(struct context *ctx, const struct token *token,
4743            const char *str, unsigned int len,
4744            void *buf, unsigned int size)
4745 {
4746         struct buffer *out = &(struct buffer){ .port = 0 };
4747         int ret;
4748
4749         if (buf)
4750                 out = buf;
4751         else {
4752                 ctx->objdata = 0;
4753                 ctx->object = out;
4754                 ctx->objmask = NULL;
4755                 size = sizeof(*out);
4756         }
4757         ret = parse_int(ctx, token, str, len, out, size);
4758         if (ret >= 0)
4759                 ctx->port = out->port;
4760         if (!buf)
4761                 ctx->object = NULL;
4762         return ret;
4763 }
4764
4765 /** No completion. */
4766 static int
4767 comp_none(struct context *ctx, const struct token *token,
4768           unsigned int ent, char *buf, unsigned int size)
4769 {
4770         (void)ctx;
4771         (void)token;
4772         (void)ent;
4773         (void)buf;
4774         (void)size;
4775         return 0;
4776 }
4777
4778 /** Complete boolean values. */
4779 static int
4780 comp_boolean(struct context *ctx, const struct token *token,
4781              unsigned int ent, char *buf, unsigned int size)
4782 {
4783         unsigned int i;
4784
4785         (void)ctx;
4786         (void)token;
4787         for (i = 0; boolean_name[i]; ++i)
4788                 if (buf && i == ent)
4789                         return snprintf(buf, size, "%s", boolean_name[i]);
4790         if (buf)
4791                 return -1;
4792         return i;
4793 }
4794
4795 /** Complete action names. */
4796 static int
4797 comp_action(struct context *ctx, const struct token *token,
4798             unsigned int ent, char *buf, unsigned int size)
4799 {
4800         unsigned int i;
4801
4802         (void)ctx;
4803         (void)token;
4804         for (i = 0; next_action[i]; ++i)
4805                 if (buf && i == ent)
4806                         return snprintf(buf, size, "%s",
4807                                         token_list[next_action[i]].name);
4808         if (buf)
4809                 return -1;
4810         return i;
4811 }
4812
4813 /** Complete available ports. */
4814 static int
4815 comp_port(struct context *ctx, const struct token *token,
4816           unsigned int ent, char *buf, unsigned int size)
4817 {
4818         unsigned int i = 0;
4819         portid_t p;
4820
4821         (void)ctx;
4822         (void)token;
4823         RTE_ETH_FOREACH_DEV(p) {
4824                 if (buf && i == ent)
4825                         return snprintf(buf, size, "%u", p);
4826                 ++i;
4827         }
4828         if (buf)
4829                 return -1;
4830         return i;
4831 }
4832
4833 /** Complete available rule IDs. */
4834 static int
4835 comp_rule_id(struct context *ctx, const struct token *token,
4836              unsigned int ent, char *buf, unsigned int size)
4837 {
4838         unsigned int i = 0;
4839         struct rte_port *port;
4840         struct port_flow *pf;
4841
4842         (void)token;
4843         if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
4844             ctx->port == (portid_t)RTE_PORT_ALL)
4845                 return -1;
4846         port = &ports[ctx->port];
4847         for (pf = port->flow_list; pf != NULL; pf = pf->next) {
4848                 if (buf && i == ent)
4849                         return snprintf(buf, size, "%u", pf->id);
4850                 ++i;
4851         }
4852         if (buf)
4853                 return -1;
4854         return i;
4855 }
4856
4857 /** Complete type field for RSS action. */
4858 static int
4859 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
4860                         unsigned int ent, char *buf, unsigned int size)
4861 {
4862         unsigned int i;
4863
4864         (void)ctx;
4865         (void)token;
4866         for (i = 0; rss_type_table[i].str; ++i)
4867                 ;
4868         if (!buf)
4869                 return i + 1;
4870         if (ent < i)
4871                 return snprintf(buf, size, "%s", rss_type_table[ent].str);
4872         if (ent == i)
4873                 return snprintf(buf, size, "end");
4874         return -1;
4875 }
4876
4877 /** Complete queue field for RSS action. */
4878 static int
4879 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
4880                          unsigned int ent, char *buf, unsigned int size)
4881 {
4882         (void)ctx;
4883         (void)token;
4884         if (!buf)
4885                 return nb_rxq + 1;
4886         if (ent < nb_rxq)
4887                 return snprintf(buf, size, "%u", ent);
4888         if (ent == nb_rxq)
4889                 return snprintf(buf, size, "end");
4890         return -1;
4891 }
4892
4893 /** Internal context. */
4894 static struct context cmd_flow_context;
4895
4896 /** Global parser instance (cmdline API). */
4897 cmdline_parse_inst_t cmd_flow;
4898
4899 /** Initialize context. */
4900 static void
4901 cmd_flow_context_init(struct context *ctx)
4902 {
4903         /* A full memset() is not necessary. */
4904         ctx->curr = ZERO;
4905         ctx->prev = ZERO;
4906         ctx->next_num = 0;
4907         ctx->args_num = 0;
4908         ctx->eol = 0;
4909         ctx->last = 0;
4910         ctx->port = 0;
4911         ctx->objdata = 0;
4912         ctx->object = NULL;
4913         ctx->objmask = NULL;
4914 }
4915
4916 /** Parse a token (cmdline API). */
4917 static int
4918 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
4919                unsigned int size)
4920 {
4921         struct context *ctx = &cmd_flow_context;
4922         const struct token *token;
4923         const enum index *list;
4924         int len;
4925         int i;
4926
4927         (void)hdr;
4928         token = &token_list[ctx->curr];
4929         /* Check argument length. */
4930         ctx->eol = 0;
4931         ctx->last = 1;
4932         for (len = 0; src[len]; ++len)
4933                 if (src[len] == '#' || isspace(src[len]))
4934                         break;
4935         if (!len)
4936                 return -1;
4937         /* Last argument and EOL detection. */
4938         for (i = len; src[i]; ++i)
4939                 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
4940                         break;
4941                 else if (!isspace(src[i])) {
4942                         ctx->last = 0;
4943                         break;
4944                 }
4945         for (; src[i]; ++i)
4946                 if (src[i] == '\r' || src[i] == '\n') {
4947                         ctx->eol = 1;
4948                         break;
4949                 }
4950         /* Initialize context if necessary. */
4951         if (!ctx->next_num) {
4952                 if (!token->next)
4953                         return 0;
4954                 ctx->next[ctx->next_num++] = token->next[0];
4955         }
4956         /* Process argument through candidates. */
4957         ctx->prev = ctx->curr;
4958         list = ctx->next[ctx->next_num - 1];
4959         for (i = 0; list[i]; ++i) {
4960                 const struct token *next = &token_list[list[i]];
4961                 int tmp;
4962
4963                 ctx->curr = list[i];
4964                 if (next->call)
4965                         tmp = next->call(ctx, next, src, len, result, size);
4966                 else
4967                         tmp = parse_default(ctx, next, src, len, result, size);
4968                 if (tmp == -1 || tmp != len)
4969                         continue;
4970                 token = next;
4971                 break;
4972         }
4973         if (!list[i])
4974                 return -1;
4975         --ctx->next_num;
4976         /* Push subsequent tokens if any. */
4977         if (token->next)
4978                 for (i = 0; token->next[i]; ++i) {
4979                         if (ctx->next_num == RTE_DIM(ctx->next))
4980                                 return -1;
4981                         ctx->next[ctx->next_num++] = token->next[i];
4982                 }
4983         /* Push arguments if any. */
4984         if (token->args)
4985                 for (i = 0; token->args[i]; ++i) {
4986                         if (ctx->args_num == RTE_DIM(ctx->args))
4987                                 return -1;
4988                         ctx->args[ctx->args_num++] = token->args[i];
4989                 }
4990         return len;
4991 }
4992
4993 /** Return number of completion entries (cmdline API). */
4994 static int
4995 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
4996 {
4997         struct context *ctx = &cmd_flow_context;
4998         const struct token *token = &token_list[ctx->curr];
4999         const enum index *list;
5000         int i;
5001
5002         (void)hdr;
5003         /* Count number of tokens in current list. */
5004         if (ctx->next_num)
5005                 list = ctx->next[ctx->next_num - 1];
5006         else
5007                 list = token->next[0];
5008         for (i = 0; list[i]; ++i)
5009                 ;
5010         if (!i)
5011                 return 0;
5012         /*
5013          * If there is a single token, use its completion callback, otherwise
5014          * return the number of entries.
5015          */
5016         token = &token_list[list[0]];
5017         if (i == 1 && token->comp) {
5018                 /* Save index for cmd_flow_get_help(). */
5019                 ctx->prev = list[0];
5020                 return token->comp(ctx, token, 0, NULL, 0);
5021         }
5022         return i;
5023 }
5024
5025 /** Return a completion entry (cmdline API). */
5026 static int
5027 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
5028                           char *dst, unsigned int size)
5029 {
5030         struct context *ctx = &cmd_flow_context;
5031         const struct token *token = &token_list[ctx->curr];
5032         const enum index *list;
5033         int i;
5034
5035         (void)hdr;
5036         /* Count number of tokens in current list. */
5037         if (ctx->next_num)
5038                 list = ctx->next[ctx->next_num - 1];
5039         else
5040                 list = token->next[0];
5041         for (i = 0; list[i]; ++i)
5042                 ;
5043         if (!i)
5044                 return -1;
5045         /* If there is a single token, use its completion callback. */
5046         token = &token_list[list[0]];
5047         if (i == 1 && token->comp) {
5048                 /* Save index for cmd_flow_get_help(). */
5049                 ctx->prev = list[0];
5050                 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
5051         }
5052         /* Otherwise make sure the index is valid and use defaults. */
5053         if (index >= i)
5054                 return -1;
5055         token = &token_list[list[index]];
5056         snprintf(dst, size, "%s", token->name);
5057         /* Save index for cmd_flow_get_help(). */
5058         ctx->prev = list[index];
5059         return 0;
5060 }
5061
5062 /** Populate help strings for current token (cmdline API). */
5063 static int
5064 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
5065 {
5066         struct context *ctx = &cmd_flow_context;
5067         const struct token *token = &token_list[ctx->prev];
5068
5069         (void)hdr;
5070         if (!size)
5071                 return -1;
5072         /* Set token type and update global help with details. */
5073         snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
5074         if (token->help)
5075                 cmd_flow.help_str = token->help;
5076         else
5077                 cmd_flow.help_str = token->name;
5078         return 0;
5079 }
5080
5081 /** Token definition template (cmdline API). */
5082 static struct cmdline_token_hdr cmd_flow_token_hdr = {
5083         .ops = &(struct cmdline_token_ops){
5084                 .parse = cmd_flow_parse,
5085                 .complete_get_nb = cmd_flow_complete_get_nb,
5086                 .complete_get_elt = cmd_flow_complete_get_elt,
5087                 .get_help = cmd_flow_get_help,
5088         },
5089         .offset = 0,
5090 };
5091
5092 /** Populate the next dynamic token. */
5093 static void
5094 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
5095              cmdline_parse_token_hdr_t **hdr_inst)
5096 {
5097         struct context *ctx = &cmd_flow_context;
5098
5099         /* Always reinitialize context before requesting the first token. */
5100         if (!(hdr_inst - cmd_flow.tokens))
5101                 cmd_flow_context_init(ctx);
5102         /* Return NULL when no more tokens are expected. */
5103         if (!ctx->next_num && ctx->curr) {
5104                 *hdr = NULL;
5105                 return;
5106         }
5107         /* Determine if command should end here. */
5108         if (ctx->eol && ctx->last && ctx->next_num) {
5109                 const enum index *list = ctx->next[ctx->next_num - 1];
5110                 int i;
5111
5112                 for (i = 0; list[i]; ++i) {
5113                         if (list[i] != END)
5114                                 continue;
5115                         *hdr = NULL;
5116                         return;
5117                 }
5118         }
5119         *hdr = &cmd_flow_token_hdr;
5120 }
5121
5122 /** Dispatch parsed buffer to function calls. */
5123 static void
5124 cmd_flow_parsed(const struct buffer *in)
5125 {
5126         switch (in->command) {
5127         case VALIDATE:
5128                 port_flow_validate(in->port, &in->args.vc.attr,
5129                                    in->args.vc.pattern, in->args.vc.actions);
5130                 break;
5131         case CREATE:
5132                 port_flow_create(in->port, &in->args.vc.attr,
5133                                  in->args.vc.pattern, in->args.vc.actions);
5134                 break;
5135         case DESTROY:
5136                 port_flow_destroy(in->port, in->args.destroy.rule_n,
5137                                   in->args.destroy.rule);
5138                 break;
5139         case FLUSH:
5140                 port_flow_flush(in->port);
5141                 break;
5142         case QUERY:
5143                 port_flow_query(in->port, in->args.query.rule,
5144                                 &in->args.query.action);
5145                 break;
5146         case LIST:
5147                 port_flow_list(in->port, in->args.list.group_n,
5148                                in->args.list.group);
5149                 break;
5150         case ISOLATE:
5151                 port_flow_isolate(in->port, in->args.isolate.set);
5152                 break;
5153         default:
5154                 break;
5155         }
5156 }
5157
5158 /** Token generator and output processing callback (cmdline API). */
5159 static void
5160 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
5161 {
5162         if (cl == NULL)
5163                 cmd_flow_tok(arg0, arg2);
5164         else
5165                 cmd_flow_parsed(arg0);
5166 }
5167
5168 /** Global parser instance (cmdline API). */
5169 cmdline_parse_inst_t cmd_flow = {
5170         .f = cmd_flow_cb,
5171         .data = NULL, /**< Unused. */
5172         .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
5173         .tokens = {
5174                 NULL,
5175         }, /**< Tokens are returned by cmd_flow_tok(). */
5176 };