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