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