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