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