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