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