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