New upstream version 18.11-rc2
[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 = 0,
3252                         .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
3253                         .key = NULL,
3254                         .queue = action_rss_data->queue,
3255                 },
3256                 .queue = { 0 },
3257         };
3258         for (i = 0; i < action_rss_data->conf.queue_num; ++i)
3259                 action_rss_data->queue[i] = i;
3260         action->conf = &action_rss_data->conf;
3261         return ret;
3262 }
3263
3264 /**
3265  * Parse func field for RSS action.
3266  *
3267  * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
3268  * ACTION_RSS_FUNC_* index that called this function.
3269  */
3270 static int
3271 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
3272                          const char *str, unsigned int len,
3273                          void *buf, unsigned int size)
3274 {
3275         struct action_rss_data *action_rss_data;
3276         enum rte_eth_hash_function func;
3277
3278         (void)buf;
3279         (void)size;
3280         /* Token name must match. */
3281         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3282                 return -1;
3283         switch (ctx->curr) {
3284         case ACTION_RSS_FUNC_DEFAULT:
3285                 func = RTE_ETH_HASH_FUNCTION_DEFAULT;
3286                 break;
3287         case ACTION_RSS_FUNC_TOEPLITZ:
3288                 func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
3289                 break;
3290         case ACTION_RSS_FUNC_SIMPLE_XOR:
3291                 func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
3292                 break;
3293         default:
3294                 return -1;
3295         }
3296         if (!ctx->object)
3297                 return len;
3298         action_rss_data = ctx->object;
3299         action_rss_data->conf.func = func;
3300         return len;
3301 }
3302
3303 /**
3304  * Parse type field for RSS action.
3305  *
3306  * Valid tokens are type field names and the "end" token.
3307  */
3308 static int
3309 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
3310                           const char *str, unsigned int len,
3311                           void *buf, unsigned int size)
3312 {
3313         static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
3314         struct action_rss_data *action_rss_data;
3315         unsigned int i;
3316
3317         (void)token;
3318         (void)buf;
3319         (void)size;
3320         if (ctx->curr != ACTION_RSS_TYPE)
3321                 return -1;
3322         if (!(ctx->objdata >> 16) && ctx->object) {
3323                 action_rss_data = ctx->object;
3324                 action_rss_data->conf.types = 0;
3325         }
3326         if (!strcmp_partial("end", str, len)) {
3327                 ctx->objdata &= 0xffff;
3328                 return len;
3329         }
3330         for (i = 0; rss_type_table[i].str; ++i)
3331                 if (!strcmp_partial(rss_type_table[i].str, str, len))
3332                         break;
3333         if (!rss_type_table[i].str)
3334                 return -1;
3335         ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
3336         /* Repeat token. */
3337         if (ctx->next_num == RTE_DIM(ctx->next))
3338                 return -1;
3339         ctx->next[ctx->next_num++] = next;
3340         if (!ctx->object)
3341                 return len;
3342         action_rss_data = ctx->object;
3343         action_rss_data->conf.types |= rss_type_table[i].rss_type;
3344         return len;
3345 }
3346
3347 /**
3348  * Parse queue field for RSS action.
3349  *
3350  * Valid tokens are queue indices and the "end" token.
3351  */
3352 static int
3353 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
3354                           const char *str, unsigned int len,
3355                           void *buf, unsigned int size)
3356 {
3357         static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
3358         struct action_rss_data *action_rss_data;
3359         int ret;
3360         int i;
3361
3362         (void)token;
3363         (void)buf;
3364         (void)size;
3365         if (ctx->curr != ACTION_RSS_QUEUE)
3366                 return -1;
3367         i = ctx->objdata >> 16;
3368         if (!strcmp_partial("end", str, len)) {
3369                 ctx->objdata &= 0xffff;
3370                 goto end;
3371         }
3372         if (i >= ACTION_RSS_QUEUE_NUM)
3373                 return -1;
3374         if (push_args(ctx,
3375                       ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
3376                                      i * sizeof(action_rss_data->queue[i]),
3377                                      sizeof(action_rss_data->queue[i]))))
3378                 return -1;
3379         ret = parse_int(ctx, token, str, len, NULL, 0);
3380         if (ret < 0) {
3381                 pop_args(ctx);
3382                 return -1;
3383         }
3384         ++i;
3385         ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
3386         /* Repeat token. */
3387         if (ctx->next_num == RTE_DIM(ctx->next))
3388                 return -1;
3389         ctx->next[ctx->next_num++] = next;
3390 end:
3391         if (!ctx->object)
3392                 return len;
3393         action_rss_data = ctx->object;
3394         action_rss_data->conf.queue_num = i;
3395         action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
3396         return len;
3397 }
3398
3399 /** Parse VXLAN encap action. */
3400 static int
3401 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
3402                             const char *str, unsigned int len,
3403                             void *buf, unsigned int size)
3404 {
3405         struct buffer *out = buf;
3406         struct rte_flow_action *action;
3407         struct action_vxlan_encap_data *action_vxlan_encap_data;
3408         int ret;
3409
3410         ret = parse_vc(ctx, token, str, len, buf, size);
3411         if (ret < 0)
3412                 return ret;
3413         /* Nothing else to do if there is no buffer. */
3414         if (!out)
3415                 return ret;
3416         if (!out->args.vc.actions_n)
3417                 return -1;
3418         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3419         /* Point to selected object. */
3420         ctx->object = out->args.vc.data;
3421         ctx->objmask = NULL;
3422         /* Set up default configuration. */
3423         action_vxlan_encap_data = ctx->object;
3424         *action_vxlan_encap_data = (struct action_vxlan_encap_data){
3425                 .conf = (struct rte_flow_action_vxlan_encap){
3426                         .definition = action_vxlan_encap_data->items,
3427                 },
3428                 .items = {
3429                         {
3430                                 .type = RTE_FLOW_ITEM_TYPE_ETH,
3431                                 .spec = &action_vxlan_encap_data->item_eth,
3432                                 .mask = &rte_flow_item_eth_mask,
3433                         },
3434                         {
3435                                 .type = RTE_FLOW_ITEM_TYPE_VLAN,
3436                                 .spec = &action_vxlan_encap_data->item_vlan,
3437                                 .mask = &rte_flow_item_vlan_mask,
3438                         },
3439                         {
3440                                 .type = RTE_FLOW_ITEM_TYPE_IPV4,
3441                                 .spec = &action_vxlan_encap_data->item_ipv4,
3442                                 .mask = &rte_flow_item_ipv4_mask,
3443                         },
3444                         {
3445                                 .type = RTE_FLOW_ITEM_TYPE_UDP,
3446                                 .spec = &action_vxlan_encap_data->item_udp,
3447                                 .mask = &rte_flow_item_udp_mask,
3448                         },
3449                         {
3450                                 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
3451                                 .spec = &action_vxlan_encap_data->item_vxlan,
3452                                 .mask = &rte_flow_item_vxlan_mask,
3453                         },
3454                         {
3455                                 .type = RTE_FLOW_ITEM_TYPE_END,
3456                         },
3457                 },
3458                 .item_eth.type = 0,
3459                 .item_vlan = {
3460                         .tci = vxlan_encap_conf.vlan_tci,
3461                         .inner_type = 0,
3462                 },
3463                 .item_ipv4.hdr = {
3464                         .src_addr = vxlan_encap_conf.ipv4_src,
3465                         .dst_addr = vxlan_encap_conf.ipv4_dst,
3466                 },
3467                 .item_udp.hdr = {
3468                         .src_port = vxlan_encap_conf.udp_src,
3469                         .dst_port = vxlan_encap_conf.udp_dst,
3470                 },
3471                 .item_vxlan.flags = 0,
3472         };
3473         memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes,
3474                vxlan_encap_conf.eth_dst, ETHER_ADDR_LEN);
3475         memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
3476                vxlan_encap_conf.eth_src, ETHER_ADDR_LEN);
3477         if (!vxlan_encap_conf.select_ipv4) {
3478                 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
3479                        &vxlan_encap_conf.ipv6_src,
3480                        sizeof(vxlan_encap_conf.ipv6_src));
3481                 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
3482                        &vxlan_encap_conf.ipv6_dst,
3483                        sizeof(vxlan_encap_conf.ipv6_dst));
3484                 action_vxlan_encap_data->items[2] = (struct rte_flow_item){
3485                         .type = RTE_FLOW_ITEM_TYPE_IPV6,
3486                         .spec = &action_vxlan_encap_data->item_ipv6,
3487                         .mask = &rte_flow_item_ipv6_mask,
3488                 };
3489         }
3490         if (!vxlan_encap_conf.select_vlan)
3491                 action_vxlan_encap_data->items[1].type =
3492                         RTE_FLOW_ITEM_TYPE_VOID;
3493         memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
3494                RTE_DIM(vxlan_encap_conf.vni));
3495         action->conf = &action_vxlan_encap_data->conf;
3496         return ret;
3497 }
3498
3499 /** Parse NVGRE encap action. */
3500 static int
3501 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
3502                             const char *str, unsigned int len,
3503                             void *buf, unsigned int size)
3504 {
3505         struct buffer *out = buf;
3506         struct rte_flow_action *action;
3507         struct action_nvgre_encap_data *action_nvgre_encap_data;
3508         int ret;
3509
3510         ret = parse_vc(ctx, token, str, len, buf, size);
3511         if (ret < 0)
3512                 return ret;
3513         /* Nothing else to do if there is no buffer. */
3514         if (!out)
3515                 return ret;
3516         if (!out->args.vc.actions_n)
3517                 return -1;
3518         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3519         /* Point to selected object. */
3520         ctx->object = out->args.vc.data;
3521         ctx->objmask = NULL;
3522         /* Set up default configuration. */
3523         action_nvgre_encap_data = ctx->object;
3524         *action_nvgre_encap_data = (struct action_nvgre_encap_data){
3525                 .conf = (struct rte_flow_action_nvgre_encap){
3526                         .definition = action_nvgre_encap_data->items,
3527                 },
3528                 .items = {
3529                         {
3530                                 .type = RTE_FLOW_ITEM_TYPE_ETH,
3531                                 .spec = &action_nvgre_encap_data->item_eth,
3532                                 .mask = &rte_flow_item_eth_mask,
3533                         },
3534                         {
3535                                 .type = RTE_FLOW_ITEM_TYPE_VLAN,
3536                                 .spec = &action_nvgre_encap_data->item_vlan,
3537                                 .mask = &rte_flow_item_vlan_mask,
3538                         },
3539                         {
3540                                 .type = RTE_FLOW_ITEM_TYPE_IPV4,
3541                                 .spec = &action_nvgre_encap_data->item_ipv4,
3542                                 .mask = &rte_flow_item_ipv4_mask,
3543                         },
3544                         {
3545                                 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
3546                                 .spec = &action_nvgre_encap_data->item_nvgre,
3547                                 .mask = &rte_flow_item_nvgre_mask,
3548                         },
3549                         {
3550                                 .type = RTE_FLOW_ITEM_TYPE_END,
3551                         },
3552                 },
3553                 .item_eth.type = 0,
3554                 .item_vlan = {
3555                         .tci = nvgre_encap_conf.vlan_tci,
3556                         .inner_type = 0,
3557                 },
3558                 .item_ipv4.hdr = {
3559                        .src_addr = nvgre_encap_conf.ipv4_src,
3560                        .dst_addr = nvgre_encap_conf.ipv4_dst,
3561                 },
3562                 .item_nvgre.flow_id = 0,
3563         };
3564         memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
3565                nvgre_encap_conf.eth_dst, ETHER_ADDR_LEN);
3566         memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
3567                nvgre_encap_conf.eth_src, ETHER_ADDR_LEN);
3568         if (!nvgre_encap_conf.select_ipv4) {
3569                 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
3570                        &nvgre_encap_conf.ipv6_src,
3571                        sizeof(nvgre_encap_conf.ipv6_src));
3572                 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
3573                        &nvgre_encap_conf.ipv6_dst,
3574                        sizeof(nvgre_encap_conf.ipv6_dst));
3575                 action_nvgre_encap_data->items[2] = (struct rte_flow_item){
3576                         .type = RTE_FLOW_ITEM_TYPE_IPV6,
3577                         .spec = &action_nvgre_encap_data->item_ipv6,
3578                         .mask = &rte_flow_item_ipv6_mask,
3579                 };
3580         }
3581         if (!nvgre_encap_conf.select_vlan)
3582                 action_nvgre_encap_data->items[1].type =
3583                         RTE_FLOW_ITEM_TYPE_VOID;
3584         memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
3585                RTE_DIM(nvgre_encap_conf.tni));
3586         action->conf = &action_nvgre_encap_data->conf;
3587         return ret;
3588 }
3589
3590 /** Parse l2 encap action. */
3591 static int
3592 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
3593                          const char *str, unsigned int len,
3594                          void *buf, unsigned int size)
3595 {
3596         struct buffer *out = buf;
3597         struct rte_flow_action *action;
3598         struct action_raw_encap_data *action_encap_data;
3599         struct rte_flow_item_eth eth = { .type = 0, };
3600         struct rte_flow_item_vlan vlan = {
3601                 .tci = mplsoudp_encap_conf.vlan_tci,
3602                 .inner_type = 0,
3603         };
3604         uint8_t *header;
3605         int ret;
3606
3607         ret = parse_vc(ctx, token, str, len, buf, size);
3608         if (ret < 0)
3609                 return ret;
3610         /* Nothing else to do if there is no buffer. */
3611         if (!out)
3612                 return ret;
3613         if (!out->args.vc.actions_n)
3614                 return -1;
3615         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3616         /* Point to selected object. */
3617         ctx->object = out->args.vc.data;
3618         ctx->objmask = NULL;
3619         /* Copy the headers to the buffer. */
3620         action_encap_data = ctx->object;
3621         *action_encap_data = (struct action_raw_encap_data) {
3622                 .conf = (struct rte_flow_action_raw_encap){
3623                         .data = action_encap_data->data,
3624                 },
3625                 .data = {},
3626         };
3627         header = action_encap_data->data;
3628         if (l2_encap_conf.select_vlan)
3629                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
3630         else if (l2_encap_conf.select_ipv4)
3631                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3632         else
3633                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3634         memcpy(eth.dst.addr_bytes,
3635                l2_encap_conf.eth_dst, ETHER_ADDR_LEN);
3636         memcpy(eth.src.addr_bytes,
3637                l2_encap_conf.eth_src, ETHER_ADDR_LEN);
3638         memcpy(header, &eth, sizeof(eth));
3639         header += sizeof(eth);
3640         if (l2_encap_conf.select_vlan) {
3641                 if (l2_encap_conf.select_ipv4)
3642                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3643                 else
3644                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3645                 memcpy(header, &vlan, sizeof(vlan));
3646                 header += sizeof(vlan);
3647         }
3648         action_encap_data->conf.size = header -
3649                 action_encap_data->data;
3650         action->conf = &action_encap_data->conf;
3651         return ret;
3652 }
3653
3654 /** Parse l2 decap action. */
3655 static int
3656 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
3657                          const char *str, unsigned int len,
3658                          void *buf, unsigned int size)
3659 {
3660         struct buffer *out = buf;
3661         struct rte_flow_action *action;
3662         struct action_raw_decap_data *action_decap_data;
3663         struct rte_flow_item_eth eth = { .type = 0, };
3664         struct rte_flow_item_vlan vlan = {
3665                 .tci = mplsoudp_encap_conf.vlan_tci,
3666                 .inner_type = 0,
3667         };
3668         uint8_t *header;
3669         int ret;
3670
3671         ret = parse_vc(ctx, token, str, len, buf, size);
3672         if (ret < 0)
3673                 return ret;
3674         /* Nothing else to do if there is no buffer. */
3675         if (!out)
3676                 return ret;
3677         if (!out->args.vc.actions_n)
3678                 return -1;
3679         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3680         /* Point to selected object. */
3681         ctx->object = out->args.vc.data;
3682         ctx->objmask = NULL;
3683         /* Copy the headers to the buffer. */
3684         action_decap_data = ctx->object;
3685         *action_decap_data = (struct action_raw_decap_data) {
3686                 .conf = (struct rte_flow_action_raw_decap){
3687                         .data = action_decap_data->data,
3688                 },
3689                 .data = {},
3690         };
3691         header = action_decap_data->data;
3692         if (l2_decap_conf.select_vlan)
3693                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
3694         memcpy(header, &eth, sizeof(eth));
3695         header += sizeof(eth);
3696         if (l2_decap_conf.select_vlan) {
3697                 memcpy(header, &vlan, sizeof(vlan));
3698                 header += sizeof(vlan);
3699         }
3700         action_decap_data->conf.size = header -
3701                 action_decap_data->data;
3702         action->conf = &action_decap_data->conf;
3703         return ret;
3704 }
3705
3706 #define ETHER_TYPE_MPLS_UNICAST 0x8847
3707
3708 /** Parse MPLSOGRE encap action. */
3709 static int
3710 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
3711                                const char *str, unsigned int len,
3712                                void *buf, unsigned int size)
3713 {
3714         struct buffer *out = buf;
3715         struct rte_flow_action *action;
3716         struct action_raw_encap_data *action_encap_data;
3717         struct rte_flow_item_eth eth = { .type = 0, };
3718         struct rte_flow_item_vlan vlan = {
3719                 .tci = mplsogre_encap_conf.vlan_tci,
3720                 .inner_type = 0,
3721         };
3722         struct rte_flow_item_ipv4 ipv4 = {
3723                 .hdr =  {
3724                         .src_addr = mplsogre_encap_conf.ipv4_src,
3725                         .dst_addr = mplsogre_encap_conf.ipv4_dst,
3726                         .next_proto_id = IPPROTO_GRE,
3727                 },
3728         };
3729         struct rte_flow_item_ipv6 ipv6 = {
3730                 .hdr =  {
3731                         .proto = IPPROTO_GRE,
3732                 },
3733         };
3734         struct rte_flow_item_gre gre = {
3735                 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
3736         };
3737         struct rte_flow_item_mpls mpls;
3738         uint8_t *header;
3739         int ret;
3740
3741         ret = parse_vc(ctx, token, str, len, buf, size);
3742         if (ret < 0)
3743                 return ret;
3744         /* Nothing else to do if there is no buffer. */
3745         if (!out)
3746                 return ret;
3747         if (!out->args.vc.actions_n)
3748                 return -1;
3749         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3750         /* Point to selected object. */
3751         ctx->object = out->args.vc.data;
3752         ctx->objmask = NULL;
3753         /* Copy the headers to the buffer. */
3754         action_encap_data = ctx->object;
3755         *action_encap_data = (struct action_raw_encap_data) {
3756                 .conf = (struct rte_flow_action_raw_encap){
3757                         .data = action_encap_data->data,
3758                 },
3759                 .data = {},
3760                 .preserve = {},
3761         };
3762         header = action_encap_data->data;
3763         if (mplsogre_encap_conf.select_vlan)
3764                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
3765         else if (mplsogre_encap_conf.select_ipv4)
3766                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3767         else
3768                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3769         memcpy(eth.dst.addr_bytes,
3770                mplsogre_encap_conf.eth_dst, ETHER_ADDR_LEN);
3771         memcpy(eth.src.addr_bytes,
3772                mplsogre_encap_conf.eth_src, ETHER_ADDR_LEN);
3773         memcpy(header, &eth, sizeof(eth));
3774         header += sizeof(eth);
3775         if (mplsogre_encap_conf.select_vlan) {
3776                 if (mplsogre_encap_conf.select_ipv4)
3777                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3778                 else
3779                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3780                 memcpy(header, &vlan, sizeof(vlan));
3781                 header += sizeof(vlan);
3782         }
3783         if (mplsogre_encap_conf.select_ipv4) {
3784                 memcpy(header, &ipv4, sizeof(ipv4));
3785                 header += sizeof(ipv4);
3786         } else {
3787                 memcpy(&ipv6.hdr.src_addr,
3788                        &mplsogre_encap_conf.ipv6_src,
3789                        sizeof(mplsogre_encap_conf.ipv6_src));
3790                 memcpy(&ipv6.hdr.dst_addr,
3791                        &mplsogre_encap_conf.ipv6_dst,
3792                        sizeof(mplsogre_encap_conf.ipv6_dst));
3793                 memcpy(header, &ipv6, sizeof(ipv6));
3794                 header += sizeof(ipv6);
3795         }
3796         memcpy(header, &gre, sizeof(gre));
3797         header += sizeof(gre);
3798         memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
3799                RTE_DIM(mplsogre_encap_conf.label));
3800         memcpy(header, &mpls, sizeof(mpls));
3801         header += sizeof(mpls);
3802         action_encap_data->conf.size = header -
3803                 action_encap_data->data;
3804         action->conf = &action_encap_data->conf;
3805         return ret;
3806 }
3807
3808 /** Parse MPLSOGRE decap action. */
3809 static int
3810 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
3811                                const char *str, unsigned int len,
3812                                void *buf, unsigned int size)
3813 {
3814         struct buffer *out = buf;
3815         struct rte_flow_action *action;
3816         struct action_raw_decap_data *action_decap_data;
3817         struct rte_flow_item_eth eth = { .type = 0, };
3818         struct rte_flow_item_vlan vlan = {.tci = 0};
3819         struct rte_flow_item_ipv4 ipv4 = {
3820                 .hdr =  {
3821                         .next_proto_id = IPPROTO_GRE,
3822                 },
3823         };
3824         struct rte_flow_item_ipv6 ipv6 = {
3825                 .hdr =  {
3826                         .proto = IPPROTO_GRE,
3827                 },
3828         };
3829         struct rte_flow_item_gre gre = {
3830                 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
3831         };
3832         struct rte_flow_item_mpls mpls;
3833         uint8_t *header;
3834         int ret;
3835
3836         ret = parse_vc(ctx, token, str, len, buf, size);
3837         if (ret < 0)
3838                 return ret;
3839         /* Nothing else to do if there is no buffer. */
3840         if (!out)
3841                 return ret;
3842         if (!out->args.vc.actions_n)
3843                 return -1;
3844         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3845         /* Point to selected object. */
3846         ctx->object = out->args.vc.data;
3847         ctx->objmask = NULL;
3848         /* Copy the headers to the buffer. */
3849         action_decap_data = ctx->object;
3850         *action_decap_data = (struct action_raw_decap_data) {
3851                 .conf = (struct rte_flow_action_raw_decap){
3852                         .data = action_decap_data->data,
3853                 },
3854                 .data = {},
3855         };
3856         header = action_decap_data->data;
3857         if (mplsogre_decap_conf.select_vlan)
3858                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
3859         else if (mplsogre_encap_conf.select_ipv4)
3860                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3861         else
3862                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3863         memcpy(eth.dst.addr_bytes,
3864                mplsogre_encap_conf.eth_dst, ETHER_ADDR_LEN);
3865         memcpy(eth.src.addr_bytes,
3866                mplsogre_encap_conf.eth_src, ETHER_ADDR_LEN);
3867         memcpy(header, &eth, sizeof(eth));
3868         header += sizeof(eth);
3869         if (mplsogre_encap_conf.select_vlan) {
3870                 if (mplsogre_encap_conf.select_ipv4)
3871                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3872                 else
3873                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3874                 memcpy(header, &vlan, sizeof(vlan));
3875                 header += sizeof(vlan);
3876         }
3877         if (mplsogre_encap_conf.select_ipv4) {
3878                 memcpy(header, &ipv4, sizeof(ipv4));
3879                 header += sizeof(ipv4);
3880         } else {
3881                 memcpy(header, &ipv6, sizeof(ipv6));
3882                 header += sizeof(ipv6);
3883         }
3884         memcpy(header, &gre, sizeof(gre));
3885         header += sizeof(gre);
3886         memset(&mpls, 0, sizeof(mpls));
3887         memcpy(header, &mpls, sizeof(mpls));
3888         header += sizeof(mpls);
3889         action_decap_data->conf.size = header -
3890                 action_decap_data->data;
3891         action->conf = &action_decap_data->conf;
3892         return ret;
3893 }
3894
3895 /** Parse MPLSOUDP encap action. */
3896 static int
3897 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
3898                                const char *str, unsigned int len,
3899                                void *buf, unsigned int size)
3900 {
3901         struct buffer *out = buf;
3902         struct rte_flow_action *action;
3903         struct action_raw_encap_data *action_encap_data;
3904         struct rte_flow_item_eth eth = { .type = 0, };
3905         struct rte_flow_item_vlan vlan = {
3906                 .tci = mplsoudp_encap_conf.vlan_tci,
3907                 .inner_type = 0,
3908         };
3909         struct rte_flow_item_ipv4 ipv4 = {
3910                 .hdr =  {
3911                         .src_addr = mplsoudp_encap_conf.ipv4_src,
3912                         .dst_addr = mplsoudp_encap_conf.ipv4_dst,
3913                         .next_proto_id = IPPROTO_UDP,
3914                 },
3915         };
3916         struct rte_flow_item_ipv6 ipv6 = {
3917                 .hdr =  {
3918                         .proto = IPPROTO_UDP,
3919                 },
3920         };
3921         struct rte_flow_item_udp udp = {
3922                 .hdr = {
3923                         .src_port = mplsoudp_encap_conf.udp_src,
3924                         .dst_port = mplsoudp_encap_conf.udp_dst,
3925                 },
3926         };
3927         struct rte_flow_item_mpls mpls;
3928         uint8_t *header;
3929         int ret;
3930
3931         ret = parse_vc(ctx, token, str, len, buf, size);
3932         if (ret < 0)
3933                 return ret;
3934         /* Nothing else to do if there is no buffer. */
3935         if (!out)
3936                 return ret;
3937         if (!out->args.vc.actions_n)
3938                 return -1;
3939         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3940         /* Point to selected object. */
3941         ctx->object = out->args.vc.data;
3942         ctx->objmask = NULL;
3943         /* Copy the headers to the buffer. */
3944         action_encap_data = ctx->object;
3945         *action_encap_data = (struct action_raw_encap_data) {
3946                 .conf = (struct rte_flow_action_raw_encap){
3947                         .data = action_encap_data->data,
3948                 },
3949                 .data = {},
3950                 .preserve = {},
3951         };
3952         header = action_encap_data->data;
3953         if (mplsoudp_encap_conf.select_vlan)
3954                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
3955         else if (mplsoudp_encap_conf.select_ipv4)
3956                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3957         else
3958                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3959         memcpy(eth.dst.addr_bytes,
3960                mplsoudp_encap_conf.eth_dst, ETHER_ADDR_LEN);
3961         memcpy(eth.src.addr_bytes,
3962                mplsoudp_encap_conf.eth_src, ETHER_ADDR_LEN);
3963         memcpy(header, &eth, sizeof(eth));
3964         header += sizeof(eth);
3965         if (mplsoudp_encap_conf.select_vlan) {
3966                 if (mplsoudp_encap_conf.select_ipv4)
3967                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3968                 else
3969                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3970                 memcpy(header, &vlan, sizeof(vlan));
3971                 header += sizeof(vlan);
3972         }
3973         if (mplsoudp_encap_conf.select_ipv4) {
3974                 memcpy(header, &ipv4, sizeof(ipv4));
3975                 header += sizeof(ipv4);
3976         } else {
3977                 memcpy(&ipv6.hdr.src_addr,
3978                        &mplsoudp_encap_conf.ipv6_src,
3979                        sizeof(mplsoudp_encap_conf.ipv6_src));
3980                 memcpy(&ipv6.hdr.dst_addr,
3981                        &mplsoudp_encap_conf.ipv6_dst,
3982                        sizeof(mplsoudp_encap_conf.ipv6_dst));
3983                 memcpy(header, &ipv6, sizeof(ipv6));
3984                 header += sizeof(ipv6);
3985         }
3986         memcpy(header, &udp, sizeof(udp));
3987         header += sizeof(udp);
3988         memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
3989                RTE_DIM(mplsoudp_encap_conf.label));
3990         memcpy(header, &mpls, sizeof(mpls));
3991         header += sizeof(mpls);
3992         action_encap_data->conf.size = header -
3993                 action_encap_data->data;
3994         action->conf = &action_encap_data->conf;
3995         return ret;
3996 }
3997
3998 /** Parse MPLSOUDP decap action. */
3999 static int
4000 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
4001                                const char *str, unsigned int len,
4002                                void *buf, unsigned int size)
4003 {
4004         struct buffer *out = buf;
4005         struct rte_flow_action *action;
4006         struct action_raw_decap_data *action_decap_data;
4007         struct rte_flow_item_eth eth = { .type = 0, };
4008         struct rte_flow_item_vlan vlan = {.tci = 0};
4009         struct rte_flow_item_ipv4 ipv4 = {
4010                 .hdr =  {
4011                         .next_proto_id = IPPROTO_UDP,
4012                 },
4013         };
4014         struct rte_flow_item_ipv6 ipv6 = {
4015                 .hdr =  {
4016                         .proto = IPPROTO_UDP,
4017                 },
4018         };
4019         struct rte_flow_item_udp udp = {
4020                 .hdr = {
4021                         .dst_port = rte_cpu_to_be_16(6635),
4022                 },
4023         };
4024         struct rte_flow_item_mpls mpls;
4025         uint8_t *header;
4026         int ret;
4027
4028         ret = parse_vc(ctx, token, str, len, buf, size);
4029         if (ret < 0)
4030                 return ret;
4031         /* Nothing else to do if there is no buffer. */
4032         if (!out)
4033                 return ret;
4034         if (!out->args.vc.actions_n)
4035                 return -1;
4036         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4037         /* Point to selected object. */
4038         ctx->object = out->args.vc.data;
4039         ctx->objmask = NULL;
4040         /* Copy the headers to the buffer. */
4041         action_decap_data = ctx->object;
4042         *action_decap_data = (struct action_raw_decap_data) {
4043                 .conf = (struct rte_flow_action_raw_decap){
4044                         .data = action_decap_data->data,
4045                 },
4046                 .data = {},
4047         };
4048         header = action_decap_data->data;
4049         if (mplsoudp_decap_conf.select_vlan)
4050                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
4051         else if (mplsoudp_encap_conf.select_ipv4)
4052                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
4053         else
4054                 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
4055         memcpy(eth.dst.addr_bytes,
4056                mplsoudp_encap_conf.eth_dst, ETHER_ADDR_LEN);
4057         memcpy(eth.src.addr_bytes,
4058                mplsoudp_encap_conf.eth_src, ETHER_ADDR_LEN);
4059         memcpy(header, &eth, sizeof(eth));
4060         header += sizeof(eth);
4061         if (mplsoudp_encap_conf.select_vlan) {
4062                 if (mplsoudp_encap_conf.select_ipv4)
4063                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
4064                 else
4065                         vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
4066                 memcpy(header, &vlan, sizeof(vlan));
4067                 header += sizeof(vlan);
4068         }
4069         if (mplsoudp_encap_conf.select_ipv4) {
4070                 memcpy(header, &ipv4, sizeof(ipv4));
4071                 header += sizeof(ipv4);
4072         } else {
4073                 memcpy(header, &ipv6, sizeof(ipv6));
4074                 header += sizeof(ipv6);
4075         }
4076         memcpy(header, &udp, sizeof(udp));
4077         header += sizeof(udp);
4078         memset(&mpls, 0, sizeof(mpls));
4079         memcpy(header, &mpls, sizeof(mpls));
4080         header += sizeof(mpls);
4081         action_decap_data->conf.size = header -
4082                 action_decap_data->data;
4083         action->conf = &action_decap_data->conf;
4084         return ret;
4085 }
4086
4087 /** Parse tokens for destroy command. */
4088 static int
4089 parse_destroy(struct context *ctx, const struct token *token,
4090               const char *str, unsigned int len,
4091               void *buf, unsigned int size)
4092 {
4093         struct buffer *out = buf;
4094
4095         /* Token name must match. */
4096         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4097                 return -1;
4098         /* Nothing else to do if there is no buffer. */
4099         if (!out)
4100                 return len;
4101         if (!out->command) {
4102                 if (ctx->curr != DESTROY)
4103                         return -1;
4104                 if (sizeof(*out) > size)
4105                         return -1;
4106                 out->command = ctx->curr;
4107                 ctx->objdata = 0;
4108                 ctx->object = out;
4109                 ctx->objmask = NULL;
4110                 out->args.destroy.rule =
4111                         (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
4112                                                sizeof(double));
4113                 return len;
4114         }
4115         if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
4116              sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
4117                 return -1;
4118         ctx->objdata = 0;
4119         ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
4120         ctx->objmask = NULL;
4121         return len;
4122 }
4123
4124 /** Parse tokens for flush command. */
4125 static int
4126 parse_flush(struct context *ctx, const struct token *token,
4127             const char *str, unsigned int len,
4128             void *buf, unsigned int size)
4129 {
4130         struct buffer *out = buf;
4131
4132         /* Token name must match. */
4133         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4134                 return -1;
4135         /* Nothing else to do if there is no buffer. */
4136         if (!out)
4137                 return len;
4138         if (!out->command) {
4139                 if (ctx->curr != FLUSH)
4140                         return -1;
4141                 if (sizeof(*out) > size)
4142                         return -1;
4143                 out->command = ctx->curr;
4144                 ctx->objdata = 0;
4145                 ctx->object = out;
4146                 ctx->objmask = NULL;
4147         }
4148         return len;
4149 }
4150
4151 /** Parse tokens for query command. */
4152 static int
4153 parse_query(struct context *ctx, const struct token *token,
4154             const char *str, unsigned int len,
4155             void *buf, unsigned int size)
4156 {
4157         struct buffer *out = buf;
4158
4159         /* Token name must match. */
4160         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4161                 return -1;
4162         /* Nothing else to do if there is no buffer. */
4163         if (!out)
4164                 return len;
4165         if (!out->command) {
4166                 if (ctx->curr != QUERY)
4167                         return -1;
4168                 if (sizeof(*out) > size)
4169                         return -1;
4170                 out->command = ctx->curr;
4171                 ctx->objdata = 0;
4172                 ctx->object = out;
4173                 ctx->objmask = NULL;
4174         }
4175         return len;
4176 }
4177
4178 /** Parse action names. */
4179 static int
4180 parse_action(struct context *ctx, const struct token *token,
4181              const char *str, unsigned int len,
4182              void *buf, unsigned int size)
4183 {
4184         struct buffer *out = buf;
4185         const struct arg *arg = pop_args(ctx);
4186         unsigned int i;
4187
4188         (void)size;
4189         /* Argument is expected. */
4190         if (!arg)
4191                 return -1;
4192         /* Parse action name. */
4193         for (i = 0; next_action[i]; ++i) {
4194                 const struct parse_action_priv *priv;
4195
4196                 token = &token_list[next_action[i]];
4197                 if (strcmp_partial(token->name, str, len))
4198                         continue;
4199                 priv = token->priv;
4200                 if (!priv)
4201                         goto error;
4202                 if (out)
4203                         memcpy((uint8_t *)ctx->object + arg->offset,
4204                                &priv->type,
4205                                arg->size);
4206                 return len;
4207         }
4208 error:
4209         push_args(ctx, arg);
4210         return -1;
4211 }
4212
4213 /** Parse tokens for list command. */
4214 static int
4215 parse_list(struct context *ctx, const struct token *token,
4216            const char *str, unsigned int len,
4217            void *buf, unsigned int size)
4218 {
4219         struct buffer *out = buf;
4220
4221         /* Token name must match. */
4222         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4223                 return -1;
4224         /* Nothing else to do if there is no buffer. */
4225         if (!out)
4226                 return len;
4227         if (!out->command) {
4228                 if (ctx->curr != LIST)
4229                         return -1;
4230                 if (sizeof(*out) > size)
4231                         return -1;
4232                 out->command = ctx->curr;
4233                 ctx->objdata = 0;
4234                 ctx->object = out;
4235                 ctx->objmask = NULL;
4236                 out->args.list.group =
4237                         (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
4238                                                sizeof(double));
4239                 return len;
4240         }
4241         if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
4242              sizeof(*out->args.list.group)) > (uint8_t *)out + size)
4243                 return -1;
4244         ctx->objdata = 0;
4245         ctx->object = out->args.list.group + out->args.list.group_n++;
4246         ctx->objmask = NULL;
4247         return len;
4248 }
4249
4250 /** Parse tokens for isolate command. */
4251 static int
4252 parse_isolate(struct context *ctx, const struct token *token,
4253               const char *str, unsigned int len,
4254               void *buf, unsigned int size)
4255 {
4256         struct buffer *out = buf;
4257
4258         /* Token name must match. */
4259         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4260                 return -1;
4261         /* Nothing else to do if there is no buffer. */
4262         if (!out)
4263                 return len;
4264         if (!out->command) {
4265                 if (ctx->curr != ISOLATE)
4266                         return -1;
4267                 if (sizeof(*out) > size)
4268                         return -1;
4269                 out->command = ctx->curr;
4270                 ctx->objdata = 0;
4271                 ctx->object = out;
4272                 ctx->objmask = NULL;
4273         }
4274         return len;
4275 }
4276
4277 /**
4278  * Parse signed/unsigned integers 8 to 64-bit long.
4279  *
4280  * Last argument (ctx->args) is retrieved to determine integer type and
4281  * storage location.
4282  */
4283 static int
4284 parse_int(struct context *ctx, const struct token *token,
4285           const char *str, unsigned int len,
4286           void *buf, unsigned int size)
4287 {
4288         const struct arg *arg = pop_args(ctx);
4289         uintmax_t u;
4290         char *end;
4291
4292         (void)token;
4293         /* Argument is expected. */
4294         if (!arg)
4295                 return -1;
4296         errno = 0;
4297         u = arg->sign ?
4298                 (uintmax_t)strtoimax(str, &end, 0) :
4299                 strtoumax(str, &end, 0);
4300         if (errno || (size_t)(end - str) != len)
4301                 goto error;
4302         if (arg->bounded &&
4303             ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
4304                             (intmax_t)u > (intmax_t)arg->max)) ||
4305              (!arg->sign && (u < arg->min || u > arg->max))))
4306                 goto error;
4307         if (!ctx->object)
4308                 return len;
4309         if (arg->mask) {
4310                 if (!arg_entry_bf_fill(ctx->object, u, arg) ||
4311                     !arg_entry_bf_fill(ctx->objmask, -1, arg))
4312                         goto error;
4313                 return len;
4314         }
4315         buf = (uint8_t *)ctx->object + arg->offset;
4316         size = arg->size;
4317 objmask:
4318         switch (size) {
4319         case sizeof(uint8_t):
4320                 *(uint8_t *)buf = u;
4321                 break;
4322         case sizeof(uint16_t):
4323                 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
4324                 break;
4325         case sizeof(uint8_t [3]):
4326 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4327                 if (!arg->hton) {
4328                         ((uint8_t *)buf)[0] = u;
4329                         ((uint8_t *)buf)[1] = u >> 8;
4330                         ((uint8_t *)buf)[2] = u >> 16;
4331                         break;
4332                 }
4333 #endif
4334                 ((uint8_t *)buf)[0] = u >> 16;
4335                 ((uint8_t *)buf)[1] = u >> 8;
4336                 ((uint8_t *)buf)[2] = u;
4337                 break;
4338         case sizeof(uint32_t):
4339                 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
4340                 break;
4341         case sizeof(uint64_t):
4342                 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
4343                 break;
4344         default:
4345                 goto error;
4346         }
4347         if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
4348                 u = -1;
4349                 buf = (uint8_t *)ctx->objmask + arg->offset;
4350                 goto objmask;
4351         }
4352         return len;
4353 error:
4354         push_args(ctx, arg);
4355         return -1;
4356 }
4357
4358 /**
4359  * Parse a string.
4360  *
4361  * Three arguments (ctx->args) are retrieved from the stack to store data,
4362  * its actual length and address (in that order).
4363  */
4364 static int
4365 parse_string(struct context *ctx, const struct token *token,
4366              const char *str, unsigned int len,
4367              void *buf, unsigned int size)
4368 {
4369         const struct arg *arg_data = pop_args(ctx);
4370         const struct arg *arg_len = pop_args(ctx);
4371         const struct arg *arg_addr = pop_args(ctx);
4372         char tmp[16]; /* Ought to be enough. */
4373         int ret;
4374
4375         /* Arguments are expected. */
4376         if (!arg_data)
4377                 return -1;
4378         if (!arg_len) {
4379                 push_args(ctx, arg_data);
4380                 return -1;
4381         }
4382         if (!arg_addr) {
4383                 push_args(ctx, arg_len);
4384                 push_args(ctx, arg_data);
4385                 return -1;
4386         }
4387         size = arg_data->size;
4388         /* Bit-mask fill is not supported. */
4389         if (arg_data->mask || size < len)
4390                 goto error;
4391         if (!ctx->object)
4392                 return len;
4393         /* Let parse_int() fill length information first. */
4394         ret = snprintf(tmp, sizeof(tmp), "%u", len);
4395         if (ret < 0)
4396                 goto error;
4397         push_args(ctx, arg_len);
4398         ret = parse_int(ctx, token, tmp, ret, NULL, 0);
4399         if (ret < 0) {
4400                 pop_args(ctx);
4401                 goto error;
4402         }
4403         buf = (uint8_t *)ctx->object + arg_data->offset;
4404         /* Output buffer is not necessarily NUL-terminated. */
4405         memcpy(buf, str, len);
4406         memset((uint8_t *)buf + len, 0x00, size - len);
4407         if (ctx->objmask)
4408                 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
4409         /* Save address if requested. */
4410         if (arg_addr->size) {
4411                 memcpy((uint8_t *)ctx->object + arg_addr->offset,
4412                        (void *[]){
4413                         (uint8_t *)ctx->object + arg_data->offset
4414                        },
4415                        arg_addr->size);
4416                 if (ctx->objmask)
4417                         memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
4418                                (void *[]){
4419                                 (uint8_t *)ctx->objmask + arg_data->offset
4420                                },
4421                                arg_addr->size);
4422         }
4423         return len;
4424 error:
4425         push_args(ctx, arg_addr);
4426         push_args(ctx, arg_len);
4427         push_args(ctx, arg_data);
4428         return -1;
4429 }
4430
4431 /**
4432  * Parse a MAC address.
4433  *
4434  * Last argument (ctx->args) is retrieved to determine storage size and
4435  * location.
4436  */
4437 static int
4438 parse_mac_addr(struct context *ctx, const struct token *token,
4439                const char *str, unsigned int len,
4440                void *buf, unsigned int size)
4441 {
4442         const struct arg *arg = pop_args(ctx);
4443         struct ether_addr tmp;
4444         int ret;
4445
4446         (void)token;
4447         /* Argument is expected. */
4448         if (!arg)
4449                 return -1;
4450         size = arg->size;
4451         /* Bit-mask fill is not supported. */
4452         if (arg->mask || size != sizeof(tmp))
4453                 goto error;
4454         /* Only network endian is supported. */
4455         if (!arg->hton)
4456                 goto error;
4457         ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
4458         if (ret < 0 || (unsigned int)ret != len)
4459                 goto error;
4460         if (!ctx->object)
4461                 return len;
4462         buf = (uint8_t *)ctx->object + arg->offset;
4463         memcpy(buf, &tmp, size);
4464         if (ctx->objmask)
4465                 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
4466         return len;
4467 error:
4468         push_args(ctx, arg);
4469         return -1;
4470 }
4471
4472 /**
4473  * Parse an IPv4 address.
4474  *
4475  * Last argument (ctx->args) is retrieved to determine storage size and
4476  * location.
4477  */
4478 static int
4479 parse_ipv4_addr(struct context *ctx, const struct token *token,
4480                 const char *str, unsigned int len,
4481                 void *buf, unsigned int size)
4482 {
4483         const struct arg *arg = pop_args(ctx);
4484         char str2[len + 1];
4485         struct in_addr tmp;
4486         int ret;
4487
4488         /* Argument is expected. */
4489         if (!arg)
4490                 return -1;
4491         size = arg->size;
4492         /* Bit-mask fill is not supported. */
4493         if (arg->mask || size != sizeof(tmp))
4494                 goto error;
4495         /* Only network endian is supported. */
4496         if (!arg->hton)
4497                 goto error;
4498         memcpy(str2, str, len);
4499         str2[len] = '\0';
4500         ret = inet_pton(AF_INET, str2, &tmp);
4501         if (ret != 1) {
4502                 /* Attempt integer parsing. */
4503                 push_args(ctx, arg);
4504                 return parse_int(ctx, token, str, len, buf, size);
4505         }
4506         if (!ctx->object)
4507                 return len;
4508         buf = (uint8_t *)ctx->object + arg->offset;
4509         memcpy(buf, &tmp, size);
4510         if (ctx->objmask)
4511                 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
4512         return len;
4513 error:
4514         push_args(ctx, arg);
4515         return -1;
4516 }
4517
4518 /**
4519  * Parse an IPv6 address.
4520  *
4521  * Last argument (ctx->args) is retrieved to determine storage size and
4522  * location.
4523  */
4524 static int
4525 parse_ipv6_addr(struct context *ctx, const struct token *token,
4526                 const char *str, unsigned int len,
4527                 void *buf, unsigned int size)
4528 {
4529         const struct arg *arg = pop_args(ctx);
4530         char str2[len + 1];
4531         struct in6_addr tmp;
4532         int ret;
4533
4534         (void)token;
4535         /* Argument is expected. */
4536         if (!arg)
4537                 return -1;
4538         size = arg->size;
4539         /* Bit-mask fill is not supported. */
4540         if (arg->mask || size != sizeof(tmp))
4541                 goto error;
4542         /* Only network endian is supported. */
4543         if (!arg->hton)
4544                 goto error;
4545         memcpy(str2, str, len);
4546         str2[len] = '\0';
4547         ret = inet_pton(AF_INET6, str2, &tmp);
4548         if (ret != 1)
4549                 goto error;
4550         if (!ctx->object)
4551                 return len;
4552         buf = (uint8_t *)ctx->object + arg->offset;
4553         memcpy(buf, &tmp, size);
4554         if (ctx->objmask)
4555                 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
4556         return len;
4557 error:
4558         push_args(ctx, arg);
4559         return -1;
4560 }
4561
4562 /** Boolean values (even indices stand for false). */
4563 static const char *const boolean_name[] = {
4564         "0", "1",
4565         "false", "true",
4566         "no", "yes",
4567         "N", "Y",
4568         "off", "on",
4569         NULL,
4570 };
4571
4572 /**
4573  * Parse a boolean value.
4574  *
4575  * Last argument (ctx->args) is retrieved to determine storage size and
4576  * location.
4577  */
4578 static int
4579 parse_boolean(struct context *ctx, const struct token *token,
4580               const char *str, unsigned int len,
4581               void *buf, unsigned int size)
4582 {
4583         const struct arg *arg = pop_args(ctx);
4584         unsigned int i;
4585         int ret;
4586
4587         /* Argument is expected. */
4588         if (!arg)
4589                 return -1;
4590         for (i = 0; boolean_name[i]; ++i)
4591                 if (!strcmp_partial(boolean_name[i], str, len))
4592                         break;
4593         /* Process token as integer. */
4594         if (boolean_name[i])
4595                 str = i & 1 ? "1" : "0";
4596         push_args(ctx, arg);
4597         ret = parse_int(ctx, token, str, strlen(str), buf, size);
4598         return ret > 0 ? (int)len : ret;
4599 }
4600
4601 /** Parse port and update context. */
4602 static int
4603 parse_port(struct context *ctx, const struct token *token,
4604            const char *str, unsigned int len,
4605            void *buf, unsigned int size)
4606 {
4607         struct buffer *out = &(struct buffer){ .port = 0 };
4608         int ret;
4609
4610         if (buf)
4611                 out = buf;
4612         else {
4613                 ctx->objdata = 0;
4614                 ctx->object = out;
4615                 ctx->objmask = NULL;
4616                 size = sizeof(*out);
4617         }
4618         ret = parse_int(ctx, token, str, len, out, size);
4619         if (ret >= 0)
4620                 ctx->port = out->port;
4621         if (!buf)
4622                 ctx->object = NULL;
4623         return ret;
4624 }
4625
4626 /** No completion. */
4627 static int
4628 comp_none(struct context *ctx, const struct token *token,
4629           unsigned int ent, char *buf, unsigned int size)
4630 {
4631         (void)ctx;
4632         (void)token;
4633         (void)ent;
4634         (void)buf;
4635         (void)size;
4636         return 0;
4637 }
4638
4639 /** Complete boolean values. */
4640 static int
4641 comp_boolean(struct context *ctx, const struct token *token,
4642              unsigned int ent, char *buf, unsigned int size)
4643 {
4644         unsigned int i;
4645
4646         (void)ctx;
4647         (void)token;
4648         for (i = 0; boolean_name[i]; ++i)
4649                 if (buf && i == ent)
4650                         return snprintf(buf, size, "%s", boolean_name[i]);
4651         if (buf)
4652                 return -1;
4653         return i;
4654 }
4655
4656 /** Complete action names. */
4657 static int
4658 comp_action(struct context *ctx, const struct token *token,
4659             unsigned int ent, char *buf, unsigned int size)
4660 {
4661         unsigned int i;
4662
4663         (void)ctx;
4664         (void)token;
4665         for (i = 0; next_action[i]; ++i)
4666                 if (buf && i == ent)
4667                         return snprintf(buf, size, "%s",
4668                                         token_list[next_action[i]].name);
4669         if (buf)
4670                 return -1;
4671         return i;
4672 }
4673
4674 /** Complete available ports. */
4675 static int
4676 comp_port(struct context *ctx, const struct token *token,
4677           unsigned int ent, char *buf, unsigned int size)
4678 {
4679         unsigned int i = 0;
4680         portid_t p;
4681
4682         (void)ctx;
4683         (void)token;
4684         RTE_ETH_FOREACH_DEV(p) {
4685                 if (buf && i == ent)
4686                         return snprintf(buf, size, "%u", p);
4687                 ++i;
4688         }
4689         if (buf)
4690                 return -1;
4691         return i;
4692 }
4693
4694 /** Complete available rule IDs. */
4695 static int
4696 comp_rule_id(struct context *ctx, const struct token *token,
4697              unsigned int ent, char *buf, unsigned int size)
4698 {
4699         unsigned int i = 0;
4700         struct rte_port *port;
4701         struct port_flow *pf;
4702
4703         (void)token;
4704         if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
4705             ctx->port == (portid_t)RTE_PORT_ALL)
4706                 return -1;
4707         port = &ports[ctx->port];
4708         for (pf = port->flow_list; pf != NULL; pf = pf->next) {
4709                 if (buf && i == ent)
4710                         return snprintf(buf, size, "%u", pf->id);
4711                 ++i;
4712         }
4713         if (buf)
4714                 return -1;
4715         return i;
4716 }
4717
4718 /** Complete type field for RSS action. */
4719 static int
4720 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
4721                         unsigned int ent, char *buf, unsigned int size)
4722 {
4723         unsigned int i;
4724
4725         (void)ctx;
4726         (void)token;
4727         for (i = 0; rss_type_table[i].str; ++i)
4728                 ;
4729         if (!buf)
4730                 return i + 1;
4731         if (ent < i)
4732                 return snprintf(buf, size, "%s", rss_type_table[ent].str);
4733         if (ent == i)
4734                 return snprintf(buf, size, "end");
4735         return -1;
4736 }
4737
4738 /** Complete queue field for RSS action. */
4739 static int
4740 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
4741                          unsigned int ent, char *buf, unsigned int size)
4742 {
4743         (void)ctx;
4744         (void)token;
4745         if (!buf)
4746                 return nb_rxq + 1;
4747         if (ent < nb_rxq)
4748                 return snprintf(buf, size, "%u", ent);
4749         if (ent == nb_rxq)
4750                 return snprintf(buf, size, "end");
4751         return -1;
4752 }
4753
4754 /** Internal context. */
4755 static struct context cmd_flow_context;
4756
4757 /** Global parser instance (cmdline API). */
4758 cmdline_parse_inst_t cmd_flow;
4759
4760 /** Initialize context. */
4761 static void
4762 cmd_flow_context_init(struct context *ctx)
4763 {
4764         /* A full memset() is not necessary. */
4765         ctx->curr = ZERO;
4766         ctx->prev = ZERO;
4767         ctx->next_num = 0;
4768         ctx->args_num = 0;
4769         ctx->eol = 0;
4770         ctx->last = 0;
4771         ctx->port = 0;
4772         ctx->objdata = 0;
4773         ctx->object = NULL;
4774         ctx->objmask = NULL;
4775 }
4776
4777 /** Parse a token (cmdline API). */
4778 static int
4779 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
4780                unsigned int size)
4781 {
4782         struct context *ctx = &cmd_flow_context;
4783         const struct token *token;
4784         const enum index *list;
4785         int len;
4786         int i;
4787
4788         (void)hdr;
4789         token = &token_list[ctx->curr];
4790         /* Check argument length. */
4791         ctx->eol = 0;
4792         ctx->last = 1;
4793         for (len = 0; src[len]; ++len)
4794                 if (src[len] == '#' || isspace(src[len]))
4795                         break;
4796         if (!len)
4797                 return -1;
4798         /* Last argument and EOL detection. */
4799         for (i = len; src[i]; ++i)
4800                 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
4801                         break;
4802                 else if (!isspace(src[i])) {
4803                         ctx->last = 0;
4804                         break;
4805                 }
4806         for (; src[i]; ++i)
4807                 if (src[i] == '\r' || src[i] == '\n') {
4808                         ctx->eol = 1;
4809                         break;
4810                 }
4811         /* Initialize context if necessary. */
4812         if (!ctx->next_num) {
4813                 if (!token->next)
4814                         return 0;
4815                 ctx->next[ctx->next_num++] = token->next[0];
4816         }
4817         /* Process argument through candidates. */
4818         ctx->prev = ctx->curr;
4819         list = ctx->next[ctx->next_num - 1];
4820         for (i = 0; list[i]; ++i) {
4821                 const struct token *next = &token_list[list[i]];
4822                 int tmp;
4823
4824                 ctx->curr = list[i];
4825                 if (next->call)
4826                         tmp = next->call(ctx, next, src, len, result, size);
4827                 else
4828                         tmp = parse_default(ctx, next, src, len, result, size);
4829                 if (tmp == -1 || tmp != len)
4830                         continue;
4831                 token = next;
4832                 break;
4833         }
4834         if (!list[i])
4835                 return -1;
4836         --ctx->next_num;
4837         /* Push subsequent tokens if any. */
4838         if (token->next)
4839                 for (i = 0; token->next[i]; ++i) {
4840                         if (ctx->next_num == RTE_DIM(ctx->next))
4841                                 return -1;
4842                         ctx->next[ctx->next_num++] = token->next[i];
4843                 }
4844         /* Push arguments if any. */
4845         if (token->args)
4846                 for (i = 0; token->args[i]; ++i) {
4847                         if (ctx->args_num == RTE_DIM(ctx->args))
4848                                 return -1;
4849                         ctx->args[ctx->args_num++] = token->args[i];
4850                 }
4851         return len;
4852 }
4853
4854 /** Return number of completion entries (cmdline API). */
4855 static int
4856 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
4857 {
4858         struct context *ctx = &cmd_flow_context;
4859         const struct token *token = &token_list[ctx->curr];
4860         const enum index *list;
4861         int i;
4862
4863         (void)hdr;
4864         /* Count number of tokens in current list. */
4865         if (ctx->next_num)
4866                 list = ctx->next[ctx->next_num - 1];
4867         else
4868                 list = token->next[0];
4869         for (i = 0; list[i]; ++i)
4870                 ;
4871         if (!i)
4872                 return 0;
4873         /*
4874          * If there is a single token, use its completion callback, otherwise
4875          * return the number of entries.
4876          */
4877         token = &token_list[list[0]];
4878         if (i == 1 && token->comp) {
4879                 /* Save index for cmd_flow_get_help(). */
4880                 ctx->prev = list[0];
4881                 return token->comp(ctx, token, 0, NULL, 0);
4882         }
4883         return i;
4884 }
4885
4886 /** Return a completion entry (cmdline API). */
4887 static int
4888 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
4889                           char *dst, unsigned int size)
4890 {
4891         struct context *ctx = &cmd_flow_context;
4892         const struct token *token = &token_list[ctx->curr];
4893         const enum index *list;
4894         int i;
4895
4896         (void)hdr;
4897         /* Count number of tokens in current list. */
4898         if (ctx->next_num)
4899                 list = ctx->next[ctx->next_num - 1];
4900         else
4901                 list = token->next[0];
4902         for (i = 0; list[i]; ++i)
4903                 ;
4904         if (!i)
4905                 return -1;
4906         /* If there is a single token, use its completion callback. */
4907         token = &token_list[list[0]];
4908         if (i == 1 && token->comp) {
4909                 /* Save index for cmd_flow_get_help(). */
4910                 ctx->prev = list[0];
4911                 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
4912         }
4913         /* Otherwise make sure the index is valid and use defaults. */
4914         if (index >= i)
4915                 return -1;
4916         token = &token_list[list[index]];
4917         snprintf(dst, size, "%s", token->name);
4918         /* Save index for cmd_flow_get_help(). */
4919         ctx->prev = list[index];
4920         return 0;
4921 }
4922
4923 /** Populate help strings for current token (cmdline API). */
4924 static int
4925 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
4926 {
4927         struct context *ctx = &cmd_flow_context;
4928         const struct token *token = &token_list[ctx->prev];
4929
4930         (void)hdr;
4931         if (!size)
4932                 return -1;
4933         /* Set token type and update global help with details. */
4934         snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
4935         if (token->help)
4936                 cmd_flow.help_str = token->help;
4937         else
4938                 cmd_flow.help_str = token->name;
4939         return 0;
4940 }
4941
4942 /** Token definition template (cmdline API). */
4943 static struct cmdline_token_hdr cmd_flow_token_hdr = {
4944         .ops = &(struct cmdline_token_ops){
4945                 .parse = cmd_flow_parse,
4946                 .complete_get_nb = cmd_flow_complete_get_nb,
4947                 .complete_get_elt = cmd_flow_complete_get_elt,
4948                 .get_help = cmd_flow_get_help,
4949         },
4950         .offset = 0,
4951 };
4952
4953 /** Populate the next dynamic token. */
4954 static void
4955 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
4956              cmdline_parse_token_hdr_t **hdr_inst)
4957 {
4958         struct context *ctx = &cmd_flow_context;
4959
4960         /* Always reinitialize context before requesting the first token. */
4961         if (!(hdr_inst - cmd_flow.tokens))
4962                 cmd_flow_context_init(ctx);
4963         /* Return NULL when no more tokens are expected. */
4964         if (!ctx->next_num && ctx->curr) {
4965                 *hdr = NULL;
4966                 return;
4967         }
4968         /* Determine if command should end here. */
4969         if (ctx->eol && ctx->last && ctx->next_num) {
4970                 const enum index *list = ctx->next[ctx->next_num - 1];
4971                 int i;
4972
4973                 for (i = 0; list[i]; ++i) {
4974                         if (list[i] != END)
4975                                 continue;
4976                         *hdr = NULL;
4977                         return;
4978                 }
4979         }
4980         *hdr = &cmd_flow_token_hdr;
4981 }
4982
4983 /** Dispatch parsed buffer to function calls. */
4984 static void
4985 cmd_flow_parsed(const struct buffer *in)
4986 {
4987         switch (in->command) {
4988         case VALIDATE:
4989                 port_flow_validate(in->port, &in->args.vc.attr,
4990                                    in->args.vc.pattern, in->args.vc.actions);
4991                 break;
4992         case CREATE:
4993                 port_flow_create(in->port, &in->args.vc.attr,
4994                                  in->args.vc.pattern, in->args.vc.actions);
4995                 break;
4996         case DESTROY:
4997                 port_flow_destroy(in->port, in->args.destroy.rule_n,
4998                                   in->args.destroy.rule);
4999                 break;
5000         case FLUSH:
5001                 port_flow_flush(in->port);
5002                 break;
5003         case QUERY:
5004                 port_flow_query(in->port, in->args.query.rule,
5005                                 &in->args.query.action);
5006                 break;
5007         case LIST:
5008                 port_flow_list(in->port, in->args.list.group_n,
5009                                in->args.list.group);
5010                 break;
5011         case ISOLATE:
5012                 port_flow_isolate(in->port, in->args.isolate.set);
5013                 break;
5014         default:
5015                 break;
5016         }
5017 }
5018
5019 /** Token generator and output processing callback (cmdline API). */
5020 static void
5021 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
5022 {
5023         if (cl == NULL)
5024                 cmd_flow_tok(arg0, arg2);
5025         else
5026                 cmd_flow_parsed(arg0);
5027 }
5028
5029 /** Global parser instance (cmdline API). */
5030 cmdline_parse_inst_t cmd_flow = {
5031         .f = cmd_flow_cb,
5032         .data = NULL, /**< Unused. */
5033         .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
5034         .tokens = {
5035                 NULL,
5036         }, /**< Tokens are returned by cmd_flow_tok(). */
5037 };