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