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