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