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