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