app/testpmd: add flow engine configuration
[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
14 #include <rte_string_fns.h>
15 #include <rte_common.h>
16 #include <rte_ethdev.h>
17 #include <rte_byteorder.h>
18 #include <cmdline_parse.h>
19 #include <cmdline_parse_etheraddr.h>
20 #include <cmdline_parse_string.h>
21 #include <cmdline_parse_num.h>
22 #include <rte_flow.h>
23 #include <rte_hexdump.h>
24 #include <rte_vxlan.h>
25 #include <rte_gre.h>
26 #include <rte_mpls.h>
27 #include <rte_gtp.h>
28 #include <rte_geneve.h>
29
30 #include "testpmd.h"
31
32 /** Parser token indices. */
33 enum index {
34         /* Special tokens. */
35         ZERO = 0,
36         END,
37         START_SET,
38         END_SET,
39
40         /* Common tokens. */
41         COMMON_INTEGER,
42         COMMON_UNSIGNED,
43         COMMON_PREFIX,
44         COMMON_BOOLEAN,
45         COMMON_STRING,
46         COMMON_HEX,
47         COMMON_FILE_PATH,
48         COMMON_MAC_ADDR,
49         COMMON_IPV4_ADDR,
50         COMMON_IPV6_ADDR,
51         COMMON_RULE_ID,
52         COMMON_PORT_ID,
53         COMMON_GROUP_ID,
54         COMMON_PRIORITY_LEVEL,
55         COMMON_INDIRECT_ACTION_ID,
56         COMMON_POLICY_ID,
57         COMMON_FLEX_HANDLE,
58         COMMON_FLEX_TOKEN,
59
60         /* TOP-level command. */
61         ADD,
62
63         /* Top-level command. */
64         SET,
65         /* Sub-leve commands. */
66         SET_RAW_ENCAP,
67         SET_RAW_DECAP,
68         SET_RAW_INDEX,
69         SET_SAMPLE_ACTIONS,
70         SET_SAMPLE_INDEX,
71
72         /* Top-level command. */
73         FLOW,
74         /* Sub-level commands. */
75         INFO,
76         CONFIGURE,
77         INDIRECT_ACTION,
78         VALIDATE,
79         CREATE,
80         DESTROY,
81         FLUSH,
82         DUMP,
83         QUERY,
84         LIST,
85         AGED,
86         ISOLATE,
87         TUNNEL,
88         FLEX,
89
90         /* Flex arguments */
91         FLEX_ITEM_INIT,
92         FLEX_ITEM_CREATE,
93         FLEX_ITEM_DESTROY,
94
95         /* Tunnel arguments. */
96         TUNNEL_CREATE,
97         TUNNEL_CREATE_TYPE,
98         TUNNEL_LIST,
99         TUNNEL_DESTROY,
100         TUNNEL_DESTROY_ID,
101
102         /* Destroy arguments. */
103         DESTROY_RULE,
104
105         /* Query arguments. */
106         QUERY_ACTION,
107
108         /* List arguments. */
109         LIST_GROUP,
110
111         /* Destroy aged flow arguments. */
112         AGED_DESTROY,
113
114         /* Validate/create arguments. */
115         VC_GROUP,
116         VC_PRIORITY,
117         VC_INGRESS,
118         VC_EGRESS,
119         VC_TRANSFER,
120         VC_TUNNEL_SET,
121         VC_TUNNEL_MATCH,
122
123         /* Dump arguments */
124         DUMP_ALL,
125         DUMP_ONE,
126
127         /* Configure arguments */
128         CONFIG_QUEUES_NUMBER,
129         CONFIG_QUEUES_SIZE,
130         CONFIG_COUNTERS_NUMBER,
131         CONFIG_AGING_OBJECTS_NUMBER,
132         CONFIG_METERS_NUMBER,
133
134         /* Indirect action arguments */
135         INDIRECT_ACTION_CREATE,
136         INDIRECT_ACTION_UPDATE,
137         INDIRECT_ACTION_DESTROY,
138         INDIRECT_ACTION_QUERY,
139
140         /* Indirect action create arguments */
141         INDIRECT_ACTION_CREATE_ID,
142         INDIRECT_ACTION_INGRESS,
143         INDIRECT_ACTION_EGRESS,
144         INDIRECT_ACTION_TRANSFER,
145         INDIRECT_ACTION_SPEC,
146
147         /* Indirect action destroy arguments */
148         INDIRECT_ACTION_DESTROY_ID,
149
150         /* Validate/create pattern. */
151         ITEM_PATTERN,
152         ITEM_PARAM_IS,
153         ITEM_PARAM_SPEC,
154         ITEM_PARAM_LAST,
155         ITEM_PARAM_MASK,
156         ITEM_PARAM_PREFIX,
157         ITEM_NEXT,
158         ITEM_END,
159         ITEM_VOID,
160         ITEM_INVERT,
161         ITEM_ANY,
162         ITEM_ANY_NUM,
163         ITEM_PF,
164         ITEM_VF,
165         ITEM_VF_ID,
166         ITEM_PHY_PORT,
167         ITEM_PHY_PORT_INDEX,
168         ITEM_PORT_ID,
169         ITEM_PORT_ID_ID,
170         ITEM_MARK,
171         ITEM_MARK_ID,
172         ITEM_RAW,
173         ITEM_RAW_RELATIVE,
174         ITEM_RAW_SEARCH,
175         ITEM_RAW_OFFSET,
176         ITEM_RAW_LIMIT,
177         ITEM_RAW_PATTERN,
178         ITEM_RAW_PATTERN_HEX,
179         ITEM_ETH,
180         ITEM_ETH_DST,
181         ITEM_ETH_SRC,
182         ITEM_ETH_TYPE,
183         ITEM_ETH_HAS_VLAN,
184         ITEM_VLAN,
185         ITEM_VLAN_TCI,
186         ITEM_VLAN_PCP,
187         ITEM_VLAN_DEI,
188         ITEM_VLAN_VID,
189         ITEM_VLAN_INNER_TYPE,
190         ITEM_VLAN_HAS_MORE_VLAN,
191         ITEM_IPV4,
192         ITEM_IPV4_VER_IHL,
193         ITEM_IPV4_TOS,
194         ITEM_IPV4_ID,
195         ITEM_IPV4_FRAGMENT_OFFSET,
196         ITEM_IPV4_TTL,
197         ITEM_IPV4_PROTO,
198         ITEM_IPV4_SRC,
199         ITEM_IPV4_DST,
200         ITEM_IPV6,
201         ITEM_IPV6_TC,
202         ITEM_IPV6_FLOW,
203         ITEM_IPV6_PROTO,
204         ITEM_IPV6_HOP,
205         ITEM_IPV6_SRC,
206         ITEM_IPV6_DST,
207         ITEM_IPV6_HAS_FRAG_EXT,
208         ITEM_ICMP,
209         ITEM_ICMP_TYPE,
210         ITEM_ICMP_CODE,
211         ITEM_ICMP_IDENT,
212         ITEM_ICMP_SEQ,
213         ITEM_UDP,
214         ITEM_UDP_SRC,
215         ITEM_UDP_DST,
216         ITEM_TCP,
217         ITEM_TCP_SRC,
218         ITEM_TCP_DST,
219         ITEM_TCP_FLAGS,
220         ITEM_SCTP,
221         ITEM_SCTP_SRC,
222         ITEM_SCTP_DST,
223         ITEM_SCTP_TAG,
224         ITEM_SCTP_CKSUM,
225         ITEM_VXLAN,
226         ITEM_VXLAN_VNI,
227         ITEM_VXLAN_LAST_RSVD,
228         ITEM_E_TAG,
229         ITEM_E_TAG_GRP_ECID_B,
230         ITEM_NVGRE,
231         ITEM_NVGRE_TNI,
232         ITEM_MPLS,
233         ITEM_MPLS_LABEL,
234         ITEM_MPLS_TC,
235         ITEM_MPLS_S,
236         ITEM_GRE,
237         ITEM_GRE_PROTO,
238         ITEM_GRE_C_RSVD0_VER,
239         ITEM_GRE_C_BIT,
240         ITEM_GRE_K_BIT,
241         ITEM_GRE_S_BIT,
242         ITEM_FUZZY,
243         ITEM_FUZZY_THRESH,
244         ITEM_GTP,
245         ITEM_GTP_FLAGS,
246         ITEM_GTP_MSG_TYPE,
247         ITEM_GTP_TEID,
248         ITEM_GTPC,
249         ITEM_GTPU,
250         ITEM_GENEVE,
251         ITEM_GENEVE_VNI,
252         ITEM_GENEVE_PROTO,
253         ITEM_GENEVE_OPTLEN,
254         ITEM_VXLAN_GPE,
255         ITEM_VXLAN_GPE_VNI,
256         ITEM_ARP_ETH_IPV4,
257         ITEM_ARP_ETH_IPV4_SHA,
258         ITEM_ARP_ETH_IPV4_SPA,
259         ITEM_ARP_ETH_IPV4_THA,
260         ITEM_ARP_ETH_IPV4_TPA,
261         ITEM_IPV6_EXT,
262         ITEM_IPV6_EXT_NEXT_HDR,
263         ITEM_IPV6_FRAG_EXT,
264         ITEM_IPV6_FRAG_EXT_NEXT_HDR,
265         ITEM_IPV6_FRAG_EXT_FRAG_DATA,
266         ITEM_IPV6_FRAG_EXT_ID,
267         ITEM_ICMP6,
268         ITEM_ICMP6_TYPE,
269         ITEM_ICMP6_CODE,
270         ITEM_ICMP6_ND_NS,
271         ITEM_ICMP6_ND_NS_TARGET_ADDR,
272         ITEM_ICMP6_ND_NA,
273         ITEM_ICMP6_ND_NA_TARGET_ADDR,
274         ITEM_ICMP6_ND_OPT,
275         ITEM_ICMP6_ND_OPT_TYPE,
276         ITEM_ICMP6_ND_OPT_SLA_ETH,
277         ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
278         ITEM_ICMP6_ND_OPT_TLA_ETH,
279         ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
280         ITEM_META,
281         ITEM_META_DATA,
282         ITEM_GRE_KEY,
283         ITEM_GRE_KEY_VALUE,
284         ITEM_GRE_OPTION,
285         ITEM_GRE_OPTION_CHECKSUM,
286         ITEM_GRE_OPTION_KEY,
287         ITEM_GRE_OPTION_SEQUENCE,
288         ITEM_GTP_PSC,
289         ITEM_GTP_PSC_QFI,
290         ITEM_GTP_PSC_PDU_T,
291         ITEM_PPPOES,
292         ITEM_PPPOED,
293         ITEM_PPPOE_SEID,
294         ITEM_PPPOE_PROTO_ID,
295         ITEM_HIGIG2,
296         ITEM_HIGIG2_CLASSIFICATION,
297         ITEM_HIGIG2_VID,
298         ITEM_TAG,
299         ITEM_TAG_DATA,
300         ITEM_TAG_INDEX,
301         ITEM_L2TPV3OIP,
302         ITEM_L2TPV3OIP_SESSION_ID,
303         ITEM_ESP,
304         ITEM_ESP_SPI,
305         ITEM_AH,
306         ITEM_AH_SPI,
307         ITEM_PFCP,
308         ITEM_PFCP_S_FIELD,
309         ITEM_PFCP_SEID,
310         ITEM_ECPRI,
311         ITEM_ECPRI_COMMON,
312         ITEM_ECPRI_COMMON_TYPE,
313         ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
314         ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
315         ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
316         ITEM_ECPRI_MSG_IQ_DATA_PCID,
317         ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
318         ITEM_ECPRI_MSG_DLY_MSR_MSRID,
319         ITEM_GENEVE_OPT,
320         ITEM_GENEVE_OPT_CLASS,
321         ITEM_GENEVE_OPT_TYPE,
322         ITEM_GENEVE_OPT_LENGTH,
323         ITEM_GENEVE_OPT_DATA,
324         ITEM_INTEGRITY,
325         ITEM_INTEGRITY_LEVEL,
326         ITEM_INTEGRITY_VALUE,
327         ITEM_CONNTRACK,
328         ITEM_POL_PORT,
329         ITEM_POL_METER,
330         ITEM_POL_POLICY,
331         ITEM_PORT_REPRESENTOR,
332         ITEM_PORT_REPRESENTOR_PORT_ID,
333         ITEM_REPRESENTED_PORT,
334         ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
335         ITEM_FLEX,
336         ITEM_FLEX_ITEM_HANDLE,
337         ITEM_FLEX_PATTERN_HANDLE,
338         ITEM_L2TPV2,
339         ITEM_L2TPV2_TYPE,
340         ITEM_L2TPV2_TYPE_DATA,
341         ITEM_L2TPV2_TYPE_DATA_L,
342         ITEM_L2TPV2_TYPE_DATA_S,
343         ITEM_L2TPV2_TYPE_DATA_O,
344         ITEM_L2TPV2_TYPE_DATA_L_S,
345         ITEM_L2TPV2_TYPE_CTRL,
346         ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
347         ITEM_L2TPV2_MSG_DATA_SESSION_ID,
348         ITEM_L2TPV2_MSG_DATA_L_LENGTH,
349         ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
350         ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
351         ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
352         ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
353         ITEM_L2TPV2_MSG_DATA_S_NS,
354         ITEM_L2TPV2_MSG_DATA_S_NR,
355         ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
356         ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
357         ITEM_L2TPV2_MSG_DATA_O_OFFSET,
358         ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
359         ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
360         ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
361         ITEM_L2TPV2_MSG_DATA_L_S_NS,
362         ITEM_L2TPV2_MSG_DATA_L_S_NR,
363         ITEM_L2TPV2_MSG_CTRL_LENGTH,
364         ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
365         ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
366         ITEM_L2TPV2_MSG_CTRL_NS,
367         ITEM_L2TPV2_MSG_CTRL_NR,
368         ITEM_PPP,
369         ITEM_PPP_ADDR,
370         ITEM_PPP_CTRL,
371         ITEM_PPP_PROTO_ID,
372
373         /* Validate/create actions. */
374         ACTIONS,
375         ACTION_NEXT,
376         ACTION_END,
377         ACTION_VOID,
378         ACTION_PASSTHRU,
379         ACTION_JUMP,
380         ACTION_JUMP_GROUP,
381         ACTION_MARK,
382         ACTION_MARK_ID,
383         ACTION_FLAG,
384         ACTION_QUEUE,
385         ACTION_QUEUE_INDEX,
386         ACTION_DROP,
387         ACTION_COUNT,
388         ACTION_COUNT_ID,
389         ACTION_RSS,
390         ACTION_RSS_FUNC,
391         ACTION_RSS_LEVEL,
392         ACTION_RSS_FUNC_DEFAULT,
393         ACTION_RSS_FUNC_TOEPLITZ,
394         ACTION_RSS_FUNC_SIMPLE_XOR,
395         ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
396         ACTION_RSS_TYPES,
397         ACTION_RSS_TYPE,
398         ACTION_RSS_KEY,
399         ACTION_RSS_KEY_LEN,
400         ACTION_RSS_QUEUES,
401         ACTION_RSS_QUEUE,
402         ACTION_PF,
403         ACTION_VF,
404         ACTION_VF_ORIGINAL,
405         ACTION_VF_ID,
406         ACTION_PHY_PORT,
407         ACTION_PHY_PORT_ORIGINAL,
408         ACTION_PHY_PORT_INDEX,
409         ACTION_PORT_ID,
410         ACTION_PORT_ID_ORIGINAL,
411         ACTION_PORT_ID_ID,
412         ACTION_METER,
413         ACTION_METER_COLOR,
414         ACTION_METER_COLOR_TYPE,
415         ACTION_METER_COLOR_GREEN,
416         ACTION_METER_COLOR_YELLOW,
417         ACTION_METER_COLOR_RED,
418         ACTION_METER_ID,
419         ACTION_OF_SET_MPLS_TTL,
420         ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
421         ACTION_OF_DEC_MPLS_TTL,
422         ACTION_OF_SET_NW_TTL,
423         ACTION_OF_SET_NW_TTL_NW_TTL,
424         ACTION_OF_DEC_NW_TTL,
425         ACTION_OF_COPY_TTL_OUT,
426         ACTION_OF_COPY_TTL_IN,
427         ACTION_OF_POP_VLAN,
428         ACTION_OF_PUSH_VLAN,
429         ACTION_OF_PUSH_VLAN_ETHERTYPE,
430         ACTION_OF_SET_VLAN_VID,
431         ACTION_OF_SET_VLAN_VID_VLAN_VID,
432         ACTION_OF_SET_VLAN_PCP,
433         ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
434         ACTION_OF_POP_MPLS,
435         ACTION_OF_POP_MPLS_ETHERTYPE,
436         ACTION_OF_PUSH_MPLS,
437         ACTION_OF_PUSH_MPLS_ETHERTYPE,
438         ACTION_VXLAN_ENCAP,
439         ACTION_VXLAN_DECAP,
440         ACTION_NVGRE_ENCAP,
441         ACTION_NVGRE_DECAP,
442         ACTION_L2_ENCAP,
443         ACTION_L2_DECAP,
444         ACTION_MPLSOGRE_ENCAP,
445         ACTION_MPLSOGRE_DECAP,
446         ACTION_MPLSOUDP_ENCAP,
447         ACTION_MPLSOUDP_DECAP,
448         ACTION_SET_IPV4_SRC,
449         ACTION_SET_IPV4_SRC_IPV4_SRC,
450         ACTION_SET_IPV4_DST,
451         ACTION_SET_IPV4_DST_IPV4_DST,
452         ACTION_SET_IPV6_SRC,
453         ACTION_SET_IPV6_SRC_IPV6_SRC,
454         ACTION_SET_IPV6_DST,
455         ACTION_SET_IPV6_DST_IPV6_DST,
456         ACTION_SET_TP_SRC,
457         ACTION_SET_TP_SRC_TP_SRC,
458         ACTION_SET_TP_DST,
459         ACTION_SET_TP_DST_TP_DST,
460         ACTION_MAC_SWAP,
461         ACTION_DEC_TTL,
462         ACTION_SET_TTL,
463         ACTION_SET_TTL_TTL,
464         ACTION_SET_MAC_SRC,
465         ACTION_SET_MAC_SRC_MAC_SRC,
466         ACTION_SET_MAC_DST,
467         ACTION_SET_MAC_DST_MAC_DST,
468         ACTION_INC_TCP_SEQ,
469         ACTION_INC_TCP_SEQ_VALUE,
470         ACTION_DEC_TCP_SEQ,
471         ACTION_DEC_TCP_SEQ_VALUE,
472         ACTION_INC_TCP_ACK,
473         ACTION_INC_TCP_ACK_VALUE,
474         ACTION_DEC_TCP_ACK,
475         ACTION_DEC_TCP_ACK_VALUE,
476         ACTION_RAW_ENCAP,
477         ACTION_RAW_DECAP,
478         ACTION_RAW_ENCAP_INDEX,
479         ACTION_RAW_ENCAP_INDEX_VALUE,
480         ACTION_RAW_DECAP_INDEX,
481         ACTION_RAW_DECAP_INDEX_VALUE,
482         ACTION_SET_TAG,
483         ACTION_SET_TAG_DATA,
484         ACTION_SET_TAG_INDEX,
485         ACTION_SET_TAG_MASK,
486         ACTION_SET_META,
487         ACTION_SET_META_DATA,
488         ACTION_SET_META_MASK,
489         ACTION_SET_IPV4_DSCP,
490         ACTION_SET_IPV4_DSCP_VALUE,
491         ACTION_SET_IPV6_DSCP,
492         ACTION_SET_IPV6_DSCP_VALUE,
493         ACTION_AGE,
494         ACTION_AGE_TIMEOUT,
495         ACTION_SAMPLE,
496         ACTION_SAMPLE_RATIO,
497         ACTION_SAMPLE_INDEX,
498         ACTION_SAMPLE_INDEX_VALUE,
499         ACTION_INDIRECT,
500         INDIRECT_ACTION_ID2PTR,
501         ACTION_MODIFY_FIELD,
502         ACTION_MODIFY_FIELD_OP,
503         ACTION_MODIFY_FIELD_OP_VALUE,
504         ACTION_MODIFY_FIELD_DST_TYPE,
505         ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
506         ACTION_MODIFY_FIELD_DST_LEVEL,
507         ACTION_MODIFY_FIELD_DST_OFFSET,
508         ACTION_MODIFY_FIELD_SRC_TYPE,
509         ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
510         ACTION_MODIFY_FIELD_SRC_LEVEL,
511         ACTION_MODIFY_FIELD_SRC_OFFSET,
512         ACTION_MODIFY_FIELD_SRC_VALUE,
513         ACTION_MODIFY_FIELD_SRC_POINTER,
514         ACTION_MODIFY_FIELD_WIDTH,
515         ACTION_CONNTRACK,
516         ACTION_CONNTRACK_UPDATE,
517         ACTION_CONNTRACK_UPDATE_DIR,
518         ACTION_CONNTRACK_UPDATE_CTX,
519         ACTION_POL_G,
520         ACTION_POL_Y,
521         ACTION_POL_R,
522         ACTION_PORT_REPRESENTOR,
523         ACTION_PORT_REPRESENTOR_PORT_ID,
524         ACTION_REPRESENTED_PORT,
525         ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
526 };
527
528 /** Maximum size for pattern in struct rte_flow_item_raw. */
529 #define ITEM_RAW_PATTERN_SIZE 512
530
531 /** Maximum size for GENEVE option data pattern in bytes. */
532 #define ITEM_GENEVE_OPT_DATA_SIZE 124
533
534 /** Storage size for struct rte_flow_item_raw including pattern. */
535 #define ITEM_RAW_SIZE \
536         (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
537
538 /** Maximum size for external pattern in struct rte_flow_action_modify_data. */
539 #define ACTION_MODIFY_PATTERN_SIZE 32
540
541 /** Storage size for struct rte_flow_action_modify_field including pattern. */
542 #define ACTION_MODIFY_SIZE \
543         (sizeof(struct rte_flow_action_modify_field) + \
544         ACTION_MODIFY_PATTERN_SIZE)
545
546 /** Maximum number of queue indices in struct rte_flow_action_rss. */
547 #define ACTION_RSS_QUEUE_NUM 128
548
549 /** Storage for struct rte_flow_action_rss including external data. */
550 struct action_rss_data {
551         struct rte_flow_action_rss conf;
552         uint8_t key[RSS_HASH_KEY_LENGTH];
553         uint16_t queue[ACTION_RSS_QUEUE_NUM];
554 };
555
556 /** Maximum data size in struct rte_flow_action_raw_encap. */
557 #define ACTION_RAW_ENCAP_MAX_DATA 512
558 #define RAW_ENCAP_CONFS_MAX_NUM 8
559
560 /** Storage for struct rte_flow_action_raw_encap. */
561 struct raw_encap_conf {
562         uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
563         uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
564         size_t size;
565 };
566
567 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
568
569 /** Storage for struct rte_flow_action_raw_encap including external data. */
570 struct action_raw_encap_data {
571         struct rte_flow_action_raw_encap conf;
572         uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
573         uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
574         uint16_t idx;
575 };
576
577 /** Storage for struct rte_flow_action_raw_decap. */
578 struct raw_decap_conf {
579         uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
580         size_t size;
581 };
582
583 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
584
585 /** Storage for struct rte_flow_action_raw_decap including external data. */
586 struct action_raw_decap_data {
587         struct rte_flow_action_raw_decap conf;
588         uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
589         uint16_t idx;
590 };
591
592 struct vxlan_encap_conf vxlan_encap_conf = {
593         .select_ipv4 = 1,
594         .select_vlan = 0,
595         .select_tos_ttl = 0,
596         .vni = "\x00\x00\x00",
597         .udp_src = 0,
598         .udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
599         .ipv4_src = RTE_IPV4(127, 0, 0, 1),
600         .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
601         .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
602                 "\x00\x00\x00\x00\x00\x00\x00\x01",
603         .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
604                 "\x00\x00\x00\x00\x00\x00\x11\x11",
605         .vlan_tci = 0,
606         .ip_tos = 0,
607         .ip_ttl = 255,
608         .eth_src = "\x00\x00\x00\x00\x00\x00",
609         .eth_dst = "\xff\xff\xff\xff\xff\xff",
610 };
611
612 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
613 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
614
615 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
616 struct action_vxlan_encap_data {
617         struct rte_flow_action_vxlan_encap conf;
618         struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
619         struct rte_flow_item_eth item_eth;
620         struct rte_flow_item_vlan item_vlan;
621         union {
622                 struct rte_flow_item_ipv4 item_ipv4;
623                 struct rte_flow_item_ipv6 item_ipv6;
624         };
625         struct rte_flow_item_udp item_udp;
626         struct rte_flow_item_vxlan item_vxlan;
627 };
628
629 struct nvgre_encap_conf nvgre_encap_conf = {
630         .select_ipv4 = 1,
631         .select_vlan = 0,
632         .tni = "\x00\x00\x00",
633         .ipv4_src = RTE_IPV4(127, 0, 0, 1),
634         .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
635         .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
636                 "\x00\x00\x00\x00\x00\x00\x00\x01",
637         .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
638                 "\x00\x00\x00\x00\x00\x00\x11\x11",
639         .vlan_tci = 0,
640         .eth_src = "\x00\x00\x00\x00\x00\x00",
641         .eth_dst = "\xff\xff\xff\xff\xff\xff",
642 };
643
644 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
645 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
646
647 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
648 struct action_nvgre_encap_data {
649         struct rte_flow_action_nvgre_encap conf;
650         struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
651         struct rte_flow_item_eth item_eth;
652         struct rte_flow_item_vlan item_vlan;
653         union {
654                 struct rte_flow_item_ipv4 item_ipv4;
655                 struct rte_flow_item_ipv6 item_ipv6;
656         };
657         struct rte_flow_item_nvgre item_nvgre;
658 };
659
660 struct l2_encap_conf l2_encap_conf;
661
662 struct l2_decap_conf l2_decap_conf;
663
664 struct mplsogre_encap_conf mplsogre_encap_conf;
665
666 struct mplsogre_decap_conf mplsogre_decap_conf;
667
668 struct mplsoudp_encap_conf mplsoudp_encap_conf;
669
670 struct mplsoudp_decap_conf mplsoudp_decap_conf;
671
672 struct rte_flow_action_conntrack conntrack_context;
673
674 #define ACTION_SAMPLE_ACTIONS_NUM 10
675 #define RAW_SAMPLE_CONFS_MAX_NUM 8
676 /** Storage for struct rte_flow_action_sample including external data. */
677 struct action_sample_data {
678         struct rte_flow_action_sample conf;
679         uint32_t idx;
680 };
681 /** Storage for struct rte_flow_action_sample. */
682 struct raw_sample_conf {
683         struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
684 };
685 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
686 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
687 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
688 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
689 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
690 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
691 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
692 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
693 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
694 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
695
696 static const char *const modify_field_ops[] = {
697         "set", "add", "sub", NULL
698 };
699
700 static const char *const modify_field_ids[] = {
701         "start", "mac_dst", "mac_src",
702         "vlan_type", "vlan_id", "mac_type",
703         "ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
704         "ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
705         "tcp_port_src", "tcp_port_dst",
706         "tcp_seq_num", "tcp_ack_num", "tcp_flags",
707         "udp_port_src", "udp_port_dst",
708         "vxlan_vni", "geneve_vni", "gtp_teid",
709         "tag", "mark", "meta", "pointer", "value", NULL
710 };
711
712 /** Maximum number of subsequent tokens and arguments on the stack. */
713 #define CTX_STACK_SIZE 16
714
715 /** Parser context. */
716 struct context {
717         /** Stack of subsequent token lists to process. */
718         const enum index *next[CTX_STACK_SIZE];
719         /** Arguments for stacked tokens. */
720         const void *args[CTX_STACK_SIZE];
721         enum index curr; /**< Current token index. */
722         enum index prev; /**< Index of the last token seen. */
723         int next_num; /**< Number of entries in next[]. */
724         int args_num; /**< Number of entries in args[]. */
725         uint32_t eol:1; /**< EOL has been detected. */
726         uint32_t last:1; /**< No more arguments. */
727         portid_t port; /**< Current port ID (for completions). */
728         uint32_t objdata; /**< Object-specific data. */
729         void *object; /**< Address of current object for relative offsets. */
730         void *objmask; /**< Object a full mask must be written to. */
731 };
732
733 /** Token argument. */
734 struct arg {
735         uint32_t hton:1; /**< Use network byte ordering. */
736         uint32_t sign:1; /**< Value is signed. */
737         uint32_t bounded:1; /**< Value is bounded. */
738         uintmax_t min; /**< Minimum value if bounded. */
739         uintmax_t max; /**< Maximum value if bounded. */
740         uint32_t offset; /**< Relative offset from ctx->object. */
741         uint32_t size; /**< Field size. */
742         const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
743 };
744
745 /** Parser token definition. */
746 struct token {
747         /** Type displayed during completion (defaults to "TOKEN"). */
748         const char *type;
749         /** Help displayed during completion (defaults to token name). */
750         const char *help;
751         /** Private data used by parser functions. */
752         const void *priv;
753         /**
754          * Lists of subsequent tokens to push on the stack. Each call to the
755          * parser consumes the last entry of that stack.
756          */
757         const enum index *const *next;
758         /** Arguments stack for subsequent tokens that need them. */
759         const struct arg *const *args;
760         /**
761          * Token-processing callback, returns -1 in case of error, the
762          * length of the matched string otherwise. If NULL, attempts to
763          * match the token name.
764          *
765          * If buf is not NULL, the result should be stored in it according
766          * to context. An error is returned if not large enough.
767          */
768         int (*call)(struct context *ctx, const struct token *token,
769                     const char *str, unsigned int len,
770                     void *buf, unsigned int size);
771         /**
772          * Callback that provides possible values for this token, used for
773          * completion. Returns -1 in case of error, the number of possible
774          * values otherwise. If NULL, the token name is used.
775          *
776          * If buf is not NULL, entry index ent is written to buf and the
777          * full length of the entry is returned (same behavior as
778          * snprintf()).
779          */
780         int (*comp)(struct context *ctx, const struct token *token,
781                     unsigned int ent, char *buf, unsigned int size);
782         /** Mandatory token name, no default value. */
783         const char *name;
784 };
785
786 /** Static initializer for the next field. */
787 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
788
789 /** Static initializer for a NEXT() entry. */
790 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
791
792 /** Static initializer for the args field. */
793 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
794
795 /** Static initializer for ARGS() to target a field. */
796 #define ARGS_ENTRY(s, f) \
797         (&(const struct arg){ \
798                 .offset = offsetof(s, f), \
799                 .size = sizeof(((s *)0)->f), \
800         })
801
802 /** Static initializer for ARGS() to target a bit-field. */
803 #define ARGS_ENTRY_BF(s, f, b) \
804         (&(const struct arg){ \
805                 .size = sizeof(s), \
806                 .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
807         })
808
809 /** Static initializer for ARGS() to target a field with limits. */
810 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
811         (&(const struct arg){ \
812                 .bounded = 1, \
813                 .min = (i), \
814                 .max = (a), \
815                 .offset = offsetof(s, f), \
816                 .size = sizeof(((s *)0)->f), \
817         })
818
819 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
820 #define ARGS_ENTRY_MASK(s, f, m) \
821         (&(const struct arg){ \
822                 .offset = offsetof(s, f), \
823                 .size = sizeof(((s *)0)->f), \
824                 .mask = (const void *)(m), \
825         })
826
827 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
828 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
829         (&(const struct arg){ \
830                 .hton = 1, \
831                 .offset = offsetof(s, f), \
832                 .size = sizeof(((s *)0)->f), \
833                 .mask = (const void *)(m), \
834         })
835
836 /** Static initializer for ARGS() to target a pointer. */
837 #define ARGS_ENTRY_PTR(s, f) \
838         (&(const struct arg){ \
839                 .size = sizeof(*((s *)0)->f), \
840         })
841
842 /** Static initializer for ARGS() with arbitrary offset and size. */
843 #define ARGS_ENTRY_ARB(o, s) \
844         (&(const struct arg){ \
845                 .offset = (o), \
846                 .size = (s), \
847         })
848
849 /** Same as ARGS_ENTRY_ARB() with bounded values. */
850 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
851         (&(const struct arg){ \
852                 .bounded = 1, \
853                 .min = (i), \
854                 .max = (a), \
855                 .offset = (o), \
856                 .size = (s), \
857         })
858
859 /** Same as ARGS_ENTRY() using network byte ordering. */
860 #define ARGS_ENTRY_HTON(s, f) \
861         (&(const struct arg){ \
862                 .hton = 1, \
863                 .offset = offsetof(s, f), \
864                 .size = sizeof(((s *)0)->f), \
865         })
866
867 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
868 #define ARG_ENTRY_HTON(s) \
869         (&(const struct arg){ \
870                 .hton = 1, \
871                 .offset = 0, \
872                 .size = sizeof(s), \
873         })
874
875 /** Parser output buffer layout expected by cmd_flow_parsed(). */
876 struct buffer {
877         enum index command; /**< Flow command. */
878         portid_t port; /**< Affected port ID. */
879         union {
880                 struct {
881                         struct rte_flow_port_attr port_attr;
882                         uint32_t nb_queue;
883                         struct rte_flow_queue_attr queue_attr;
884                 } configure; /**< Configuration arguments. */
885                 struct {
886                         uint32_t *action_id;
887                         uint32_t action_id_n;
888                 } ia_destroy; /**< Indirect action destroy arguments. */
889                 struct {
890                         uint32_t action_id;
891                 } ia; /* Indirect action query arguments */
892                 struct {
893                         struct rte_flow_attr attr;
894                         struct tunnel_ops tunnel_ops;
895                         struct rte_flow_item *pattern;
896                         struct rte_flow_action *actions;
897                         uint32_t pattern_n;
898                         uint32_t actions_n;
899                         uint8_t *data;
900                 } vc; /**< Validate/create arguments. */
901                 struct {
902                         uint32_t *rule;
903                         uint32_t rule_n;
904                 } destroy; /**< Destroy arguments. */
905                 struct {
906                         char file[128];
907                         bool mode;
908                         uint32_t rule;
909                 } dump; /**< Dump arguments. */
910                 struct {
911                         uint32_t rule;
912                         struct rte_flow_action action;
913                 } query; /**< Query arguments. */
914                 struct {
915                         uint32_t *group;
916                         uint32_t group_n;
917                 } list; /**< List arguments. */
918                 struct {
919                         int set;
920                 } isolate; /**< Isolated mode arguments. */
921                 struct {
922                         int destroy;
923                 } aged; /**< Aged arguments. */
924                 struct {
925                         uint32_t policy_id;
926                 } policy;/**< Policy arguments. */
927                 struct {
928                         uint16_t token;
929                         uintptr_t uintptr;
930                         char filename[128];
931                 } flex; /**< Flex arguments*/
932         } args; /**< Command arguments. */
933 };
934
935 /** Private data for pattern items. */
936 struct parse_item_priv {
937         enum rte_flow_item_type type; /**< Item type. */
938         uint32_t size; /**< Size of item specification structure. */
939 };
940
941 #define PRIV_ITEM(t, s) \
942         (&(const struct parse_item_priv){ \
943                 .type = RTE_FLOW_ITEM_TYPE_ ## t, \
944                 .size = s, \
945         })
946
947 /** Private data for actions. */
948 struct parse_action_priv {
949         enum rte_flow_action_type type; /**< Action type. */
950         uint32_t size; /**< Size of action configuration structure. */
951 };
952
953 #define PRIV_ACTION(t, s) \
954         (&(const struct parse_action_priv){ \
955                 .type = RTE_FLOW_ACTION_TYPE_ ## t, \
956                 .size = s, \
957         })
958
959 static const enum index next_flex_item[] = {
960         FLEX_ITEM_INIT,
961         FLEX_ITEM_CREATE,
962         FLEX_ITEM_DESTROY,
963         ZERO,
964 };
965
966 static const enum index next_config_attr[] = {
967         CONFIG_QUEUES_NUMBER,
968         CONFIG_QUEUES_SIZE,
969         CONFIG_COUNTERS_NUMBER,
970         CONFIG_AGING_OBJECTS_NUMBER,
971         CONFIG_METERS_NUMBER,
972         END,
973         ZERO,
974 };
975
976 static const enum index next_ia_create_attr[] = {
977         INDIRECT_ACTION_CREATE_ID,
978         INDIRECT_ACTION_INGRESS,
979         INDIRECT_ACTION_EGRESS,
980         INDIRECT_ACTION_TRANSFER,
981         INDIRECT_ACTION_SPEC,
982         ZERO,
983 };
984
985 static const enum index next_dump_subcmd[] = {
986         DUMP_ALL,
987         DUMP_ONE,
988         ZERO,
989 };
990
991 static const enum index next_ia_subcmd[] = {
992         INDIRECT_ACTION_CREATE,
993         INDIRECT_ACTION_UPDATE,
994         INDIRECT_ACTION_DESTROY,
995         INDIRECT_ACTION_QUERY,
996         ZERO,
997 };
998
999 static const enum index next_vc_attr[] = {
1000         VC_GROUP,
1001         VC_PRIORITY,
1002         VC_INGRESS,
1003         VC_EGRESS,
1004         VC_TRANSFER,
1005         VC_TUNNEL_SET,
1006         VC_TUNNEL_MATCH,
1007         ITEM_PATTERN,
1008         ZERO,
1009 };
1010
1011 static const enum index next_destroy_attr[] = {
1012         DESTROY_RULE,
1013         END,
1014         ZERO,
1015 };
1016
1017 static const enum index next_dump_attr[] = {
1018         COMMON_FILE_PATH,
1019         END,
1020         ZERO,
1021 };
1022
1023 static const enum index next_list_attr[] = {
1024         LIST_GROUP,
1025         END,
1026         ZERO,
1027 };
1028
1029 static const enum index next_aged_attr[] = {
1030         AGED_DESTROY,
1031         END,
1032         ZERO,
1033 };
1034
1035 static const enum index next_ia_destroy_attr[] = {
1036         INDIRECT_ACTION_DESTROY_ID,
1037         END,
1038         ZERO,
1039 };
1040
1041 static const enum index item_param[] = {
1042         ITEM_PARAM_IS,
1043         ITEM_PARAM_SPEC,
1044         ITEM_PARAM_LAST,
1045         ITEM_PARAM_MASK,
1046         ITEM_PARAM_PREFIX,
1047         ZERO,
1048 };
1049
1050 static const enum index next_item[] = {
1051         ITEM_END,
1052         ITEM_VOID,
1053         ITEM_INVERT,
1054         ITEM_ANY,
1055         ITEM_PF,
1056         ITEM_VF,
1057         ITEM_PHY_PORT,
1058         ITEM_PORT_ID,
1059         ITEM_MARK,
1060         ITEM_RAW,
1061         ITEM_ETH,
1062         ITEM_VLAN,
1063         ITEM_IPV4,
1064         ITEM_IPV6,
1065         ITEM_ICMP,
1066         ITEM_UDP,
1067         ITEM_TCP,
1068         ITEM_SCTP,
1069         ITEM_VXLAN,
1070         ITEM_E_TAG,
1071         ITEM_NVGRE,
1072         ITEM_MPLS,
1073         ITEM_GRE,
1074         ITEM_FUZZY,
1075         ITEM_GTP,
1076         ITEM_GTPC,
1077         ITEM_GTPU,
1078         ITEM_GENEVE,
1079         ITEM_VXLAN_GPE,
1080         ITEM_ARP_ETH_IPV4,
1081         ITEM_IPV6_EXT,
1082         ITEM_IPV6_FRAG_EXT,
1083         ITEM_ICMP6,
1084         ITEM_ICMP6_ND_NS,
1085         ITEM_ICMP6_ND_NA,
1086         ITEM_ICMP6_ND_OPT,
1087         ITEM_ICMP6_ND_OPT_SLA_ETH,
1088         ITEM_ICMP6_ND_OPT_TLA_ETH,
1089         ITEM_META,
1090         ITEM_GRE_KEY,
1091         ITEM_GRE_OPTION,
1092         ITEM_GTP_PSC,
1093         ITEM_PPPOES,
1094         ITEM_PPPOED,
1095         ITEM_PPPOE_PROTO_ID,
1096         ITEM_HIGIG2,
1097         ITEM_TAG,
1098         ITEM_L2TPV3OIP,
1099         ITEM_ESP,
1100         ITEM_AH,
1101         ITEM_PFCP,
1102         ITEM_ECPRI,
1103         ITEM_GENEVE_OPT,
1104         ITEM_INTEGRITY,
1105         ITEM_CONNTRACK,
1106         ITEM_PORT_REPRESENTOR,
1107         ITEM_REPRESENTED_PORT,
1108         ITEM_FLEX,
1109         ITEM_L2TPV2,
1110         ITEM_PPP,
1111         END_SET,
1112         ZERO,
1113 };
1114
1115 static const enum index item_fuzzy[] = {
1116         ITEM_FUZZY_THRESH,
1117         ITEM_NEXT,
1118         ZERO,
1119 };
1120
1121 static const enum index item_any[] = {
1122         ITEM_ANY_NUM,
1123         ITEM_NEXT,
1124         ZERO,
1125 };
1126
1127 static const enum index item_vf[] = {
1128         ITEM_VF_ID,
1129         ITEM_NEXT,
1130         ZERO,
1131 };
1132
1133 static const enum index item_phy_port[] = {
1134         ITEM_PHY_PORT_INDEX,
1135         ITEM_NEXT,
1136         ZERO,
1137 };
1138
1139 static const enum index item_port_id[] = {
1140         ITEM_PORT_ID_ID,
1141         ITEM_NEXT,
1142         ZERO,
1143 };
1144
1145 static const enum index item_mark[] = {
1146         ITEM_MARK_ID,
1147         ITEM_NEXT,
1148         ZERO,
1149 };
1150
1151 static const enum index item_raw[] = {
1152         ITEM_RAW_RELATIVE,
1153         ITEM_RAW_SEARCH,
1154         ITEM_RAW_OFFSET,
1155         ITEM_RAW_LIMIT,
1156         ITEM_RAW_PATTERN,
1157         ITEM_RAW_PATTERN_HEX,
1158         ITEM_NEXT,
1159         ZERO,
1160 };
1161
1162 static const enum index item_eth[] = {
1163         ITEM_ETH_DST,
1164         ITEM_ETH_SRC,
1165         ITEM_ETH_TYPE,
1166         ITEM_ETH_HAS_VLAN,
1167         ITEM_NEXT,
1168         ZERO,
1169 };
1170
1171 static const enum index item_vlan[] = {
1172         ITEM_VLAN_TCI,
1173         ITEM_VLAN_PCP,
1174         ITEM_VLAN_DEI,
1175         ITEM_VLAN_VID,
1176         ITEM_VLAN_INNER_TYPE,
1177         ITEM_VLAN_HAS_MORE_VLAN,
1178         ITEM_NEXT,
1179         ZERO,
1180 };
1181
1182 static const enum index item_ipv4[] = {
1183         ITEM_IPV4_VER_IHL,
1184         ITEM_IPV4_TOS,
1185         ITEM_IPV4_ID,
1186         ITEM_IPV4_FRAGMENT_OFFSET,
1187         ITEM_IPV4_TTL,
1188         ITEM_IPV4_PROTO,
1189         ITEM_IPV4_SRC,
1190         ITEM_IPV4_DST,
1191         ITEM_NEXT,
1192         ZERO,
1193 };
1194
1195 static const enum index item_ipv6[] = {
1196         ITEM_IPV6_TC,
1197         ITEM_IPV6_FLOW,
1198         ITEM_IPV6_PROTO,
1199         ITEM_IPV6_HOP,
1200         ITEM_IPV6_SRC,
1201         ITEM_IPV6_DST,
1202         ITEM_IPV6_HAS_FRAG_EXT,
1203         ITEM_NEXT,
1204         ZERO,
1205 };
1206
1207 static const enum index item_icmp[] = {
1208         ITEM_ICMP_TYPE,
1209         ITEM_ICMP_CODE,
1210         ITEM_ICMP_IDENT,
1211         ITEM_ICMP_SEQ,
1212         ITEM_NEXT,
1213         ZERO,
1214 };
1215
1216 static const enum index item_udp[] = {
1217         ITEM_UDP_SRC,
1218         ITEM_UDP_DST,
1219         ITEM_NEXT,
1220         ZERO,
1221 };
1222
1223 static const enum index item_tcp[] = {
1224         ITEM_TCP_SRC,
1225         ITEM_TCP_DST,
1226         ITEM_TCP_FLAGS,
1227         ITEM_NEXT,
1228         ZERO,
1229 };
1230
1231 static const enum index item_sctp[] = {
1232         ITEM_SCTP_SRC,
1233         ITEM_SCTP_DST,
1234         ITEM_SCTP_TAG,
1235         ITEM_SCTP_CKSUM,
1236         ITEM_NEXT,
1237         ZERO,
1238 };
1239
1240 static const enum index item_vxlan[] = {
1241         ITEM_VXLAN_VNI,
1242         ITEM_VXLAN_LAST_RSVD,
1243         ITEM_NEXT,
1244         ZERO,
1245 };
1246
1247 static const enum index item_e_tag[] = {
1248         ITEM_E_TAG_GRP_ECID_B,
1249         ITEM_NEXT,
1250         ZERO,
1251 };
1252
1253 static const enum index item_nvgre[] = {
1254         ITEM_NVGRE_TNI,
1255         ITEM_NEXT,
1256         ZERO,
1257 };
1258
1259 static const enum index item_mpls[] = {
1260         ITEM_MPLS_LABEL,
1261         ITEM_MPLS_TC,
1262         ITEM_MPLS_S,
1263         ITEM_NEXT,
1264         ZERO,
1265 };
1266
1267 static const enum index item_gre[] = {
1268         ITEM_GRE_PROTO,
1269         ITEM_GRE_C_RSVD0_VER,
1270         ITEM_GRE_C_BIT,
1271         ITEM_GRE_K_BIT,
1272         ITEM_GRE_S_BIT,
1273         ITEM_NEXT,
1274         ZERO,
1275 };
1276
1277 static const enum index item_gre_key[] = {
1278         ITEM_GRE_KEY_VALUE,
1279         ITEM_NEXT,
1280         ZERO,
1281 };
1282
1283 static const enum index item_gre_option[] = {
1284         ITEM_GRE_OPTION_CHECKSUM,
1285         ITEM_GRE_OPTION_KEY,
1286         ITEM_GRE_OPTION_SEQUENCE,
1287         ITEM_NEXT,
1288         ZERO,
1289 };
1290
1291 static const enum index item_gtp[] = {
1292         ITEM_GTP_FLAGS,
1293         ITEM_GTP_MSG_TYPE,
1294         ITEM_GTP_TEID,
1295         ITEM_NEXT,
1296         ZERO,
1297 };
1298
1299 static const enum index item_geneve[] = {
1300         ITEM_GENEVE_VNI,
1301         ITEM_GENEVE_PROTO,
1302         ITEM_GENEVE_OPTLEN,
1303         ITEM_NEXT,
1304         ZERO,
1305 };
1306
1307 static const enum index item_vxlan_gpe[] = {
1308         ITEM_VXLAN_GPE_VNI,
1309         ITEM_NEXT,
1310         ZERO,
1311 };
1312
1313 static const enum index item_arp_eth_ipv4[] = {
1314         ITEM_ARP_ETH_IPV4_SHA,
1315         ITEM_ARP_ETH_IPV4_SPA,
1316         ITEM_ARP_ETH_IPV4_THA,
1317         ITEM_ARP_ETH_IPV4_TPA,
1318         ITEM_NEXT,
1319         ZERO,
1320 };
1321
1322 static const enum index item_ipv6_ext[] = {
1323         ITEM_IPV6_EXT_NEXT_HDR,
1324         ITEM_NEXT,
1325         ZERO,
1326 };
1327
1328 static const enum index item_ipv6_frag_ext[] = {
1329         ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1330         ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1331         ITEM_IPV6_FRAG_EXT_ID,
1332         ITEM_NEXT,
1333         ZERO,
1334 };
1335
1336 static const enum index item_icmp6[] = {
1337         ITEM_ICMP6_TYPE,
1338         ITEM_ICMP6_CODE,
1339         ITEM_NEXT,
1340         ZERO,
1341 };
1342
1343 static const enum index item_icmp6_nd_ns[] = {
1344         ITEM_ICMP6_ND_NS_TARGET_ADDR,
1345         ITEM_NEXT,
1346         ZERO,
1347 };
1348
1349 static const enum index item_icmp6_nd_na[] = {
1350         ITEM_ICMP6_ND_NA_TARGET_ADDR,
1351         ITEM_NEXT,
1352         ZERO,
1353 };
1354
1355 static const enum index item_icmp6_nd_opt[] = {
1356         ITEM_ICMP6_ND_OPT_TYPE,
1357         ITEM_NEXT,
1358         ZERO,
1359 };
1360
1361 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1362         ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1363         ITEM_NEXT,
1364         ZERO,
1365 };
1366
1367 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1368         ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1369         ITEM_NEXT,
1370         ZERO,
1371 };
1372
1373 static const enum index item_meta[] = {
1374         ITEM_META_DATA,
1375         ITEM_NEXT,
1376         ZERO,
1377 };
1378
1379 static const enum index item_gtp_psc[] = {
1380         ITEM_GTP_PSC_QFI,
1381         ITEM_GTP_PSC_PDU_T,
1382         ITEM_NEXT,
1383         ZERO,
1384 };
1385
1386 static const enum index item_pppoed[] = {
1387         ITEM_PPPOE_SEID,
1388         ITEM_NEXT,
1389         ZERO,
1390 };
1391
1392 static const enum index item_pppoes[] = {
1393         ITEM_PPPOE_SEID,
1394         ITEM_NEXT,
1395         ZERO,
1396 };
1397
1398 static const enum index item_pppoe_proto_id[] = {
1399         ITEM_NEXT,
1400         ZERO,
1401 };
1402
1403 static const enum index item_higig2[] = {
1404         ITEM_HIGIG2_CLASSIFICATION,
1405         ITEM_HIGIG2_VID,
1406         ITEM_NEXT,
1407         ZERO,
1408 };
1409
1410 static const enum index item_esp[] = {
1411         ITEM_ESP_SPI,
1412         ITEM_NEXT,
1413         ZERO,
1414 };
1415
1416 static const enum index item_ah[] = {
1417         ITEM_AH_SPI,
1418         ITEM_NEXT,
1419         ZERO,
1420 };
1421
1422 static const enum index item_pfcp[] = {
1423         ITEM_PFCP_S_FIELD,
1424         ITEM_PFCP_SEID,
1425         ITEM_NEXT,
1426         ZERO,
1427 };
1428
1429 static const enum index next_set_raw[] = {
1430         SET_RAW_INDEX,
1431         ITEM_ETH,
1432         ZERO,
1433 };
1434
1435 static const enum index item_tag[] = {
1436         ITEM_TAG_DATA,
1437         ITEM_TAG_INDEX,
1438         ITEM_NEXT,
1439         ZERO,
1440 };
1441
1442 static const enum index item_l2tpv3oip[] = {
1443         ITEM_L2TPV3OIP_SESSION_ID,
1444         ITEM_NEXT,
1445         ZERO,
1446 };
1447
1448 static const enum index item_ecpri[] = {
1449         ITEM_ECPRI_COMMON,
1450         ITEM_NEXT,
1451         ZERO,
1452 };
1453
1454 static const enum index item_ecpri_common[] = {
1455         ITEM_ECPRI_COMMON_TYPE,
1456         ZERO,
1457 };
1458
1459 static const enum index item_ecpri_common_type[] = {
1460         ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
1461         ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
1462         ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
1463         ZERO,
1464 };
1465
1466 static const enum index item_geneve_opt[] = {
1467         ITEM_GENEVE_OPT_CLASS,
1468         ITEM_GENEVE_OPT_TYPE,
1469         ITEM_GENEVE_OPT_LENGTH,
1470         ITEM_GENEVE_OPT_DATA,
1471         ITEM_NEXT,
1472         ZERO,
1473 };
1474
1475 static const enum index item_integrity[] = {
1476         ITEM_INTEGRITY_LEVEL,
1477         ITEM_INTEGRITY_VALUE,
1478         ZERO,
1479 };
1480
1481 static const enum index item_integrity_lv[] = {
1482         ITEM_INTEGRITY_LEVEL,
1483         ITEM_INTEGRITY_VALUE,
1484         ITEM_NEXT,
1485         ZERO,
1486 };
1487
1488 static const enum index item_port_representor[] = {
1489         ITEM_PORT_REPRESENTOR_PORT_ID,
1490         ITEM_NEXT,
1491         ZERO,
1492 };
1493
1494 static const enum index item_represented_port[] = {
1495         ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
1496         ITEM_NEXT,
1497         ZERO,
1498 };
1499
1500 static const enum index item_flex[] = {
1501         ITEM_FLEX_PATTERN_HANDLE,
1502         ITEM_FLEX_ITEM_HANDLE,
1503         ITEM_NEXT,
1504         ZERO,
1505 };
1506
1507 static const enum index item_l2tpv2[] = {
1508         ITEM_L2TPV2_TYPE,
1509         ITEM_NEXT,
1510         ZERO,
1511 };
1512
1513 static const enum index item_l2tpv2_type[] = {
1514         ITEM_L2TPV2_TYPE_DATA,
1515         ITEM_L2TPV2_TYPE_DATA_L,
1516         ITEM_L2TPV2_TYPE_DATA_S,
1517         ITEM_L2TPV2_TYPE_DATA_O,
1518         ITEM_L2TPV2_TYPE_DATA_L_S,
1519         ITEM_L2TPV2_TYPE_CTRL,
1520         ZERO,
1521 };
1522
1523 static const enum index item_l2tpv2_type_data[] = {
1524         ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
1525         ITEM_L2TPV2_MSG_DATA_SESSION_ID,
1526         ITEM_NEXT,
1527         ZERO,
1528 };
1529
1530 static const enum index item_l2tpv2_type_data_l[] = {
1531         ITEM_L2TPV2_MSG_DATA_L_LENGTH,
1532         ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
1533         ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
1534         ITEM_NEXT,
1535         ZERO,
1536 };
1537
1538 static const enum index item_l2tpv2_type_data_s[] = {
1539         ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
1540         ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
1541         ITEM_L2TPV2_MSG_DATA_S_NS,
1542         ITEM_L2TPV2_MSG_DATA_S_NR,
1543         ITEM_NEXT,
1544         ZERO,
1545 };
1546
1547 static const enum index item_l2tpv2_type_data_o[] = {
1548         ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
1549         ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
1550         ITEM_L2TPV2_MSG_DATA_O_OFFSET,
1551         ITEM_NEXT,
1552         ZERO,
1553 };
1554
1555 static const enum index item_l2tpv2_type_data_l_s[] = {
1556         ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
1557         ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
1558         ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
1559         ITEM_L2TPV2_MSG_DATA_L_S_NS,
1560         ITEM_L2TPV2_MSG_DATA_L_S_NR,
1561         ITEM_NEXT,
1562         ZERO,
1563 };
1564
1565 static const enum index item_l2tpv2_type_ctrl[] = {
1566         ITEM_L2TPV2_MSG_CTRL_LENGTH,
1567         ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
1568         ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
1569         ITEM_L2TPV2_MSG_CTRL_NS,
1570         ITEM_L2TPV2_MSG_CTRL_NR,
1571         ITEM_NEXT,
1572         ZERO,
1573 };
1574
1575 static const enum index item_ppp[] = {
1576         ITEM_PPP_ADDR,
1577         ITEM_PPP_CTRL,
1578         ITEM_PPP_PROTO_ID,
1579         ITEM_NEXT,
1580         ZERO,
1581 };
1582
1583 static const enum index next_action[] = {
1584         ACTION_END,
1585         ACTION_VOID,
1586         ACTION_PASSTHRU,
1587         ACTION_JUMP,
1588         ACTION_MARK,
1589         ACTION_FLAG,
1590         ACTION_QUEUE,
1591         ACTION_DROP,
1592         ACTION_COUNT,
1593         ACTION_RSS,
1594         ACTION_PF,
1595         ACTION_VF,
1596         ACTION_PHY_PORT,
1597         ACTION_PORT_ID,
1598         ACTION_METER,
1599         ACTION_METER_COLOR,
1600         ACTION_OF_SET_MPLS_TTL,
1601         ACTION_OF_DEC_MPLS_TTL,
1602         ACTION_OF_SET_NW_TTL,
1603         ACTION_OF_DEC_NW_TTL,
1604         ACTION_OF_COPY_TTL_OUT,
1605         ACTION_OF_COPY_TTL_IN,
1606         ACTION_OF_POP_VLAN,
1607         ACTION_OF_PUSH_VLAN,
1608         ACTION_OF_SET_VLAN_VID,
1609         ACTION_OF_SET_VLAN_PCP,
1610         ACTION_OF_POP_MPLS,
1611         ACTION_OF_PUSH_MPLS,
1612         ACTION_VXLAN_ENCAP,
1613         ACTION_VXLAN_DECAP,
1614         ACTION_NVGRE_ENCAP,
1615         ACTION_NVGRE_DECAP,
1616         ACTION_L2_ENCAP,
1617         ACTION_L2_DECAP,
1618         ACTION_MPLSOGRE_ENCAP,
1619         ACTION_MPLSOGRE_DECAP,
1620         ACTION_MPLSOUDP_ENCAP,
1621         ACTION_MPLSOUDP_DECAP,
1622         ACTION_SET_IPV4_SRC,
1623         ACTION_SET_IPV4_DST,
1624         ACTION_SET_IPV6_SRC,
1625         ACTION_SET_IPV6_DST,
1626         ACTION_SET_TP_SRC,
1627         ACTION_SET_TP_DST,
1628         ACTION_MAC_SWAP,
1629         ACTION_DEC_TTL,
1630         ACTION_SET_TTL,
1631         ACTION_SET_MAC_SRC,
1632         ACTION_SET_MAC_DST,
1633         ACTION_INC_TCP_SEQ,
1634         ACTION_DEC_TCP_SEQ,
1635         ACTION_INC_TCP_ACK,
1636         ACTION_DEC_TCP_ACK,
1637         ACTION_RAW_ENCAP,
1638         ACTION_RAW_DECAP,
1639         ACTION_SET_TAG,
1640         ACTION_SET_META,
1641         ACTION_SET_IPV4_DSCP,
1642         ACTION_SET_IPV6_DSCP,
1643         ACTION_AGE,
1644         ACTION_SAMPLE,
1645         ACTION_INDIRECT,
1646         ACTION_MODIFY_FIELD,
1647         ACTION_CONNTRACK,
1648         ACTION_CONNTRACK_UPDATE,
1649         ACTION_PORT_REPRESENTOR,
1650         ACTION_REPRESENTED_PORT,
1651         ZERO,
1652 };
1653
1654 static const enum index action_mark[] = {
1655         ACTION_MARK_ID,
1656         ACTION_NEXT,
1657         ZERO,
1658 };
1659
1660 static const enum index action_queue[] = {
1661         ACTION_QUEUE_INDEX,
1662         ACTION_NEXT,
1663         ZERO,
1664 };
1665
1666 static const enum index action_count[] = {
1667         ACTION_COUNT_ID,
1668         ACTION_NEXT,
1669         ZERO,
1670 };
1671
1672 static const enum index action_rss[] = {
1673         ACTION_RSS_FUNC,
1674         ACTION_RSS_LEVEL,
1675         ACTION_RSS_TYPES,
1676         ACTION_RSS_KEY,
1677         ACTION_RSS_KEY_LEN,
1678         ACTION_RSS_QUEUES,
1679         ACTION_NEXT,
1680         ZERO,
1681 };
1682
1683 static const enum index action_vf[] = {
1684         ACTION_VF_ORIGINAL,
1685         ACTION_VF_ID,
1686         ACTION_NEXT,
1687         ZERO,
1688 };
1689
1690 static const enum index action_phy_port[] = {
1691         ACTION_PHY_PORT_ORIGINAL,
1692         ACTION_PHY_PORT_INDEX,
1693         ACTION_NEXT,
1694         ZERO,
1695 };
1696
1697 static const enum index action_port_id[] = {
1698         ACTION_PORT_ID_ORIGINAL,
1699         ACTION_PORT_ID_ID,
1700         ACTION_NEXT,
1701         ZERO,
1702 };
1703
1704 static const enum index action_meter[] = {
1705         ACTION_METER_ID,
1706         ACTION_NEXT,
1707         ZERO,
1708 };
1709
1710 static const enum index action_meter_color[] = {
1711         ACTION_METER_COLOR_TYPE,
1712         ACTION_NEXT,
1713         ZERO,
1714 };
1715
1716 static const enum index action_of_set_mpls_ttl[] = {
1717         ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
1718         ACTION_NEXT,
1719         ZERO,
1720 };
1721
1722 static const enum index action_of_set_nw_ttl[] = {
1723         ACTION_OF_SET_NW_TTL_NW_TTL,
1724         ACTION_NEXT,
1725         ZERO,
1726 };
1727
1728 static const enum index action_of_push_vlan[] = {
1729         ACTION_OF_PUSH_VLAN_ETHERTYPE,
1730         ACTION_NEXT,
1731         ZERO,
1732 };
1733
1734 static const enum index action_of_set_vlan_vid[] = {
1735         ACTION_OF_SET_VLAN_VID_VLAN_VID,
1736         ACTION_NEXT,
1737         ZERO,
1738 };
1739
1740 static const enum index action_of_set_vlan_pcp[] = {
1741         ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
1742         ACTION_NEXT,
1743         ZERO,
1744 };
1745
1746 static const enum index action_of_pop_mpls[] = {
1747         ACTION_OF_POP_MPLS_ETHERTYPE,
1748         ACTION_NEXT,
1749         ZERO,
1750 };
1751
1752 static const enum index action_of_push_mpls[] = {
1753         ACTION_OF_PUSH_MPLS_ETHERTYPE,
1754         ACTION_NEXT,
1755         ZERO,
1756 };
1757
1758 static const enum index action_set_ipv4_src[] = {
1759         ACTION_SET_IPV4_SRC_IPV4_SRC,
1760         ACTION_NEXT,
1761         ZERO,
1762 };
1763
1764 static const enum index action_set_mac_src[] = {
1765         ACTION_SET_MAC_SRC_MAC_SRC,
1766         ACTION_NEXT,
1767         ZERO,
1768 };
1769
1770 static const enum index action_set_ipv4_dst[] = {
1771         ACTION_SET_IPV4_DST_IPV4_DST,
1772         ACTION_NEXT,
1773         ZERO,
1774 };
1775
1776 static const enum index action_set_ipv6_src[] = {
1777         ACTION_SET_IPV6_SRC_IPV6_SRC,
1778         ACTION_NEXT,
1779         ZERO,
1780 };
1781
1782 static const enum index action_set_ipv6_dst[] = {
1783         ACTION_SET_IPV6_DST_IPV6_DST,
1784         ACTION_NEXT,
1785         ZERO,
1786 };
1787
1788 static const enum index action_set_tp_src[] = {
1789         ACTION_SET_TP_SRC_TP_SRC,
1790         ACTION_NEXT,
1791         ZERO,
1792 };
1793
1794 static const enum index action_set_tp_dst[] = {
1795         ACTION_SET_TP_DST_TP_DST,
1796         ACTION_NEXT,
1797         ZERO,
1798 };
1799
1800 static const enum index action_set_ttl[] = {
1801         ACTION_SET_TTL_TTL,
1802         ACTION_NEXT,
1803         ZERO,
1804 };
1805
1806 static const enum index action_jump[] = {
1807         ACTION_JUMP_GROUP,
1808         ACTION_NEXT,
1809         ZERO,
1810 };
1811
1812 static const enum index action_set_mac_dst[] = {
1813         ACTION_SET_MAC_DST_MAC_DST,
1814         ACTION_NEXT,
1815         ZERO,
1816 };
1817
1818 static const enum index action_inc_tcp_seq[] = {
1819         ACTION_INC_TCP_SEQ_VALUE,
1820         ACTION_NEXT,
1821         ZERO,
1822 };
1823
1824 static const enum index action_dec_tcp_seq[] = {
1825         ACTION_DEC_TCP_SEQ_VALUE,
1826         ACTION_NEXT,
1827         ZERO,
1828 };
1829
1830 static const enum index action_inc_tcp_ack[] = {
1831         ACTION_INC_TCP_ACK_VALUE,
1832         ACTION_NEXT,
1833         ZERO,
1834 };
1835
1836 static const enum index action_dec_tcp_ack[] = {
1837         ACTION_DEC_TCP_ACK_VALUE,
1838         ACTION_NEXT,
1839         ZERO,
1840 };
1841
1842 static const enum index action_raw_encap[] = {
1843         ACTION_RAW_ENCAP_INDEX,
1844         ACTION_NEXT,
1845         ZERO,
1846 };
1847
1848 static const enum index action_raw_decap[] = {
1849         ACTION_RAW_DECAP_INDEX,
1850         ACTION_NEXT,
1851         ZERO,
1852 };
1853
1854 static const enum index action_set_tag[] = {
1855         ACTION_SET_TAG_DATA,
1856         ACTION_SET_TAG_INDEX,
1857         ACTION_SET_TAG_MASK,
1858         ACTION_NEXT,
1859         ZERO,
1860 };
1861
1862 static const enum index action_set_meta[] = {
1863         ACTION_SET_META_DATA,
1864         ACTION_SET_META_MASK,
1865         ACTION_NEXT,
1866         ZERO,
1867 };
1868
1869 static const enum index action_set_ipv4_dscp[] = {
1870         ACTION_SET_IPV4_DSCP_VALUE,
1871         ACTION_NEXT,
1872         ZERO,
1873 };
1874
1875 static const enum index action_set_ipv6_dscp[] = {
1876         ACTION_SET_IPV6_DSCP_VALUE,
1877         ACTION_NEXT,
1878         ZERO,
1879 };
1880
1881 static const enum index action_age[] = {
1882         ACTION_AGE,
1883         ACTION_AGE_TIMEOUT,
1884         ACTION_NEXT,
1885         ZERO,
1886 };
1887
1888 static const enum index action_sample[] = {
1889         ACTION_SAMPLE,
1890         ACTION_SAMPLE_RATIO,
1891         ACTION_SAMPLE_INDEX,
1892         ACTION_NEXT,
1893         ZERO,
1894 };
1895
1896 static const enum index next_action_sample[] = {
1897         ACTION_QUEUE,
1898         ACTION_RSS,
1899         ACTION_MARK,
1900         ACTION_COUNT,
1901         ACTION_PORT_ID,
1902         ACTION_RAW_ENCAP,
1903         ACTION_VXLAN_ENCAP,
1904         ACTION_NVGRE_ENCAP,
1905         ACTION_NEXT,
1906         ZERO,
1907 };
1908
1909 static const enum index action_modify_field_dst[] = {
1910         ACTION_MODIFY_FIELD_DST_LEVEL,
1911         ACTION_MODIFY_FIELD_DST_OFFSET,
1912         ACTION_MODIFY_FIELD_SRC_TYPE,
1913         ZERO,
1914 };
1915
1916 static const enum index action_modify_field_src[] = {
1917         ACTION_MODIFY_FIELD_SRC_LEVEL,
1918         ACTION_MODIFY_FIELD_SRC_OFFSET,
1919         ACTION_MODIFY_FIELD_SRC_VALUE,
1920         ACTION_MODIFY_FIELD_SRC_POINTER,
1921         ACTION_MODIFY_FIELD_WIDTH,
1922         ZERO,
1923 };
1924
1925 static const enum index action_update_conntrack[] = {
1926         ACTION_CONNTRACK_UPDATE_DIR,
1927         ACTION_CONNTRACK_UPDATE_CTX,
1928         ACTION_NEXT,
1929         ZERO,
1930 };
1931
1932 static const enum index action_port_representor[] = {
1933         ACTION_PORT_REPRESENTOR_PORT_ID,
1934         ACTION_NEXT,
1935         ZERO,
1936 };
1937
1938 static const enum index action_represented_port[] = {
1939         ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
1940         ACTION_NEXT,
1941         ZERO,
1942 };
1943
1944 static int parse_set_raw_encap_decap(struct context *, const struct token *,
1945                                      const char *, unsigned int,
1946                                      void *, unsigned int);
1947 static int parse_set_sample_action(struct context *, const struct token *,
1948                                    const char *, unsigned int,
1949                                    void *, unsigned int);
1950 static int parse_set_init(struct context *, const struct token *,
1951                           const char *, unsigned int,
1952                           void *, unsigned int);
1953 static int
1954 parse_flex_handle(struct context *, const struct token *,
1955                   const char *, unsigned int, void *, unsigned int);
1956 static int parse_init(struct context *, const struct token *,
1957                       const char *, unsigned int,
1958                       void *, unsigned int);
1959 static int parse_vc(struct context *, const struct token *,
1960                     const char *, unsigned int,
1961                     void *, unsigned int);
1962 static int parse_vc_spec(struct context *, const struct token *,
1963                          const char *, unsigned int, void *, unsigned int);
1964 static int parse_vc_conf(struct context *, const struct token *,
1965                          const char *, unsigned int, void *, unsigned int);
1966 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
1967                                     const char *, unsigned int,
1968                                     void *, unsigned int);
1969 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *,
1970                                     const char *, unsigned int,
1971                                     void *, unsigned int);
1972 static int parse_vc_action_meter_color_type(struct context *,
1973                                         const struct token *,
1974                                         const char *, unsigned int, void *,
1975                                         unsigned int);
1976 static int parse_vc_action_rss(struct context *, const struct token *,
1977                                const char *, unsigned int, void *,
1978                                unsigned int);
1979 static int parse_vc_action_rss_func(struct context *, const struct token *,
1980                                     const char *, unsigned int, void *,
1981                                     unsigned int);
1982 static int parse_vc_action_rss_type(struct context *, const struct token *,
1983                                     const char *, unsigned int, void *,
1984                                     unsigned int);
1985 static int parse_vc_action_rss_queue(struct context *, const struct token *,
1986                                      const char *, unsigned int, void *,
1987                                      unsigned int);
1988 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
1989                                        const char *, unsigned int, void *,
1990                                        unsigned int);
1991 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
1992                                        const char *, unsigned int, void *,
1993                                        unsigned int);
1994 static int parse_vc_action_l2_encap(struct context *, const struct token *,
1995                                     const char *, unsigned int, void *,
1996                                     unsigned int);
1997 static int parse_vc_action_l2_decap(struct context *, const struct token *,
1998                                     const char *, unsigned int, void *,
1999                                     unsigned int);
2000 static int parse_vc_action_mplsogre_encap(struct context *,
2001                                           const struct token *, const char *,
2002                                           unsigned int, void *, unsigned int);
2003 static int parse_vc_action_mplsogre_decap(struct context *,
2004                                           const struct token *, const char *,
2005                                           unsigned int, void *, unsigned int);
2006 static int parse_vc_action_mplsoudp_encap(struct context *,
2007                                           const struct token *, const char *,
2008                                           unsigned int, void *, unsigned int);
2009 static int parse_vc_action_mplsoudp_decap(struct context *,
2010                                           const struct token *, const char *,
2011                                           unsigned int, void *, unsigned int);
2012 static int parse_vc_action_raw_encap(struct context *,
2013                                      const struct token *, const char *,
2014                                      unsigned int, void *, unsigned int);
2015 static int parse_vc_action_raw_decap(struct context *,
2016                                      const struct token *, const char *,
2017                                      unsigned int, void *, unsigned int);
2018 static int parse_vc_action_raw_encap_index(struct context *,
2019                                            const struct token *, const char *,
2020                                            unsigned int, void *, unsigned int);
2021 static int parse_vc_action_raw_decap_index(struct context *,
2022                                            const struct token *, const char *,
2023                                            unsigned int, void *, unsigned int);
2024 static int parse_vc_action_set_meta(struct context *ctx,
2025                                     const struct token *token, const char *str,
2026                                     unsigned int len, void *buf,
2027                                         unsigned int size);
2028 static int parse_vc_action_sample(struct context *ctx,
2029                                     const struct token *token, const char *str,
2030                                     unsigned int len, void *buf,
2031                                     unsigned int size);
2032 static int
2033 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
2034                                 const char *str, unsigned int len, void *buf,
2035                                 unsigned int size);
2036 static int
2037 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
2038                                 const char *str, unsigned int len, void *buf,
2039                                 unsigned int size);
2040 static int
2041 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
2042                                 const char *str, unsigned int len, void *buf,
2043                                 unsigned int size);
2044 static int
2045 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
2046                          const char *str, unsigned int len, void *buf,
2047                          unsigned int size);
2048 static int parse_destroy(struct context *, const struct token *,
2049                          const char *, unsigned int,
2050                          void *, unsigned int);
2051 static int parse_flush(struct context *, const struct token *,
2052                        const char *, unsigned int,
2053                        void *, unsigned int);
2054 static int parse_dump(struct context *, const struct token *,
2055                       const char *, unsigned int,
2056                       void *, unsigned int);
2057 static int parse_query(struct context *, const struct token *,
2058                        const char *, unsigned int,
2059                        void *, unsigned int);
2060 static int parse_action(struct context *, const struct token *,
2061                         const char *, unsigned int,
2062                         void *, unsigned int);
2063 static int parse_list(struct context *, const struct token *,
2064                       const char *, unsigned int,
2065                       void *, unsigned int);
2066 static int parse_aged(struct context *, const struct token *,
2067                       const char *, unsigned int,
2068                       void *, unsigned int);
2069 static int parse_isolate(struct context *, const struct token *,
2070                          const char *, unsigned int,
2071                          void *, unsigned int);
2072 static int parse_configure(struct context *, const struct token *,
2073                            const char *, unsigned int,
2074                            void *, unsigned int);
2075 static int parse_tunnel(struct context *, const struct token *,
2076                         const char *, unsigned int,
2077                         void *, unsigned int);
2078 static int parse_flex(struct context *, const struct token *,
2079                       const char *, unsigned int, void *, unsigned int);
2080 static int parse_int(struct context *, const struct token *,
2081                      const char *, unsigned int,
2082                      void *, unsigned int);
2083 static int parse_prefix(struct context *, const struct token *,
2084                         const char *, unsigned int,
2085                         void *, unsigned int);
2086 static int parse_boolean(struct context *, const struct token *,
2087                          const char *, unsigned int,
2088                          void *, unsigned int);
2089 static int parse_string(struct context *, const struct token *,
2090                         const char *, unsigned int,
2091                         void *, unsigned int);
2092 static int parse_hex(struct context *ctx, const struct token *token,
2093                         const char *str, unsigned int len,
2094                         void *buf, unsigned int size);
2095 static int parse_string0(struct context *, const struct token *,
2096                         const char *, unsigned int,
2097                         void *, unsigned int);
2098 static int parse_mac_addr(struct context *, const struct token *,
2099                           const char *, unsigned int,
2100                           void *, unsigned int);
2101 static int parse_ipv4_addr(struct context *, const struct token *,
2102                            const char *, unsigned int,
2103                            void *, unsigned int);
2104 static int parse_ipv6_addr(struct context *, const struct token *,
2105                            const char *, unsigned int,
2106                            void *, unsigned int);
2107 static int parse_port(struct context *, const struct token *,
2108                       const char *, unsigned int,
2109                       void *, unsigned int);
2110 static int parse_ia(struct context *, const struct token *,
2111                     const char *, unsigned int,
2112                     void *, unsigned int);
2113 static int parse_ia_destroy(struct context *ctx, const struct token *token,
2114                             const char *str, unsigned int len,
2115                             void *buf, unsigned int size);
2116 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
2117                            const char *str, unsigned int len, void *buf,
2118                            unsigned int size);
2119 static int parse_mp(struct context *, const struct token *,
2120                     const char *, unsigned int,
2121                     void *, unsigned int);
2122 static int comp_none(struct context *, const struct token *,
2123                      unsigned int, char *, unsigned int);
2124 static int comp_boolean(struct context *, const struct token *,
2125                         unsigned int, char *, unsigned int);
2126 static int comp_action(struct context *, const struct token *,
2127                        unsigned int, char *, unsigned int);
2128 static int comp_port(struct context *, const struct token *,
2129                      unsigned int, char *, unsigned int);
2130 static int comp_rule_id(struct context *, const struct token *,
2131                         unsigned int, char *, unsigned int);
2132 static int comp_vc_action_rss_type(struct context *, const struct token *,
2133                                    unsigned int, char *, unsigned int);
2134 static int comp_vc_action_rss_queue(struct context *, const struct token *,
2135                                     unsigned int, char *, unsigned int);
2136 static int comp_set_raw_index(struct context *, const struct token *,
2137                               unsigned int, char *, unsigned int);
2138 static int comp_set_sample_index(struct context *, const struct token *,
2139                               unsigned int, char *, unsigned int);
2140 static int comp_set_modify_field_op(struct context *, const struct token *,
2141                               unsigned int, char *, unsigned int);
2142 static int comp_set_modify_field_id(struct context *, const struct token *,
2143                               unsigned int, char *, unsigned int);
2144
2145 /** Token definitions. */
2146 static const struct token token_list[] = {
2147         /* Special tokens. */
2148         [ZERO] = {
2149                 .name = "ZERO",
2150                 .help = "null entry, abused as the entry point",
2151                 .next = NEXT(NEXT_ENTRY(FLOW, ADD)),
2152         },
2153         [END] = {
2154                 .name = "",
2155                 .type = "RETURN",
2156                 .help = "command may end here",
2157         },
2158         [START_SET] = {
2159                 .name = "START_SET",
2160                 .help = "null entry, abused as the entry point for set",
2161                 .next = NEXT(NEXT_ENTRY(SET)),
2162         },
2163         [END_SET] = {
2164                 .name = "end_set",
2165                 .type = "RETURN",
2166                 .help = "set command may end here",
2167         },
2168         /* Common tokens. */
2169         [COMMON_INTEGER] = {
2170                 .name = "{int}",
2171                 .type = "INTEGER",
2172                 .help = "integer value",
2173                 .call = parse_int,
2174                 .comp = comp_none,
2175         },
2176         [COMMON_UNSIGNED] = {
2177                 .name = "{unsigned}",
2178                 .type = "UNSIGNED",
2179                 .help = "unsigned integer value",
2180                 .call = parse_int,
2181                 .comp = comp_none,
2182         },
2183         [COMMON_PREFIX] = {
2184                 .name = "{prefix}",
2185                 .type = "PREFIX",
2186                 .help = "prefix length for bit-mask",
2187                 .call = parse_prefix,
2188                 .comp = comp_none,
2189         },
2190         [COMMON_BOOLEAN] = {
2191                 .name = "{boolean}",
2192                 .type = "BOOLEAN",
2193                 .help = "any boolean value",
2194                 .call = parse_boolean,
2195                 .comp = comp_boolean,
2196         },
2197         [COMMON_STRING] = {
2198                 .name = "{string}",
2199                 .type = "STRING",
2200                 .help = "fixed string",
2201                 .call = parse_string,
2202                 .comp = comp_none,
2203         },
2204         [COMMON_HEX] = {
2205                 .name = "{hex}",
2206                 .type = "HEX",
2207                 .help = "fixed string",
2208                 .call = parse_hex,
2209         },
2210         [COMMON_FILE_PATH] = {
2211                 .name = "{file path}",
2212                 .type = "STRING",
2213                 .help = "file path",
2214                 .call = parse_string0,
2215                 .comp = comp_none,
2216         },
2217         [COMMON_MAC_ADDR] = {
2218                 .name = "{MAC address}",
2219                 .type = "MAC-48",
2220                 .help = "standard MAC address notation",
2221                 .call = parse_mac_addr,
2222                 .comp = comp_none,
2223         },
2224         [COMMON_IPV4_ADDR] = {
2225                 .name = "{IPv4 address}",
2226                 .type = "IPV4 ADDRESS",
2227                 .help = "standard IPv4 address notation",
2228                 .call = parse_ipv4_addr,
2229                 .comp = comp_none,
2230         },
2231         [COMMON_IPV6_ADDR] = {
2232                 .name = "{IPv6 address}",
2233                 .type = "IPV6 ADDRESS",
2234                 .help = "standard IPv6 address notation",
2235                 .call = parse_ipv6_addr,
2236                 .comp = comp_none,
2237         },
2238         [COMMON_RULE_ID] = {
2239                 .name = "{rule id}",
2240                 .type = "RULE ID",
2241                 .help = "rule identifier",
2242                 .call = parse_int,
2243                 .comp = comp_rule_id,
2244         },
2245         [COMMON_PORT_ID] = {
2246                 .name = "{port_id}",
2247                 .type = "PORT ID",
2248                 .help = "port identifier",
2249                 .call = parse_port,
2250                 .comp = comp_port,
2251         },
2252         [COMMON_GROUP_ID] = {
2253                 .name = "{group_id}",
2254                 .type = "GROUP ID",
2255                 .help = "group identifier",
2256                 .call = parse_int,
2257                 .comp = comp_none,
2258         },
2259         [COMMON_PRIORITY_LEVEL] = {
2260                 .name = "{level}",
2261                 .type = "PRIORITY",
2262                 .help = "priority level",
2263                 .call = parse_int,
2264                 .comp = comp_none,
2265         },
2266         [COMMON_INDIRECT_ACTION_ID] = {
2267                 .name = "{indirect_action_id}",
2268                 .type = "INDIRECT_ACTION_ID",
2269                 .help = "indirect action id",
2270                 .call = parse_int,
2271                 .comp = comp_none,
2272         },
2273         [COMMON_POLICY_ID] = {
2274                 .name = "{policy_id}",
2275                 .type = "POLICY_ID",
2276                 .help = "policy id",
2277                 .call = parse_int,
2278                 .comp = comp_none,
2279         },
2280         [COMMON_FLEX_TOKEN] = {
2281                 .name = "{flex token}",
2282                 .type = "flex token",
2283                 .help = "flex token",
2284                 .call = parse_int,
2285                 .comp = comp_none,
2286         },
2287         [COMMON_FLEX_HANDLE] = {
2288                 .name = "{flex handle}",
2289                 .type = "FLEX HANDLE",
2290                 .help = "fill flex item data",
2291                 .call = parse_flex_handle,
2292                 .comp = comp_none,
2293         },
2294         /* Top-level command. */
2295         [FLOW] = {
2296                 .name = "flow",
2297                 .type = "{command} {port_id} [{arg} [...]]",
2298                 .help = "manage ingress/egress flow rules",
2299                 .next = NEXT(NEXT_ENTRY
2300                              (INFO,
2301                               CONFIGURE,
2302                               INDIRECT_ACTION,
2303                               VALIDATE,
2304                               CREATE,
2305                               DESTROY,
2306                               FLUSH,
2307                               DUMP,
2308                               LIST,
2309                               AGED,
2310                               QUERY,
2311                               ISOLATE,
2312                               TUNNEL,
2313                               FLEX)),
2314                 .call = parse_init,
2315         },
2316         /* Top-level command. */
2317         [INFO] = {
2318                 .name = "info",
2319                 .help = "get information about flow engine",
2320                 .next = NEXT(NEXT_ENTRY(END),
2321                              NEXT_ENTRY(COMMON_PORT_ID)),
2322                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2323                 .call = parse_configure,
2324         },
2325         /* Top-level command. */
2326         [CONFIGURE] = {
2327                 .name = "configure",
2328                 .help = "configure flow engine",
2329                 .next = NEXT(next_config_attr,
2330                              NEXT_ENTRY(COMMON_PORT_ID)),
2331                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2332                 .call = parse_configure,
2333         },
2334         /* Configure arguments. */
2335         [CONFIG_QUEUES_NUMBER] = {
2336                 .name = "queues_number",
2337                 .help = "number of queues",
2338                 .next = NEXT(next_config_attr,
2339                              NEXT_ENTRY(COMMON_UNSIGNED)),
2340                 .args = ARGS(ARGS_ENTRY(struct buffer,
2341                                         args.configure.nb_queue)),
2342         },
2343         [CONFIG_QUEUES_SIZE] = {
2344                 .name = "queues_size",
2345                 .help = "number of elements in queues",
2346                 .next = NEXT(next_config_attr,
2347                              NEXT_ENTRY(COMMON_UNSIGNED)),
2348                 .args = ARGS(ARGS_ENTRY(struct buffer,
2349                                         args.configure.queue_attr.size)),
2350         },
2351         [CONFIG_COUNTERS_NUMBER] = {
2352                 .name = "counters_number",
2353                 .help = "number of counters",
2354                 .next = NEXT(next_config_attr,
2355                              NEXT_ENTRY(COMMON_UNSIGNED)),
2356                 .args = ARGS(ARGS_ENTRY(struct buffer,
2357                                         args.configure.port_attr.nb_counters)),
2358         },
2359         [CONFIG_AGING_OBJECTS_NUMBER] = {
2360                 .name = "aging_counters_number",
2361                 .help = "number of aging objects",
2362                 .next = NEXT(next_config_attr,
2363                              NEXT_ENTRY(COMMON_UNSIGNED)),
2364                 .args = ARGS(ARGS_ENTRY(struct buffer,
2365                                         args.configure.port_attr.nb_aging_objects)),
2366         },
2367         [CONFIG_METERS_NUMBER] = {
2368                 .name = "meters_number",
2369                 .help = "number of meters",
2370                 .next = NEXT(next_config_attr,
2371                              NEXT_ENTRY(COMMON_UNSIGNED)),
2372                 .args = ARGS(ARGS_ENTRY(struct buffer,
2373                                         args.configure.port_attr.nb_meters)),
2374         },
2375         /* Top-level command. */
2376         [INDIRECT_ACTION] = {
2377                 .name = "indirect_action",
2378                 .type = "{command} {port_id} [{arg} [...]]",
2379                 .help = "manage indirect actions",
2380                 .next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2381                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2382                 .call = parse_ia,
2383         },
2384         /* Sub-level commands. */
2385         [INDIRECT_ACTION_CREATE] = {
2386                 .name = "create",
2387                 .help = "create indirect action",
2388                 .next = NEXT(next_ia_create_attr),
2389                 .call = parse_ia,
2390         },
2391         [INDIRECT_ACTION_UPDATE] = {
2392                 .name = "update",
2393                 .help = "update indirect action",
2394                 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
2395                              NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2396                 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
2397                 .call = parse_ia,
2398         },
2399         [INDIRECT_ACTION_DESTROY] = {
2400                 .name = "destroy",
2401                 .help = "destroy indirect action",
2402                 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
2403                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2404                 .call = parse_ia_destroy,
2405         },
2406         [INDIRECT_ACTION_QUERY] = {
2407                 .name = "query",
2408                 .help = "query indirect action",
2409                 .next = NEXT(NEXT_ENTRY(END),
2410                              NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2411                 .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
2412                 .call = parse_ia,
2413         },
2414         [VALIDATE] = {
2415                 .name = "validate",
2416                 .help = "check whether a flow rule can be created",
2417                 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2418                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2419                 .call = parse_vc,
2420         },
2421         [CREATE] = {
2422                 .name = "create",
2423                 .help = "create a flow rule",
2424                 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2425                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2426                 .call = parse_vc,
2427         },
2428         [DESTROY] = {
2429                 .name = "destroy",
2430                 .help = "destroy specific flow rules",
2431                 .next = NEXT(NEXT_ENTRY(DESTROY_RULE),
2432                              NEXT_ENTRY(COMMON_PORT_ID)),
2433                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2434                 .call = parse_destroy,
2435         },
2436         [FLUSH] = {
2437                 .name = "flush",
2438                 .help = "destroy all flow rules",
2439                 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
2440                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2441                 .call = parse_flush,
2442         },
2443         [DUMP] = {
2444                 .name = "dump",
2445                 .help = "dump single/all flow rules to file",
2446                 .next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2447                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2448                 .call = parse_dump,
2449         },
2450         [QUERY] = {
2451                 .name = "query",
2452                 .help = "query an existing flow rule",
2453                 .next = NEXT(NEXT_ENTRY(QUERY_ACTION),
2454                              NEXT_ENTRY(COMMON_RULE_ID),
2455                              NEXT_ENTRY(COMMON_PORT_ID)),
2456                 .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
2457                              ARGS_ENTRY(struct buffer, args.query.rule),
2458                              ARGS_ENTRY(struct buffer, port)),
2459                 .call = parse_query,
2460         },
2461         [LIST] = {
2462                 .name = "list",
2463                 .help = "list existing flow rules",
2464                 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2465                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2466                 .call = parse_list,
2467         },
2468         [AGED] = {
2469                 .name = "aged",
2470                 .help = "list and destroy aged flows",
2471                 .next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2472                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2473                 .call = parse_aged,
2474         },
2475         [ISOLATE] = {
2476                 .name = "isolate",
2477                 .help = "restrict ingress traffic to the defined flow rules",
2478                 .next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
2479                              NEXT_ENTRY(COMMON_PORT_ID)),
2480                 .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
2481                              ARGS_ENTRY(struct buffer, port)),
2482                 .call = parse_isolate,
2483         },
2484         [FLEX] = {
2485                 .name = "flex_item",
2486                 .help = "flex item API",
2487                 .next = NEXT(next_flex_item),
2488                 .call = parse_flex,
2489         },
2490         [FLEX_ITEM_INIT] = {
2491                 .name = "init",
2492                 .help = "flex item init",
2493                 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
2494                              ARGS_ENTRY(struct buffer, port)),
2495                 .next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
2496                              NEXT_ENTRY(COMMON_PORT_ID)),
2497                 .call = parse_flex
2498         },
2499         [FLEX_ITEM_CREATE] = {
2500                 .name = "create",
2501                 .help = "flex item create",
2502                 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename),
2503                              ARGS_ENTRY(struct buffer, args.flex.token),
2504                              ARGS_ENTRY(struct buffer, port)),
2505                 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH),
2506                              NEXT_ENTRY(COMMON_FLEX_TOKEN),
2507                              NEXT_ENTRY(COMMON_PORT_ID)),
2508                 .call = parse_flex
2509         },
2510         [FLEX_ITEM_DESTROY] = {
2511                 .name = "destroy",
2512                 .help = "flex item destroy",
2513                 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
2514                              ARGS_ENTRY(struct buffer, port)),
2515                 .next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
2516                              NEXT_ENTRY(COMMON_PORT_ID)),
2517                 .call = parse_flex
2518         },
2519         [TUNNEL] = {
2520                 .name = "tunnel",
2521                 .help = "new tunnel API",
2522                 .next = NEXT(NEXT_ENTRY
2523                              (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
2524                 .call = parse_tunnel,
2525         },
2526         /* Tunnel arguments. */
2527         [TUNNEL_CREATE] = {
2528                 .name = "create",
2529                 .help = "create new tunnel object",
2530                 .next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
2531                              NEXT_ENTRY(COMMON_PORT_ID)),
2532                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2533                 .call = parse_tunnel,
2534         },
2535         [TUNNEL_CREATE_TYPE] = {
2536                 .name = "type",
2537                 .help = "create new tunnel",
2538                 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
2539                 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
2540                 .call = parse_tunnel,
2541         },
2542         [TUNNEL_DESTROY] = {
2543                 .name = "destroy",
2544                 .help = "destroy tunnel",
2545                 .next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
2546                              NEXT_ENTRY(COMMON_PORT_ID)),
2547                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2548                 .call = parse_tunnel,
2549         },
2550         [TUNNEL_DESTROY_ID] = {
2551                 .name = "id",
2552                 .help = "tunnel identifier to destroy",
2553                 .next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
2554                 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2555                 .call = parse_tunnel,
2556         },
2557         [TUNNEL_LIST] = {
2558                 .name = "list",
2559                 .help = "list existing tunnels",
2560                 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
2561                 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2562                 .call = parse_tunnel,
2563         },
2564         /* Destroy arguments. */
2565         [DESTROY_RULE] = {
2566                 .name = "rule",
2567                 .help = "specify a rule identifier",
2568                 .next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
2569                 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
2570                 .call = parse_destroy,
2571         },
2572         /* Dump arguments. */
2573         [DUMP_ALL] = {
2574                 .name = "all",
2575                 .help = "dump all",
2576                 .next = NEXT(next_dump_attr),
2577                 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
2578                 .call = parse_dump,
2579         },
2580         [DUMP_ONE] = {
2581                 .name = "rule",
2582                 .help = "dump one rule",
2583                 .next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
2584                 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
2585                                 ARGS_ENTRY(struct buffer, args.dump.rule)),
2586                 .call = parse_dump,
2587         },
2588         /* Query arguments. */
2589         [QUERY_ACTION] = {
2590                 .name = "{action}",
2591                 .type = "ACTION",
2592                 .help = "action to query, must be part of the rule",
2593                 .call = parse_action,
2594                 .comp = comp_action,
2595         },
2596         /* List arguments. */
2597         [LIST_GROUP] = {
2598                 .name = "group",
2599                 .help = "specify a group",
2600                 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
2601                 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
2602                 .call = parse_list,
2603         },
2604         [AGED_DESTROY] = {
2605                 .name = "destroy",
2606                 .help = "specify aged flows need be destroyed",
2607                 .call = parse_aged,
2608                 .comp = comp_none,
2609         },
2610         /* Validate/create attributes. */
2611         [VC_GROUP] = {
2612                 .name = "group",
2613                 .help = "specify a group",
2614                 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
2615                 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
2616                 .call = parse_vc,
2617         },
2618         [VC_PRIORITY] = {
2619                 .name = "priority",
2620                 .help = "specify a priority level",
2621                 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
2622                 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
2623                 .call = parse_vc,
2624         },
2625         [VC_INGRESS] = {
2626                 .name = "ingress",
2627                 .help = "affect rule to ingress",
2628                 .next = NEXT(next_vc_attr),
2629                 .call = parse_vc,
2630         },
2631         [VC_EGRESS] = {
2632                 .name = "egress",
2633                 .help = "affect rule to egress",
2634                 .next = NEXT(next_vc_attr),
2635                 .call = parse_vc,
2636         },
2637         [VC_TRANSFER] = {
2638                 .name = "transfer",
2639                 .help = "apply rule directly to endpoints found in pattern",
2640                 .next = NEXT(next_vc_attr),
2641                 .call = parse_vc,
2642         },
2643         [VC_TUNNEL_SET] = {
2644                 .name = "tunnel_set",
2645                 .help = "tunnel steer rule",
2646                 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
2647                 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2648                 .call = parse_vc,
2649         },
2650         [VC_TUNNEL_MATCH] = {
2651                 .name = "tunnel_match",
2652                 .help = "tunnel match rule",
2653                 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
2654                 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2655                 .call = parse_vc,
2656         },
2657         /* Validate/create pattern. */
2658         [ITEM_PATTERN] = {
2659                 .name = "pattern",
2660                 .help = "submit a list of pattern items",
2661                 .next = NEXT(next_item),
2662                 .call = parse_vc,
2663         },
2664         [ITEM_PARAM_IS] = {
2665                 .name = "is",
2666                 .help = "match value perfectly (with full bit-mask)",
2667                 .call = parse_vc_spec,
2668         },
2669         [ITEM_PARAM_SPEC] = {
2670                 .name = "spec",
2671                 .help = "match value according to configured bit-mask",
2672                 .call = parse_vc_spec,
2673         },
2674         [ITEM_PARAM_LAST] = {
2675                 .name = "last",
2676                 .help = "specify upper bound to establish a range",
2677                 .call = parse_vc_spec,
2678         },
2679         [ITEM_PARAM_MASK] = {
2680                 .name = "mask",
2681                 .help = "specify bit-mask with relevant bits set to one",
2682                 .call = parse_vc_spec,
2683         },
2684         [ITEM_PARAM_PREFIX] = {
2685                 .name = "prefix",
2686                 .help = "generate bit-mask from a prefix length",
2687                 .call = parse_vc_spec,
2688         },
2689         [ITEM_NEXT] = {
2690                 .name = "/",
2691                 .help = "specify next pattern item",
2692                 .next = NEXT(next_item),
2693         },
2694         [ITEM_END] = {
2695                 .name = "end",
2696                 .help = "end list of pattern items",
2697                 .priv = PRIV_ITEM(END, 0),
2698                 .next = NEXT(NEXT_ENTRY(ACTIONS)),
2699                 .call = parse_vc,
2700         },
2701         [ITEM_VOID] = {
2702                 .name = "void",
2703                 .help = "no-op pattern item",
2704                 .priv = PRIV_ITEM(VOID, 0),
2705                 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2706                 .call = parse_vc,
2707         },
2708         [ITEM_INVERT] = {
2709                 .name = "invert",
2710                 .help = "perform actions when pattern does not match",
2711                 .priv = PRIV_ITEM(INVERT, 0),
2712                 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2713                 .call = parse_vc,
2714         },
2715         [ITEM_ANY] = {
2716                 .name = "any",
2717                 .help = "match any protocol for the current layer",
2718                 .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
2719                 .next = NEXT(item_any),
2720                 .call = parse_vc,
2721         },
2722         [ITEM_ANY_NUM] = {
2723                 .name = "num",
2724                 .help = "number of layers covered",
2725                 .next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2726                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
2727         },
2728         [ITEM_PF] = {
2729                 .name = "pf",
2730                 .help = "match traffic from/to the physical function",
2731                 .priv = PRIV_ITEM(PF, 0),
2732                 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2733                 .call = parse_vc,
2734         },
2735         [ITEM_VF] = {
2736                 .name = "vf",
2737                 .help = "match traffic from/to a virtual function ID",
2738                 .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
2739                 .next = NEXT(item_vf),
2740                 .call = parse_vc,
2741         },
2742         [ITEM_VF_ID] = {
2743                 .name = "id",
2744                 .help = "VF ID",
2745                 .next = NEXT(item_vf, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2746                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
2747         },
2748         [ITEM_PHY_PORT] = {
2749                 .name = "phy_port",
2750                 .help = "match traffic from/to a specific physical port",
2751                 .priv = PRIV_ITEM(PHY_PORT,
2752                                   sizeof(struct rte_flow_item_phy_port)),
2753                 .next = NEXT(item_phy_port),
2754                 .call = parse_vc,
2755         },
2756         [ITEM_PHY_PORT_INDEX] = {
2757                 .name = "index",
2758                 .help = "physical port index",
2759                 .next = NEXT(item_phy_port, NEXT_ENTRY(COMMON_UNSIGNED),
2760                              item_param),
2761                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)),
2762         },
2763         [ITEM_PORT_ID] = {
2764                 .name = "port_id",
2765                 .help = "match traffic from/to a given DPDK port ID",
2766                 .priv = PRIV_ITEM(PORT_ID,
2767                                   sizeof(struct rte_flow_item_port_id)),
2768                 .next = NEXT(item_port_id),
2769                 .call = parse_vc,
2770         },
2771         [ITEM_PORT_ID_ID] = {
2772                 .name = "id",
2773                 .help = "DPDK port ID",
2774                 .next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
2775                              item_param),
2776                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
2777         },
2778         [ITEM_MARK] = {
2779                 .name = "mark",
2780                 .help = "match traffic against value set in previously matched rule",
2781                 .priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
2782                 .next = NEXT(item_mark),
2783                 .call = parse_vc,
2784         },
2785         [ITEM_MARK_ID] = {
2786                 .name = "id",
2787                 .help = "Integer value to match against",
2788                 .next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
2789                              item_param),
2790                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
2791         },
2792         [ITEM_RAW] = {
2793                 .name = "raw",
2794                 .help = "match an arbitrary byte string",
2795                 .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
2796                 .next = NEXT(item_raw),
2797                 .call = parse_vc,
2798         },
2799         [ITEM_RAW_RELATIVE] = {
2800                 .name = "relative",
2801                 .help = "look for pattern after the previous item",
2802                 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2803                 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
2804                                            relative, 1)),
2805         },
2806         [ITEM_RAW_SEARCH] = {
2807                 .name = "search",
2808                 .help = "search pattern from offset (see also limit)",
2809                 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2810                 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
2811                                            search, 1)),
2812         },
2813         [ITEM_RAW_OFFSET] = {
2814                 .name = "offset",
2815                 .help = "absolute or relative offset for pattern",
2816                 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
2817                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
2818         },
2819         [ITEM_RAW_LIMIT] = {
2820                 .name = "limit",
2821                 .help = "search area limit for start of pattern",
2822                 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2823                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
2824         },
2825         [ITEM_RAW_PATTERN] = {
2826                 .name = "pattern",
2827                 .help = "byte string to look for",
2828                 .next = NEXT(item_raw,
2829                              NEXT_ENTRY(COMMON_STRING),
2830                              NEXT_ENTRY(ITEM_PARAM_IS,
2831                                         ITEM_PARAM_SPEC,
2832                                         ITEM_PARAM_MASK)),
2833                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
2834                              ARGS_ENTRY(struct rte_flow_item_raw, length),
2835                              ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
2836                                             ITEM_RAW_PATTERN_SIZE)),
2837         },
2838         [ITEM_RAW_PATTERN_HEX] = {
2839                 .name = "pattern_hex",
2840                 .help = "hex string to look for",
2841                 .next = NEXT(item_raw,
2842                              NEXT_ENTRY(COMMON_HEX),
2843                              NEXT_ENTRY(ITEM_PARAM_IS,
2844                                         ITEM_PARAM_SPEC,
2845                                         ITEM_PARAM_MASK)),
2846                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
2847                              ARGS_ENTRY(struct rte_flow_item_raw, length),
2848                              ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
2849                                             ITEM_RAW_PATTERN_SIZE)),
2850         },
2851         [ITEM_ETH] = {
2852                 .name = "eth",
2853                 .help = "match Ethernet header",
2854                 .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
2855                 .next = NEXT(item_eth),
2856                 .call = parse_vc,
2857         },
2858         [ITEM_ETH_DST] = {
2859                 .name = "dst",
2860                 .help = "destination MAC",
2861                 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
2862                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
2863         },
2864         [ITEM_ETH_SRC] = {
2865                 .name = "src",
2866                 .help = "source MAC",
2867                 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
2868                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
2869         },
2870         [ITEM_ETH_TYPE] = {
2871                 .name = "type",
2872                 .help = "EtherType",
2873                 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2874                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
2875         },
2876         [ITEM_ETH_HAS_VLAN] = {
2877                 .name = "has_vlan",
2878                 .help = "packet header contains VLAN",
2879                 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2880                 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
2881                                            has_vlan, 1)),
2882         },
2883         [ITEM_VLAN] = {
2884                 .name = "vlan",
2885                 .help = "match 802.1Q/ad VLAN tag",
2886                 .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
2887                 .next = NEXT(item_vlan),
2888                 .call = parse_vc,
2889         },
2890         [ITEM_VLAN_TCI] = {
2891                 .name = "tci",
2892                 .help = "tag control information",
2893                 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2894                              item_param),
2895                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
2896         },
2897         [ITEM_VLAN_PCP] = {
2898                 .name = "pcp",
2899                 .help = "priority code point",
2900                 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2901                              item_param),
2902                 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2903                                                   tci, "\xe0\x00")),
2904         },
2905         [ITEM_VLAN_DEI] = {
2906                 .name = "dei",
2907                 .help = "drop eligible indicator",
2908                 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2909                              item_param),
2910                 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2911                                                   tci, "\x10\x00")),
2912         },
2913         [ITEM_VLAN_VID] = {
2914                 .name = "vid",
2915                 .help = "VLAN identifier",
2916                 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2917                              item_param),
2918                 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2919                                                   tci, "\x0f\xff")),
2920         },
2921         [ITEM_VLAN_INNER_TYPE] = {
2922                 .name = "inner_type",
2923                 .help = "inner EtherType",
2924                 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2925                              item_param),
2926                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
2927                                              inner_type)),
2928         },
2929         [ITEM_VLAN_HAS_MORE_VLAN] = {
2930                 .name = "has_more_vlan",
2931                 .help = "packet header contains another VLAN",
2932                 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2933                              item_param),
2934                 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
2935                                            has_more_vlan, 1)),
2936         },
2937         [ITEM_IPV4] = {
2938                 .name = "ipv4",
2939                 .help = "match IPv4 header",
2940                 .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
2941                 .next = NEXT(item_ipv4),
2942                 .call = parse_vc,
2943         },
2944         [ITEM_IPV4_VER_IHL] = {
2945                 .name = "version_ihl",
2946                 .help = "match header length",
2947                 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2948                              item_param),
2949                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
2950                                      hdr.version_ihl)),
2951         },
2952         [ITEM_IPV4_TOS] = {
2953                 .name = "tos",
2954                 .help = "type of service",
2955                 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2956                              item_param),
2957                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2958                                              hdr.type_of_service)),
2959         },
2960         [ITEM_IPV4_ID] = {
2961                 .name = "packet_id",
2962                 .help = "fragment packet id",
2963                 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2964                              item_param),
2965                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2966                                              hdr.packet_id)),
2967         },
2968         [ITEM_IPV4_FRAGMENT_OFFSET] = {
2969                 .name = "fragment_offset",
2970                 .help = "fragmentation flags and fragment offset",
2971                 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2972                              item_param),
2973                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2974                                              hdr.fragment_offset)),
2975         },
2976         [ITEM_IPV4_TTL] = {
2977                 .name = "ttl",
2978                 .help = "time to live",
2979                 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2980                              item_param),
2981                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2982                                              hdr.time_to_live)),
2983         },
2984         [ITEM_IPV4_PROTO] = {
2985                 .name = "proto",
2986                 .help = "next protocol ID",
2987                 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2988                              item_param),
2989                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2990                                              hdr.next_proto_id)),
2991         },
2992         [ITEM_IPV4_SRC] = {
2993                 .name = "src",
2994                 .help = "source address",
2995                 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
2996                              item_param),
2997                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2998                                              hdr.src_addr)),
2999         },
3000         [ITEM_IPV4_DST] = {
3001                 .name = "dst",
3002                 .help = "destination address",
3003                 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3004                              item_param),
3005                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3006                                              hdr.dst_addr)),
3007         },
3008         [ITEM_IPV6] = {
3009                 .name = "ipv6",
3010                 .help = "match IPv6 header",
3011                 .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
3012                 .next = NEXT(item_ipv6),
3013                 .call = parse_vc,
3014         },
3015         [ITEM_IPV6_TC] = {
3016                 .name = "tc",
3017                 .help = "traffic class",
3018                 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3019                              item_param),
3020                 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
3021                                                   hdr.vtc_flow,
3022                                                   "\x0f\xf0\x00\x00")),
3023         },
3024         [ITEM_IPV6_FLOW] = {
3025                 .name = "flow",
3026                 .help = "flow label",
3027                 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3028                              item_param),
3029                 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
3030                                                   hdr.vtc_flow,
3031                                                   "\x00\x0f\xff\xff")),
3032         },
3033         [ITEM_IPV6_PROTO] = {
3034                 .name = "proto",
3035                 .help = "protocol (next header)",
3036                 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3037                              item_param),
3038                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3039                                              hdr.proto)),
3040         },
3041         [ITEM_IPV6_HOP] = {
3042                 .name = "hop",
3043                 .help = "hop limit",
3044                 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3045                              item_param),
3046                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3047                                              hdr.hop_limits)),
3048         },
3049         [ITEM_IPV6_SRC] = {
3050                 .name = "src",
3051                 .help = "source address",
3052                 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
3053                              item_param),
3054                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3055                                              hdr.src_addr)),
3056         },
3057         [ITEM_IPV6_DST] = {
3058                 .name = "dst",
3059                 .help = "destination address",
3060                 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
3061                              item_param),
3062                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3063                                              hdr.dst_addr)),
3064         },
3065         [ITEM_IPV6_HAS_FRAG_EXT] = {
3066                 .name = "has_frag_ext",
3067                 .help = "fragment packet attribute",
3068                 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3069                              item_param),
3070                 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
3071                                            has_frag_ext, 1)),
3072         },
3073         [ITEM_ICMP] = {
3074                 .name = "icmp",
3075                 .help = "match ICMP header",
3076                 .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
3077                 .next = NEXT(item_icmp),
3078                 .call = parse_vc,
3079         },
3080         [ITEM_ICMP_TYPE] = {
3081                 .name = "type",
3082                 .help = "ICMP packet type",
3083                 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3084                              item_param),
3085                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3086                                              hdr.icmp_type)),
3087         },
3088         [ITEM_ICMP_CODE] = {
3089                 .name = "code",
3090                 .help = "ICMP packet code",
3091                 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3092                              item_param),
3093                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3094                                              hdr.icmp_code)),
3095         },
3096         [ITEM_ICMP_IDENT] = {
3097                 .name = "ident",
3098                 .help = "ICMP packet identifier",
3099                 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3100                              item_param),
3101                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3102                                              hdr.icmp_ident)),
3103         },
3104         [ITEM_ICMP_SEQ] = {
3105                 .name = "seq",
3106                 .help = "ICMP packet sequence number",
3107                 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3108                              item_param),
3109                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3110                                              hdr.icmp_seq_nb)),
3111         },
3112         [ITEM_UDP] = {
3113                 .name = "udp",
3114                 .help = "match UDP header",
3115                 .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
3116                 .next = NEXT(item_udp),
3117                 .call = parse_vc,
3118         },
3119         [ITEM_UDP_SRC] = {
3120                 .name = "src",
3121                 .help = "UDP source port",
3122                 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
3123                              item_param),
3124                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
3125                                              hdr.src_port)),
3126         },
3127         [ITEM_UDP_DST] = {
3128                 .name = "dst",
3129                 .help = "UDP destination port",
3130                 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3131                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
3132                                              hdr.dst_port)),
3133         },
3134         [ITEM_TCP] = {
3135                 .name = "tcp",
3136                 .help = "match TCP header",
3137                 .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
3138                 .next = NEXT(item_tcp),
3139                 .call = parse_vc,
3140         },
3141         [ITEM_TCP_SRC] = {
3142                 .name = "src",
3143                 .help = "TCP source port",
3144                 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3145                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3146                                              hdr.src_port)),
3147         },
3148         [ITEM_TCP_DST] = {
3149                 .name = "dst",
3150                 .help = "TCP destination port",
3151                 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3152                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3153                                              hdr.dst_port)),
3154         },
3155         [ITEM_TCP_FLAGS] = {
3156                 .name = "flags",
3157                 .help = "TCP flags",
3158                 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3159                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3160                                              hdr.tcp_flags)),
3161         },
3162         [ITEM_SCTP] = {
3163                 .name = "sctp",
3164                 .help = "match SCTP header",
3165                 .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
3166                 .next = NEXT(item_sctp),
3167                 .call = parse_vc,
3168         },
3169         [ITEM_SCTP_SRC] = {
3170                 .name = "src",
3171                 .help = "SCTP source port",
3172                 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3173                              item_param),
3174                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3175                                              hdr.src_port)),
3176         },
3177         [ITEM_SCTP_DST] = {
3178                 .name = "dst",
3179                 .help = "SCTP destination port",
3180                 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3181                              item_param),
3182                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3183                                              hdr.dst_port)),
3184         },
3185         [ITEM_SCTP_TAG] = {
3186                 .name = "tag",
3187                 .help = "validation tag",
3188                 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3189                              item_param),
3190                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3191                                              hdr.tag)),
3192         },
3193         [ITEM_SCTP_CKSUM] = {
3194                 .name = "cksum",
3195                 .help = "checksum",
3196                 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3197                              item_param),
3198                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3199                                              hdr.cksum)),
3200         },
3201         [ITEM_VXLAN] = {
3202                 .name = "vxlan",
3203                 .help = "match VXLAN header",
3204                 .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
3205                 .next = NEXT(item_vxlan),
3206                 .call = parse_vc,
3207         },
3208         [ITEM_VXLAN_VNI] = {
3209                 .name = "vni",
3210                 .help = "VXLAN identifier",
3211                 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
3212                              item_param),
3213                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
3214         },
3215         [ITEM_VXLAN_LAST_RSVD] = {
3216                 .name = "last_rsvd",
3217                 .help = "VXLAN last reserved bits",
3218                 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
3219                              item_param),
3220                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
3221                                              rsvd1)),
3222         },
3223         [ITEM_E_TAG] = {
3224                 .name = "e_tag",
3225                 .help = "match E-Tag header",
3226                 .priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
3227                 .next = NEXT(item_e_tag),
3228                 .call = parse_vc,
3229         },
3230         [ITEM_E_TAG_GRP_ECID_B] = {
3231                 .name = "grp_ecid_b",
3232                 .help = "GRP and E-CID base",
3233                 .next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
3234                              item_param),
3235                 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
3236                                                   rsvd_grp_ecid_b,
3237                                                   "\x3f\xff")),
3238         },
3239         [ITEM_NVGRE] = {
3240                 .name = "nvgre",
3241                 .help = "match NVGRE header",
3242                 .priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
3243                 .next = NEXT(item_nvgre),
3244                 .call = parse_vc,
3245         },
3246         [ITEM_NVGRE_TNI] = {
3247                 .name = "tni",
3248                 .help = "virtual subnet ID",
3249                 .next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
3250                              item_param),
3251                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
3252         },
3253         [ITEM_MPLS] = {
3254                 .name = "mpls",
3255                 .help = "match MPLS header",
3256                 .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
3257                 .next = NEXT(item_mpls),
3258                 .call = parse_vc,
3259         },
3260         [ITEM_MPLS_LABEL] = {
3261                 .name = "label",
3262                 .help = "MPLS label",
3263                 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3264                              item_param),
3265                 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
3266                                                   label_tc_s,
3267                                                   "\xff\xff\xf0")),
3268         },
3269         [ITEM_MPLS_TC] = {
3270                 .name = "tc",
3271                 .help = "MPLS Traffic Class",
3272                 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3273                              item_param),
3274                 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
3275                                                   label_tc_s,
3276                                                   "\x00\x00\x0e")),
3277         },
3278         [ITEM_MPLS_S] = {
3279                 .name = "s",
3280                 .help = "MPLS Bottom-of-Stack",
3281                 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3282                              item_param),
3283                 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
3284                                                   label_tc_s,
3285                                                   "\x00\x00\x01")),
3286         },
3287         [ITEM_GRE] = {
3288                 .name = "gre",
3289                 .help = "match GRE header",
3290                 .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
3291                 .next = NEXT(item_gre),
3292                 .call = parse_vc,
3293         },
3294         [ITEM_GRE_PROTO] = {
3295                 .name = "protocol",
3296                 .help = "GRE protocol type",
3297                 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
3298                              item_param),
3299                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
3300                                              protocol)),
3301         },
3302         [ITEM_GRE_C_RSVD0_VER] = {
3303                 .name = "c_rsvd0_ver",
3304                 .help =
3305                         "checksum (1b), undefined (1b), key bit (1b),"
3306                         " sequence number (1b), reserved 0 (9b),"
3307                         " version (3b)",
3308                 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
3309                              item_param),
3310                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
3311                                              c_rsvd0_ver)),
3312         },
3313         [ITEM_GRE_C_BIT] = {
3314                 .name = "c_bit",
3315                 .help = "checksum bit (C)",
3316                 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
3317                              item_param),
3318                 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3319                                                   c_rsvd0_ver,
3320                                                   "\x80\x00\x00\x00")),
3321         },
3322         [ITEM_GRE_S_BIT] = {
3323                 .name = "s_bit",
3324                 .help = "sequence number bit (S)",
3325                 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3326                 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3327                                                   c_rsvd0_ver,
3328                                                   "\x10\x00\x00\x00")),
3329         },
3330         [ITEM_GRE_K_BIT] = {
3331                 .name = "k_bit",
3332                 .help = "key bit (K)",
3333                 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3334                 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3335                                                   c_rsvd0_ver,
3336                                                   "\x20\x00\x00\x00")),
3337         },
3338         [ITEM_FUZZY] = {
3339                 .name = "fuzzy",
3340                 .help = "fuzzy pattern match, expect faster than default",
3341                 .priv = PRIV_ITEM(FUZZY,
3342                                 sizeof(struct rte_flow_item_fuzzy)),
3343                 .next = NEXT(item_fuzzy),
3344                 .call = parse_vc,
3345         },
3346         [ITEM_FUZZY_THRESH] = {
3347                 .name = "thresh",
3348                 .help = "match accuracy threshold",
3349                 .next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
3350                              item_param),
3351                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
3352                                         thresh)),
3353         },
3354         [ITEM_GTP] = {
3355                 .name = "gtp",
3356                 .help = "match GTP header",
3357                 .priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
3358                 .next = NEXT(item_gtp),
3359                 .call = parse_vc,
3360         },
3361         [ITEM_GTP_FLAGS] = {
3362                 .name = "v_pt_rsv_flags",
3363                 .help = "GTP flags",
3364                 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3365                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
3366                                         v_pt_rsv_flags)),
3367         },
3368         [ITEM_GTP_MSG_TYPE] = {
3369                 .name = "msg_type",
3370                 .help = "GTP message type",
3371                 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3372                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, msg_type)),
3373         },
3374         [ITEM_GTP_TEID] = {
3375                 .name = "teid",
3376                 .help = "tunnel endpoint identifier",
3377                 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3378                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
3379         },
3380         [ITEM_GTPC] = {
3381                 .name = "gtpc",
3382                 .help = "match GTP header",
3383                 .priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
3384                 .next = NEXT(item_gtp),
3385                 .call = parse_vc,
3386         },
3387         [ITEM_GTPU] = {
3388                 .name = "gtpu",
3389                 .help = "match GTP header",
3390                 .priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
3391                 .next = NEXT(item_gtp),
3392                 .call = parse_vc,
3393         },
3394         [ITEM_GENEVE] = {
3395                 .name = "geneve",
3396                 .help = "match GENEVE header",
3397                 .priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
3398                 .next = NEXT(item_geneve),
3399                 .call = parse_vc,
3400         },
3401         [ITEM_GENEVE_VNI] = {
3402                 .name = "vni",
3403                 .help = "virtual network identifier",
3404                 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3405                              item_param),
3406                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
3407         },
3408         [ITEM_GENEVE_PROTO] = {
3409                 .name = "protocol",
3410                 .help = "GENEVE protocol type",
3411                 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3412                              item_param),
3413                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
3414                                              protocol)),
3415         },
3416         [ITEM_GENEVE_OPTLEN] = {
3417                 .name = "optlen",
3418                 .help = "GENEVE options length in dwords",
3419                 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3420                              item_param),
3421                 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
3422                                                   ver_opt_len_o_c_rsvd0,
3423                                                   "\x3f\x00")),
3424         },
3425         [ITEM_VXLAN_GPE] = {
3426                 .name = "vxlan-gpe",
3427                 .help = "match VXLAN-GPE header",
3428                 .priv = PRIV_ITEM(VXLAN_GPE,
3429                                   sizeof(struct rte_flow_item_vxlan_gpe)),
3430                 .next = NEXT(item_vxlan_gpe),
3431                 .call = parse_vc,
3432         },
3433         [ITEM_VXLAN_GPE_VNI] = {
3434                 .name = "vni",
3435                 .help = "VXLAN-GPE identifier",
3436                 .next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
3437                              item_param),
3438                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
3439                                              vni)),
3440         },
3441         [ITEM_ARP_ETH_IPV4] = {
3442                 .name = "arp_eth_ipv4",
3443                 .help = "match ARP header for Ethernet/IPv4",
3444                 .priv = PRIV_ITEM(ARP_ETH_IPV4,
3445                                   sizeof(struct rte_flow_item_arp_eth_ipv4)),
3446                 .next = NEXT(item_arp_eth_ipv4),
3447                 .call = parse_vc,
3448         },
3449         [ITEM_ARP_ETH_IPV4_SHA] = {
3450                 .name = "sha",
3451                 .help = "sender hardware address",
3452                 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
3453                              item_param),
3454                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3455                                              sha)),
3456         },
3457         [ITEM_ARP_ETH_IPV4_SPA] = {
3458                 .name = "spa",
3459                 .help = "sender IPv4 address",
3460                 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3461                              item_param),
3462                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3463                                              spa)),
3464         },
3465         [ITEM_ARP_ETH_IPV4_THA] = {
3466                 .name = "tha",
3467                 .help = "target hardware address",
3468                 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
3469                              item_param),
3470                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3471                                              tha)),
3472         },
3473         [ITEM_ARP_ETH_IPV4_TPA] = {
3474                 .name = "tpa",
3475                 .help = "target IPv4 address",
3476                 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3477                              item_param),
3478                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3479                                              tpa)),
3480         },
3481         [ITEM_IPV6_EXT] = {
3482                 .name = "ipv6_ext",
3483                 .help = "match presence of any IPv6 extension header",
3484                 .priv = PRIV_ITEM(IPV6_EXT,
3485                                   sizeof(struct rte_flow_item_ipv6_ext)),
3486                 .next = NEXT(item_ipv6_ext),
3487                 .call = parse_vc,
3488         },
3489         [ITEM_IPV6_EXT_NEXT_HDR] = {
3490                 .name = "next_hdr",
3491                 .help = "next header",
3492                 .next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3493                              item_param),
3494                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
3495                                              next_hdr)),
3496         },
3497         [ITEM_IPV6_FRAG_EXT] = {
3498                 .name = "ipv6_frag_ext",
3499                 .help = "match presence of IPv6 fragment extension header",
3500                 .priv = PRIV_ITEM(IPV6_FRAG_EXT,
3501                                 sizeof(struct rte_flow_item_ipv6_frag_ext)),
3502                 .next = NEXT(item_ipv6_frag_ext),
3503                 .call = parse_vc,
3504         },
3505         [ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
3506                 .name = "next_hdr",
3507                 .help = "next header",
3508                 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3509                              item_param),
3510                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
3511                                         hdr.next_header)),
3512         },
3513         [ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
3514                 .name = "frag_data",
3515                 .help = "fragment flags and offset",
3516                 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3517                              item_param),
3518                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
3519                                              hdr.frag_data)),
3520         },
3521         [ITEM_IPV6_FRAG_EXT_ID] = {
3522                 .name = "packet_id",
3523                 .help = "fragment packet id",
3524                 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3525                              item_param),
3526                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
3527                                              hdr.id)),
3528         },
3529         [ITEM_ICMP6] = {
3530                 .name = "icmp6",
3531                 .help = "match any ICMPv6 header",
3532                 .priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
3533                 .next = NEXT(item_icmp6),
3534                 .call = parse_vc,
3535         },
3536         [ITEM_ICMP6_TYPE] = {
3537                 .name = "type",
3538                 .help = "ICMPv6 type",
3539                 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
3540                              item_param),
3541                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
3542                                              type)),
3543         },
3544         [ITEM_ICMP6_CODE] = {
3545                 .name = "code",
3546                 .help = "ICMPv6 code",
3547                 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
3548                              item_param),
3549                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
3550                                              code)),
3551         },
3552         [ITEM_ICMP6_ND_NS] = {
3553                 .name = "icmp6_nd_ns",
3554                 .help = "match ICMPv6 neighbor discovery solicitation",
3555                 .priv = PRIV_ITEM(ICMP6_ND_NS,
3556                                   sizeof(struct rte_flow_item_icmp6_nd_ns)),
3557                 .next = NEXT(item_icmp6_nd_ns),
3558                 .call = parse_vc,
3559         },
3560         [ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
3561                 .name = "target_addr",
3562                 .help = "target address",
3563                 .next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
3564                              item_param),
3565                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
3566                                              target_addr)),
3567         },
3568         [ITEM_ICMP6_ND_NA] = {
3569                 .name = "icmp6_nd_na",
3570                 .help = "match ICMPv6 neighbor discovery advertisement",
3571                 .priv = PRIV_ITEM(ICMP6_ND_NA,
3572                                   sizeof(struct rte_flow_item_icmp6_nd_na)),
3573                 .next = NEXT(item_icmp6_nd_na),
3574                 .call = parse_vc,
3575         },
3576         [ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
3577                 .name = "target_addr",
3578                 .help = "target address",
3579                 .next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
3580                              item_param),
3581                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
3582                                              target_addr)),
3583         },
3584         [ITEM_ICMP6_ND_OPT] = {
3585                 .name = "icmp6_nd_opt",
3586                 .help = "match presence of any ICMPv6 neighbor discovery"
3587                         " option",
3588                 .priv = PRIV_ITEM(ICMP6_ND_OPT,
3589                                   sizeof(struct rte_flow_item_icmp6_nd_opt)),
3590                 .next = NEXT(item_icmp6_nd_opt),
3591                 .call = parse_vc,
3592         },
3593         [ITEM_ICMP6_ND_OPT_TYPE] = {
3594                 .name = "type",
3595                 .help = "ND option type",
3596                 .next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3597                              item_param),
3598                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
3599                                              type)),
3600         },
3601         [ITEM_ICMP6_ND_OPT_SLA_ETH] = {
3602                 .name = "icmp6_nd_opt_sla_eth",
3603                 .help = "match ICMPv6 neighbor discovery source Ethernet"
3604                         " link-layer address option",
3605                 .priv = PRIV_ITEM
3606                         (ICMP6_ND_OPT_SLA_ETH,
3607                          sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
3608                 .next = NEXT(item_icmp6_nd_opt_sla_eth),
3609                 .call = parse_vc,
3610         },
3611         [ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
3612                 .name = "sla",
3613                 .help = "source Ethernet LLA",
3614                 .next = NEXT(item_icmp6_nd_opt_sla_eth,
3615                              NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3616                 .args = ARGS(ARGS_ENTRY_HTON
3617                              (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
3618         },
3619         [ITEM_ICMP6_ND_OPT_TLA_ETH] = {
3620                 .name = "icmp6_nd_opt_tla_eth",
3621                 .help = "match ICMPv6 neighbor discovery target Ethernet"
3622                         " link-layer address option",
3623                 .priv = PRIV_ITEM
3624                         (ICMP6_ND_OPT_TLA_ETH,
3625                          sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
3626                 .next = NEXT(item_icmp6_nd_opt_tla_eth),
3627                 .call = parse_vc,
3628         },
3629         [ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
3630                 .name = "tla",
3631                 .help = "target Ethernet LLA",
3632                 .next = NEXT(item_icmp6_nd_opt_tla_eth,
3633                              NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3634                 .args = ARGS(ARGS_ENTRY_HTON
3635                              (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
3636         },
3637         [ITEM_META] = {
3638                 .name = "meta",
3639                 .help = "match metadata header",
3640                 .priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
3641                 .next = NEXT(item_meta),
3642                 .call = parse_vc,
3643         },
3644         [ITEM_META_DATA] = {
3645                 .name = "data",
3646                 .help = "metadata value",
3647                 .next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
3648                              item_param),
3649                 .args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
3650                                              data, "\xff\xff\xff\xff")),
3651         },
3652         [ITEM_GRE_KEY] = {
3653                 .name = "gre_key",
3654                 .help = "match GRE key",
3655                 .priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
3656                 .next = NEXT(item_gre_key),
3657                 .call = parse_vc,
3658         },
3659         [ITEM_GRE_KEY_VALUE] = {
3660                 .name = "value",
3661                 .help = "key value",
3662                 .next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
3663                              item_param),
3664                 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
3665         },
3666         [ITEM_GRE_OPTION] = {
3667                 .name = "gre_option",
3668                 .help = "match GRE optional fields",
3669                 .priv = PRIV_ITEM(GRE_OPTION,
3670                                   sizeof(struct rte_flow_item_gre_opt)),
3671                 .next = NEXT(item_gre_option),
3672                 .call = parse_vc,
3673         },
3674         [ITEM_GRE_OPTION_CHECKSUM] = {
3675                 .name = "checksum",
3676                 .help = "match GRE checksum",
3677                 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
3678                              item_param),
3679                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
3680                                              checksum_rsvd.checksum)),
3681         },
3682         [ITEM_GRE_OPTION_KEY] = {
3683                 .name = "key",
3684                 .help = "match GRE key",
3685                 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
3686                              item_param),
3687                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
3688                                              key.key)),
3689         },
3690         [ITEM_GRE_OPTION_SEQUENCE] = {
3691                 .name = "sequence",
3692                 .help = "match GRE sequence",
3693                 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
3694                              item_param),
3695                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
3696                                              sequence.sequence)),
3697         },
3698         [ITEM_GTP_PSC] = {
3699                 .name = "gtp_psc",
3700                 .help = "match GTP extension header with type 0x85",
3701                 .priv = PRIV_ITEM(GTP_PSC,
3702                                 sizeof(struct rte_flow_item_gtp_psc)),
3703                 .next = NEXT(item_gtp_psc),
3704                 .call = parse_vc,
3705         },
3706         [ITEM_GTP_PSC_QFI] = {
3707                 .name = "qfi",
3708                 .help = "QoS flow identifier",
3709                 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
3710                              item_param),
3711                 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
3712                                         hdr.qfi, 6)),
3713         },
3714         [ITEM_GTP_PSC_PDU_T] = {
3715                 .name = "pdu_t",
3716                 .help = "PDU type",
3717                 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
3718                              item_param),
3719                 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
3720                                         hdr.type, 4)),
3721         },
3722         [ITEM_PPPOES] = {
3723                 .name = "pppoes",
3724                 .help = "match PPPoE session header",
3725                 .priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
3726                 .next = NEXT(item_pppoes),
3727                 .call = parse_vc,
3728         },
3729         [ITEM_PPPOED] = {
3730                 .name = "pppoed",
3731                 .help = "match PPPoE discovery header",
3732                 .priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
3733                 .next = NEXT(item_pppoed),
3734                 .call = parse_vc,
3735         },
3736         [ITEM_PPPOE_SEID] = {
3737                 .name = "seid",
3738                 .help = "session identifier",
3739                 .next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
3740                              item_param),
3741                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
3742                                         session_id)),
3743         },
3744         [ITEM_PPPOE_PROTO_ID] = {
3745                 .name = "pppoe_proto_id",
3746                 .help = "match PPPoE session protocol identifier",
3747                 .priv = PRIV_ITEM(PPPOE_PROTO_ID,
3748                                 sizeof(struct rte_flow_item_pppoe_proto_id)),
3749                 .next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
3750                              item_param),
3751                 .args = ARGS(ARGS_ENTRY_HTON
3752                              (struct rte_flow_item_pppoe_proto_id, proto_id)),
3753                 .call = parse_vc,
3754         },
3755         [ITEM_HIGIG2] = {
3756                 .name = "higig2",
3757                 .help = "matches higig2 header",
3758                 .priv = PRIV_ITEM(HIGIG2,
3759                                 sizeof(struct rte_flow_item_higig2_hdr)),
3760                 .next = NEXT(item_higig2),
3761                 .call = parse_vc,
3762         },
3763         [ITEM_HIGIG2_CLASSIFICATION] = {
3764                 .name = "classification",
3765                 .help = "matches classification of higig2 header",
3766                 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
3767                              item_param),
3768                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
3769                                         hdr.ppt1.classification)),
3770         },
3771         [ITEM_HIGIG2_VID] = {
3772                 .name = "vid",
3773                 .help = "matches vid of higig2 header",
3774                 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
3775                              item_param),
3776                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
3777                                         hdr.ppt1.vid)),
3778         },
3779         [ITEM_TAG] = {
3780                 .name = "tag",
3781                 .help = "match tag value",
3782                 .priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
3783                 .next = NEXT(item_tag),
3784                 .call = parse_vc,
3785         },
3786         [ITEM_TAG_DATA] = {
3787                 .name = "data",
3788                 .help = "tag value to match",
3789                 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3790                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
3791         },
3792         [ITEM_TAG_INDEX] = {
3793                 .name = "index",
3794                 .help = "index of tag array to match",
3795                 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
3796                              NEXT_ENTRY(ITEM_PARAM_IS)),
3797                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
3798         },
3799         [ITEM_L2TPV3OIP] = {
3800                 .name = "l2tpv3oip",
3801                 .help = "match L2TPv3 over IP header",
3802                 .priv = PRIV_ITEM(L2TPV3OIP,
3803                                   sizeof(struct rte_flow_item_l2tpv3oip)),
3804                 .next = NEXT(item_l2tpv3oip),
3805                 .call = parse_vc,
3806         },
3807         [ITEM_L2TPV3OIP_SESSION_ID] = {
3808                 .name = "session_id",
3809                 .help = "session identifier",
3810                 .next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
3811                              item_param),
3812                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
3813                                              session_id)),
3814         },
3815         [ITEM_ESP] = {
3816                 .name = "esp",
3817                 .help = "match ESP header",
3818                 .priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
3819                 .next = NEXT(item_esp),
3820                 .call = parse_vc,
3821         },
3822         [ITEM_ESP_SPI] = {
3823                 .name = "spi",
3824                 .help = "security policy index",
3825                 .next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3826                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
3827                                 hdr.spi)),
3828         },
3829         [ITEM_AH] = {
3830                 .name = "ah",
3831                 .help = "match AH header",
3832                 .priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
3833                 .next = NEXT(item_ah),
3834                 .call = parse_vc,
3835         },
3836         [ITEM_AH_SPI] = {
3837                 .name = "spi",
3838                 .help = "security parameters index",
3839                 .next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3840                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
3841         },
3842         [ITEM_PFCP] = {
3843                 .name = "pfcp",
3844                 .help = "match pfcp header",
3845                 .priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
3846                 .next = NEXT(item_pfcp),
3847                 .call = parse_vc,
3848         },
3849         [ITEM_PFCP_S_FIELD] = {
3850                 .name = "s_field",
3851                 .help = "S field",
3852                 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
3853                              item_param),
3854                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
3855                                 s_field)),
3856         },
3857         [ITEM_PFCP_SEID] = {
3858                 .name = "seid",
3859                 .help = "session endpoint identifier",
3860                 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
3861                              item_param),
3862                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
3863         },
3864         [ITEM_ECPRI] = {
3865                 .name = "ecpri",
3866                 .help = "match eCPRI header",
3867                 .priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
3868                 .next = NEXT(item_ecpri),
3869                 .call = parse_vc,
3870         },
3871         [ITEM_ECPRI_COMMON] = {
3872                 .name = "common",
3873                 .help = "eCPRI common header",
3874                 .next = NEXT(item_ecpri_common),
3875         },
3876         [ITEM_ECPRI_COMMON_TYPE] = {
3877                 .name = "type",
3878                 .help = "type of common header",
3879                 .next = NEXT(item_ecpri_common_type),
3880                 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
3881         },
3882         [ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
3883                 .name = "iq_data",
3884                 .help = "Type #0: IQ Data",
3885                 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
3886                                         ITEM_NEXT)),
3887                 .call = parse_vc_item_ecpri_type,
3888         },
3889         [ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
3890                 .name = "pc_id",
3891                 .help = "Physical Channel ID",
3892                 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
3893                                 ITEM_ECPRI_COMMON, ITEM_NEXT),
3894                                 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3895                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3896                                 hdr.type0.pc_id)),
3897         },
3898         [ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
3899                 .name = "rtc_ctrl",
3900                 .help = "Type #2: Real-Time Control Data",
3901                 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
3902                                         ITEM_NEXT)),
3903                 .call = parse_vc_item_ecpri_type,
3904         },
3905         [ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
3906                 .name = "rtc_id",
3907                 .help = "Real-Time Control Data ID",
3908                 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
3909                                 ITEM_ECPRI_COMMON, ITEM_NEXT),
3910                                 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3911                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3912                                 hdr.type2.rtc_id)),
3913         },
3914         [ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
3915                 .name = "delay_measure",
3916                 .help = "Type #5: One-Way Delay Measurement",
3917                 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
3918                                         ITEM_NEXT)),
3919                 .call = parse_vc_item_ecpri_type,
3920         },
3921         [ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
3922                 .name = "msr_id",
3923                 .help = "Measurement ID",
3924                 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
3925                                 ITEM_ECPRI_COMMON, ITEM_NEXT),
3926                                 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3927                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3928                                 hdr.type5.msr_id)),
3929         },
3930         [ITEM_GENEVE_OPT] = {
3931                 .name = "geneve-opt",
3932                 .help = "GENEVE header option",
3933                 .priv = PRIV_ITEM(GENEVE_OPT,
3934                                   sizeof(struct rte_flow_item_geneve_opt) +
3935                                   ITEM_GENEVE_OPT_DATA_SIZE),
3936                 .next = NEXT(item_geneve_opt),
3937                 .call = parse_vc,
3938         },
3939         [ITEM_GENEVE_OPT_CLASS] = {
3940                 .name = "class",
3941                 .help = "GENEVE option class",
3942                 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3943                              item_param),
3944                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
3945                                              option_class)),
3946         },
3947         [ITEM_GENEVE_OPT_TYPE] = {
3948                 .name = "type",
3949                 .help = "GENEVE option type",
3950                 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3951                              item_param),
3952                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
3953                                         option_type)),
3954         },
3955         [ITEM_GENEVE_OPT_LENGTH] = {
3956                 .name = "length",
3957                 .help = "GENEVE option data length (in 32b words)",
3958                 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3959                              item_param),
3960                 .args = ARGS(ARGS_ENTRY_BOUNDED(
3961                                 struct rte_flow_item_geneve_opt, option_len,
3962                                 0, 31)),
3963         },
3964         [ITEM_GENEVE_OPT_DATA] = {
3965                 .name = "data",
3966                 .help = "GENEVE option data pattern",
3967                 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
3968                              item_param),
3969                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
3970                              ARGS_ENTRY_ARB(0, 0),
3971                              ARGS_ENTRY_ARB
3972                                 (sizeof(struct rte_flow_item_geneve_opt),
3973                                 ITEM_GENEVE_OPT_DATA_SIZE)),
3974         },
3975         [ITEM_INTEGRITY] = {
3976                 .name = "integrity",
3977                 .help = "match packet integrity",
3978                 .priv = PRIV_ITEM(INTEGRITY,
3979                                   sizeof(struct rte_flow_item_integrity)),
3980                 .next = NEXT(item_integrity),
3981                 .call = parse_vc,
3982         },
3983         [ITEM_INTEGRITY_LEVEL] = {
3984                 .name = "level",
3985                 .help = "integrity level",
3986                 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
3987                              item_param),
3988                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
3989         },
3990         [ITEM_INTEGRITY_VALUE] = {
3991                 .name = "value",
3992                 .help = "integrity value",
3993                 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
3994                              item_param),
3995                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
3996         },
3997         [ITEM_CONNTRACK] = {
3998                 .name = "conntrack",
3999                 .help = "conntrack state",
4000                 .next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
4001                              item_param),
4002                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
4003         },
4004         [ITEM_PORT_REPRESENTOR] = {
4005                 .name = "port_representor",
4006                 .help = "match traffic entering the embedded switch from the given ethdev",
4007                 .priv = PRIV_ITEM(PORT_REPRESENTOR,
4008                                   sizeof(struct rte_flow_item_ethdev)),
4009                 .next = NEXT(item_port_representor),
4010                 .call = parse_vc,
4011         },
4012         [ITEM_PORT_REPRESENTOR_PORT_ID] = {
4013                 .name = "port_id",
4014                 .help = "ethdev port ID",
4015                 .next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
4016                              item_param),
4017                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
4018         },
4019         [ITEM_REPRESENTED_PORT] = {
4020                 .name = "represented_port",
4021                 .help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
4022                 .priv = PRIV_ITEM(REPRESENTED_PORT,
4023                                   sizeof(struct rte_flow_item_ethdev)),
4024                 .next = NEXT(item_represented_port),
4025                 .call = parse_vc,
4026         },
4027         [ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
4028                 .name = "ethdev_port_id",
4029                 .help = "ethdev port ID",
4030                 .next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
4031                              item_param),
4032                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
4033         },
4034         [ITEM_FLEX] = {
4035                 .name = "flex",
4036                 .help = "match flex header",
4037                 .priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
4038                 .next = NEXT(item_flex),
4039                 .call = parse_vc,
4040         },
4041         [ITEM_FLEX_ITEM_HANDLE] = {
4042                 .name = "item",
4043                 .help = "flex item handle",
4044                 .next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
4045                              NEXT_ENTRY(ITEM_PARAM_IS)),
4046                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
4047         },
4048         [ITEM_FLEX_PATTERN_HANDLE] = {
4049                 .name = "pattern",
4050                 .help = "flex pattern handle",
4051                 .next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
4052                              NEXT_ENTRY(ITEM_PARAM_IS)),
4053                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
4054         },
4055         [ITEM_L2TPV2] = {
4056                 .name = "l2tpv2",
4057                 .help = "match L2TPv2 header",
4058                 .priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
4059                 .next = NEXT(item_l2tpv2),
4060                 .call = parse_vc,
4061         },
4062         [ITEM_L2TPV2_TYPE] = {
4063                 .name = "type",
4064                 .help = "type of l2tpv2",
4065                 .next = NEXT(item_l2tpv2_type),
4066                 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
4067         },
4068         [ITEM_L2TPV2_TYPE_DATA] = {
4069                 .name = "data",
4070                 .help = "Type #7: data message without any options",
4071                 .next = NEXT(item_l2tpv2_type_data),
4072                 .call = parse_vc_item_l2tpv2_type,
4073         },
4074         [ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
4075                 .name = "tunnel_id",
4076                 .help = "tunnel identifier",
4077                 .next = NEXT(item_l2tpv2_type_data,
4078                              NEXT_ENTRY(COMMON_UNSIGNED),
4079                              item_param),
4080                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4081                                              hdr.type7.tunnel_id)),
4082         },
4083         [ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
4084                 .name = "session_id",
4085                 .help = "session identifier",
4086                 .next = NEXT(item_l2tpv2_type_data,
4087                              NEXT_ENTRY(COMMON_UNSIGNED),
4088                              item_param),
4089                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4090                                              hdr.type7.session_id)),
4091         },
4092         [ITEM_L2TPV2_TYPE_DATA_L] = {
4093                 .name = "data_l",
4094                 .help = "Type #6: data message with length option",
4095                 .next = NEXT(item_l2tpv2_type_data_l),
4096                 .call = parse_vc_item_l2tpv2_type,
4097         },
4098         [ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
4099                 .name = "length",
4100                 .help = "message length",
4101                 .next = NEXT(item_l2tpv2_type_data_l,
4102                              NEXT_ENTRY(COMMON_UNSIGNED),
4103                              item_param),
4104                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4105                                              hdr.type6.length)),
4106         },
4107         [ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
4108                 .name = "tunnel_id",
4109                 .help = "tunnel identifier",
4110                 .next = NEXT(item_l2tpv2_type_data_l,
4111                              NEXT_ENTRY(COMMON_UNSIGNED),
4112                              item_param),
4113                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4114                                              hdr.type6.tunnel_id)),
4115         },
4116         [ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
4117                 .name = "session_id",
4118                 .help = "session identifier",
4119                 .next = NEXT(item_l2tpv2_type_data_l,
4120                              NEXT_ENTRY(COMMON_UNSIGNED),
4121                              item_param),
4122                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4123                                              hdr.type6.session_id)),
4124         },
4125         [ITEM_L2TPV2_TYPE_DATA_S] = {
4126                 .name = "data_s",
4127                 .help = "Type #5: data message with ns, nr option",
4128                 .next = NEXT(item_l2tpv2_type_data_s),
4129                 .call = parse_vc_item_l2tpv2_type,
4130         },
4131         [ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
4132                 .name = "tunnel_id",
4133                 .help = "tunnel identifier",
4134                 .next = NEXT(item_l2tpv2_type_data_s,
4135                              NEXT_ENTRY(COMMON_UNSIGNED),
4136                              item_param),
4137                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4138                                              hdr.type5.tunnel_id)),
4139         },
4140         [ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
4141                 .name = "session_id",
4142                 .help = "session identifier",
4143                 .next = NEXT(item_l2tpv2_type_data_s,
4144                              NEXT_ENTRY(COMMON_UNSIGNED),
4145                              item_param),
4146                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4147                                              hdr.type5.session_id)),
4148         },
4149         [ITEM_L2TPV2_MSG_DATA_S_NS] = {
4150                 .name = "ns",
4151                 .help = "sequence number for message",
4152                 .next = NEXT(item_l2tpv2_type_data_s,
4153                              NEXT_ENTRY(COMMON_UNSIGNED),
4154                              item_param),
4155                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4156                                              hdr.type5.ns)),
4157         },
4158         [ITEM_L2TPV2_MSG_DATA_S_NR] = {
4159                 .name = "nr",
4160                 .help = "sequence number for next receive message",
4161                 .next = NEXT(item_l2tpv2_type_data_s,
4162                              NEXT_ENTRY(COMMON_UNSIGNED),
4163                              item_param),
4164                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4165                                              hdr.type5.nr)),
4166         },
4167         [ITEM_L2TPV2_TYPE_DATA_O] = {
4168                 .name = "data_o",
4169                 .help = "Type #4: data message with offset option",
4170                 .next = NEXT(item_l2tpv2_type_data_o),
4171                 .call = parse_vc_item_l2tpv2_type,
4172         },
4173         [ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
4174                 .name = "tunnel_id",
4175                 .help = "tunnel identifier",
4176                 .next = NEXT(item_l2tpv2_type_data_o,
4177                              NEXT_ENTRY(COMMON_UNSIGNED),
4178                              item_param),
4179                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4180                                              hdr.type4.tunnel_id)),
4181         },
4182         [ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
4183                 .name = "session_id",
4184                 .help = "session identifier",
4185                 .next = NEXT(item_l2tpv2_type_data_o,
4186                              NEXT_ENTRY(COMMON_UNSIGNED),
4187                              item_param),
4188                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4189                                              hdr.type5.session_id)),
4190         },
4191         [ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
4192                 .name = "offset_size",
4193                 .help = "the size of offset padding",
4194                 .next = NEXT(item_l2tpv2_type_data_o,
4195                              NEXT_ENTRY(COMMON_UNSIGNED),
4196                              item_param),
4197                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4198                                              hdr.type4.offset_size)),
4199         },
4200         [ITEM_L2TPV2_TYPE_DATA_L_S] = {
4201                 .name = "data_l_s",
4202                 .help = "Type #3: data message contains length, ns, nr "
4203                         "options",
4204                 .next = NEXT(item_l2tpv2_type_data_l_s),
4205                 .call = parse_vc_item_l2tpv2_type,
4206         },
4207         [ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
4208                 .name = "length",
4209                 .help = "message length",
4210                 .next = NEXT(item_l2tpv2_type_data_l_s,
4211                              NEXT_ENTRY(COMMON_UNSIGNED),
4212                              item_param),
4213                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4214                                              hdr.type3.length)),
4215         },
4216         [ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
4217                 .name = "tunnel_id",
4218                 .help = "tunnel identifier",
4219                 .next = NEXT(item_l2tpv2_type_data_l_s,
4220                              NEXT_ENTRY(COMMON_UNSIGNED),
4221                              item_param),
4222                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4223                                              hdr.type3.tunnel_id)),
4224         },
4225         [ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
4226                 .name = "session_id",
4227                 .help = "session identifier",
4228                 .next = NEXT(item_l2tpv2_type_data_l_s,
4229                              NEXT_ENTRY(COMMON_UNSIGNED),
4230                              item_param),
4231                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4232                                              hdr.type3.session_id)),
4233         },
4234         [ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
4235                 .name = "ns",
4236                 .help = "sequence number for message",
4237                 .next = NEXT(item_l2tpv2_type_data_l_s,
4238                              NEXT_ENTRY(COMMON_UNSIGNED),
4239                              item_param),
4240                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4241                                              hdr.type3.ns)),
4242         },
4243         [ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
4244                 .name = "nr",
4245                 .help = "sequence number for next receive message",
4246                 .next = NEXT(item_l2tpv2_type_data_l_s,
4247                              NEXT_ENTRY(COMMON_UNSIGNED),
4248                              item_param),
4249                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4250                                              hdr.type3.nr)),
4251         },
4252         [ITEM_L2TPV2_TYPE_CTRL] = {
4253                 .name = "control",
4254                 .help = "Type #3: conrtol message contains length, ns, nr "
4255                         "options",
4256                 .next = NEXT(item_l2tpv2_type_ctrl),
4257                 .call = parse_vc_item_l2tpv2_type,
4258         },
4259         [ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
4260                 .name = "length",
4261                 .help = "message length",
4262                 .next = NEXT(item_l2tpv2_type_ctrl,
4263                              NEXT_ENTRY(COMMON_UNSIGNED),
4264                              item_param),
4265                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4266                                              hdr.type3.length)),
4267         },
4268         [ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
4269                 .name = "tunnel_id",
4270                 .help = "tunnel identifier",
4271                 .next = NEXT(item_l2tpv2_type_ctrl,
4272                              NEXT_ENTRY(COMMON_UNSIGNED),
4273                              item_param),
4274                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4275                                              hdr.type3.tunnel_id)),
4276         },
4277         [ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
4278                 .name = "session_id",
4279                 .help = "session identifier",
4280                 .next = NEXT(item_l2tpv2_type_ctrl,
4281                              NEXT_ENTRY(COMMON_UNSIGNED),
4282                              item_param),
4283                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4284                                              hdr.type3.session_id)),
4285         },
4286         [ITEM_L2TPV2_MSG_CTRL_NS] = {
4287                 .name = "ns",
4288                 .help = "sequence number for message",
4289                 .next = NEXT(item_l2tpv2_type_ctrl,
4290                              NEXT_ENTRY(COMMON_UNSIGNED),
4291                              item_param),
4292                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4293                                              hdr.type3.ns)),
4294         },
4295         [ITEM_L2TPV2_MSG_CTRL_NR] = {
4296                 .name = "nr",
4297                 .help = "sequence number for next receive message",
4298                 .next = NEXT(item_l2tpv2_type_ctrl,
4299                              NEXT_ENTRY(COMMON_UNSIGNED),
4300                              item_param),
4301                 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4302                                              hdr.type3.nr)),
4303         },
4304         [ITEM_PPP] = {
4305                 .name = "ppp",
4306                 .help = "match PPP header",
4307                 .priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
4308                 .next = NEXT(item_ppp),
4309                 .call = parse_vc,
4310         },
4311         [ITEM_PPP_ADDR] = {
4312                 .name = "addr",
4313                 .help = "PPP address",
4314                 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
4315                              item_param),
4316                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
4317         },
4318         [ITEM_PPP_CTRL] = {
4319                 .name = "ctrl",
4320                 .help = "PPP control",
4321                 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
4322                              item_param),
4323                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
4324         },
4325         [ITEM_PPP_PROTO_ID] = {
4326                 .name = "proto_id",
4327                 .help = "PPP protocol identifier",
4328                 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
4329                              item_param),
4330                 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
4331                                         hdr.proto_id)),
4332         },
4333         /* Validate/create actions. */
4334         [ACTIONS] = {
4335                 .name = "actions",
4336                 .help = "submit a list of associated actions",
4337                 .next = NEXT(next_action),
4338                 .call = parse_vc,
4339         },
4340         [ACTION_NEXT] = {
4341                 .name = "/",
4342                 .help = "specify next action",
4343                 .next = NEXT(next_action),
4344         },
4345         [ACTION_END] = {
4346                 .name = "end",
4347                 .help = "end list of actions",
4348                 .priv = PRIV_ACTION(END, 0),
4349                 .call = parse_vc,
4350         },
4351         [ACTION_VOID] = {
4352                 .name = "void",
4353                 .help = "no-op action",
4354                 .priv = PRIV_ACTION(VOID, 0),
4355                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4356                 .call = parse_vc,
4357         },
4358         [ACTION_PASSTHRU] = {
4359                 .name = "passthru",
4360                 .help = "let subsequent rule process matched packets",
4361                 .priv = PRIV_ACTION(PASSTHRU, 0),
4362                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4363                 .call = parse_vc,
4364         },
4365         [ACTION_JUMP] = {
4366                 .name = "jump",
4367                 .help = "redirect traffic to a given group",
4368                 .priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
4369                 .next = NEXT(action_jump),
4370                 .call = parse_vc,
4371         },
4372         [ACTION_JUMP_GROUP] = {
4373                 .name = "group",
4374                 .help = "group to redirect traffic to",
4375                 .next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
4376                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
4377                 .call = parse_vc_conf,
4378         },
4379         [ACTION_MARK] = {
4380                 .name = "mark",
4381                 .help = "attach 32 bit value to packets",
4382                 .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
4383                 .next = NEXT(action_mark),
4384                 .call = parse_vc,
4385         },
4386         [ACTION_MARK_ID] = {
4387                 .name = "id",
4388                 .help = "32 bit value to return with packets",
4389                 .next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
4390                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
4391                 .call = parse_vc_conf,
4392         },
4393         [ACTION_FLAG] = {
4394                 .name = "flag",
4395                 .help = "flag packets",
4396                 .priv = PRIV_ACTION(FLAG, 0),
4397                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4398                 .call = parse_vc,
4399         },
4400         [ACTION_QUEUE] = {
4401                 .name = "queue",
4402                 .help = "assign packets to a given queue index",
4403                 .priv = PRIV_ACTION(QUEUE,
4404                                     sizeof(struct rte_flow_action_queue)),
4405                 .next = NEXT(action_queue),
4406                 .call = parse_vc,
4407         },
4408         [ACTION_QUEUE_INDEX] = {
4409                 .name = "index",
4410                 .help = "queue index to use",
4411                 .next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
4412                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
4413                 .call = parse_vc_conf,
4414         },
4415         [ACTION_DROP] = {
4416                 .name = "drop",
4417                 .help = "drop packets (note: passthru has priority)",
4418                 .priv = PRIV_ACTION(DROP, 0),
4419                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4420                 .call = parse_vc,
4421         },
4422         [ACTION_COUNT] = {
4423                 .name = "count",
4424                 .help = "enable counters for this rule",
4425                 .priv = PRIV_ACTION(COUNT,
4426                                     sizeof(struct rte_flow_action_count)),
4427                 .next = NEXT(action_count),
4428                 .call = parse_vc,
4429         },
4430         [ACTION_COUNT_ID] = {
4431                 .name = "identifier",
4432                 .help = "counter identifier to use",
4433                 .next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
4434                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
4435                 .call = parse_vc_conf,
4436         },
4437         [ACTION_RSS] = {
4438                 .name = "rss",
4439                 .help = "spread packets among several queues",
4440                 .priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
4441                 .next = NEXT(action_rss),
4442                 .call = parse_vc_action_rss,
4443         },
4444         [ACTION_RSS_FUNC] = {
4445                 .name = "func",
4446                 .help = "RSS hash function to apply",
4447                 .next = NEXT(action_rss,
4448                              NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
4449                                         ACTION_RSS_FUNC_TOEPLITZ,
4450                                         ACTION_RSS_FUNC_SIMPLE_XOR,
4451                                         ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
4452         },
4453         [ACTION_RSS_FUNC_DEFAULT] = {
4454                 .name = "default",
4455                 .help = "default hash function",
4456                 .call = parse_vc_action_rss_func,
4457         },
4458         [ACTION_RSS_FUNC_TOEPLITZ] = {
4459                 .name = "toeplitz",
4460                 .help = "Toeplitz hash function",
4461                 .call = parse_vc_action_rss_func,
4462         },
4463         [ACTION_RSS_FUNC_SIMPLE_XOR] = {
4464                 .name = "simple_xor",
4465                 .help = "simple XOR hash function",
4466                 .call = parse_vc_action_rss_func,
4467         },
4468         [ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
4469                 .name = "symmetric_toeplitz",
4470                 .help = "Symmetric Toeplitz hash function",
4471                 .call = parse_vc_action_rss_func,
4472         },
4473         [ACTION_RSS_LEVEL] = {
4474                 .name = "level",
4475                 .help = "encapsulation level for \"types\"",
4476                 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
4477                 .args = ARGS(ARGS_ENTRY_ARB
4478                              (offsetof(struct action_rss_data, conf) +
4479                               offsetof(struct rte_flow_action_rss, level),
4480                               sizeof(((struct rte_flow_action_rss *)0)->
4481                                      level))),
4482         },
4483         [ACTION_RSS_TYPES] = {
4484                 .name = "types",
4485                 .help = "specific RSS hash types",
4486                 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
4487         },
4488         [ACTION_RSS_TYPE] = {
4489                 .name = "{type}",
4490                 .help = "RSS hash type",
4491                 .call = parse_vc_action_rss_type,
4492                 .comp = comp_vc_action_rss_type,
4493         },
4494         [ACTION_RSS_KEY] = {
4495                 .name = "key",
4496                 .help = "RSS hash key",
4497                 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
4498                 .args = ARGS(ARGS_ENTRY_ARB
4499                              (offsetof(struct action_rss_data, conf) +
4500                               offsetof(struct rte_flow_action_rss, key),
4501                               sizeof(((struct rte_flow_action_rss *)0)->key)),
4502                              ARGS_ENTRY_ARB
4503                              (offsetof(struct action_rss_data, conf) +
4504                               offsetof(struct rte_flow_action_rss, key_len),
4505                               sizeof(((struct rte_flow_action_rss *)0)->
4506                                      key_len)),
4507                              ARGS_ENTRY(struct action_rss_data, key)),
4508         },
4509         [ACTION_RSS_KEY_LEN] = {
4510                 .name = "key_len",
4511                 .help = "RSS hash key length in bytes",
4512                 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
4513                 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
4514                              (offsetof(struct action_rss_data, conf) +
4515                               offsetof(struct rte_flow_action_rss, key_len),
4516                               sizeof(((struct rte_flow_action_rss *)0)->
4517                                      key_len),
4518                               0,
4519                               RSS_HASH_KEY_LENGTH)),
4520         },
4521         [ACTION_RSS_QUEUES] = {
4522                 .name = "queues",
4523                 .help = "queue indices to use",
4524                 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
4525                 .call = parse_vc_conf,
4526         },
4527         [ACTION_RSS_QUEUE] = {
4528                 .name = "{queue}",
4529                 .help = "queue index",
4530                 .call = parse_vc_action_rss_queue,
4531                 .comp = comp_vc_action_rss_queue,
4532         },
4533         [ACTION_PF] = {
4534                 .name = "pf",
4535                 .help = "direct traffic to physical function",
4536                 .priv = PRIV_ACTION(PF, 0),
4537                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4538                 .call = parse_vc,
4539         },
4540         [ACTION_VF] = {
4541                 .name = "vf",
4542                 .help = "direct traffic to a virtual function ID",
4543                 .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
4544                 .next = NEXT(action_vf),
4545                 .call = parse_vc,
4546         },
4547         [ACTION_VF_ORIGINAL] = {
4548                 .name = "original",
4549                 .help = "use original VF ID if possible",
4550                 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
4551                 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
4552                                            original, 1)),
4553                 .call = parse_vc_conf,
4554         },
4555         [ACTION_VF_ID] = {
4556                 .name = "id",
4557                 .help = "VF ID",
4558                 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
4559                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
4560                 .call = parse_vc_conf,
4561         },
4562         [ACTION_PHY_PORT] = {
4563                 .name = "phy_port",
4564                 .help = "direct packets to physical port index",
4565                 .priv = PRIV_ACTION(PHY_PORT,
4566                                     sizeof(struct rte_flow_action_phy_port)),
4567                 .next = NEXT(action_phy_port),
4568                 .call = parse_vc,
4569         },
4570         [ACTION_PHY_PORT_ORIGINAL] = {
4571                 .name = "original",
4572                 .help = "use original port index if possible",
4573                 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_BOOLEAN)),
4574                 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port,
4575                                            original, 1)),
4576                 .call = parse_vc_conf,
4577         },
4578         [ACTION_PHY_PORT_INDEX] = {
4579                 .name = "index",
4580                 .help = "physical port index",
4581                 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_UNSIGNED)),
4582                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port,
4583                                         index)),
4584                 .call = parse_vc_conf,
4585         },
4586         [ACTION_PORT_ID] = {
4587                 .name = "port_id",
4588                 .help = "direct matching traffic to a given DPDK port ID",
4589                 .priv = PRIV_ACTION(PORT_ID,
4590                                     sizeof(struct rte_flow_action_port_id)),
4591                 .next = NEXT(action_port_id),
4592                 .call = parse_vc,
4593         },
4594         [ACTION_PORT_ID_ORIGINAL] = {
4595                 .name = "original",
4596                 .help = "use original DPDK port ID if possible",
4597                 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
4598                 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
4599                                            original, 1)),
4600                 .call = parse_vc_conf,
4601         },
4602         [ACTION_PORT_ID_ID] = {
4603                 .name = "id",
4604                 .help = "DPDK port ID",
4605                 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
4606                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
4607                 .call = parse_vc_conf,
4608         },
4609         [ACTION_METER] = {
4610                 .name = "meter",
4611                 .help = "meter the directed packets at given id",
4612                 .priv = PRIV_ACTION(METER,
4613                                     sizeof(struct rte_flow_action_meter)),
4614                 .next = NEXT(action_meter),
4615                 .call = parse_vc,
4616         },
4617         [ACTION_METER_COLOR] = {
4618                 .name = "color",
4619                 .help = "meter color for the packets",
4620                 .priv = PRIV_ACTION(METER_COLOR,
4621                                 sizeof(struct rte_flow_action_meter_color)),
4622                 .next = NEXT(action_meter_color),
4623                 .call = parse_vc,
4624         },
4625         [ACTION_METER_COLOR_TYPE] = {
4626                 .name = "type",
4627                 .help = "specific meter color",
4628                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
4629                                 NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
4630                                         ACTION_METER_COLOR_YELLOW,
4631                                         ACTION_METER_COLOR_RED)),
4632         },
4633         [ACTION_METER_COLOR_GREEN] = {
4634                 .name = "green",
4635                 .help = "meter color green",
4636                 .call = parse_vc_action_meter_color_type,
4637         },
4638         [ACTION_METER_COLOR_YELLOW] = {
4639                 .name = "yellow",
4640                 .help = "meter color yellow",
4641                 .call = parse_vc_action_meter_color_type,
4642         },
4643         [ACTION_METER_COLOR_RED] = {
4644                 .name = "red",
4645                 .help = "meter color red",
4646                 .call = parse_vc_action_meter_color_type,
4647         },
4648         [ACTION_METER_ID] = {
4649                 .name = "mtr_id",
4650                 .help = "meter id to use",
4651                 .next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
4652                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
4653                 .call = parse_vc_conf,
4654         },
4655         [ACTION_OF_SET_MPLS_TTL] = {
4656                 .name = "of_set_mpls_ttl",
4657                 .help = "OpenFlow's OFPAT_SET_MPLS_TTL",
4658                 .priv = PRIV_ACTION
4659                         (OF_SET_MPLS_TTL,
4660                          sizeof(struct rte_flow_action_of_set_mpls_ttl)),
4661                 .next = NEXT(action_of_set_mpls_ttl),
4662                 .call = parse_vc,
4663         },
4664         [ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = {
4665                 .name = "mpls_ttl",
4666                 .help = "MPLS TTL",
4667                 .next = NEXT(action_of_set_mpls_ttl,
4668                              NEXT_ENTRY(COMMON_UNSIGNED)),
4669                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl,
4670                                         mpls_ttl)),
4671                 .call = parse_vc_conf,
4672         },
4673         [ACTION_OF_DEC_MPLS_TTL] = {
4674                 .name = "of_dec_mpls_ttl",
4675                 .help = "OpenFlow's OFPAT_DEC_MPLS_TTL",
4676                 .priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0),
4677                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4678                 .call = parse_vc,
4679         },
4680         [ACTION_OF_SET_NW_TTL] = {
4681                 .name = "of_set_nw_ttl",
4682                 .help = "OpenFlow's OFPAT_SET_NW_TTL",
4683                 .priv = PRIV_ACTION
4684                         (OF_SET_NW_TTL,
4685                          sizeof(struct rte_flow_action_of_set_nw_ttl)),
4686                 .next = NEXT(action_of_set_nw_ttl),
4687                 .call = parse_vc,
4688         },
4689         [ACTION_OF_SET_NW_TTL_NW_TTL] = {
4690                 .name = "nw_ttl",
4691                 .help = "IP TTL",
4692                 .next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
4693                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl,
4694                                         nw_ttl)),
4695                 .call = parse_vc_conf,
4696         },
4697         [ACTION_OF_DEC_NW_TTL] = {
4698                 .name = "of_dec_nw_ttl",
4699                 .help = "OpenFlow's OFPAT_DEC_NW_TTL",
4700                 .priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
4701                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4702                 .call = parse_vc,
4703         },
4704         [ACTION_OF_COPY_TTL_OUT] = {
4705                 .name = "of_copy_ttl_out",
4706                 .help = "OpenFlow's OFPAT_COPY_TTL_OUT",
4707                 .priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0),
4708                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4709                 .call = parse_vc,
4710         },
4711         [ACTION_OF_COPY_TTL_IN] = {
4712                 .name = "of_copy_ttl_in",
4713                 .help = "OpenFlow's OFPAT_COPY_TTL_IN",
4714                 .priv = PRIV_ACTION(OF_COPY_TTL_IN, 0),
4715                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4716                 .call = parse_vc,
4717         },
4718         [ACTION_OF_POP_VLAN] = {
4719                 .name = "of_pop_vlan",
4720                 .help = "OpenFlow's OFPAT_POP_VLAN",
4721                 .priv = PRIV_ACTION(OF_POP_VLAN, 0),
4722                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4723                 .call = parse_vc,
4724         },
4725         [ACTION_OF_PUSH_VLAN] = {
4726                 .name = "of_push_vlan",
4727                 .help = "OpenFlow's OFPAT_PUSH_VLAN",
4728                 .priv = PRIV_ACTION
4729                         (OF_PUSH_VLAN,
4730                          sizeof(struct rte_flow_action_of_push_vlan)),
4731                 .next = NEXT(action_of_push_vlan),
4732                 .call = parse_vc,
4733         },
4734         [ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
4735                 .name = "ethertype",
4736                 .help = "EtherType",
4737                 .next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
4738                 .args = ARGS(ARGS_ENTRY_HTON
4739                              (struct rte_flow_action_of_push_vlan,
4740                               ethertype)),
4741                 .call = parse_vc_conf,
4742         },
4743         [ACTION_OF_SET_VLAN_VID] = {
4744                 .name = "of_set_vlan_vid",
4745                 .help = "OpenFlow's OFPAT_SET_VLAN_VID",
4746                 .priv = PRIV_ACTION
4747                         (OF_SET_VLAN_VID,
4748                          sizeof(struct rte_flow_action_of_set_vlan_vid)),
4749                 .next = NEXT(action_of_set_vlan_vid),
4750                 .call = parse_vc,
4751         },
4752         [ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
4753                 .name = "vlan_vid",
4754                 .help = "VLAN id",
4755                 .next = NEXT(action_of_set_vlan_vid,
4756                              NEXT_ENTRY(COMMON_UNSIGNED)),
4757                 .args = ARGS(ARGS_ENTRY_HTON
4758                              (struct rte_flow_action_of_set_vlan_vid,
4759                               vlan_vid)),
4760                 .call = parse_vc_conf,
4761         },
4762         [ACTION_OF_SET_VLAN_PCP] = {
4763                 .name = "of_set_vlan_pcp",
4764                 .help = "OpenFlow's OFPAT_SET_VLAN_PCP",
4765                 .priv = PRIV_ACTION
4766                         (OF_SET_VLAN_PCP,
4767                          sizeof(struct rte_flow_action_of_set_vlan_pcp)),
4768                 .next = NEXT(action_of_set_vlan_pcp),
4769                 .call = parse_vc,
4770         },
4771         [ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
4772                 .name = "vlan_pcp",
4773                 .help = "VLAN priority",
4774                 .next = NEXT(action_of_set_vlan_pcp,
4775                              NEXT_ENTRY(COMMON_UNSIGNED)),
4776                 .args = ARGS(ARGS_ENTRY_HTON
4777                              (struct rte_flow_action_of_set_vlan_pcp,
4778                               vlan_pcp)),
4779                 .call = parse_vc_conf,
4780         },
4781         [ACTION_OF_POP_MPLS] = {
4782                 .name = "of_pop_mpls",
4783                 .help = "OpenFlow's OFPAT_POP_MPLS",
4784                 .priv = PRIV_ACTION(OF_POP_MPLS,
4785                                     sizeof(struct rte_flow_action_of_pop_mpls)),
4786                 .next = NEXT(action_of_pop_mpls),
4787                 .call = parse_vc,
4788         },
4789         [ACTION_OF_POP_MPLS_ETHERTYPE] = {
4790                 .name = "ethertype",
4791                 .help = "EtherType",
4792                 .next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
4793                 .args = ARGS(ARGS_ENTRY_HTON
4794                              (struct rte_flow_action_of_pop_mpls,
4795                               ethertype)),
4796                 .call = parse_vc_conf,
4797         },
4798         [ACTION_OF_PUSH_MPLS] = {
4799                 .name = "of_push_mpls",
4800                 .help = "OpenFlow's OFPAT_PUSH_MPLS",
4801                 .priv = PRIV_ACTION
4802                         (OF_PUSH_MPLS,
4803                          sizeof(struct rte_flow_action_of_push_mpls)),
4804                 .next = NEXT(action_of_push_mpls),
4805                 .call = parse_vc,
4806         },
4807         [ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
4808                 .name = "ethertype",
4809                 .help = "EtherType",
4810                 .next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
4811                 .args = ARGS(ARGS_ENTRY_HTON
4812                              (struct rte_flow_action_of_push_mpls,
4813                               ethertype)),
4814                 .call = parse_vc_conf,
4815         },
4816         [ACTION_VXLAN_ENCAP] = {
4817                 .name = "vxlan_encap",
4818                 .help = "VXLAN encapsulation, uses configuration set by \"set"
4819                         " vxlan\"",
4820                 .priv = PRIV_ACTION(VXLAN_ENCAP,
4821                                     sizeof(struct action_vxlan_encap_data)),
4822                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4823                 .call = parse_vc_action_vxlan_encap,
4824         },
4825         [ACTION_VXLAN_DECAP] = {
4826                 .name = "vxlan_decap",
4827                 .help = "Performs a decapsulation action by stripping all"
4828                         " headers of the VXLAN tunnel network overlay from the"
4829                         " matched flow.",
4830                 .priv = PRIV_ACTION(VXLAN_DECAP, 0),
4831                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4832                 .call = parse_vc,
4833         },
4834         [ACTION_NVGRE_ENCAP] = {
4835                 .name = "nvgre_encap",
4836                 .help = "NVGRE encapsulation, uses configuration set by \"set"
4837                         " nvgre\"",
4838                 .priv = PRIV_ACTION(NVGRE_ENCAP,
4839                                     sizeof(struct action_nvgre_encap_data)),
4840                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4841                 .call = parse_vc_action_nvgre_encap,
4842         },
4843         [ACTION_NVGRE_DECAP] = {
4844                 .name = "nvgre_decap",
4845                 .help = "Performs a decapsulation action by stripping all"
4846                         " headers of the NVGRE tunnel network overlay from the"
4847                         " matched flow.",
4848                 .priv = PRIV_ACTION(NVGRE_DECAP, 0),
4849                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4850                 .call = parse_vc,
4851         },
4852         [ACTION_L2_ENCAP] = {
4853                 .name = "l2_encap",
4854                 .help = "l2 encap, uses configuration set by"
4855                         " \"set l2_encap\"",
4856                 .priv = PRIV_ACTION(RAW_ENCAP,
4857                                     sizeof(struct action_raw_encap_data)),
4858                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4859                 .call = parse_vc_action_l2_encap,
4860         },
4861         [ACTION_L2_DECAP] = {
4862                 .name = "l2_decap",
4863                 .help = "l2 decap, uses configuration set by"
4864                         " \"set l2_decap\"",
4865                 .priv = PRIV_ACTION(RAW_DECAP,
4866                                     sizeof(struct action_raw_decap_data)),
4867                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4868                 .call = parse_vc_action_l2_decap,
4869         },
4870         [ACTION_MPLSOGRE_ENCAP] = {
4871                 .name = "mplsogre_encap",
4872                 .help = "mplsogre encapsulation, uses configuration set by"
4873                         " \"set mplsogre_encap\"",
4874                 .priv = PRIV_ACTION(RAW_ENCAP,
4875                                     sizeof(struct action_raw_encap_data)),
4876                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4877                 .call = parse_vc_action_mplsogre_encap,
4878         },
4879         [ACTION_MPLSOGRE_DECAP] = {
4880                 .name = "mplsogre_decap",
4881                 .help = "mplsogre decapsulation, uses configuration set by"
4882                         " \"set mplsogre_decap\"",
4883                 .priv = PRIV_ACTION(RAW_DECAP,
4884                                     sizeof(struct action_raw_decap_data)),
4885                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4886                 .call = parse_vc_action_mplsogre_decap,
4887         },
4888         [ACTION_MPLSOUDP_ENCAP] = {
4889                 .name = "mplsoudp_encap",
4890                 .help = "mplsoudp encapsulation, uses configuration set by"
4891                         " \"set mplsoudp_encap\"",
4892                 .priv = PRIV_ACTION(RAW_ENCAP,
4893                                     sizeof(struct action_raw_encap_data)),
4894                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4895                 .call = parse_vc_action_mplsoudp_encap,
4896         },
4897         [ACTION_MPLSOUDP_DECAP] = {
4898                 .name = "mplsoudp_decap",
4899                 .help = "mplsoudp decapsulation, uses configuration set by"
4900                         " \"set mplsoudp_decap\"",
4901                 .priv = PRIV_ACTION(RAW_DECAP,
4902                                     sizeof(struct action_raw_decap_data)),
4903                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4904                 .call = parse_vc_action_mplsoudp_decap,
4905         },
4906         [ACTION_SET_IPV4_SRC] = {
4907                 .name = "set_ipv4_src",
4908                 .help = "Set a new IPv4 source address in the outermost"
4909                         " IPv4 header",
4910                 .priv = PRIV_ACTION(SET_IPV4_SRC,
4911                         sizeof(struct rte_flow_action_set_ipv4)),
4912                 .next = NEXT(action_set_ipv4_src),
4913                 .call = parse_vc,
4914         },
4915         [ACTION_SET_IPV4_SRC_IPV4_SRC] = {
4916                 .name = "ipv4_addr",
4917                 .help = "new IPv4 source address to set",
4918                 .next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
4919                 .args = ARGS(ARGS_ENTRY_HTON
4920                         (struct rte_flow_action_set_ipv4, ipv4_addr)),
4921                 .call = parse_vc_conf,
4922         },
4923         [ACTION_SET_IPV4_DST] = {
4924                 .name = "set_ipv4_dst",
4925                 .help = "Set a new IPv4 destination address in the outermost"
4926                         " IPv4 header",
4927                 .priv = PRIV_ACTION(SET_IPV4_DST,
4928                         sizeof(struct rte_flow_action_set_ipv4)),
4929                 .next = NEXT(action_set_ipv4_dst),
4930                 .call = parse_vc,
4931         },
4932         [ACTION_SET_IPV4_DST_IPV4_DST] = {
4933                 .name = "ipv4_addr",
4934                 .help = "new IPv4 destination address to set",
4935                 .next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
4936                 .args = ARGS(ARGS_ENTRY_HTON
4937                         (struct rte_flow_action_set_ipv4, ipv4_addr)),
4938                 .call = parse_vc_conf,
4939         },
4940         [ACTION_SET_IPV6_SRC] = {
4941                 .name = "set_ipv6_src",
4942                 .help = "Set a new IPv6 source address in the outermost"
4943                         " IPv6 header",
4944                 .priv = PRIV_ACTION(SET_IPV6_SRC,
4945                         sizeof(struct rte_flow_action_set_ipv6)),
4946                 .next = NEXT(action_set_ipv6_src),
4947                 .call = parse_vc,
4948         },
4949         [ACTION_SET_IPV6_SRC_IPV6_SRC] = {
4950                 .name = "ipv6_addr",
4951                 .help = "new IPv6 source address to set",
4952                 .next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
4953                 .args = ARGS(ARGS_ENTRY_HTON
4954                         (struct rte_flow_action_set_ipv6, ipv6_addr)),
4955                 .call = parse_vc_conf,
4956         },
4957         [ACTION_SET_IPV6_DST] = {
4958                 .name = "set_ipv6_dst",
4959                 .help = "Set a new IPv6 destination address in the outermost"
4960                         " IPv6 header",
4961                 .priv = PRIV_ACTION(SET_IPV6_DST,
4962                         sizeof(struct rte_flow_action_set_ipv6)),
4963                 .next = NEXT(action_set_ipv6_dst),
4964                 .call = parse_vc,
4965         },
4966         [ACTION_SET_IPV6_DST_IPV6_DST] = {
4967                 .name = "ipv6_addr",
4968                 .help = "new IPv6 destination address to set",
4969                 .next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
4970                 .args = ARGS(ARGS_ENTRY_HTON
4971                         (struct rte_flow_action_set_ipv6, ipv6_addr)),
4972                 .call = parse_vc_conf,
4973         },
4974         [ACTION_SET_TP_SRC] = {
4975                 .name = "set_tp_src",
4976                 .help = "set a new source port number in the outermost"
4977                         " TCP/UDP header",
4978                 .priv = PRIV_ACTION(SET_TP_SRC,
4979                         sizeof(struct rte_flow_action_set_tp)),
4980                 .next = NEXT(action_set_tp_src),
4981                 .call = parse_vc,
4982         },
4983         [ACTION_SET_TP_SRC_TP_SRC] = {
4984                 .name = "port",
4985                 .help = "new source port number to set",
4986                 .next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
4987                 .args = ARGS(ARGS_ENTRY_HTON
4988                              (struct rte_flow_action_set_tp, port)),
4989                 .call = parse_vc_conf,
4990         },
4991         [ACTION_SET_TP_DST] = {
4992                 .name = "set_tp_dst",
4993                 .help = "set a new destination port number in the outermost"
4994                         " TCP/UDP header",
4995                 .priv = PRIV_ACTION(SET_TP_DST,
4996                         sizeof(struct rte_flow_action_set_tp)),
4997                 .next = NEXT(action_set_tp_dst),
4998                 .call = parse_vc,
4999         },
5000         [ACTION_SET_TP_DST_TP_DST] = {
5001                 .name = "port",
5002                 .help = "new destination port number to set",
5003                 .next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
5004                 .args = ARGS(ARGS_ENTRY_HTON
5005                              (struct rte_flow_action_set_tp, port)),
5006                 .call = parse_vc_conf,
5007         },
5008         [ACTION_MAC_SWAP] = {
5009                 .name = "mac_swap",
5010                 .help = "Swap the source and destination MAC addresses"
5011                         " in the outermost Ethernet header",
5012                 .priv = PRIV_ACTION(MAC_SWAP, 0),
5013                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5014                 .call = parse_vc,
5015         },
5016         [ACTION_DEC_TTL] = {
5017                 .name = "dec_ttl",
5018                 .help = "decrease network TTL if available",
5019                 .priv = PRIV_ACTION(DEC_TTL, 0),
5020                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5021                 .call = parse_vc,
5022         },
5023         [ACTION_SET_TTL] = {
5024                 .name = "set_ttl",
5025                 .help = "set ttl value",
5026                 .priv = PRIV_ACTION(SET_TTL,
5027                         sizeof(struct rte_flow_action_set_ttl)),
5028                 .next = NEXT(action_set_ttl),
5029                 .call = parse_vc,
5030         },
5031         [ACTION_SET_TTL_TTL] = {
5032                 .name = "ttl_value",
5033                 .help = "new ttl value to set",
5034                 .next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
5035                 .args = ARGS(ARGS_ENTRY_HTON
5036                              (struct rte_flow_action_set_ttl, ttl_value)),
5037                 .call = parse_vc_conf,
5038         },
5039         [ACTION_SET_MAC_SRC] = {
5040                 .name = "set_mac_src",
5041                 .help = "set source mac address",
5042                 .priv = PRIV_ACTION(SET_MAC_SRC,
5043                         sizeof(struct rte_flow_action_set_mac)),
5044                 .next = NEXT(action_set_mac_src),
5045                 .call = parse_vc,
5046         },
5047         [ACTION_SET_MAC_SRC_MAC_SRC] = {
5048                 .name = "mac_addr",
5049                 .help = "new source mac address",
5050                 .next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
5051                 .args = ARGS(ARGS_ENTRY_HTON
5052                              (struct rte_flow_action_set_mac, mac_addr)),
5053                 .call = parse_vc_conf,
5054         },
5055         [ACTION_SET_MAC_DST] = {
5056                 .name = "set_mac_dst",
5057                 .help = "set destination mac address",
5058                 .priv = PRIV_ACTION(SET_MAC_DST,
5059                         sizeof(struct rte_flow_action_set_mac)),
5060                 .next = NEXT(action_set_mac_dst),
5061                 .call = parse_vc,
5062         },
5063         [ACTION_SET_MAC_DST_MAC_DST] = {
5064                 .name = "mac_addr",
5065                 .help = "new destination mac address to set",
5066                 .next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
5067                 .args = ARGS(ARGS_ENTRY_HTON
5068                              (struct rte_flow_action_set_mac, mac_addr)),
5069                 .call = parse_vc_conf,
5070         },
5071         [ACTION_INC_TCP_SEQ] = {
5072                 .name = "inc_tcp_seq",
5073                 .help = "increase TCP sequence number",
5074                 .priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
5075                 .next = NEXT(action_inc_tcp_seq),
5076                 .call = parse_vc,
5077         },
5078         [ACTION_INC_TCP_SEQ_VALUE] = {
5079                 .name = "value",
5080                 .help = "the value to increase TCP sequence number by",
5081                 .next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
5082                 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5083                 .call = parse_vc_conf,
5084         },
5085         [ACTION_DEC_TCP_SEQ] = {
5086                 .name = "dec_tcp_seq",
5087                 .help = "decrease TCP sequence number",
5088                 .priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
5089                 .next = NEXT(action_dec_tcp_seq),
5090                 .call = parse_vc,
5091         },
5092         [ACTION_DEC_TCP_SEQ_VALUE] = {
5093                 .name = "value",
5094                 .help = "the value to decrease TCP sequence number by",
5095                 .next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
5096                 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5097                 .call = parse_vc_conf,
5098         },
5099         [ACTION_INC_TCP_ACK] = {
5100                 .name = "inc_tcp_ack",
5101                 .help = "increase TCP acknowledgment number",
5102                 .priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
5103                 .next = NEXT(action_inc_tcp_ack),
5104                 .call = parse_vc,
5105         },
5106         [ACTION_INC_TCP_ACK_VALUE] = {
5107                 .name = "value",
5108                 .help = "the value to increase TCP acknowledgment number by",
5109                 .next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
5110                 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5111                 .call = parse_vc_conf,
5112         },
5113         [ACTION_DEC_TCP_ACK] = {
5114                 .name = "dec_tcp_ack",
5115                 .help = "decrease TCP acknowledgment number",
5116                 .priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
5117                 .next = NEXT(action_dec_tcp_ack),
5118                 .call = parse_vc,
5119         },
5120         [ACTION_DEC_TCP_ACK_VALUE] = {
5121                 .name = "value",
5122                 .help = "the value to decrease TCP acknowledgment number by",
5123                 .next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
5124                 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5125                 .call = parse_vc_conf,
5126         },
5127         [ACTION_RAW_ENCAP] = {
5128                 .name = "raw_encap",
5129                 .help = "encapsulation data, defined by set raw_encap",
5130                 .priv = PRIV_ACTION(RAW_ENCAP,
5131                         sizeof(struct action_raw_encap_data)),
5132                 .next = NEXT(action_raw_encap),
5133                 .call = parse_vc_action_raw_encap,
5134         },
5135         [ACTION_RAW_ENCAP_INDEX] = {
5136                 .name = "index",
5137                 .help = "the index of raw_encap_confs",
5138                 .next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
5139         },
5140         [ACTION_RAW_ENCAP_INDEX_VALUE] = {
5141                 .name = "{index}",
5142                 .type = "UNSIGNED",
5143                 .help = "unsigned integer value",
5144                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5145                 .call = parse_vc_action_raw_encap_index,
5146                 .comp = comp_set_raw_index,
5147         },
5148         [ACTION_RAW_DECAP] = {
5149                 .name = "raw_decap",
5150                 .help = "decapsulation data, defined by set raw_encap",
5151                 .priv = PRIV_ACTION(RAW_DECAP,
5152                         sizeof(struct action_raw_decap_data)),
5153                 .next = NEXT(action_raw_decap),
5154                 .call = parse_vc_action_raw_decap,
5155         },
5156         [ACTION_RAW_DECAP_INDEX] = {
5157                 .name = "index",
5158                 .help = "the index of raw_encap_confs",
5159                 .next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
5160         },
5161         [ACTION_RAW_DECAP_INDEX_VALUE] = {
5162                 .name = "{index}",
5163                 .type = "UNSIGNED",
5164                 .help = "unsigned integer value",
5165                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5166                 .call = parse_vc_action_raw_decap_index,
5167                 .comp = comp_set_raw_index,
5168         },
5169         [ACTION_MODIFY_FIELD] = {
5170                 .name = "modify_field",
5171                 .help = "modify destination field with data from source field",
5172                 .priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
5173                 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
5174                 .call = parse_vc,
5175         },
5176         [ACTION_MODIFY_FIELD_OP] = {
5177                 .name = "op",
5178                 .help = "operation type",
5179                 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
5180                         NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
5181                 .call = parse_vc_conf,
5182         },
5183         [ACTION_MODIFY_FIELD_OP_VALUE] = {
5184                 .name = "{operation}",
5185                 .help = "operation type value",
5186                 .call = parse_vc_modify_field_op,
5187                 .comp = comp_set_modify_field_op,
5188         },
5189         [ACTION_MODIFY_FIELD_DST_TYPE] = {
5190                 .name = "dst_type",
5191                 .help = "destination field type",
5192                 .next = NEXT(action_modify_field_dst,
5193                         NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
5194                 .call = parse_vc_conf,
5195         },
5196         [ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
5197                 .name = "{dst_type}",
5198                 .help = "destination field type value",
5199                 .call = parse_vc_modify_field_id,
5200                 .comp = comp_set_modify_field_id,
5201         },
5202         [ACTION_MODIFY_FIELD_DST_LEVEL] = {
5203                 .name = "dst_level",
5204                 .help = "destination field level",
5205                 .next = NEXT(action_modify_field_dst,
5206                              NEXT_ENTRY(COMMON_UNSIGNED)),
5207                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5208                                         dst.level)),
5209                 .call = parse_vc_conf,
5210         },
5211         [ACTION_MODIFY_FIELD_DST_OFFSET] = {
5212                 .name = "dst_offset",
5213                 .help = "destination field bit offset",
5214                 .next = NEXT(action_modify_field_dst,
5215                              NEXT_ENTRY(COMMON_UNSIGNED)),
5216                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5217                                         dst.offset)),
5218                 .call = parse_vc_conf,
5219         },
5220         [ACTION_MODIFY_FIELD_SRC_TYPE] = {
5221                 .name = "src_type",
5222                 .help = "source field type",
5223                 .next = NEXT(action_modify_field_src,
5224                         NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
5225                 .call = parse_vc_conf,
5226         },
5227         [ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
5228                 .name = "{src_type}",
5229                 .help = "source field type value",
5230                 .call = parse_vc_modify_field_id,
5231                 .comp = comp_set_modify_field_id,
5232         },
5233         [ACTION_MODIFY_FIELD_SRC_LEVEL] = {
5234                 .name = "src_level",
5235                 .help = "source field level",
5236                 .next = NEXT(action_modify_field_src,
5237                              NEXT_ENTRY(COMMON_UNSIGNED)),
5238                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5239                                         src.level)),
5240                 .call = parse_vc_conf,
5241         },
5242         [ACTION_MODIFY_FIELD_SRC_OFFSET] = {
5243                 .name = "src_offset",
5244                 .help = "source field bit offset",
5245                 .next = NEXT(action_modify_field_src,
5246                              NEXT_ENTRY(COMMON_UNSIGNED)),
5247                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5248                                         src.offset)),
5249                 .call = parse_vc_conf,
5250         },
5251         [ACTION_MODIFY_FIELD_SRC_VALUE] = {
5252                 .name = "src_value",
5253                 .help = "source immediate value",
5254                 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
5255                              NEXT_ENTRY(COMMON_HEX)),
5256                 .args = ARGS(ARGS_ENTRY_ARB(0, 0),
5257                              ARGS_ENTRY_ARB(0, 0),
5258                              ARGS_ENTRY(struct rte_flow_action_modify_field,
5259                                         src.value)),
5260                 .call = parse_vc_conf,
5261         },
5262         [ACTION_MODIFY_FIELD_SRC_POINTER] = {
5263                 .name = "src_ptr",
5264                 .help = "pointer to source immediate value",
5265                 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
5266                              NEXT_ENTRY(COMMON_HEX)),
5267                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5268                                         src.pvalue),
5269                              ARGS_ENTRY_ARB(0, 0),
5270                              ARGS_ENTRY_ARB
5271                                 (sizeof(struct rte_flow_action_modify_field),
5272                                  ACTION_MODIFY_PATTERN_SIZE)),
5273                 .call = parse_vc_conf,
5274         },
5275         [ACTION_MODIFY_FIELD_WIDTH] = {
5276                 .name = "width",
5277                 .help = "number of bits to copy",
5278                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
5279                         NEXT_ENTRY(COMMON_UNSIGNED)),
5280                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5281                                         width)),
5282                 .call = parse_vc_conf,
5283         },
5284         /* Top level command. */
5285         [SET] = {
5286                 .name = "set",
5287                 .help = "set raw encap/decap/sample data",
5288                 .type = "set raw_encap|raw_decap <index> <pattern>"
5289                                 " or set sample_actions <index> <action>",
5290                 .next = NEXT(NEXT_ENTRY
5291                              (SET_RAW_ENCAP,
5292                               SET_RAW_DECAP,
5293                               SET_SAMPLE_ACTIONS)),
5294                 .call = parse_set_init,
5295         },
5296         /* Sub-level commands. */
5297         [SET_RAW_ENCAP] = {
5298                 .name = "raw_encap",
5299                 .help = "set raw encap data",
5300                 .next = NEXT(next_set_raw),
5301                 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5302                                 (offsetof(struct buffer, port),
5303                                  sizeof(((struct buffer *)0)->port),
5304                                  0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
5305                 .call = parse_set_raw_encap_decap,
5306         },
5307         [SET_RAW_DECAP] = {
5308                 .name = "raw_decap",
5309                 .help = "set raw decap data",
5310                 .next = NEXT(next_set_raw),
5311                 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5312                                 (offsetof(struct buffer, port),
5313                                  sizeof(((struct buffer *)0)->port),
5314                                  0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
5315                 .call = parse_set_raw_encap_decap,
5316         },
5317         [SET_RAW_INDEX] = {
5318                 .name = "{index}",
5319                 .type = "COMMON_UNSIGNED",
5320                 .help = "index of raw_encap/raw_decap data",
5321                 .next = NEXT(next_item),
5322                 .call = parse_port,
5323         },
5324         [SET_SAMPLE_INDEX] = {
5325                 .name = "{index}",
5326                 .type = "UNSIGNED",
5327                 .help = "index of sample actions",
5328                 .next = NEXT(next_action_sample),
5329                 .call = parse_port,
5330         },
5331         [SET_SAMPLE_ACTIONS] = {
5332                 .name = "sample_actions",
5333                 .help = "set sample actions list",
5334                 .next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
5335                 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5336                                 (offsetof(struct buffer, port),
5337                                  sizeof(((struct buffer *)0)->port),
5338                                  0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
5339                 .call = parse_set_sample_action,
5340         },
5341         [ACTION_SET_TAG] = {
5342                 .name = "set_tag",
5343                 .help = "set tag",
5344                 .priv = PRIV_ACTION(SET_TAG,
5345                         sizeof(struct rte_flow_action_set_tag)),
5346                 .next = NEXT(action_set_tag),
5347                 .call = parse_vc,
5348         },
5349         [ACTION_SET_TAG_INDEX] = {
5350                 .name = "index",
5351                 .help = "index of tag array",
5352                 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
5353                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
5354                 .call = parse_vc_conf,
5355         },
5356         [ACTION_SET_TAG_DATA] = {
5357                 .name = "data",
5358                 .help = "tag value",
5359                 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
5360                 .args = ARGS(ARGS_ENTRY
5361                              (struct rte_flow_action_set_tag, data)),
5362                 .call = parse_vc_conf,
5363         },
5364         [ACTION_SET_TAG_MASK] = {
5365                 .name = "mask",
5366                 .help = "mask for tag value",
5367                 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
5368                 .args = ARGS(ARGS_ENTRY
5369                              (struct rte_flow_action_set_tag, mask)),
5370                 .call = parse_vc_conf,
5371         },
5372         [ACTION_SET_META] = {
5373                 .name = "set_meta",
5374                 .help = "set metadata",
5375                 .priv = PRIV_ACTION(SET_META,
5376                         sizeof(struct rte_flow_action_set_meta)),
5377                 .next = NEXT(action_set_meta),
5378                 .call = parse_vc_action_set_meta,
5379         },
5380         [ACTION_SET_META_DATA] = {
5381                 .name = "data",
5382                 .help = "metadata value",
5383                 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
5384                 .args = ARGS(ARGS_ENTRY
5385                              (struct rte_flow_action_set_meta, data)),
5386                 .call = parse_vc_conf,
5387         },
5388         [ACTION_SET_META_MASK] = {
5389                 .name = "mask",
5390                 .help = "mask for metadata value",
5391                 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
5392                 .args = ARGS(ARGS_ENTRY
5393                              (struct rte_flow_action_set_meta, mask)),
5394                 .call = parse_vc_conf,
5395         },
5396         [ACTION_SET_IPV4_DSCP] = {
5397                 .name = "set_ipv4_dscp",
5398                 .help = "set DSCP value",
5399                 .priv = PRIV_ACTION(SET_IPV4_DSCP,
5400                         sizeof(struct rte_flow_action_set_dscp)),
5401                 .next = NEXT(action_set_ipv4_dscp),
5402                 .call = parse_vc,
5403         },
5404         [ACTION_SET_IPV4_DSCP_VALUE] = {
5405                 .name = "dscp_value",
5406                 .help = "new IPv4 DSCP value to set",
5407                 .next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
5408                 .args = ARGS(ARGS_ENTRY
5409                              (struct rte_flow_action_set_dscp, dscp)),
5410                 .call = parse_vc_conf,
5411         },
5412         [ACTION_SET_IPV6_DSCP] = {
5413                 .name = "set_ipv6_dscp",
5414                 .help = "set DSCP value",
5415                 .priv = PRIV_ACTION(SET_IPV6_DSCP,
5416                         sizeof(struct rte_flow_action_set_dscp)),
5417                 .next = NEXT(action_set_ipv6_dscp),
5418                 .call = parse_vc,
5419         },
5420         [ACTION_SET_IPV6_DSCP_VALUE] = {
5421                 .name = "dscp_value",
5422                 .help = "new IPv6 DSCP value to set",
5423                 .next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
5424                 .args = ARGS(ARGS_ENTRY
5425                              (struct rte_flow_action_set_dscp, dscp)),
5426                 .call = parse_vc_conf,
5427         },
5428         [ACTION_AGE] = {
5429                 .name = "age",
5430                 .help = "set a specific metadata header",
5431                 .next = NEXT(action_age),
5432                 .priv = PRIV_ACTION(AGE,
5433                         sizeof(struct rte_flow_action_age)),
5434                 .call = parse_vc,
5435         },
5436         [ACTION_AGE_TIMEOUT] = {
5437                 .name = "timeout",
5438                 .help = "flow age timeout value",
5439                 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
5440                                            timeout, 24)),
5441                 .next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
5442                 .call = parse_vc_conf,
5443         },
5444         [ACTION_SAMPLE] = {
5445                 .name = "sample",
5446                 .help = "set a sample action",
5447                 .next = NEXT(action_sample),
5448                 .priv = PRIV_ACTION(SAMPLE,
5449                         sizeof(struct action_sample_data)),
5450                 .call = parse_vc_action_sample,
5451         },
5452         [ACTION_SAMPLE_RATIO] = {
5453                 .name = "ratio",
5454                 .help = "flow sample ratio value",
5455                 .next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
5456                 .args = ARGS(ARGS_ENTRY_ARB
5457                              (offsetof(struct action_sample_data, conf) +
5458                               offsetof(struct rte_flow_action_sample, ratio),
5459                               sizeof(((struct rte_flow_action_sample *)0)->
5460                                      ratio))),
5461         },
5462         [ACTION_SAMPLE_INDEX] = {
5463                 .name = "index",
5464                 .help = "the index of sample actions list",
5465                 .next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
5466         },
5467         [ACTION_SAMPLE_INDEX_VALUE] = {
5468                 .name = "{index}",
5469                 .type = "COMMON_UNSIGNED",
5470                 .help = "unsigned integer value",
5471                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5472                 .call = parse_vc_action_sample_index,
5473                 .comp = comp_set_sample_index,
5474         },
5475         [ACTION_CONNTRACK] = {
5476                 .name = "conntrack",
5477                 .help = "create a conntrack object",
5478                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5479                 .priv = PRIV_ACTION(CONNTRACK,
5480                                     sizeof(struct rte_flow_action_conntrack)),
5481                 .call = parse_vc,
5482         },
5483         [ACTION_CONNTRACK_UPDATE] = {
5484                 .name = "conntrack_update",
5485                 .help = "update a conntrack object",
5486                 .next = NEXT(action_update_conntrack),
5487                 .priv = PRIV_ACTION(CONNTRACK,
5488                                     sizeof(struct rte_flow_modify_conntrack)),
5489                 .call = parse_vc,
5490         },
5491         [ACTION_CONNTRACK_UPDATE_DIR] = {
5492                 .name = "dir",
5493                 .help = "update a conntrack object direction",
5494                 .next = NEXT(action_update_conntrack),
5495                 .call = parse_vc_action_conntrack_update,
5496         },
5497         [ACTION_CONNTRACK_UPDATE_CTX] = {
5498                 .name = "ctx",
5499                 .help = "update a conntrack object context",
5500                 .next = NEXT(action_update_conntrack),
5501                 .call = parse_vc_action_conntrack_update,
5502         },
5503         [ACTION_PORT_REPRESENTOR] = {
5504                 .name = "port_representor",
5505                 .help = "at embedded switch level, send matching traffic to the given ethdev",
5506                 .priv = PRIV_ACTION(PORT_REPRESENTOR,
5507                                     sizeof(struct rte_flow_action_ethdev)),
5508                 .next = NEXT(action_port_representor),
5509                 .call = parse_vc,
5510         },
5511         [ACTION_PORT_REPRESENTOR_PORT_ID] = {
5512                 .name = "port_id",
5513                 .help = "ethdev port ID",
5514                 .next = NEXT(action_port_representor,
5515                              NEXT_ENTRY(COMMON_UNSIGNED)),
5516                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
5517                                         port_id)),
5518                 .call = parse_vc_conf,
5519         },
5520         [ACTION_REPRESENTED_PORT] = {
5521                 .name = "represented_port",
5522                 .help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
5523                 .priv = PRIV_ACTION(REPRESENTED_PORT,
5524                                 sizeof(struct rte_flow_action_ethdev)),
5525                 .next = NEXT(action_represented_port),
5526                 .call = parse_vc,
5527         },
5528         [ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
5529                 .name = "ethdev_port_id",
5530                 .help = "ethdev port ID",
5531                 .next = NEXT(action_represented_port,
5532                              NEXT_ENTRY(COMMON_UNSIGNED)),
5533                 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
5534                                         port_id)),
5535                 .call = parse_vc_conf,
5536         },
5537         /* Indirect action destroy arguments. */
5538         [INDIRECT_ACTION_DESTROY_ID] = {
5539                 .name = "action_id",
5540                 .help = "specify a indirect action id to destroy",
5541                 .next = NEXT(next_ia_destroy_attr,
5542                              NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
5543                 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
5544                                             args.ia_destroy.action_id)),
5545                 .call = parse_ia_destroy,
5546         },
5547         /* Indirect action create arguments. */
5548         [INDIRECT_ACTION_CREATE_ID] = {
5549                 .name = "action_id",
5550                 .help = "specify a indirect action id to create",
5551                 .next = NEXT(next_ia_create_attr,
5552                              NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
5553                 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
5554         },
5555         [ACTION_INDIRECT] = {
5556                 .name = "indirect",
5557                 .help = "apply indirect action by id",
5558                 .priv = PRIV_ACTION(INDIRECT, 0),
5559                 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
5560                 .args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
5561                 .call = parse_vc,
5562         },
5563         [INDIRECT_ACTION_ID2PTR] = {
5564                 .name = "{action_id}",
5565                 .type = "INDIRECT_ACTION_ID",
5566                 .help = "indirect action id",
5567                 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5568                 .call = parse_ia_id2ptr,
5569                 .comp = comp_none,
5570         },
5571         [INDIRECT_ACTION_INGRESS] = {
5572                 .name = "ingress",
5573                 .help = "affect rule to ingress",
5574                 .next = NEXT(next_ia_create_attr),
5575                 .call = parse_ia,
5576         },
5577         [INDIRECT_ACTION_EGRESS] = {
5578                 .name = "egress",
5579                 .help = "affect rule to egress",
5580                 .next = NEXT(next_ia_create_attr),
5581                 .call = parse_ia,
5582         },
5583         [INDIRECT_ACTION_TRANSFER] = {
5584                 .name = "transfer",
5585                 .help = "affect rule to transfer",
5586                 .next = NEXT(next_ia_create_attr),
5587                 .call = parse_ia,
5588         },
5589         [INDIRECT_ACTION_SPEC] = {
5590                 .name = "action",
5591                 .help = "specify action to create indirect handle",
5592                 .next = NEXT(next_action),
5593         },
5594         [ACTION_POL_G] = {
5595                 .name = "g_actions",
5596                 .help = "submit a list of associated actions for green",
5597                 .next = NEXT(next_action),
5598                 .call = parse_mp,
5599         },
5600         [ACTION_POL_Y] = {
5601                 .name = "y_actions",
5602                 .help = "submit a list of associated actions for yellow",
5603                 .next = NEXT(next_action),
5604         },
5605         [ACTION_POL_R] = {
5606                 .name = "r_actions",
5607                 .help = "submit a list of associated actions for red",
5608                 .next = NEXT(next_action),
5609         },
5610
5611         /* Top-level command. */
5612         [ADD] = {
5613                 .name = "add",
5614                 .type = "port meter policy {port_id} {arg}",
5615                 .help = "add port meter policy",
5616                 .next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
5617                 .call = parse_init,
5618         },
5619         /* Sub-level commands. */
5620         [ITEM_POL_PORT] = {
5621                 .name = "port",
5622                 .help = "add port meter policy",
5623                 .next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
5624         },
5625         [ITEM_POL_METER] = {
5626                 .name = "meter",
5627                 .help = "add port meter policy",
5628                 .next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
5629         },
5630         [ITEM_POL_POLICY] = {
5631                 .name = "policy",
5632                 .help = "add port meter policy",
5633                 .next = NEXT(NEXT_ENTRY(ACTION_POL_R),
5634                                 NEXT_ENTRY(ACTION_POL_Y),
5635                                 NEXT_ENTRY(ACTION_POL_G),
5636                                 NEXT_ENTRY(COMMON_POLICY_ID),
5637                                 NEXT_ENTRY(COMMON_PORT_ID)),
5638                 .args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
5639                                 ARGS_ENTRY(struct buffer, port)),
5640                 .call = parse_mp,
5641         },
5642 };
5643
5644 /** Remove and return last entry from argument stack. */
5645 static const struct arg *
5646 pop_args(struct context *ctx)
5647 {
5648         return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
5649 }
5650
5651 /** Add entry on top of the argument stack. */
5652 static int
5653 push_args(struct context *ctx, const struct arg *arg)
5654 {
5655         if (ctx->args_num == CTX_STACK_SIZE)
5656                 return -1;
5657         ctx->args[ctx->args_num++] = arg;
5658         return 0;
5659 }
5660
5661 /** Spread value into buffer according to bit-mask. */
5662 static size_t
5663 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
5664 {
5665         uint32_t i = arg->size;
5666         uint32_t end = 0;
5667         int sub = 1;
5668         int add = 0;
5669         size_t len = 0;
5670
5671         if (!arg->mask)
5672                 return 0;
5673 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5674         if (!arg->hton) {
5675                 i = 0;
5676                 end = arg->size;
5677                 sub = 0;
5678                 add = 1;
5679         }
5680 #endif
5681         while (i != end) {
5682                 unsigned int shift = 0;
5683                 uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
5684
5685                 for (shift = 0; arg->mask[i] >> shift; ++shift) {
5686                         if (!(arg->mask[i] & (1 << shift)))
5687                                 continue;
5688                         ++len;
5689                         if (!dst)
5690                                 continue;
5691                         *buf &= ~(1 << shift);
5692                         *buf |= (val & 1) << shift;
5693                         val >>= 1;
5694                 }
5695                 i += add;
5696         }
5697         return len;
5698 }
5699
5700 /** Compare a string with a partial one of a given length. */
5701 static int
5702 strcmp_partial(const char *full, const char *partial, size_t partial_len)
5703 {
5704         int r = strncmp(full, partial, partial_len);
5705
5706         if (r)
5707                 return r;
5708         if (strlen(full) <= partial_len)
5709                 return 0;
5710         return full[partial_len];
5711 }
5712
5713 /**
5714  * Parse a prefix length and generate a bit-mask.
5715  *
5716  * Last argument (ctx->args) is retrieved to determine mask size, storage
5717  * location and whether the result must use network byte ordering.
5718  */
5719 static int
5720 parse_prefix(struct context *ctx, const struct token *token,
5721              const char *str, unsigned int len,
5722              void *buf, unsigned int size)
5723 {
5724         const struct arg *arg = pop_args(ctx);
5725         static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
5726         char *end;
5727         uintmax_t u;
5728         unsigned int bytes;
5729         unsigned int extra;
5730
5731         (void)token;
5732         /* Argument is expected. */
5733         if (!arg)
5734                 return -1;
5735         errno = 0;
5736         u = strtoumax(str, &end, 0);
5737         if (errno || (size_t)(end - str) != len)
5738                 goto error;
5739         if (arg->mask) {
5740                 uintmax_t v = 0;
5741
5742                 extra = arg_entry_bf_fill(NULL, 0, arg);
5743                 if (u > extra)
5744                         goto error;
5745                 if (!ctx->object)
5746                         return len;
5747                 extra -= u;
5748                 while (u--)
5749                         (v <<= 1, v |= 1);
5750                 v <<= extra;
5751                 if (!arg_entry_bf_fill(ctx->object, v, arg) ||
5752                     !arg_entry_bf_fill(ctx->objmask, -1, arg))
5753                         goto error;
5754                 return len;
5755         }
5756         bytes = u / 8;
5757         extra = u % 8;
5758         size = arg->size;
5759         if (bytes > size || bytes + !!extra > size)
5760                 goto error;
5761         if (!ctx->object)
5762                 return len;
5763         buf = (uint8_t *)ctx->object + arg->offset;
5764 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5765         if (!arg->hton) {
5766                 memset((uint8_t *)buf + size - bytes, 0xff, bytes);
5767                 memset(buf, 0x00, size - bytes);
5768                 if (extra)
5769                         ((uint8_t *)buf)[size - bytes - 1] = conv[extra];
5770         } else
5771 #endif
5772         {
5773                 memset(buf, 0xff, bytes);
5774                 memset((uint8_t *)buf + bytes, 0x00, size - bytes);
5775                 if (extra)
5776                         ((uint8_t *)buf)[bytes] = conv[extra];
5777         }
5778         if (ctx->objmask)
5779                 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
5780         return len;
5781 error:
5782         push_args(ctx, arg);
5783         return -1;
5784 }
5785
5786 /** Default parsing function for token name matching. */
5787 static int
5788 parse_default(struct context *ctx, const struct token *token,
5789               const char *str, unsigned int len,
5790               void *buf, unsigned int size)
5791 {
5792         (void)ctx;
5793         (void)buf;
5794         (void)size;
5795         if (strcmp_partial(token->name, str, len))
5796                 return -1;
5797         return len;
5798 }
5799
5800 /** Parse flow command, initialize output buffer for subsequent tokens. */
5801 static int
5802 parse_init(struct context *ctx, const struct token *token,
5803            const char *str, unsigned int len,
5804            void *buf, unsigned int size)
5805 {
5806         struct buffer *out = buf;
5807
5808         /* Token name must match. */
5809         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5810                 return -1;
5811         /* Nothing else to do if there is no buffer. */
5812         if (!out)
5813                 return len;
5814         /* Make sure buffer is large enough. */
5815         if (size < sizeof(*out))
5816                 return -1;
5817         /* Initialize buffer. */
5818         memset(out, 0x00, sizeof(*out));
5819         memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
5820         ctx->objdata = 0;
5821         ctx->object = out;
5822         ctx->objmask = NULL;
5823         return len;
5824 }
5825
5826 /** Parse tokens for indirect action commands. */
5827 static int
5828 parse_ia(struct context *ctx, const struct token *token,
5829          const char *str, unsigned int len,
5830          void *buf, unsigned int size)
5831 {
5832         struct buffer *out = buf;
5833
5834         /* Token name must match. */
5835         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5836                 return -1;
5837         /* Nothing else to do if there is no buffer. */
5838         if (!out)
5839                 return len;
5840         if (!out->command) {
5841                 if (ctx->curr != INDIRECT_ACTION)
5842                         return -1;
5843                 if (sizeof(*out) > size)
5844                         return -1;
5845                 out->command = ctx->curr;
5846                 ctx->objdata = 0;
5847                 ctx->object = out;
5848                 ctx->objmask = NULL;
5849                 out->args.vc.data = (uint8_t *)out + size;
5850                 return len;
5851         }
5852         switch (ctx->curr) {
5853         case INDIRECT_ACTION_CREATE:
5854         case INDIRECT_ACTION_UPDATE:
5855                 out->args.vc.actions =
5856                         (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5857                                                sizeof(double));
5858                 out->args.vc.attr.group = UINT32_MAX;
5859                 /* fallthrough */
5860         case INDIRECT_ACTION_QUERY:
5861                 out->command = ctx->curr;
5862                 ctx->objdata = 0;
5863                 ctx->object = out;
5864                 ctx->objmask = NULL;
5865                 return len;
5866         case INDIRECT_ACTION_EGRESS:
5867                 out->args.vc.attr.egress = 1;
5868                 return len;
5869         case INDIRECT_ACTION_INGRESS:
5870                 out->args.vc.attr.ingress = 1;
5871                 return len;
5872         case INDIRECT_ACTION_TRANSFER:
5873                 out->args.vc.attr.transfer = 1;
5874                 return len;
5875         default:
5876                 return -1;
5877         }
5878 }
5879
5880
5881 /** Parse tokens for indirect action destroy command. */
5882 static int
5883 parse_ia_destroy(struct context *ctx, const struct token *token,
5884                  const char *str, unsigned int len,
5885                  void *buf, unsigned int size)
5886 {
5887         struct buffer *out = buf;
5888         uint32_t *action_id;
5889
5890         /* Token name must match. */
5891         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5892                 return -1;
5893         /* Nothing else to do if there is no buffer. */
5894         if (!out)
5895                 return len;
5896         if (!out->command || out->command == INDIRECT_ACTION) {
5897                 if (ctx->curr != INDIRECT_ACTION_DESTROY)
5898                         return -1;
5899                 if (sizeof(*out) > size)
5900                         return -1;
5901                 out->command = ctx->curr;
5902                 ctx->objdata = 0;
5903                 ctx->object = out;
5904                 ctx->objmask = NULL;
5905                 out->args.ia_destroy.action_id =
5906                         (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5907                                                sizeof(double));
5908                 return len;
5909         }
5910         action_id = out->args.ia_destroy.action_id
5911                     + out->args.ia_destroy.action_id_n++;
5912         if ((uint8_t *)action_id > (uint8_t *)out + size)
5913                 return -1;
5914         ctx->objdata = 0;
5915         ctx->object = action_id;
5916         ctx->objmask = NULL;
5917         return len;
5918 }
5919
5920 /** Parse tokens for meter policy action commands. */
5921 static int
5922 parse_mp(struct context *ctx, const struct token *token,
5923         const char *str, unsigned int len,
5924         void *buf, unsigned int size)
5925 {
5926         struct buffer *out = buf;
5927
5928         /* Token name must match. */
5929         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5930                 return -1;
5931         /* Nothing else to do if there is no buffer. */
5932         if (!out)
5933                 return len;
5934         if (!out->command) {
5935                 if (ctx->curr != ITEM_POL_POLICY)
5936                         return -1;
5937                 if (sizeof(*out) > size)
5938                         return -1;
5939                 out->command = ctx->curr;
5940                 ctx->objdata = 0;
5941                 ctx->object = out;
5942                 ctx->objmask = NULL;
5943                 out->args.vc.data = (uint8_t *)out + size;
5944                 return len;
5945         }
5946         switch (ctx->curr) {
5947         case ACTION_POL_G:
5948                 out->args.vc.actions =
5949                         (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5950                                         sizeof(double));
5951                 out->command = ctx->curr;
5952                 ctx->objdata = 0;
5953                 ctx->object = out;
5954                 ctx->objmask = NULL;
5955                 return len;
5956         default:
5957                 return -1;
5958         }
5959 }
5960
5961 /** Parse tokens for validate/create commands. */
5962 static int
5963 parse_vc(struct context *ctx, const struct token *token,
5964          const char *str, unsigned int len,
5965          void *buf, unsigned int size)
5966 {
5967         struct buffer *out = buf;
5968         uint8_t *data;
5969         uint32_t data_size;
5970
5971         /* Token name must match. */
5972         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5973                 return -1;
5974         /* Nothing else to do if there is no buffer. */
5975         if (!out)
5976                 return len;
5977         if (!out->command) {
5978                 if (ctx->curr != VALIDATE && ctx->curr != CREATE)
5979                         return -1;
5980                 if (sizeof(*out) > size)
5981                         return -1;
5982                 out->command = ctx->curr;
5983                 ctx->objdata = 0;
5984                 ctx->object = out;
5985                 ctx->objmask = NULL;
5986                 out->args.vc.data = (uint8_t *)out + size;
5987                 return len;
5988         }
5989         ctx->objdata = 0;
5990         switch (ctx->curr) {
5991         default:
5992                 ctx->object = &out->args.vc.attr;
5993                 break;
5994         case VC_TUNNEL_SET:
5995         case VC_TUNNEL_MATCH:
5996                 ctx->object = &out->args.vc.tunnel_ops;
5997                 break;
5998         }
5999         ctx->objmask = NULL;
6000         switch (ctx->curr) {
6001         case VC_GROUP:
6002         case VC_PRIORITY:
6003                 return len;
6004         case VC_TUNNEL_SET:
6005                 out->args.vc.tunnel_ops.enabled = 1;
6006                 out->args.vc.tunnel_ops.actions = 1;
6007                 return len;
6008         case VC_TUNNEL_MATCH:
6009                 out->args.vc.tunnel_ops.enabled = 1;
6010                 out->args.vc.tunnel_ops.items = 1;
6011                 return len;
6012         case VC_INGRESS:
6013                 out->args.vc.attr.ingress = 1;
6014                 return len;
6015         case VC_EGRESS:
6016                 out->args.vc.attr.egress = 1;
6017                 return len;
6018         case VC_TRANSFER:
6019                 out->args.vc.attr.transfer = 1;
6020                 return len;
6021         case ITEM_PATTERN:
6022                 out->args.vc.pattern =
6023                         (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6024                                                sizeof(double));
6025                 ctx->object = out->args.vc.pattern;
6026                 ctx->objmask = NULL;
6027                 return len;
6028         case ACTIONS:
6029                 out->args.vc.actions =
6030                         (void *)RTE_ALIGN_CEIL((uintptr_t)
6031                                                (out->args.vc.pattern +
6032                                                 out->args.vc.pattern_n),
6033                                                sizeof(double));
6034                 ctx->object = out->args.vc.actions;
6035                 ctx->objmask = NULL;
6036                 return len;
6037         default:
6038                 if (!token->priv)
6039                         return -1;
6040                 break;
6041         }
6042         if (!out->args.vc.actions) {
6043                 const struct parse_item_priv *priv = token->priv;
6044                 struct rte_flow_item *item =
6045                         out->args.vc.pattern + out->args.vc.pattern_n;
6046
6047                 data_size = priv->size * 3; /* spec, last, mask */
6048                 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
6049                                                (out->args.vc.data - data_size),
6050                                                sizeof(double));
6051                 if ((uint8_t *)item + sizeof(*item) > data)
6052                         return -1;
6053                 *item = (struct rte_flow_item){
6054                         .type = priv->type,
6055                 };
6056                 ++out->args.vc.pattern_n;
6057                 ctx->object = item;
6058                 ctx->objmask = NULL;
6059         } else {
6060                 const struct parse_action_priv *priv = token->priv;
6061                 struct rte_flow_action *action =
6062                         out->args.vc.actions + out->args.vc.actions_n;
6063
6064                 data_size = priv->size; /* configuration */
6065                 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
6066                                                (out->args.vc.data - data_size),
6067                                                sizeof(double));
6068                 if ((uint8_t *)action + sizeof(*action) > data)
6069                         return -1;
6070                 *action = (struct rte_flow_action){
6071                         .type = priv->type,
6072                         .conf = data_size ? data : NULL,
6073                 };
6074                 ++out->args.vc.actions_n;
6075                 ctx->object = action;
6076                 ctx->objmask = NULL;
6077         }
6078         memset(data, 0, data_size);
6079         out->args.vc.data = data;
6080         ctx->objdata = data_size;
6081         return len;
6082 }
6083
6084 /** Parse pattern item parameter type. */
6085 static int
6086 parse_vc_spec(struct context *ctx, const struct token *token,
6087               const char *str, unsigned int len,
6088               void *buf, unsigned int size)
6089 {
6090         struct buffer *out = buf;
6091         struct rte_flow_item *item;
6092         uint32_t data_size;
6093         int index;
6094         int objmask = 0;
6095
6096         (void)size;
6097         /* Token name must match. */
6098         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6099                 return -1;
6100         /* Parse parameter types. */
6101         switch (ctx->curr) {
6102                 static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
6103
6104         case ITEM_PARAM_IS:
6105                 index = 0;
6106                 objmask = 1;
6107                 break;
6108         case ITEM_PARAM_SPEC:
6109                 index = 0;
6110                 break;
6111         case ITEM_PARAM_LAST:
6112                 index = 1;
6113                 break;
6114         case ITEM_PARAM_PREFIX:
6115                 /* Modify next token to expect a prefix. */
6116                 if (ctx->next_num < 2)
6117                         return -1;
6118                 ctx->next[ctx->next_num - 2] = prefix;
6119                 /* Fall through. */
6120         case ITEM_PARAM_MASK:
6121                 index = 2;
6122                 break;
6123         default:
6124                 return -1;
6125         }
6126         /* Nothing else to do if there is no buffer. */
6127         if (!out)
6128                 return len;
6129         if (!out->args.vc.pattern_n)
6130                 return -1;
6131         item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
6132         data_size = ctx->objdata / 3; /* spec, last, mask */
6133         /* Point to selected object. */
6134         ctx->object = out->args.vc.data + (data_size * index);
6135         if (objmask) {
6136                 ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
6137                 item->mask = ctx->objmask;
6138         } else
6139                 ctx->objmask = NULL;
6140         /* Update relevant item pointer. */
6141         *((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
6142                 ctx->object;
6143         return len;
6144 }
6145
6146 /** Parse action configuration field. */
6147 static int
6148 parse_vc_conf(struct context *ctx, const struct token *token,
6149               const char *str, unsigned int len,
6150               void *buf, unsigned int size)
6151 {
6152         struct buffer *out = buf;
6153
6154         (void)size;
6155         /* Token name must match. */
6156         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6157                 return -1;
6158         /* Nothing else to do if there is no buffer. */
6159         if (!out)
6160                 return len;
6161         /* Point to selected object. */
6162         ctx->object = out->args.vc.data;
6163         ctx->objmask = NULL;
6164         return len;
6165 }
6166
6167 /** Parse eCPRI common header type field. */
6168 static int
6169 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
6170                          const char *str, unsigned int len,
6171                          void *buf, unsigned int size)
6172 {
6173         struct rte_flow_item_ecpri *ecpri;
6174         struct rte_flow_item_ecpri *ecpri_mask;
6175         struct rte_flow_item *item;
6176         uint32_t data_size;
6177         uint8_t msg_type;
6178         struct buffer *out = buf;
6179         const struct arg *arg;
6180
6181         (void)size;
6182         /* Token name must match. */
6183         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6184                 return -1;
6185         switch (ctx->curr) {
6186         case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
6187                 msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
6188                 break;
6189         case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
6190                 msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
6191                 break;
6192         case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
6193                 msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
6194                 break;
6195         default:
6196                 return -1;
6197         }
6198         if (!ctx->object)
6199                 return len;
6200         arg = pop_args(ctx);
6201         if (!arg)
6202                 return -1;
6203         ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
6204         ecpri->hdr.common.type = msg_type;
6205         data_size = ctx->objdata / 3; /* spec, last, mask */
6206         ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
6207                                                     (data_size * 2));
6208         ecpri_mask->hdr.common.type = 0xFF;
6209         if (arg->hton) {
6210                 ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
6211                 ecpri_mask->hdr.common.u32 =
6212                                 rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
6213         }
6214         item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
6215         item->spec = ecpri;
6216         item->mask = ecpri_mask;
6217         return len;
6218 }
6219
6220 /** Parse L2TPv2 common header type field. */
6221 static int
6222 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
6223                          const char *str, unsigned int len,
6224                          void *buf, unsigned int size)
6225 {
6226         struct rte_flow_item_l2tpv2 *l2tpv2;
6227         struct rte_flow_item_l2tpv2 *l2tpv2_mask;
6228         struct rte_flow_item *item;
6229         uint32_t data_size;
6230         uint16_t msg_type = 0;
6231         struct buffer *out = buf;
6232         const struct arg *arg;
6233
6234         (void)size;
6235         /* Token name must match. */
6236         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6237                 return -1;
6238         switch (ctx->curr) {
6239         case ITEM_L2TPV2_TYPE_DATA:
6240                 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
6241                 break;
6242         case ITEM_L2TPV2_TYPE_DATA_L:
6243                 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
6244                 break;
6245         case ITEM_L2TPV2_TYPE_DATA_S:
6246                 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
6247                 break;
6248         case ITEM_L2TPV2_TYPE_DATA_O:
6249                 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
6250                 break;
6251         case ITEM_L2TPV2_TYPE_DATA_L_S:
6252                 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
6253                 break;
6254         case ITEM_L2TPV2_TYPE_CTRL:
6255                 msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
6256                 break;
6257         default:
6258                 return -1;
6259         }
6260         if (!ctx->object)
6261                 return len;
6262         arg = pop_args(ctx);
6263         if (!arg)
6264                 return -1;
6265         l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
6266         l2tpv2->hdr.common.flags_version |= msg_type;
6267         data_size = ctx->objdata / 3; /* spec, last, mask */
6268         l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
6269                                                     (data_size * 2));
6270         l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
6271         if (arg->hton) {
6272                 l2tpv2->hdr.common.flags_version =
6273                         rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
6274                 l2tpv2_mask->hdr.common.flags_version =
6275                     rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
6276         }
6277         item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
6278         item->spec = l2tpv2;
6279         item->mask = l2tpv2_mask;
6280         return len;
6281 }
6282
6283 /** Parse meter color action type. */
6284 static int
6285 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
6286                                 const char *str, unsigned int len,
6287                                 void *buf, unsigned int size)
6288 {
6289         struct rte_flow_action *action_data;
6290         struct rte_flow_action_meter_color *conf;
6291         enum rte_color color;
6292
6293         (void)buf;
6294         (void)size;
6295         /* Token name must match. */
6296         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6297                 return -1;
6298         switch (ctx->curr) {
6299         case ACTION_METER_COLOR_GREEN:
6300                 color = RTE_COLOR_GREEN;
6301         break;
6302         case ACTION_METER_COLOR_YELLOW:
6303                 color = RTE_COLOR_YELLOW;
6304         break;
6305         case ACTION_METER_COLOR_RED:
6306                 color = RTE_COLOR_RED;
6307         break;
6308         default:
6309                 return -1;
6310         }
6311
6312         if (!ctx->object)
6313                 return len;
6314         action_data = ctx->object;
6315         conf = (struct rte_flow_action_meter_color *)
6316                                         (uintptr_t)(action_data->conf);
6317         conf->color = color;
6318         return len;
6319 }
6320
6321 /** Parse RSS action. */
6322 static int
6323 parse_vc_action_rss(struct context *ctx, const struct token *token,
6324                     const char *str, unsigned int len,
6325                     void *buf, unsigned int size)
6326 {
6327         struct buffer *out = buf;
6328         struct rte_flow_action *action;
6329         struct action_rss_data *action_rss_data;
6330         unsigned int i;
6331         int ret;
6332
6333         ret = parse_vc(ctx, token, str, len, buf, size);
6334         if (ret < 0)
6335                 return ret;
6336         /* Nothing else to do if there is no buffer. */
6337         if (!out)
6338                 return ret;
6339         if (!out->args.vc.actions_n)
6340                 return -1;
6341         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6342         /* Point to selected object. */
6343         ctx->object = out->args.vc.data;
6344         ctx->objmask = NULL;
6345         /* Set up default configuration. */
6346         action_rss_data = ctx->object;
6347         *action_rss_data = (struct action_rss_data){
6348                 .conf = (struct rte_flow_action_rss){
6349                         .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
6350                         .level = 0,
6351                         .types = rss_hf,
6352                         .key_len = 0,
6353                         .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
6354                         .key = NULL,
6355                         .queue = action_rss_data->queue,
6356                 },
6357                 .queue = { 0 },
6358         };
6359         for (i = 0; i < action_rss_data->conf.queue_num; ++i)
6360                 action_rss_data->queue[i] = i;
6361         action->conf = &action_rss_data->conf;
6362         return ret;
6363 }
6364
6365 /**
6366  * Parse func field for RSS action.
6367  *
6368  * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
6369  * ACTION_RSS_FUNC_* index that called this function.
6370  */
6371 static int
6372 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
6373                          const char *str, unsigned int len,
6374                          void *buf, unsigned int size)
6375 {
6376         struct action_rss_data *action_rss_data;
6377         enum rte_eth_hash_function func;
6378
6379         (void)buf;
6380         (void)size;
6381         /* Token name must match. */
6382         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6383                 return -1;
6384         switch (ctx->curr) {
6385         case ACTION_RSS_FUNC_DEFAULT:
6386                 func = RTE_ETH_HASH_FUNCTION_DEFAULT;
6387                 break;
6388         case ACTION_RSS_FUNC_TOEPLITZ:
6389                 func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
6390                 break;
6391         case ACTION_RSS_FUNC_SIMPLE_XOR:
6392                 func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
6393                 break;
6394         case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
6395                 func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
6396                 break;
6397         default:
6398                 return -1;
6399         }
6400         if (!ctx->object)
6401                 return len;
6402         action_rss_data = ctx->object;
6403         action_rss_data->conf.func = func;
6404         return len;
6405 }
6406
6407 /**
6408  * Parse type field for RSS action.
6409  *
6410  * Valid tokens are type field names and the "end" token.
6411  */
6412 static int
6413 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
6414                           const char *str, unsigned int len,
6415                           void *buf, unsigned int size)
6416 {
6417         static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
6418         struct action_rss_data *action_rss_data;
6419         unsigned int i;
6420
6421         (void)token;
6422         (void)buf;
6423         (void)size;
6424         if (ctx->curr != ACTION_RSS_TYPE)
6425                 return -1;
6426         if (!(ctx->objdata >> 16) && ctx->object) {
6427                 action_rss_data = ctx->object;
6428                 action_rss_data->conf.types = 0;
6429         }
6430         if (!strcmp_partial("end", str, len)) {
6431                 ctx->objdata &= 0xffff;
6432                 return len;
6433         }
6434         for (i = 0; rss_type_table[i].str; ++i)
6435                 if (!strcmp_partial(rss_type_table[i].str, str, len))
6436                         break;
6437         if (!rss_type_table[i].str)
6438                 return -1;
6439         ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
6440         /* Repeat token. */
6441         if (ctx->next_num == RTE_DIM(ctx->next))
6442                 return -1;
6443         ctx->next[ctx->next_num++] = next;
6444         if (!ctx->object)
6445                 return len;
6446         action_rss_data = ctx->object;
6447         action_rss_data->conf.types |= rss_type_table[i].rss_type;
6448         return len;
6449 }
6450
6451 /**
6452  * Parse queue field for RSS action.
6453  *
6454  * Valid tokens are queue indices and the "end" token.
6455  */
6456 static int
6457 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
6458                           const char *str, unsigned int len,
6459                           void *buf, unsigned int size)
6460 {
6461         static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
6462         struct action_rss_data *action_rss_data;
6463         const struct arg *arg;
6464         int ret;
6465         int i;
6466
6467         (void)token;
6468         (void)buf;
6469         (void)size;
6470         if (ctx->curr != ACTION_RSS_QUEUE)
6471                 return -1;
6472         i = ctx->objdata >> 16;
6473         if (!strcmp_partial("end", str, len)) {
6474                 ctx->objdata &= 0xffff;
6475                 goto end;
6476         }
6477         if (i >= ACTION_RSS_QUEUE_NUM)
6478                 return -1;
6479         arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
6480                              i * sizeof(action_rss_data->queue[i]),
6481                              sizeof(action_rss_data->queue[i]));
6482         if (push_args(ctx, arg))
6483                 return -1;
6484         ret = parse_int(ctx, token, str, len, NULL, 0);
6485         if (ret < 0) {
6486                 pop_args(ctx);
6487                 return -1;
6488         }
6489         ++i;
6490         ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
6491         /* Repeat token. */
6492         if (ctx->next_num == RTE_DIM(ctx->next))
6493                 return -1;
6494         ctx->next[ctx->next_num++] = next;
6495 end:
6496         if (!ctx->object)
6497                 return len;
6498         action_rss_data = ctx->object;
6499         action_rss_data->conf.queue_num = i;
6500         action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
6501         return len;
6502 }
6503
6504 /** Setup VXLAN encap configuration. */
6505 static int
6506 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
6507 {
6508         /* Set up default configuration. */
6509         *action_vxlan_encap_data = (struct action_vxlan_encap_data){
6510                 .conf = (struct rte_flow_action_vxlan_encap){
6511                         .definition = action_vxlan_encap_data->items,
6512                 },
6513                 .items = {
6514                         {
6515                                 .type = RTE_FLOW_ITEM_TYPE_ETH,
6516                                 .spec = &action_vxlan_encap_data->item_eth,
6517                                 .mask = &rte_flow_item_eth_mask,
6518                         },
6519                         {
6520                                 .type = RTE_FLOW_ITEM_TYPE_VLAN,
6521                                 .spec = &action_vxlan_encap_data->item_vlan,
6522                                 .mask = &rte_flow_item_vlan_mask,
6523                         },
6524                         {
6525                                 .type = RTE_FLOW_ITEM_TYPE_IPV4,
6526                                 .spec = &action_vxlan_encap_data->item_ipv4,
6527                                 .mask = &rte_flow_item_ipv4_mask,
6528                         },
6529                         {
6530                                 .type = RTE_FLOW_ITEM_TYPE_UDP,
6531                                 .spec = &action_vxlan_encap_data->item_udp,
6532                                 .mask = &rte_flow_item_udp_mask,
6533                         },
6534                         {
6535                                 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
6536                                 .spec = &action_vxlan_encap_data->item_vxlan,
6537                                 .mask = &rte_flow_item_vxlan_mask,
6538                         },
6539                         {
6540                                 .type = RTE_FLOW_ITEM_TYPE_END,
6541                         },
6542                 },
6543                 .item_eth.type = 0,
6544                 .item_vlan = {
6545                         .tci = vxlan_encap_conf.vlan_tci,
6546                         .inner_type = 0,
6547                 },
6548                 .item_ipv4.hdr = {
6549                         .src_addr = vxlan_encap_conf.ipv4_src,
6550                         .dst_addr = vxlan_encap_conf.ipv4_dst,
6551                 },
6552                 .item_udp.hdr = {
6553                         .src_port = vxlan_encap_conf.udp_src,
6554                         .dst_port = vxlan_encap_conf.udp_dst,
6555                 },
6556                 .item_vxlan.flags = 0,
6557         };
6558         memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes,
6559                vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6560         memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
6561                vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6562         if (!vxlan_encap_conf.select_ipv4) {
6563                 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
6564                        &vxlan_encap_conf.ipv6_src,
6565                        sizeof(vxlan_encap_conf.ipv6_src));
6566                 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
6567                        &vxlan_encap_conf.ipv6_dst,
6568                        sizeof(vxlan_encap_conf.ipv6_dst));
6569                 action_vxlan_encap_data->items[2] = (struct rte_flow_item){
6570                         .type = RTE_FLOW_ITEM_TYPE_IPV6,
6571                         .spec = &action_vxlan_encap_data->item_ipv6,
6572                         .mask = &rte_flow_item_ipv6_mask,
6573                 };
6574         }
6575         if (!vxlan_encap_conf.select_vlan)
6576                 action_vxlan_encap_data->items[1].type =
6577                         RTE_FLOW_ITEM_TYPE_VOID;
6578         if (vxlan_encap_conf.select_tos_ttl) {
6579                 if (vxlan_encap_conf.select_ipv4) {
6580                         static struct rte_flow_item_ipv4 ipv4_mask_tos;
6581
6582                         memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
6583                                sizeof(ipv4_mask_tos));
6584                         ipv4_mask_tos.hdr.type_of_service = 0xff;
6585                         ipv4_mask_tos.hdr.time_to_live = 0xff;
6586                         action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
6587                                         vxlan_encap_conf.ip_tos;
6588                         action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
6589                                         vxlan_encap_conf.ip_ttl;
6590                         action_vxlan_encap_data->items[2].mask =
6591                                                         &ipv4_mask_tos;
6592                 } else {
6593                         static struct rte_flow_item_ipv6 ipv6_mask_tos;
6594
6595                         memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
6596                                sizeof(ipv6_mask_tos));
6597                         ipv6_mask_tos.hdr.vtc_flow |=
6598                                 RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
6599                         ipv6_mask_tos.hdr.hop_limits = 0xff;
6600                         action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
6601                                 rte_cpu_to_be_32
6602                                         ((uint32_t)vxlan_encap_conf.ip_tos <<
6603                                          RTE_IPV6_HDR_TC_SHIFT);
6604                         action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
6605                                         vxlan_encap_conf.ip_ttl;
6606                         action_vxlan_encap_data->items[2].mask =
6607                                                         &ipv6_mask_tos;
6608                 }
6609         }
6610         memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
6611                RTE_DIM(vxlan_encap_conf.vni));
6612         return 0;
6613 }
6614
6615 /** Parse VXLAN encap action. */
6616 static int
6617 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
6618                             const char *str, unsigned int len,
6619                             void *buf, unsigned int size)
6620 {
6621         struct buffer *out = buf;
6622         struct rte_flow_action *action;
6623         struct action_vxlan_encap_data *action_vxlan_encap_data;
6624         int ret;
6625
6626         ret = parse_vc(ctx, token, str, len, buf, size);
6627         if (ret < 0)
6628                 return ret;
6629         /* Nothing else to do if there is no buffer. */
6630         if (!out)
6631                 return ret;
6632         if (!out->args.vc.actions_n)
6633                 return -1;
6634         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6635         /* Point to selected object. */
6636         ctx->object = out->args.vc.data;
6637         ctx->objmask = NULL;
6638         action_vxlan_encap_data = ctx->object;
6639         parse_setup_vxlan_encap_data(action_vxlan_encap_data);
6640         action->conf = &action_vxlan_encap_data->conf;
6641         return ret;
6642 }
6643
6644 /** Setup NVGRE encap configuration. */
6645 static int
6646 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
6647 {
6648         /* Set up default configuration. */
6649         *action_nvgre_encap_data = (struct action_nvgre_encap_data){
6650                 .conf = (struct rte_flow_action_nvgre_encap){
6651                         .definition = action_nvgre_encap_data->items,
6652                 },
6653                 .items = {
6654                         {
6655                                 .type = RTE_FLOW_ITEM_TYPE_ETH,
6656                                 .spec = &action_nvgre_encap_data->item_eth,
6657                                 .mask = &rte_flow_item_eth_mask,
6658                         },
6659                         {
6660                                 .type = RTE_FLOW_ITEM_TYPE_VLAN,
6661                                 .spec = &action_nvgre_encap_data->item_vlan,
6662                                 .mask = &rte_flow_item_vlan_mask,
6663                         },
6664                         {
6665                                 .type = RTE_FLOW_ITEM_TYPE_IPV4,
6666                                 .spec = &action_nvgre_encap_data->item_ipv4,
6667                                 .mask = &rte_flow_item_ipv4_mask,
6668                         },
6669                         {
6670                                 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
6671                                 .spec = &action_nvgre_encap_data->item_nvgre,
6672                                 .mask = &rte_flow_item_nvgre_mask,
6673                         },
6674                         {
6675                                 .type = RTE_FLOW_ITEM_TYPE_END,
6676                         },
6677                 },
6678                 .item_eth.type = 0,
6679                 .item_vlan = {
6680                         .tci = nvgre_encap_conf.vlan_tci,
6681                         .inner_type = 0,
6682                 },
6683                 .item_ipv4.hdr = {
6684                        .src_addr = nvgre_encap_conf.ipv4_src,
6685                        .dst_addr = nvgre_encap_conf.ipv4_dst,
6686                 },
6687                 .item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
6688                 .item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
6689                 .item_nvgre.flow_id = 0,
6690         };
6691         memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
6692                nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6693         memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
6694                nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6695         if (!nvgre_encap_conf.select_ipv4) {
6696                 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
6697                        &nvgre_encap_conf.ipv6_src,
6698                        sizeof(nvgre_encap_conf.ipv6_src));
6699                 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
6700                        &nvgre_encap_conf.ipv6_dst,
6701                        sizeof(nvgre_encap_conf.ipv6_dst));
6702                 action_nvgre_encap_data->items[2] = (struct rte_flow_item){
6703                         .type = RTE_FLOW_ITEM_TYPE_IPV6,
6704                         .spec = &action_nvgre_encap_data->item_ipv6,
6705                         .mask = &rte_flow_item_ipv6_mask,
6706                 };
6707         }
6708         if (!nvgre_encap_conf.select_vlan)
6709                 action_nvgre_encap_data->items[1].type =
6710                         RTE_FLOW_ITEM_TYPE_VOID;
6711         memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
6712                RTE_DIM(nvgre_encap_conf.tni));
6713         return 0;
6714 }
6715
6716 /** Parse NVGRE encap action. */
6717 static int
6718 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
6719                             const char *str, unsigned int len,
6720                             void *buf, unsigned int size)
6721 {
6722         struct buffer *out = buf;
6723         struct rte_flow_action *action;
6724         struct action_nvgre_encap_data *action_nvgre_encap_data;
6725         int ret;
6726
6727         ret = parse_vc(ctx, token, str, len, buf, size);
6728         if (ret < 0)
6729                 return ret;
6730         /* Nothing else to do if there is no buffer. */
6731         if (!out)
6732                 return ret;
6733         if (!out->args.vc.actions_n)
6734                 return -1;
6735         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6736         /* Point to selected object. */
6737         ctx->object = out->args.vc.data;
6738         ctx->objmask = NULL;
6739         action_nvgre_encap_data = ctx->object;
6740         parse_setup_nvgre_encap_data(action_nvgre_encap_data);
6741         action->conf = &action_nvgre_encap_data->conf;
6742         return ret;
6743 }
6744
6745 /** Parse l2 encap action. */
6746 static int
6747 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
6748                          const char *str, unsigned int len,
6749                          void *buf, unsigned int size)
6750 {
6751         struct buffer *out = buf;
6752         struct rte_flow_action *action;
6753         struct action_raw_encap_data *action_encap_data;
6754         struct rte_flow_item_eth eth = { .type = 0, };
6755         struct rte_flow_item_vlan vlan = {
6756                 .tci = mplsoudp_encap_conf.vlan_tci,
6757                 .inner_type = 0,
6758         };
6759         uint8_t *header;
6760         int ret;
6761
6762         ret = parse_vc(ctx, token, str, len, buf, size);
6763         if (ret < 0)
6764                 return ret;
6765         /* Nothing else to do if there is no buffer. */
6766         if (!out)
6767                 return ret;
6768         if (!out->args.vc.actions_n)
6769                 return -1;
6770         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6771         /* Point to selected object. */
6772         ctx->object = out->args.vc.data;
6773         ctx->objmask = NULL;
6774         /* Copy the headers to the buffer. */
6775         action_encap_data = ctx->object;
6776         *action_encap_data = (struct action_raw_encap_data) {
6777                 .conf = (struct rte_flow_action_raw_encap){
6778                         .data = action_encap_data->data,
6779                 },
6780                 .data = {},
6781         };
6782         header = action_encap_data->data;
6783         if (l2_encap_conf.select_vlan)
6784                 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6785         else if (l2_encap_conf.select_ipv4)
6786                 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6787         else
6788                 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6789         memcpy(eth.dst.addr_bytes,
6790                l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6791         memcpy(eth.src.addr_bytes,
6792                l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6793         memcpy(header, &eth, sizeof(eth));
6794         header += sizeof(eth);
6795         if (l2_encap_conf.select_vlan) {
6796                 if (l2_encap_conf.select_ipv4)
6797                         vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6798                 else
6799                         vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6800                 memcpy(header, &vlan, sizeof(vlan));
6801                 header += sizeof(vlan);
6802         }
6803         action_encap_data->conf.size = header -
6804                 action_encap_data->data;
6805         action->conf = &action_encap_data->conf;
6806         return ret;
6807 }
6808
6809 /** Parse l2 decap action. */
6810 static int
6811 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
6812                          const char *str, unsigned int len,
6813                          void *buf, unsigned int size)
6814 {
6815         struct buffer *out = buf;
6816         struct rte_flow_action *action;
6817         struct action_raw_decap_data *action_decap_data;
6818         struct rte_flow_item_eth eth = { .type = 0, };
6819         struct rte_flow_item_vlan vlan = {
6820                 .tci = mplsoudp_encap_conf.vlan_tci,
6821                 .inner_type = 0,
6822         };
6823         uint8_t *header;
6824         int ret;
6825
6826         ret = parse_vc(ctx, token, str, len, buf, size);
6827         if (ret < 0)
6828                 return ret;
6829         /* Nothing else to do if there is no buffer. */
6830         if (!out)
6831                 return ret;
6832         if (!out->args.vc.actions_n)
6833                 return -1;
6834         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6835         /* Point to selected object. */
6836         ctx->object = out->args.vc.data;
6837         ctx->objmask = NULL;
6838         /* Copy the headers to the buffer. */
6839         action_decap_data = ctx->object;
6840         *action_decap_data = (struct action_raw_decap_data) {
6841                 .conf = (struct rte_flow_action_raw_decap){
6842                         .data = action_decap_data->data,
6843                 },
6844                 .data = {},
6845         };
6846         header = action_decap_data->data;
6847         if (l2_decap_conf.select_vlan)
6848                 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6849         memcpy(header, &eth, sizeof(eth));
6850         header += sizeof(eth);
6851         if (l2_decap_conf.select_vlan) {
6852                 memcpy(header, &vlan, sizeof(vlan));
6853                 header += sizeof(vlan);
6854         }
6855         action_decap_data->conf.size = header -
6856                 action_decap_data->data;
6857         action->conf = &action_decap_data->conf;
6858         return ret;
6859 }
6860
6861 #define ETHER_TYPE_MPLS_UNICAST 0x8847
6862
6863 /** Parse MPLSOGRE encap action. */
6864 static int
6865 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
6866                                const char *str, unsigned int len,
6867                                void *buf, unsigned int size)
6868 {
6869         struct buffer *out = buf;
6870         struct rte_flow_action *action;
6871         struct action_raw_encap_data *action_encap_data;
6872         struct rte_flow_item_eth eth = { .type = 0, };
6873         struct rte_flow_item_vlan vlan = {
6874                 .tci = mplsogre_encap_conf.vlan_tci,
6875                 .inner_type = 0,
6876         };
6877         struct rte_flow_item_ipv4 ipv4 = {
6878                 .hdr =  {
6879                         .src_addr = mplsogre_encap_conf.ipv4_src,
6880                         .dst_addr = mplsogre_encap_conf.ipv4_dst,
6881                         .next_proto_id = IPPROTO_GRE,
6882                         .version_ihl = RTE_IPV4_VHL_DEF,
6883                         .time_to_live = IPDEFTTL,
6884                 },
6885         };
6886         struct rte_flow_item_ipv6 ipv6 = {
6887                 .hdr =  {
6888                         .proto = IPPROTO_GRE,
6889                         .hop_limits = IPDEFTTL,
6890                 },
6891         };
6892         struct rte_flow_item_gre gre = {
6893                 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
6894         };
6895         struct rte_flow_item_mpls mpls = {
6896                 .ttl = 0,
6897         };
6898         uint8_t *header;
6899         int ret;
6900
6901         ret = parse_vc(ctx, token, str, len, buf, size);
6902         if (ret < 0)
6903                 return ret;
6904         /* Nothing else to do if there is no buffer. */
6905         if (!out)
6906                 return ret;
6907         if (!out->args.vc.actions_n)
6908                 return -1;
6909         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6910         /* Point to selected object. */
6911         ctx->object = out->args.vc.data;
6912         ctx->objmask = NULL;
6913         /* Copy the headers to the buffer. */
6914         action_encap_data = ctx->object;
6915         *action_encap_data = (struct action_raw_encap_data) {
6916                 .conf = (struct rte_flow_action_raw_encap){
6917                         .data = action_encap_data->data,
6918                 },
6919                 .data = {},
6920                 .preserve = {},
6921         };
6922         header = action_encap_data->data;
6923         if (mplsogre_encap_conf.select_vlan)
6924                 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6925         else if (mplsogre_encap_conf.select_ipv4)
6926                 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6927         else
6928                 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6929         memcpy(eth.dst.addr_bytes,
6930                mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6931         memcpy(eth.src.addr_bytes,
6932                mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6933         memcpy(header, &eth, sizeof(eth));
6934         header += sizeof(eth);
6935         if (mplsogre_encap_conf.select_vlan) {
6936                 if (mplsogre_encap_conf.select_ipv4)
6937                         vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6938                 else
6939                         vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6940                 memcpy(header, &vlan, sizeof(vlan));
6941                 header += sizeof(vlan);
6942         }
6943         if (mplsogre_encap_conf.select_ipv4) {
6944                 memcpy(header, &ipv4, sizeof(ipv4));
6945                 header += sizeof(ipv4);
6946         } else {
6947                 memcpy(&ipv6.hdr.src_addr,
6948                        &mplsogre_encap_conf.ipv6_src,
6949                        sizeof(mplsogre_encap_conf.ipv6_src));
6950                 memcpy(&ipv6.hdr.dst_addr,
6951                        &mplsogre_encap_conf.ipv6_dst,
6952                        sizeof(mplsogre_encap_conf.ipv6_dst));
6953                 memcpy(header, &ipv6, sizeof(ipv6));
6954                 header += sizeof(ipv6);
6955         }
6956         memcpy(header, &gre, sizeof(gre));
6957         header += sizeof(gre);
6958         memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
6959                RTE_DIM(mplsogre_encap_conf.label));
6960         mpls.label_tc_s[2] |= 0x1;
6961         memcpy(header, &mpls, sizeof(mpls));
6962         header += sizeof(mpls);
6963         action_encap_data->conf.size = header -
6964                 action_encap_data->data;
6965         action->conf = &action_encap_data->conf;
6966         return ret;
6967 }
6968
6969 /** Parse MPLSOGRE decap action. */
6970 static int
6971 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
6972                                const char *str, unsigned int len,
6973                                void *buf, unsigned int size)
6974 {
6975         struct buffer *out = buf;
6976         struct rte_flow_action *action;
6977         struct action_raw_decap_data *action_decap_data;
6978         struct rte_flow_item_eth eth = { .type = 0, };
6979         struct rte_flow_item_vlan vlan = {.tci = 0};
6980         struct rte_flow_item_ipv4 ipv4 = {
6981                 .hdr =  {
6982                         .next_proto_id = IPPROTO_GRE,
6983                 },
6984         };
6985         struct rte_flow_item_ipv6 ipv6 = {
6986                 .hdr =  {
6987                         .proto = IPPROTO_GRE,
6988                 },
6989         };
6990         struct rte_flow_item_gre gre = {
6991                 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
6992         };
6993         struct rte_flow_item_mpls mpls;
6994         uint8_t *header;
6995         int ret;
6996
6997         ret = parse_vc(ctx, token, str, len, buf, size);
6998         if (ret < 0)
6999                 return ret;
7000         /* Nothing else to do if there is no buffer. */
7001         if (!out)
7002                 return ret;
7003         if (!out->args.vc.actions_n)
7004                 return -1;
7005         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7006         /* Point to selected object. */
7007         ctx->object = out->args.vc.data;
7008         ctx->objmask = NULL;
7009         /* Copy the headers to the buffer. */
7010         action_decap_data = ctx->object;
7011         *action_decap_data = (struct action_raw_decap_data) {
7012                 .conf = (struct rte_flow_action_raw_decap){
7013                         .data = action_decap_data->data,
7014                 },
7015                 .data = {},
7016         };
7017         header = action_decap_data->data;
7018         if (mplsogre_decap_conf.select_vlan)
7019                 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7020         else if (mplsogre_encap_conf.select_ipv4)
7021                 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7022         else
7023                 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7024         memcpy(eth.dst.addr_bytes,
7025                mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7026         memcpy(eth.src.addr_bytes,
7027                mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7028         memcpy(header, &eth, sizeof(eth));
7029         header += sizeof(eth);
7030         if (mplsogre_encap_conf.select_vlan) {
7031                 if (mplsogre_encap_conf.select_ipv4)
7032                         vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7033                 else
7034                         vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7035                 memcpy(header, &vlan, sizeof(vlan));
7036                 header += sizeof(vlan);
7037         }
7038         if (mplsogre_encap_conf.select_ipv4) {
7039                 memcpy(header, &ipv4, sizeof(ipv4));
7040                 header += sizeof(ipv4);
7041         } else {
7042                 memcpy(header, &ipv6, sizeof(ipv6));
7043                 header += sizeof(ipv6);
7044         }
7045         memcpy(header, &gre, sizeof(gre));
7046         header += sizeof(gre);
7047         memset(&mpls, 0, sizeof(mpls));
7048         memcpy(header, &mpls, sizeof(mpls));
7049         header += sizeof(mpls);
7050         action_decap_data->conf.size = header -
7051                 action_decap_data->data;
7052         action->conf = &action_decap_data->conf;
7053         return ret;
7054 }
7055
7056 /** Parse MPLSOUDP encap action. */
7057 static int
7058 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
7059                                const char *str, unsigned int len,
7060                                void *buf, unsigned int size)
7061 {
7062         struct buffer *out = buf;
7063         struct rte_flow_action *action;
7064         struct action_raw_encap_data *action_encap_data;
7065         struct rte_flow_item_eth eth = { .type = 0, };
7066         struct rte_flow_item_vlan vlan = {
7067                 .tci = mplsoudp_encap_conf.vlan_tci,
7068                 .inner_type = 0,
7069         };
7070         struct rte_flow_item_ipv4 ipv4 = {
7071                 .hdr =  {
7072                         .src_addr = mplsoudp_encap_conf.ipv4_src,
7073                         .dst_addr = mplsoudp_encap_conf.ipv4_dst,
7074                         .next_proto_id = IPPROTO_UDP,
7075                         .version_ihl = RTE_IPV4_VHL_DEF,
7076                         .time_to_live = IPDEFTTL,
7077                 },
7078         };
7079         struct rte_flow_item_ipv6 ipv6 = {
7080                 .hdr =  {
7081                         .proto = IPPROTO_UDP,
7082                         .hop_limits = IPDEFTTL,
7083                 },
7084         };
7085         struct rte_flow_item_udp udp = {
7086                 .hdr = {
7087                         .src_port = mplsoudp_encap_conf.udp_src,
7088                         .dst_port = mplsoudp_encap_conf.udp_dst,
7089                 },
7090         };
7091         struct rte_flow_item_mpls mpls;
7092         uint8_t *header;
7093         int ret;
7094
7095         ret = parse_vc(ctx, token, str, len, buf, size);
7096         if (ret < 0)
7097                 return ret;
7098         /* Nothing else to do if there is no buffer. */
7099         if (!out)
7100                 return ret;
7101         if (!out->args.vc.actions_n)
7102                 return -1;
7103         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7104         /* Point to selected object. */
7105         ctx->object = out->args.vc.data;
7106         ctx->objmask = NULL;
7107         /* Copy the headers to the buffer. */
7108         action_encap_data = ctx->object;
7109         *action_encap_data = (struct action_raw_encap_data) {
7110                 .conf = (struct rte_flow_action_raw_encap){
7111                         .data = action_encap_data->data,
7112                 },
7113                 .data = {},
7114                 .preserve = {},
7115         };
7116         header = action_encap_data->data;
7117         if (mplsoudp_encap_conf.select_vlan)
7118                 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7119         else if (mplsoudp_encap_conf.select_ipv4)
7120                 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7121         else
7122                 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7123         memcpy(eth.dst.addr_bytes,
7124                mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7125         memcpy(eth.src.addr_bytes,
7126                mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7127         memcpy(header, &eth, sizeof(eth));
7128         header += sizeof(eth);
7129         if (mplsoudp_encap_conf.select_vlan) {
7130                 if (mplsoudp_encap_conf.select_ipv4)
7131                         vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7132                 else
7133                         vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7134                 memcpy(header, &vlan, sizeof(vlan));
7135                 header += sizeof(vlan);
7136         }
7137         if (mplsoudp_encap_conf.select_ipv4) {
7138                 memcpy(header, &ipv4, sizeof(ipv4));
7139                 header += sizeof(ipv4);
7140         } else {
7141                 memcpy(&ipv6.hdr.src_addr,
7142                        &mplsoudp_encap_conf.ipv6_src,
7143                        sizeof(mplsoudp_encap_conf.ipv6_src));
7144                 memcpy(&ipv6.hdr.dst_addr,
7145                        &mplsoudp_encap_conf.ipv6_dst,
7146                        sizeof(mplsoudp_encap_conf.ipv6_dst));
7147                 memcpy(header, &ipv6, sizeof(ipv6));
7148                 header += sizeof(ipv6);
7149         }
7150         memcpy(header, &udp, sizeof(udp));
7151         header += sizeof(udp);
7152         memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
7153                RTE_DIM(mplsoudp_encap_conf.label));
7154         mpls.label_tc_s[2] |= 0x1;
7155         memcpy(header, &mpls, sizeof(mpls));
7156         header += sizeof(mpls);
7157         action_encap_data->conf.size = header -
7158                 action_encap_data->data;
7159         action->conf = &action_encap_data->conf;
7160         return ret;
7161 }
7162
7163 /** Parse MPLSOUDP decap action. */
7164 static int
7165 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
7166                                const char *str, unsigned int len,
7167                                void *buf, unsigned int size)
7168 {
7169         struct buffer *out = buf;
7170         struct rte_flow_action *action;
7171         struct action_raw_decap_data *action_decap_data;
7172         struct rte_flow_item_eth eth = { .type = 0, };
7173         struct rte_flow_item_vlan vlan = {.tci = 0};
7174         struct rte_flow_item_ipv4 ipv4 = {
7175                 .hdr =  {
7176                         .next_proto_id = IPPROTO_UDP,
7177                 },
7178         };
7179         struct rte_flow_item_ipv6 ipv6 = {
7180                 .hdr =  {
7181                         .proto = IPPROTO_UDP,
7182                 },
7183         };
7184         struct rte_flow_item_udp udp = {
7185                 .hdr = {
7186                         .dst_port = rte_cpu_to_be_16(6635),
7187                 },
7188         };
7189         struct rte_flow_item_mpls mpls;
7190         uint8_t *header;
7191         int ret;
7192
7193         ret = parse_vc(ctx, token, str, len, buf, size);
7194         if (ret < 0)
7195                 return ret;
7196         /* Nothing else to do if there is no buffer. */
7197         if (!out)
7198                 return ret;
7199         if (!out->args.vc.actions_n)
7200                 return -1;
7201         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7202         /* Point to selected object. */
7203         ctx->object = out->args.vc.data;
7204         ctx->objmask = NULL;
7205         /* Copy the headers to the buffer. */
7206         action_decap_data = ctx->object;
7207         *action_decap_data = (struct action_raw_decap_data) {
7208                 .conf = (struct rte_flow_action_raw_decap){
7209                         .data = action_decap_data->data,
7210                 },
7211                 .data = {},
7212         };
7213         header = action_decap_data->data;
7214         if (mplsoudp_decap_conf.select_vlan)
7215                 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7216         else if (mplsoudp_encap_conf.select_ipv4)
7217                 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7218         else
7219                 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7220         memcpy(eth.dst.addr_bytes,
7221                mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7222         memcpy(eth.src.addr_bytes,
7223                mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7224         memcpy(header, &eth, sizeof(eth));
7225         header += sizeof(eth);
7226         if (mplsoudp_encap_conf.select_vlan) {
7227                 if (mplsoudp_encap_conf.select_ipv4)
7228                         vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7229                 else
7230                         vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7231                 memcpy(header, &vlan, sizeof(vlan));
7232                 header += sizeof(vlan);
7233         }
7234         if (mplsoudp_encap_conf.select_ipv4) {
7235                 memcpy(header, &ipv4, sizeof(ipv4));
7236                 header += sizeof(ipv4);
7237         } else {
7238                 memcpy(header, &ipv6, sizeof(ipv6));
7239                 header += sizeof(ipv6);
7240         }
7241         memcpy(header, &udp, sizeof(udp));
7242         header += sizeof(udp);
7243         memset(&mpls, 0, sizeof(mpls));
7244         memcpy(header, &mpls, sizeof(mpls));
7245         header += sizeof(mpls);
7246         action_decap_data->conf.size = header -
7247                 action_decap_data->data;
7248         action->conf = &action_decap_data->conf;
7249         return ret;
7250 }
7251
7252 static int
7253 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
7254                                 const char *str, unsigned int len, void *buf,
7255                                 unsigned int size)
7256 {
7257         struct action_raw_decap_data *action_raw_decap_data;
7258         struct rte_flow_action *action;
7259         const struct arg *arg;
7260         struct buffer *out = buf;
7261         int ret;
7262         uint16_t idx;
7263
7264         RTE_SET_USED(token);
7265         RTE_SET_USED(buf);
7266         RTE_SET_USED(size);
7267         arg = ARGS_ENTRY_ARB_BOUNDED
7268                 (offsetof(struct action_raw_decap_data, idx),
7269                  sizeof(((struct action_raw_decap_data *)0)->idx),
7270                  0, RAW_ENCAP_CONFS_MAX_NUM - 1);
7271         if (push_args(ctx, arg))
7272                 return -1;
7273         ret = parse_int(ctx, token, str, len, NULL, 0);
7274         if (ret < 0) {
7275                 pop_args(ctx);
7276                 return -1;
7277         }
7278         if (!ctx->object)
7279                 return len;
7280         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7281         action_raw_decap_data = ctx->object;
7282         idx = action_raw_decap_data->idx;
7283         action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
7284         action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
7285         action->conf = &action_raw_decap_data->conf;
7286         return len;
7287 }
7288
7289
7290 static int
7291 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
7292                                 const char *str, unsigned int len, void *buf,
7293                                 unsigned int size)
7294 {
7295         struct action_raw_encap_data *action_raw_encap_data;
7296         struct rte_flow_action *action;
7297         const struct arg *arg;
7298         struct buffer *out = buf;
7299         int ret;
7300         uint16_t idx;
7301
7302         RTE_SET_USED(token);
7303         RTE_SET_USED(buf);
7304         RTE_SET_USED(size);
7305         if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
7306                 return -1;
7307         arg = ARGS_ENTRY_ARB_BOUNDED
7308                 (offsetof(struct action_raw_encap_data, idx),
7309                  sizeof(((struct action_raw_encap_data *)0)->idx),
7310                  0, RAW_ENCAP_CONFS_MAX_NUM - 1);
7311         if (push_args(ctx, arg))
7312                 return -1;
7313         ret = parse_int(ctx, token, str, len, NULL, 0);
7314         if (ret < 0) {
7315                 pop_args(ctx);
7316                 return -1;
7317         }
7318         if (!ctx->object)
7319                 return len;
7320         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7321         action_raw_encap_data = ctx->object;
7322         idx = action_raw_encap_data->idx;
7323         action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
7324         action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
7325         action_raw_encap_data->conf.preserve = NULL;
7326         action->conf = &action_raw_encap_data->conf;
7327         return len;
7328 }
7329
7330 static int
7331 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
7332                           const char *str, unsigned int len, void *buf,
7333                           unsigned int size)
7334 {
7335         struct buffer *out = buf;
7336         struct rte_flow_action *action;
7337         struct action_raw_encap_data *action_raw_encap_data = NULL;
7338         int ret;
7339
7340         ret = parse_vc(ctx, token, str, len, buf, size);
7341         if (ret < 0)
7342                 return ret;
7343         /* Nothing else to do if there is no buffer. */
7344         if (!out)
7345                 return ret;
7346         if (!out->args.vc.actions_n)
7347                 return -1;
7348         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7349         /* Point to selected object. */
7350         ctx->object = out->args.vc.data;
7351         ctx->objmask = NULL;
7352         /* Copy the headers to the buffer. */
7353         action_raw_encap_data = ctx->object;
7354         action_raw_encap_data->conf.data = raw_encap_confs[0].data;
7355         action_raw_encap_data->conf.preserve = NULL;
7356         action_raw_encap_data->conf.size = raw_encap_confs[0].size;
7357         action->conf = &action_raw_encap_data->conf;
7358         return ret;
7359 }
7360
7361 static int
7362 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
7363                           const char *str, unsigned int len, void *buf,
7364                           unsigned int size)
7365 {
7366         struct buffer *out = buf;
7367         struct rte_flow_action *action;
7368         struct action_raw_decap_data *action_raw_decap_data = NULL;
7369         int ret;
7370
7371         ret = parse_vc(ctx, token, str, len, buf, size);
7372         if (ret < 0)
7373                 return ret;
7374         /* Nothing else to do if there is no buffer. */
7375         if (!out)
7376                 return ret;
7377         if (!out->args.vc.actions_n)
7378                 return -1;
7379         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7380         /* Point to selected object. */
7381         ctx->object = out->args.vc.data;
7382         ctx->objmask = NULL;
7383         /* Copy the headers to the buffer. */
7384         action_raw_decap_data = ctx->object;
7385         action_raw_decap_data->conf.data = raw_decap_confs[0].data;
7386         action_raw_decap_data->conf.size = raw_decap_confs[0].size;
7387         action->conf = &action_raw_decap_data->conf;
7388         return ret;
7389 }
7390
7391 static int
7392 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
7393                          const char *str, unsigned int len, void *buf,
7394                          unsigned int size)
7395 {
7396         int ret;
7397
7398         ret = parse_vc(ctx, token, str, len, buf, size);
7399         if (ret < 0)
7400                 return ret;
7401         ret = rte_flow_dynf_metadata_register();
7402         if (ret < 0)
7403                 return -1;
7404         return len;
7405 }
7406
7407 static int
7408 parse_vc_action_sample(struct context *ctx, const struct token *token,
7409                          const char *str, unsigned int len, void *buf,
7410                          unsigned int size)
7411 {
7412         struct buffer *out = buf;
7413         struct rte_flow_action *action;
7414         struct action_sample_data *action_sample_data = NULL;
7415         static struct rte_flow_action end_action = {
7416                 RTE_FLOW_ACTION_TYPE_END, 0
7417         };
7418         int ret;
7419
7420         ret = parse_vc(ctx, token, str, len, buf, size);
7421         if (ret < 0)
7422                 return ret;
7423         /* Nothing else to do if there is no buffer. */
7424         if (!out)
7425                 return ret;
7426         if (!out->args.vc.actions_n)
7427                 return -1;
7428         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7429         /* Point to selected object. */
7430         ctx->object = out->args.vc.data;
7431         ctx->objmask = NULL;
7432         /* Copy the headers to the buffer. */
7433         action_sample_data = ctx->object;
7434         action_sample_data->conf.actions = &end_action;
7435         action->conf = &action_sample_data->conf;
7436         return ret;
7437 }
7438
7439 static int
7440 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
7441                                 const char *str, unsigned int len, void *buf,
7442                                 unsigned int size)
7443 {
7444         struct action_sample_data *action_sample_data;
7445         struct rte_flow_action *action;
7446         const struct arg *arg;
7447         struct buffer *out = buf;
7448         int ret;
7449         uint16_t idx;
7450
7451         RTE_SET_USED(token);
7452         RTE_SET_USED(buf);
7453         RTE_SET_USED(size);
7454         if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
7455                 return -1;
7456         arg = ARGS_ENTRY_ARB_BOUNDED
7457                 (offsetof(struct action_sample_data, idx),
7458                  sizeof(((struct action_sample_data *)0)->idx),
7459                  0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
7460         if (push_args(ctx, arg))
7461                 return -1;
7462         ret = parse_int(ctx, token, str, len, NULL, 0);
7463         if (ret < 0) {
7464                 pop_args(ctx);
7465                 return -1;
7466         }
7467         if (!ctx->object)
7468                 return len;
7469         action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7470         action_sample_data = ctx->object;
7471         idx = action_sample_data->idx;
7472         action_sample_data->conf.actions = raw_sample_confs[idx].data;
7473         action->conf = &action_sample_data->conf;
7474         return len;
7475 }
7476
7477 /** Parse operation for modify_field command. */
7478 static int
7479 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
7480                          const char *str, unsigned int len, void *buf,
7481                          unsigned int size)
7482 {
7483         struct rte_flow_action_modify_field *action_modify_field;
7484         unsigned int i;
7485
7486         (void)token;
7487         (void)buf;
7488         (void)size;
7489         if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
7490                 return -1;
7491         for (i = 0; modify_field_ops[i]; ++i)
7492                 if (!strcmp_partial(modify_field_ops[i], str, len))
7493                         break;
7494         if (!modify_field_ops[i])
7495                 return -1;
7496         if (!ctx->object)
7497                 return len;
7498         action_modify_field = ctx->object;
7499         action_modify_field->operation = (enum rte_flow_modify_op)i;
7500         return len;
7501 }
7502
7503 /** Parse id for modify_field command. */
7504 static int
7505 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
7506                          const char *str, unsigned int len, void *buf,
7507                          unsigned int size)
7508 {
7509         struct rte_flow_action_modify_field *action_modify_field;
7510         unsigned int i;
7511
7512         (void)token;
7513         (void)buf;
7514         (void)size;
7515         if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
7516                 ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
7517                 return -1;
7518         for (i = 0; modify_field_ids[i]; ++i)
7519                 if (!strcmp_partial(modify_field_ids[i], str, len))
7520                         break;
7521         if (!modify_field_ids[i])
7522                 return -1;
7523         if (!ctx->object)
7524                 return len;
7525         action_modify_field = ctx->object;
7526         if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
7527                 action_modify_field->dst.field = (enum rte_flow_field_id)i;
7528         else
7529                 action_modify_field->src.field = (enum rte_flow_field_id)i;
7530         return len;
7531 }
7532
7533 /** Parse the conntrack update, not a rte_flow_action. */
7534 static int
7535 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
7536                          const char *str, unsigned int len, void *buf,
7537                          unsigned int size)
7538 {
7539         struct buffer *out = buf;
7540         struct rte_flow_modify_conntrack *ct_modify = NULL;
7541
7542         (void)size;
7543         if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
7544             ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
7545                 return -1;
7546         /* Token name must match. */
7547         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7548                 return -1;
7549         /* Nothing else to do if there is no buffer. */
7550         if (!out)
7551                 return len;
7552         ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
7553         if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
7554                 ct_modify->new_ct.is_original_dir =
7555                                 conntrack_context.is_original_dir;
7556                 ct_modify->direction = 1;
7557         } else {
7558                 uint32_t old_dir;
7559
7560                 old_dir = ct_modify->new_ct.is_original_dir;
7561                 memcpy(&ct_modify->new_ct, &conntrack_context,
7562                        sizeof(conntrack_context));
7563                 ct_modify->new_ct.is_original_dir = old_dir;
7564                 ct_modify->state = 1;
7565         }
7566         return len;
7567 }
7568
7569 /** Parse tokens for destroy command. */
7570 static int
7571 parse_destroy(struct context *ctx, const struct token *token,
7572               const char *str, unsigned int len,
7573               void *buf, unsigned int size)
7574 {
7575         struct buffer *out = buf;
7576
7577         /* Token name must match. */
7578         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7579                 return -1;
7580         /* Nothing else to do if there is no buffer. */
7581         if (!out)
7582                 return len;
7583         if (!out->command) {
7584                 if (ctx->curr != DESTROY)
7585                         return -1;
7586                 if (sizeof(*out) > size)
7587                         return -1;
7588                 out->command = ctx->curr;
7589                 ctx->objdata = 0;
7590                 ctx->object = out;
7591                 ctx->objmask = NULL;
7592                 out->args.destroy.rule =
7593                         (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7594                                                sizeof(double));
7595                 return len;
7596         }
7597         if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
7598              sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
7599                 return -1;
7600         ctx->objdata = 0;
7601         ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
7602         ctx->objmask = NULL;
7603         return len;
7604 }
7605
7606 /** Parse tokens for flush command. */
7607 static int
7608 parse_flush(struct context *ctx, const struct token *token,
7609             const char *str, unsigned int len,
7610             void *buf, unsigned int size)
7611 {
7612         struct buffer *out = buf;
7613
7614         /* Token name must match. */
7615         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7616                 return -1;
7617         /* Nothing else to do if there is no buffer. */
7618         if (!out)
7619                 return len;
7620         if (!out->command) {
7621                 if (ctx->curr != FLUSH)
7622                         return -1;
7623                 if (sizeof(*out) > size)
7624                         return -1;
7625                 out->command = ctx->curr;
7626                 ctx->objdata = 0;
7627                 ctx->object = out;
7628                 ctx->objmask = NULL;
7629         }
7630         return len;
7631 }
7632
7633 /** Parse tokens for dump command. */
7634 static int
7635 parse_dump(struct context *ctx, const struct token *token,
7636             const char *str, unsigned int len,
7637             void *buf, unsigned int size)
7638 {
7639         struct buffer *out = buf;
7640
7641         /* Token name must match. */
7642         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7643                 return -1;
7644         /* Nothing else to do if there is no buffer. */
7645         if (!out)
7646                 return len;
7647         if (!out->command) {
7648                 if (ctx->curr != DUMP)
7649                         return -1;
7650                 if (sizeof(*out) > size)
7651                         return -1;
7652                 out->command = ctx->curr;
7653                 ctx->objdata = 0;
7654                 ctx->object = out;
7655                 ctx->objmask = NULL;
7656                 return len;
7657         }
7658         switch (ctx->curr) {
7659         case DUMP_ALL:
7660         case DUMP_ONE:
7661                 out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
7662                 out->command = ctx->curr;
7663                 ctx->objdata = 0;
7664                 ctx->object = out;
7665                 ctx->objmask = NULL;
7666                 return len;
7667         default:
7668                 return -1;
7669         }
7670 }
7671
7672 /** Parse tokens for query command. */
7673 static int
7674 parse_query(struct context *ctx, const struct token *token,
7675             const char *str, unsigned int len,
7676             void *buf, unsigned int size)
7677 {
7678         struct buffer *out = buf;
7679
7680         /* Token name must match. */
7681         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7682                 return -1;
7683         /* Nothing else to do if there is no buffer. */
7684         if (!out)
7685                 return len;
7686         if (!out->command) {
7687                 if (ctx->curr != QUERY)
7688                         return -1;
7689                 if (sizeof(*out) > size)
7690                         return -1;
7691                 out->command = ctx->curr;
7692                 ctx->objdata = 0;
7693                 ctx->object = out;
7694                 ctx->objmask = NULL;
7695         }
7696         return len;
7697 }
7698
7699 /** Parse action names. */
7700 static int
7701 parse_action(struct context *ctx, const struct token *token,
7702              const char *str, unsigned int len,
7703              void *buf, unsigned int size)
7704 {
7705         struct buffer *out = buf;
7706         const struct arg *arg = pop_args(ctx);
7707         unsigned int i;
7708
7709         (void)size;
7710         /* Argument is expected. */
7711         if (!arg)
7712                 return -1;
7713         /* Parse action name. */
7714         for (i = 0; next_action[i]; ++i) {
7715                 const struct parse_action_priv *priv;
7716
7717                 token = &token_list[next_action[i]];
7718                 if (strcmp_partial(token->name, str, len))
7719                         continue;
7720                 priv = token->priv;
7721                 if (!priv)
7722                         goto error;
7723                 if (out)
7724                         memcpy((uint8_t *)ctx->object + arg->offset,
7725                                &priv->type,
7726                                arg->size);
7727                 return len;
7728         }
7729 error:
7730         push_args(ctx, arg);
7731         return -1;
7732 }
7733
7734 /** Parse tokens for list command. */
7735 static int
7736 parse_list(struct context *ctx, const struct token *token,
7737            const char *str, unsigned int len,
7738            void *buf, unsigned int size)
7739 {
7740         struct buffer *out = buf;
7741
7742         /* Token name must match. */
7743         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7744                 return -1;
7745         /* Nothing else to do if there is no buffer. */
7746         if (!out)
7747                 return len;
7748         if (!out->command) {
7749                 if (ctx->curr != LIST)
7750                         return -1;
7751                 if (sizeof(*out) > size)
7752                         return -1;
7753                 out->command = ctx->curr;
7754                 ctx->objdata = 0;
7755                 ctx->object = out;
7756                 ctx->objmask = NULL;
7757                 out->args.list.group =
7758                         (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7759                                                sizeof(double));
7760                 return len;
7761         }
7762         if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
7763              sizeof(*out->args.list.group)) > (uint8_t *)out + size)
7764                 return -1;
7765         ctx->objdata = 0;
7766         ctx->object = out->args.list.group + out->args.list.group_n++;
7767         ctx->objmask = NULL;
7768         return len;
7769 }
7770
7771 /** Parse tokens for list all aged flows command. */
7772 static int
7773 parse_aged(struct context *ctx, const struct token *token,
7774            const char *str, unsigned int len,
7775            void *buf, unsigned int size)
7776 {
7777         struct buffer *out = buf;
7778
7779         /* Token name must match. */
7780         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7781                 return -1;
7782         /* Nothing else to do if there is no buffer. */
7783         if (!out)
7784                 return len;
7785         if (!out->command) {
7786                 if (ctx->curr != AGED)
7787                         return -1;
7788                 if (sizeof(*out) > size)
7789                         return -1;
7790                 out->command = ctx->curr;
7791                 ctx->objdata = 0;
7792                 ctx->object = out;
7793                 ctx->objmask = NULL;
7794         }
7795         if (ctx->curr == AGED_DESTROY)
7796                 out->args.aged.destroy = 1;
7797         return len;
7798 }
7799
7800 /** Parse tokens for isolate command. */
7801 static int
7802 parse_isolate(struct context *ctx, const struct token *token,
7803               const char *str, unsigned int len,
7804               void *buf, unsigned int size)
7805 {
7806         struct buffer *out = buf;
7807
7808         /* Token name must match. */
7809         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7810                 return -1;
7811         /* Nothing else to do if there is no buffer. */
7812         if (!out)
7813                 return len;
7814         if (!out->command) {
7815                 if (ctx->curr != ISOLATE)
7816                         return -1;
7817                 if (sizeof(*out) > size)
7818                         return -1;
7819                 out->command = ctx->curr;
7820                 ctx->objdata = 0;
7821                 ctx->object = out;
7822                 ctx->objmask = NULL;
7823         }
7824         return len;
7825 }
7826
7827 /** Parse tokens for info/configure command. */
7828 static int
7829 parse_configure(struct context *ctx, const struct token *token,
7830                 const char *str, unsigned int len,
7831                 void *buf, unsigned int size)
7832 {
7833         struct buffer *out = buf;
7834
7835         /* Token name must match. */
7836         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7837                 return -1;
7838         /* Nothing else to do if there is no buffer. */
7839         if (!out)
7840                 return len;
7841         if (!out->command) {
7842                 if (ctx->curr != INFO && ctx->curr != CONFIGURE)
7843                         return -1;
7844                 if (sizeof(*out) > size)
7845                         return -1;
7846                 out->command = ctx->curr;
7847                 ctx->objdata = 0;
7848                 ctx->object = out;
7849                 ctx->objmask = NULL;
7850         }
7851         return len;
7852 }
7853
7854 static int
7855 parse_flex(struct context *ctx, const struct token *token,
7856              const char *str, unsigned int len,
7857              void *buf, unsigned int size)
7858 {
7859         struct buffer *out = buf;
7860
7861         /* Token name must match. */
7862         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7863                 return -1;
7864         /* Nothing else to do if there is no buffer. */
7865         if (!out)
7866                 return len;
7867         if (out->command == ZERO) {
7868                 if (ctx->curr != FLEX)
7869                         return -1;
7870                 if (sizeof(*out) > size)
7871                         return -1;
7872                 out->command = ctx->curr;
7873                 ctx->objdata = 0;
7874                 ctx->object = out;
7875                 ctx->objmask = NULL;
7876         } else {
7877                 switch (ctx->curr) {
7878                 default:
7879                         break;
7880                 case FLEX_ITEM_INIT:
7881                 case FLEX_ITEM_CREATE:
7882                 case FLEX_ITEM_DESTROY:
7883                         out->command = ctx->curr;
7884                         break;
7885                 }
7886         }
7887
7888         return len;
7889 }
7890
7891 static int
7892 parse_tunnel(struct context *ctx, const struct token *token,
7893              const char *str, unsigned int len,
7894              void *buf, unsigned int size)
7895 {
7896         struct buffer *out = buf;
7897
7898         /* Token name must match. */
7899         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7900                 return -1;
7901         /* Nothing else to do if there is no buffer. */
7902         if (!out)
7903                 return len;
7904         if (!out->command) {
7905                 if (ctx->curr != TUNNEL)
7906                         return -1;
7907                 if (sizeof(*out) > size)
7908                         return -1;
7909                 out->command = ctx->curr;
7910                 ctx->objdata = 0;
7911                 ctx->object = out;
7912                 ctx->objmask = NULL;
7913         } else {
7914                 switch (ctx->curr) {
7915                 default:
7916                         break;
7917                 case TUNNEL_CREATE:
7918                 case TUNNEL_DESTROY:
7919                 case TUNNEL_LIST:
7920                         out->command = ctx->curr;
7921                         break;
7922                 case TUNNEL_CREATE_TYPE:
7923                 case TUNNEL_DESTROY_ID:
7924                         ctx->object = &out->args.vc.tunnel_ops;
7925                         break;
7926                 }
7927         }
7928
7929         return len;
7930 }
7931
7932 /**
7933  * Parse signed/unsigned integers 8 to 64-bit long.
7934  *
7935  * Last argument (ctx->args) is retrieved to determine integer type and
7936  * storage location.
7937  */
7938 static int
7939 parse_int(struct context *ctx, const struct token *token,
7940           const char *str, unsigned int len,
7941           void *buf, unsigned int size)
7942 {
7943         const struct arg *arg = pop_args(ctx);
7944         uintmax_t u;
7945         char *end;
7946
7947         (void)token;
7948         /* Argument is expected. */
7949         if (!arg)
7950                 return -1;
7951         errno = 0;
7952         u = arg->sign ?
7953                 (uintmax_t)strtoimax(str, &end, 0) :
7954                 strtoumax(str, &end, 0);
7955         if (errno || (size_t)(end - str) != len)
7956                 goto error;
7957         if (arg->bounded &&
7958             ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
7959                             (intmax_t)u > (intmax_t)arg->max)) ||
7960              (!arg->sign && (u < arg->min || u > arg->max))))
7961                 goto error;
7962         if (!ctx->object)
7963                 return len;
7964         if (arg->mask) {
7965                 if (!arg_entry_bf_fill(ctx->object, u, arg) ||
7966                     !arg_entry_bf_fill(ctx->objmask, -1, arg))
7967                         goto error;
7968                 return len;
7969         }
7970         buf = (uint8_t *)ctx->object + arg->offset;
7971         size = arg->size;
7972         if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
7973                 return -1;
7974 objmask:
7975         switch (size) {
7976         case sizeof(uint8_t):
7977                 *(uint8_t *)buf = u;
7978                 break;
7979         case sizeof(uint16_t):
7980                 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
7981                 break;
7982         case sizeof(uint8_t [3]):
7983 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
7984                 if (!arg->hton) {
7985                         ((uint8_t *)buf)[0] = u;
7986                         ((uint8_t *)buf)[1] = u >> 8;
7987                         ((uint8_t *)buf)[2] = u >> 16;
7988                         break;
7989                 }
7990 #endif
7991                 ((uint8_t *)buf)[0] = u >> 16;
7992                 ((uint8_t *)buf)[1] = u >> 8;
7993                 ((uint8_t *)buf)[2] = u;
7994                 break;
7995         case sizeof(uint32_t):
7996                 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
7997                 break;
7998         case sizeof(uint64_t):
7999                 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
8000                 break;
8001         default:
8002                 goto error;
8003         }
8004         if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
8005                 u = -1;
8006                 buf = (uint8_t *)ctx->objmask + arg->offset;
8007                 goto objmask;
8008         }
8009         return len;
8010 error:
8011         push_args(ctx, arg);
8012         return -1;
8013 }
8014
8015 /**
8016  * Parse a string.
8017  *
8018  * Three arguments (ctx->args) are retrieved from the stack to store data,
8019  * its actual length and address (in that order).
8020  */
8021 static int
8022 parse_string(struct context *ctx, const struct token *token,
8023              const char *str, unsigned int len,
8024              void *buf, unsigned int size)
8025 {
8026         const struct arg *arg_data = pop_args(ctx);
8027         const struct arg *arg_len = pop_args(ctx);
8028         const struct arg *arg_addr = pop_args(ctx);
8029         char tmp[16]; /* Ought to be enough. */
8030         int ret;
8031
8032         /* Arguments are expected. */
8033         if (!arg_data)
8034                 return -1;
8035         if (!arg_len) {
8036                 push_args(ctx, arg_data);
8037                 return -1;
8038         }
8039         if (!arg_addr) {
8040                 push_args(ctx, arg_len);
8041                 push_args(ctx, arg_data);
8042                 return -1;
8043         }
8044         size = arg_data->size;
8045         /* Bit-mask fill is not supported. */
8046         if (arg_data->mask || size < len)
8047                 goto error;
8048         if (!ctx->object)
8049                 return len;
8050         /* Let parse_int() fill length information first. */
8051         ret = snprintf(tmp, sizeof(tmp), "%u", len);
8052         if (ret < 0)
8053                 goto error;
8054         push_args(ctx, arg_len);
8055         ret = parse_int(ctx, token, tmp, ret, NULL, 0);
8056         if (ret < 0) {
8057                 pop_args(ctx);
8058                 goto error;
8059         }
8060         buf = (uint8_t *)ctx->object + arg_data->offset;
8061         /* Output buffer is not necessarily NUL-terminated. */
8062         memcpy(buf, str, len);
8063         memset((uint8_t *)buf + len, 0x00, size - len);
8064         if (ctx->objmask)
8065                 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
8066         /* Save address if requested. */
8067         if (arg_addr->size) {
8068                 memcpy((uint8_t *)ctx->object + arg_addr->offset,
8069                        (void *[]){
8070                         (uint8_t *)ctx->object + arg_data->offset
8071                        },
8072                        arg_addr->size);
8073                 if (ctx->objmask)
8074                         memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
8075                                (void *[]){
8076                                 (uint8_t *)ctx->objmask + arg_data->offset
8077                                },
8078                                arg_addr->size);
8079         }
8080         return len;
8081 error:
8082         push_args(ctx, arg_addr);
8083         push_args(ctx, arg_len);
8084         push_args(ctx, arg_data);
8085         return -1;
8086 }
8087
8088 static int
8089 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
8090 {
8091         const uint8_t *head = dst;
8092         uint32_t left;
8093
8094         /* Check input parameters */
8095         if ((src == NULL) ||
8096                 (dst == NULL) ||
8097                 (size == NULL) ||
8098                 (*size == 0))
8099                 return -1;
8100
8101         left = *size;
8102
8103         /* Convert chars to bytes */
8104         while (left) {
8105                 char tmp[3], *end = tmp;
8106                 uint32_t read_lim = left & 1 ? 1 : 2;
8107
8108                 snprintf(tmp, read_lim + 1, "%s", src);
8109                 *dst = strtoul(tmp, &end, 16);
8110                 if (*end) {
8111                         *dst = 0;
8112                         *size = (uint32_t)(dst - head);
8113                         return -1;
8114                 }
8115                 left -= read_lim;
8116                 src += read_lim;
8117                 dst++;
8118         }
8119         *dst = 0;
8120         *size = (uint32_t)(dst - head);
8121         return 0;
8122 }
8123
8124 static int
8125 parse_hex(struct context *ctx, const struct token *token,
8126                 const char *str, unsigned int len,
8127                 void *buf, unsigned int size)
8128 {
8129         const struct arg *arg_data = pop_args(ctx);
8130         const struct arg *arg_len = pop_args(ctx);
8131         const struct arg *arg_addr = pop_args(ctx);
8132         char tmp[16]; /* Ought to be enough. */
8133         int ret;
8134         unsigned int hexlen = len;
8135         unsigned int length = 256;
8136         uint8_t hex_tmp[length];
8137
8138         /* Arguments are expected. */
8139         if (!arg_data)
8140                 return -1;
8141         if (!arg_len) {
8142                 push_args(ctx, arg_data);
8143                 return -1;
8144         }
8145         if (!arg_addr) {
8146                 push_args(ctx, arg_len);
8147                 push_args(ctx, arg_data);
8148                 return -1;
8149         }
8150         size = arg_data->size;
8151         /* Bit-mask fill is not supported. */
8152         if (arg_data->mask)
8153                 goto error;
8154         if (!ctx->object)
8155                 return len;
8156
8157         /* translate bytes string to array. */
8158         if (str[0] == '0' && ((str[1] == 'x') ||
8159                         (str[1] == 'X'))) {
8160                 str += 2;
8161                 hexlen -= 2;
8162         }
8163         if (hexlen > length)
8164                 goto error;
8165         ret = parse_hex_string(str, hex_tmp, &hexlen);
8166         if (ret < 0)
8167                 goto error;
8168         /* Check the converted binary fits into data buffer. */
8169         if (hexlen > size)
8170                 goto error;
8171         /* Let parse_int() fill length information first. */
8172         ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
8173         if (ret < 0)
8174                 goto error;
8175         /* Save length if requested. */
8176         if (arg_len->size) {
8177                 push_args(ctx, arg_len);
8178                 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
8179                 if (ret < 0) {
8180                         pop_args(ctx);
8181                         goto error;
8182                 }
8183         }
8184         buf = (uint8_t *)ctx->object + arg_data->offset;
8185         /* Output buffer is not necessarily NUL-terminated. */
8186         memcpy(buf, hex_tmp, hexlen);
8187         memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
8188         if (ctx->objmask)
8189                 memset((uint8_t *)ctx->objmask + arg_data->offset,
8190                                         0xff, hexlen);
8191         /* Save address if requested. */
8192         if (arg_addr->size) {
8193                 memcpy((uint8_t *)ctx->object + arg_addr->offset,
8194                        (void *[]){
8195                         (uint8_t *)ctx->object + arg_data->offset
8196                        },
8197                        arg_addr->size);
8198                 if (ctx->objmask)
8199                         memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
8200                                (void *[]){
8201                                 (uint8_t *)ctx->objmask + arg_data->offset
8202                                },
8203                                arg_addr->size);
8204         }
8205         return len;
8206 error:
8207         push_args(ctx, arg_addr);
8208         push_args(ctx, arg_len);
8209         push_args(ctx, arg_data);
8210         return -1;
8211
8212 }
8213
8214 /**
8215  * Parse a zero-ended string.
8216  */
8217 static int
8218 parse_string0(struct context *ctx, const struct token *token __rte_unused,
8219              const char *str, unsigned int len,
8220              void *buf, unsigned int size)
8221 {
8222         const struct arg *arg_data = pop_args(ctx);
8223
8224         /* Arguments are expected. */
8225         if (!arg_data)
8226                 return -1;
8227         size = arg_data->size;
8228         /* Bit-mask fill is not supported. */
8229         if (arg_data->mask || size < len + 1)
8230                 goto error;
8231         if (!ctx->object)
8232                 return len;
8233         buf = (uint8_t *)ctx->object + arg_data->offset;
8234         strncpy(buf, str, len);
8235         if (ctx->objmask)
8236                 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
8237         return len;
8238 error:
8239         push_args(ctx, arg_data);
8240         return -1;
8241 }
8242
8243 /**
8244  * Parse a MAC address.
8245  *
8246  * Last argument (ctx->args) is retrieved to determine storage size and
8247  * location.
8248  */
8249 static int
8250 parse_mac_addr(struct context *ctx, const struct token *token,
8251                const char *str, unsigned int len,
8252                void *buf, unsigned int size)
8253 {
8254         const struct arg *arg = pop_args(ctx);
8255         struct rte_ether_addr tmp;
8256         int ret;
8257
8258         (void)token;
8259         /* Argument is expected. */
8260         if (!arg)
8261                 return -1;
8262         size = arg->size;
8263         /* Bit-mask fill is not supported. */
8264         if (arg->mask || size != sizeof(tmp))
8265                 goto error;
8266         /* Only network endian is supported. */
8267         if (!arg->hton)
8268                 goto error;
8269         ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
8270         if (ret < 0 || (unsigned int)ret != len)
8271                 goto error;
8272         if (!ctx->object)
8273                 return len;
8274         buf = (uint8_t *)ctx->object + arg->offset;
8275         memcpy(buf, &tmp, size);
8276         if (ctx->objmask)
8277                 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8278         return len;
8279 error:
8280         push_args(ctx, arg);
8281         return -1;
8282 }
8283
8284 /**
8285  * Parse an IPv4 address.
8286  *
8287  * Last argument (ctx->args) is retrieved to determine storage size and
8288  * location.
8289  */
8290 static int
8291 parse_ipv4_addr(struct context *ctx, const struct token *token,
8292                 const char *str, unsigned int len,
8293                 void *buf, unsigned int size)
8294 {
8295         const struct arg *arg = pop_args(ctx);
8296         char str2[len + 1];
8297         struct in_addr tmp;
8298         int ret;
8299
8300         /* Argument is expected. */
8301         if (!arg)
8302                 return -1;
8303         size = arg->size;
8304         /* Bit-mask fill is not supported. */
8305         if (arg->mask || size != sizeof(tmp))
8306                 goto error;
8307         /* Only network endian is supported. */
8308         if (!arg->hton)
8309                 goto error;
8310         memcpy(str2, str, len);
8311         str2[len] = '\0';
8312         ret = inet_pton(AF_INET, str2, &tmp);
8313         if (ret != 1) {
8314                 /* Attempt integer parsing. */
8315                 push_args(ctx, arg);
8316                 return parse_int(ctx, token, str, len, buf, size);
8317         }
8318         if (!ctx->object)
8319                 return len;
8320         buf = (uint8_t *)ctx->object + arg->offset;
8321         memcpy(buf, &tmp, size);
8322         if (ctx->objmask)
8323                 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8324         return len;
8325 error:
8326         push_args(ctx, arg);
8327         return -1;
8328 }
8329
8330 /**
8331  * Parse an IPv6 address.
8332  *
8333  * Last argument (ctx->args) is retrieved to determine storage size and
8334  * location.
8335  */
8336 static int
8337 parse_ipv6_addr(struct context *ctx, const struct token *token,
8338                 const char *str, unsigned int len,
8339                 void *buf, unsigned int size)
8340 {
8341         const struct arg *arg = pop_args(ctx);
8342         char str2[len + 1];
8343         struct in6_addr tmp;
8344         int ret;
8345
8346         (void)token;
8347         /* Argument is expected. */
8348         if (!arg)
8349                 return -1;
8350         size = arg->size;
8351         /* Bit-mask fill is not supported. */
8352         if (arg->mask || size != sizeof(tmp))
8353                 goto error;
8354         /* Only network endian is supported. */
8355         if (!arg->hton)
8356                 goto error;
8357         memcpy(str2, str, len);
8358         str2[len] = '\0';
8359         ret = inet_pton(AF_INET6, str2, &tmp);
8360         if (ret != 1)
8361                 goto error;
8362         if (!ctx->object)
8363                 return len;
8364         buf = (uint8_t *)ctx->object + arg->offset;
8365         memcpy(buf, &tmp, size);
8366         if (ctx->objmask)
8367                 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8368         return len;
8369 error:
8370         push_args(ctx, arg);
8371         return -1;
8372 }
8373
8374 /** Boolean values (even indices stand for false). */
8375 static const char *const boolean_name[] = {
8376         "0", "1",
8377         "false", "true",
8378         "no", "yes",
8379         "N", "Y",
8380         "off", "on",
8381         NULL,
8382 };
8383
8384 /**
8385  * Parse a boolean value.
8386  *
8387  * Last argument (ctx->args) is retrieved to determine storage size and
8388  * location.
8389  */
8390 static int
8391 parse_boolean(struct context *ctx, const struct token *token,
8392               const char *str, unsigned int len,
8393               void *buf, unsigned int size)
8394 {
8395         const struct arg *arg = pop_args(ctx);
8396         unsigned int i;
8397         int ret;
8398
8399         /* Argument is expected. */
8400         if (!arg)
8401                 return -1;
8402         for (i = 0; boolean_name[i]; ++i)
8403                 if (!strcmp_partial(boolean_name[i], str, len))
8404                         break;
8405         /* Process token as integer. */
8406         if (boolean_name[i])
8407                 str = i & 1 ? "1" : "0";
8408         push_args(ctx, arg);
8409         ret = parse_int(ctx, token, str, strlen(str), buf, size);
8410         return ret > 0 ? (int)len : ret;
8411 }
8412
8413 /** Parse port and update context. */
8414 static int
8415 parse_port(struct context *ctx, const struct token *token,
8416            const char *str, unsigned int len,
8417            void *buf, unsigned int size)
8418 {
8419         struct buffer *out = &(struct buffer){ .port = 0 };
8420         int ret;
8421
8422         if (buf)
8423                 out = buf;
8424         else {
8425                 ctx->objdata = 0;
8426                 ctx->object = out;
8427                 ctx->objmask = NULL;
8428                 size = sizeof(*out);
8429         }
8430         ret = parse_int(ctx, token, str, len, out, size);
8431         if (ret >= 0)
8432                 ctx->port = out->port;
8433         if (!buf)
8434                 ctx->object = NULL;
8435         return ret;
8436 }
8437
8438 static int
8439 parse_ia_id2ptr(struct context *ctx, const struct token *token,
8440                 const char *str, unsigned int len,
8441                 void *buf, unsigned int size)
8442 {
8443         struct rte_flow_action *action = ctx->object;
8444         uint32_t id;
8445         int ret;
8446
8447         (void)buf;
8448         (void)size;
8449         ctx->objdata = 0;
8450         ctx->object = &id;
8451         ctx->objmask = NULL;
8452         ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
8453         ctx->object = action;
8454         if (ret != (int)len)
8455                 return ret;
8456         /* set indirect action */
8457         if (action) {
8458                 action->conf = port_action_handle_get_by_id(ctx->port, id);
8459                 ret = (action->conf) ? ret : -1;
8460         }
8461         return ret;
8462 }
8463
8464 /** Parse set command, initialize output buffer for subsequent tokens. */
8465 static int
8466 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
8467                           const char *str, unsigned int len,
8468                           void *buf, unsigned int size)
8469 {
8470         struct buffer *out = buf;
8471
8472         /* Token name must match. */
8473         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8474                 return -1;
8475         /* Nothing else to do if there is no buffer. */
8476         if (!out)
8477                 return len;
8478         /* Make sure buffer is large enough. */
8479         if (size < sizeof(*out))
8480                 return -1;
8481         ctx->objdata = 0;
8482         ctx->objmask = NULL;
8483         ctx->object = out;
8484         if (!out->command)
8485                 return -1;
8486         out->command = ctx->curr;
8487         /* For encap/decap we need is pattern */
8488         out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8489                                                        sizeof(double));
8490         return len;
8491 }
8492
8493 /** Parse set command, initialize output buffer for subsequent tokens. */
8494 static int
8495 parse_set_sample_action(struct context *ctx, const struct token *token,
8496                           const char *str, unsigned int len,
8497                           void *buf, unsigned int size)
8498 {
8499         struct buffer *out = buf;
8500
8501         /* Token name must match. */
8502         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8503                 return -1;
8504         /* Nothing else to do if there is no buffer. */
8505         if (!out)
8506                 return len;
8507         /* Make sure buffer is large enough. */
8508         if (size < sizeof(*out))
8509                 return -1;
8510         ctx->objdata = 0;
8511         ctx->objmask = NULL;
8512         ctx->object = out;
8513         if (!out->command)
8514                 return -1;
8515         out->command = ctx->curr;
8516         /* For sampler we need is actions */
8517         out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8518                                                        sizeof(double));
8519         return len;
8520 }
8521
8522 /**
8523  * Parse set raw_encap/raw_decap command,
8524  * initialize output buffer for subsequent tokens.
8525  */
8526 static int
8527 parse_set_init(struct context *ctx, const struct token *token,
8528                const char *str, unsigned int len,
8529                void *buf, unsigned int size)
8530 {
8531         struct buffer *out = buf;
8532
8533         /* Token name must match. */
8534         if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8535                 return -1;
8536         /* Nothing else to do if there is no buffer. */
8537         if (!out)
8538                 return len;
8539         /* Make sure buffer is large enough. */
8540         if (size < sizeof(*out))
8541                 return -1;
8542         /* Initialize buffer. */
8543         memset(out, 0x00, sizeof(*out));
8544         memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
8545         ctx->objdata = 0;
8546         ctx->object = out;
8547         ctx->objmask = NULL;
8548         if (!out->command) {
8549                 if (ctx->curr != SET)
8550                         return -1;
8551                 if (sizeof(*out) > size)
8552                         return -1;
8553                 out->command = ctx->curr;
8554                 out->args.vc.data = (uint8_t *)out + size;
8555                 ctx->object  = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8556                                                        sizeof(double));
8557         }
8558         return len;
8559 }
8560
8561 /*
8562  * Replace testpmd handles in a flex flow item with real values.
8563  */
8564 static int
8565 parse_flex_handle(struct context *ctx, const struct token *token,
8566                   const char *str, unsigned int len,
8567                   void *buf, unsigned int size)
8568 {
8569         struct rte_flow_item_flex *spec, *mask;
8570         const struct rte_flow_item_flex *src_spec, *src_mask;
8571         const struct arg *arg = pop_args(ctx);
8572         uint32_t offset;
8573         uint16_t handle;
8574         int ret;
8575
8576         if (!arg) {
8577                 printf("Bad environment\n");
8578                 return -1;
8579         }
8580         offset = arg->offset;
8581         push_args(ctx, arg);
8582         ret = parse_int(ctx, token, str, len, buf, size);
8583         if (ret <= 0 || !ctx->object)
8584                 return ret;
8585         if (ctx->port >= RTE_MAX_ETHPORTS) {
8586                 printf("Bad port\n");
8587                 return -1;
8588         }
8589         if (offset == offsetof(struct rte_flow_item_flex, handle)) {
8590                 const struct flex_item *fp;
8591                 struct rte_flow_item_flex *item_flex = ctx->object;
8592                 handle = (uint16_t)(uintptr_t)item_flex->handle;
8593                 if (handle >= FLEX_MAX_PARSERS_NUM) {
8594                         printf("Bad flex item handle\n");
8595                         return -1;
8596                 }
8597                 fp = flex_items[ctx->port][handle];
8598                 if (!fp) {
8599                         printf("Bad flex item handle\n");
8600                         return -1;
8601                 }
8602                 item_flex->handle = fp->flex_handle;
8603         } else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
8604                 handle = (uint16_t)(uintptr_t)
8605                         ((struct rte_flow_item_flex *)ctx->object)->pattern;
8606                 if (handle >= FLEX_MAX_PATTERNS_NUM) {
8607                         printf("Bad pattern handle\n");
8608                         return -1;
8609                 }
8610                 src_spec = &flex_patterns[handle].spec;
8611                 src_mask = &flex_patterns[handle].mask;
8612                 spec = ctx->object;
8613                 mask = spec + 2; /* spec, last, mask */
8614                 /* fill flow rule spec and mask parameters */
8615                 spec->length = src_spec->length;
8616                 spec->pattern = src_spec->pattern;
8617                 mask->length = src_mask->length;
8618                 mask->pattern = src_mask->pattern;
8619         } else {
8620                 printf("Bad arguments - unknown flex item offset\n");
8621                 return -1;
8622         }
8623         return ret;
8624 }
8625
8626 /** No completion. */
8627 static int
8628 comp_none(struct context *ctx, const struct token *token,
8629           unsigned int ent, char *buf, unsigned int size)
8630 {
8631         (void)ctx;
8632         (void)token;
8633         (void)ent;
8634         (void)buf;
8635         (void)size;
8636         return 0;
8637 }
8638
8639 /** Complete boolean values. */
8640 static int
8641 comp_boolean(struct context *ctx, const struct token *token,
8642              unsigned int ent, char *buf, unsigned int size)
8643 {
8644         unsigned int i;
8645
8646         (void)ctx;
8647         (void)token;
8648         for (i = 0; boolean_name[i]; ++i)
8649                 if (buf && i == ent)
8650                         return strlcpy(buf, boolean_name[i], size);
8651         if (buf)
8652                 return -1;
8653         return i;
8654 }
8655
8656 /** Complete action names. */
8657 static int
8658 comp_action(struct context *ctx, const struct token *token,
8659             unsigned int ent, char *buf, unsigned int size)
8660 {
8661         unsigned int i;
8662
8663         (void)ctx;
8664         (void)token;
8665         for (i = 0; next_action[i]; ++i)
8666                 if (buf && i == ent)
8667                         return strlcpy(buf, token_list[next_action[i]].name,
8668                                        size);
8669         if (buf)
8670                 return -1;
8671         return i;
8672 }
8673
8674 /** Complete available ports. */
8675 static int
8676 comp_port(struct context *ctx, const struct token *token,
8677           unsigned int ent, char *buf, unsigned int size)
8678 {
8679         unsigned int i = 0;
8680         portid_t p;
8681
8682         (void)ctx;
8683         (void)token;
8684         RTE_ETH_FOREACH_DEV(p) {
8685                 if (buf && i == ent)
8686                         return snprintf(buf, size, "%u", p);
8687                 ++i;
8688         }
8689         if (buf)
8690                 return -1;
8691         return i;
8692 }
8693
8694 /** Complete available rule IDs. */
8695 static int
8696 comp_rule_id(struct context *ctx, const struct token *token,
8697              unsigned int ent, char *buf, unsigned int size)
8698 {
8699         unsigned int i = 0;
8700         struct rte_port *port;
8701         struct port_flow *pf;
8702
8703         (void)token;
8704         if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
8705             ctx->port == (portid_t)RTE_PORT_ALL)
8706                 return -1;
8707         port = &ports[ctx->port];
8708         for (pf = port->flow_list; pf != NULL; pf = pf->next) {
8709                 if (buf && i == ent)
8710                         return snprintf(buf, size, "%u", pf->id);
8711                 ++i;
8712         }
8713         if (buf)
8714                 return -1;
8715         return i;
8716 }
8717
8718 /** Complete type field for RSS action. */
8719 static int
8720 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
8721                         unsigned int ent, char *buf, unsigned int size)
8722 {
8723         unsigned int i;
8724
8725         (void)ctx;
8726         (void)token;
8727         for (i = 0; rss_type_table[i].str; ++i)
8728                 ;
8729         if (!buf)
8730                 return i + 1;
8731         if (ent < i)
8732                 return strlcpy(buf, rss_type_table[ent].str, size);
8733         if (ent == i)
8734                 return snprintf(buf, size, "end");
8735         return -1;
8736 }
8737
8738 /** Complete queue field for RSS action. */
8739 static int
8740 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
8741                          unsigned int ent, char *buf, unsigned int size)
8742 {
8743         (void)ctx;
8744         (void)token;
8745         if (!buf)
8746                 return nb_rxq + 1;
8747         if (ent < nb_rxq)
8748                 return snprintf(buf, size, "%u", ent);
8749         if (ent == nb_rxq)
8750                 return snprintf(buf, size, "end");
8751         return -1;
8752 }
8753
8754 /** Complete index number for set raw_encap/raw_decap commands. */
8755 static int
8756 comp_set_raw_index(struct context *ctx, const struct token *token,
8757                    unsigned int ent, char *buf, unsigned int size)
8758 {
8759         uint16_t idx = 0;
8760         uint16_t nb = 0;
8761
8762         RTE_SET_USED(ctx);
8763         RTE_SET_USED(token);
8764         for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
8765                 if (buf && idx == ent)
8766                         return snprintf(buf, size, "%u", idx);
8767                 ++nb;
8768         }
8769         return nb;
8770 }
8771
8772 /** Complete index number for set raw_encap/raw_decap commands. */
8773 static int
8774 comp_set_sample_index(struct context *ctx, const struct token *token,
8775                    unsigned int ent, char *buf, unsigned int size)
8776 {
8777         uint16_t idx = 0;
8778         uint16_t nb = 0;
8779
8780         RTE_SET_USED(ctx);
8781         RTE_SET_USED(token);
8782         for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
8783                 if (buf && idx == ent)
8784                         return snprintf(buf, size, "%u", idx);
8785                 ++nb;
8786         }
8787         return nb;
8788 }
8789
8790 /** Complete operation for modify_field command. */
8791 static int
8792 comp_set_modify_field_op(struct context *ctx, const struct token *token,
8793                    unsigned int ent, char *buf, unsigned int size)
8794 {
8795         RTE_SET_USED(ctx);
8796         RTE_SET_USED(token);
8797         if (!buf)
8798                 return RTE_DIM(modify_field_ops);
8799         if (ent < RTE_DIM(modify_field_ops) - 1)
8800                 return strlcpy(buf, modify_field_ops[ent], size);
8801         return -1;
8802 }
8803
8804 /** Complete field id for modify_field command. */
8805 static int
8806 comp_set_modify_field_id(struct context *ctx, const struct token *token,
8807                    unsigned int ent, char *buf, unsigned int size)
8808 {
8809         const char *name;
8810
8811         RTE_SET_USED(token);
8812         if (!buf)
8813                 return RTE_DIM(modify_field_ids);
8814         if (ent >= RTE_DIM(modify_field_ids) - 1)
8815                 return -1;
8816         name = modify_field_ids[ent];
8817         if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
8818             (strcmp(name, "pointer") && strcmp(name, "value")))
8819                 return strlcpy(buf, name, size);
8820         return -1;
8821 }
8822
8823 /** Internal context. */
8824 static struct context cmd_flow_context;
8825
8826 /** Global parser instance (cmdline API). */
8827 cmdline_parse_inst_t cmd_flow;
8828 cmdline_parse_inst_t cmd_set_raw;
8829
8830 /** Initialize context. */
8831 static void
8832 cmd_flow_context_init(struct context *ctx)
8833 {
8834         /* A full memset() is not necessary. */
8835         ctx->curr = ZERO;
8836         ctx->prev = ZERO;
8837         ctx->next_num = 0;
8838         ctx->args_num = 0;
8839         ctx->eol = 0;
8840         ctx->last = 0;
8841         ctx->port = 0;
8842         ctx->objdata = 0;
8843         ctx->object = NULL;
8844         ctx->objmask = NULL;
8845 }
8846
8847 /** Parse a token (cmdline API). */
8848 static int
8849 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
8850                unsigned int size)
8851 {
8852         struct context *ctx = &cmd_flow_context;
8853         const struct token *token;
8854         const enum index *list;
8855         int len;
8856         int i;
8857
8858         (void)hdr;
8859         token = &token_list[ctx->curr];
8860         /* Check argument length. */
8861         ctx->eol = 0;
8862         ctx->last = 1;
8863         for (len = 0; src[len]; ++len)
8864                 if (src[len] == '#' || isspace(src[len]))
8865                         break;
8866         if (!len)
8867                 return -1;
8868         /* Last argument and EOL detection. */
8869         for (i = len; src[i]; ++i)
8870                 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
8871                         break;
8872                 else if (!isspace(src[i])) {
8873                         ctx->last = 0;
8874                         break;
8875                 }
8876         for (; src[i]; ++i)
8877                 if (src[i] == '\r' || src[i] == '\n') {
8878                         ctx->eol = 1;
8879                         break;
8880                 }
8881         /* Initialize context if necessary. */
8882         if (!ctx->next_num) {
8883                 if (!token->next)
8884                         return 0;
8885                 ctx->next[ctx->next_num++] = token->next[0];
8886         }
8887         /* Process argument through candidates. */
8888         ctx->prev = ctx->curr;
8889         list = ctx->next[ctx->next_num - 1];
8890         for (i = 0; list[i]; ++i) {
8891                 const struct token *next = &token_list[list[i]];
8892                 int tmp;
8893
8894                 ctx->curr = list[i];
8895                 if (next->call)
8896                         tmp = next->call(ctx, next, src, len, result, size);
8897                 else
8898                         tmp = parse_default(ctx, next, src, len, result, size);
8899                 if (tmp == -1 || tmp != len)
8900                         continue;
8901                 token = next;
8902                 break;
8903         }
8904         if (!list[i])
8905                 return -1;
8906         --ctx->next_num;
8907         /* Push subsequent tokens if any. */
8908         if (token->next)
8909                 for (i = 0; token->next[i]; ++i) {
8910                         if (ctx->next_num == RTE_DIM(ctx->next))
8911                                 return -1;
8912                         ctx->next[ctx->next_num++] = token->next[i];
8913                 }
8914         /* Push arguments if any. */
8915         if (token->args)
8916                 for (i = 0; token->args[i]; ++i) {
8917                         if (ctx->args_num == RTE_DIM(ctx->args))
8918                                 return -1;
8919                         ctx->args[ctx->args_num++] = token->args[i];
8920                 }
8921         return len;
8922 }
8923
8924 int
8925 flow_parse(const char *src, void *result, unsigned int size,
8926            struct rte_flow_attr **attr,
8927            struct rte_flow_item **pattern, struct rte_flow_action **actions)
8928 {
8929         int ret;
8930         struct context saved_flow_ctx = cmd_flow_context;
8931
8932         cmd_flow_context_init(&cmd_flow_context);
8933         do {
8934                 ret = cmd_flow_parse(NULL, src, result, size);
8935                 if (ret > 0) {
8936                         src += ret;
8937                         while (isspace(*src))
8938                                 src++;
8939                 }
8940         } while (ret > 0 && strlen(src));
8941         cmd_flow_context = saved_flow_ctx;
8942         *attr = &((struct buffer *)result)->args.vc.attr;
8943         *pattern = ((struct buffer *)result)->args.vc.pattern;
8944         *actions = ((struct buffer *)result)->args.vc.actions;
8945         return (ret >= 0 && !strlen(src)) ? 0 : -1;
8946 }
8947
8948 /** Return number of completion entries (cmdline API). */
8949 static int
8950 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
8951 {
8952         struct context *ctx = &cmd_flow_context;
8953         const struct token *token = &token_list[ctx->curr];
8954         const enum index *list;
8955         int i;
8956
8957         (void)hdr;
8958         /* Count number of tokens in current list. */
8959         if (ctx->next_num)
8960                 list = ctx->next[ctx->next_num - 1];
8961         else
8962                 list = token->next[0];
8963         for (i = 0; list[i]; ++i)
8964                 ;
8965         if (!i)
8966                 return 0;
8967         /*
8968          * If there is a single token, use its completion callback, otherwise
8969          * return the number of entries.
8970          */
8971         token = &token_list[list[0]];
8972         if (i == 1 && token->comp) {
8973                 /* Save index for cmd_flow_get_help(). */
8974                 ctx->prev = list[0];
8975                 return token->comp(ctx, token, 0, NULL, 0);
8976         }
8977         return i;
8978 }
8979
8980 /** Return a completion entry (cmdline API). */
8981 static int
8982 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
8983                           char *dst, unsigned int size)
8984 {
8985         struct context *ctx = &cmd_flow_context;
8986         const struct token *token = &token_list[ctx->curr];
8987         const enum index *list;
8988         int i;
8989
8990         (void)hdr;
8991         /* Count number of tokens in current list. */
8992         if (ctx->next_num)
8993                 list = ctx->next[ctx->next_num - 1];
8994         else
8995                 list = token->next[0];
8996         for (i = 0; list[i]; ++i)
8997                 ;
8998         if (!i)
8999                 return -1;
9000         /* If there is a single token, use its completion callback. */
9001         token = &token_list[list[0]];
9002         if (i == 1 && token->comp) {
9003                 /* Save index for cmd_flow_get_help(). */
9004                 ctx->prev = list[0];
9005                 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
9006         }
9007         /* Otherwise make sure the index is valid and use defaults. */
9008         if (index >= i)
9009                 return -1;
9010         token = &token_list[list[index]];
9011         strlcpy(dst, token->name, size);
9012         /* Save index for cmd_flow_get_help(). */
9013         ctx->prev = list[index];
9014         return 0;
9015 }
9016
9017 /** Populate help strings for current token (cmdline API). */
9018 static int
9019 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
9020 {
9021         struct context *ctx = &cmd_flow_context;
9022         const struct token *token = &token_list[ctx->prev];
9023
9024         (void)hdr;
9025         if (!size)
9026                 return -1;
9027         /* Set token type and update global help with details. */
9028         strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
9029         if (token->help)
9030                 cmd_flow.help_str = token->help;
9031         else
9032                 cmd_flow.help_str = token->name;
9033         return 0;
9034 }
9035
9036 /** Token definition template (cmdline API). */
9037 static struct cmdline_token_hdr cmd_flow_token_hdr = {
9038         .ops = &(struct cmdline_token_ops){
9039                 .parse = cmd_flow_parse,
9040                 .complete_get_nb = cmd_flow_complete_get_nb,
9041                 .complete_get_elt = cmd_flow_complete_get_elt,
9042                 .get_help = cmd_flow_get_help,
9043         },
9044         .offset = 0,
9045 };
9046
9047 /** Populate the next dynamic token. */
9048 static void
9049 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
9050              cmdline_parse_token_hdr_t **hdr_inst)
9051 {
9052         struct context *ctx = &cmd_flow_context;
9053
9054         /* Always reinitialize context before requesting the first token. */
9055         if (!(hdr_inst - cmd_flow.tokens))
9056                 cmd_flow_context_init(ctx);
9057         /* Return NULL when no more tokens are expected. */
9058         if (!ctx->next_num && ctx->curr) {
9059                 *hdr = NULL;
9060                 return;
9061         }
9062         /* Determine if command should end here. */
9063         if (ctx->eol && ctx->last && ctx->next_num) {
9064                 const enum index *list = ctx->next[ctx->next_num - 1];
9065                 int i;
9066
9067                 for (i = 0; list[i]; ++i) {
9068                         if (list[i] != END)
9069                                 continue;
9070                         *hdr = NULL;
9071                         return;
9072                 }
9073         }
9074         *hdr = &cmd_flow_token_hdr;
9075 }
9076
9077 /** Dispatch parsed buffer to function calls. */
9078 static void
9079 cmd_flow_parsed(const struct buffer *in)
9080 {
9081         switch (in->command) {
9082         case INFO:
9083                 port_flow_get_info(in->port);
9084                 break;
9085         case CONFIGURE:
9086                 port_flow_configure(in->port,
9087                                     &in->args.configure.port_attr,
9088                                     in->args.configure.nb_queue,
9089                                     &in->args.configure.queue_attr);
9090                 break;
9091         case INDIRECT_ACTION_CREATE:
9092                 port_action_handle_create(
9093                                 in->port, in->args.vc.attr.group,
9094                                 &((const struct rte_flow_indir_action_conf) {
9095                                         .ingress = in->args.vc.attr.ingress,
9096                                         .egress = in->args.vc.attr.egress,
9097                                         .transfer = in->args.vc.attr.transfer,
9098                                 }),
9099                                 in->args.vc.actions);
9100                 break;
9101         case INDIRECT_ACTION_DESTROY:
9102                 port_action_handle_destroy(in->port,
9103                                            in->args.ia_destroy.action_id_n,
9104                                            in->args.ia_destroy.action_id);
9105                 break;
9106         case INDIRECT_ACTION_UPDATE:
9107                 port_action_handle_update(in->port, in->args.vc.attr.group,
9108                                           in->args.vc.actions);
9109                 break;
9110         case INDIRECT_ACTION_QUERY:
9111                 port_action_handle_query(in->port, in->args.ia.action_id);
9112                 break;
9113         case VALIDATE:
9114                 port_flow_validate(in->port, &in->args.vc.attr,
9115                                    in->args.vc.pattern, in->args.vc.actions,
9116                                    &in->args.vc.tunnel_ops);
9117                 break;
9118         case CREATE:
9119                 port_flow_create(in->port, &in->args.vc.attr,
9120                                  in->args.vc.pattern, in->args.vc.actions,
9121                                  &in->args.vc.tunnel_ops);
9122                 break;
9123         case DESTROY:
9124                 port_flow_destroy(in->port, in->args.destroy.rule_n,
9125                                   in->args.destroy.rule);
9126                 break;
9127         case FLUSH:
9128                 port_flow_flush(in->port);
9129                 break;
9130         case DUMP_ONE:
9131         case DUMP_ALL:
9132                 port_flow_dump(in->port, in->args.dump.mode,
9133                                 in->args.dump.rule, in->args.dump.file);
9134                 break;
9135         case QUERY:
9136                 port_flow_query(in->port, in->args.query.rule,
9137                                 &in->args.query.action);
9138                 break;
9139         case LIST:
9140                 port_flow_list(in->port, in->args.list.group_n,
9141                                in->args.list.group);
9142                 break;
9143         case ISOLATE:
9144                 port_flow_isolate(in->port, in->args.isolate.set);
9145                 break;
9146         case AGED:
9147                 port_flow_aged(in->port, in->args.aged.destroy);
9148                 break;
9149         case TUNNEL_CREATE:
9150                 port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
9151                 break;
9152         case TUNNEL_DESTROY:
9153                 port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
9154                 break;
9155         case TUNNEL_LIST:
9156                 port_flow_tunnel_list(in->port);
9157                 break;
9158         case ACTION_POL_G:
9159                 port_meter_policy_add(in->port, in->args.policy.policy_id,
9160                                         in->args.vc.actions);
9161                 break;
9162         case FLEX_ITEM_CREATE:
9163                 flex_item_create(in->port, in->args.flex.token,
9164                                  in->args.flex.filename);
9165                 break;
9166         case FLEX_ITEM_DESTROY:
9167                 flex_item_destroy(in->port, in->args.flex.token);
9168                 break;
9169         default:
9170                 break;
9171         }
9172 }
9173
9174 /** Token generator and output processing callback (cmdline API). */
9175 static void
9176 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
9177 {
9178         if (cl == NULL)
9179                 cmd_flow_tok(arg0, arg2);
9180         else
9181                 cmd_flow_parsed(arg0);
9182 }
9183
9184 /** Global parser instance (cmdline API). */
9185 cmdline_parse_inst_t cmd_flow = {
9186         .f = cmd_flow_cb,
9187         .data = NULL, /**< Unused. */
9188         .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
9189         .tokens = {
9190                 NULL,
9191         }, /**< Tokens are returned by cmd_flow_tok(). */
9192 };
9193
9194 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
9195
9196 static void
9197 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
9198 {
9199         struct rte_ipv4_hdr *ipv4;
9200         struct rte_ether_hdr *eth;
9201         struct rte_ipv6_hdr *ipv6;
9202         struct rte_vxlan_hdr *vxlan;
9203         struct rte_vxlan_gpe_hdr *gpe;
9204         struct rte_flow_item_nvgre *nvgre;
9205         uint32_t ipv6_vtc_flow;
9206
9207         switch (item->type) {
9208         case RTE_FLOW_ITEM_TYPE_ETH:
9209                 eth = (struct rte_ether_hdr *)buf;
9210                 if (next_proto)
9211                         eth->ether_type = rte_cpu_to_be_16(next_proto);
9212                 break;
9213         case RTE_FLOW_ITEM_TYPE_IPV4:
9214                 ipv4 = (struct rte_ipv4_hdr *)buf;
9215                 if (!ipv4->version_ihl)
9216                         ipv4->version_ihl = RTE_IPV4_VHL_DEF;
9217                 if (next_proto && ipv4->next_proto_id == 0)
9218                         ipv4->next_proto_id = (uint8_t)next_proto;
9219                 break;
9220         case RTE_FLOW_ITEM_TYPE_IPV6:
9221                 ipv6 = (struct rte_ipv6_hdr *)buf;
9222                 if (next_proto && ipv6->proto == 0)
9223                         ipv6->proto = (uint8_t)next_proto;
9224                 ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
9225                 ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
9226                 ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
9227                 ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
9228                 break;
9229         case RTE_FLOW_ITEM_TYPE_VXLAN:
9230                 vxlan = (struct rte_vxlan_hdr *)buf;
9231                 vxlan->vx_flags = 0x08;
9232                 break;
9233         case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
9234                 gpe = (struct rte_vxlan_gpe_hdr *)buf;
9235                 gpe->vx_flags = 0x0C;
9236                 break;
9237         case RTE_FLOW_ITEM_TYPE_NVGRE:
9238                 nvgre = (struct rte_flow_item_nvgre *)buf;
9239                 nvgre->protocol = rte_cpu_to_be_16(0x6558);
9240                 nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
9241                 break;
9242         default:
9243                 break;
9244         }
9245 }
9246
9247 /** Helper of get item's default mask. */
9248 static const void *
9249 flow_item_default_mask(const struct rte_flow_item *item)
9250 {
9251         const void *mask = NULL;
9252         static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
9253
9254         switch (item->type) {
9255         case RTE_FLOW_ITEM_TYPE_ANY:
9256                 mask = &rte_flow_item_any_mask;
9257                 break;
9258         case RTE_FLOW_ITEM_TYPE_VF:
9259                 mask = &rte_flow_item_vf_mask;
9260                 break;
9261         case RTE_FLOW_ITEM_TYPE_PORT_ID:
9262                 mask = &rte_flow_item_port_id_mask;
9263                 break;
9264         case RTE_FLOW_ITEM_TYPE_RAW:
9265                 mask = &rte_flow_item_raw_mask;
9266                 break;
9267         case RTE_FLOW_ITEM_TYPE_ETH:
9268                 mask = &rte_flow_item_eth_mask;
9269                 break;
9270         case RTE_FLOW_ITEM_TYPE_VLAN:
9271                 mask = &rte_flow_item_vlan_mask;
9272                 break;
9273         case RTE_FLOW_ITEM_TYPE_IPV4:
9274                 mask = &rte_flow_item_ipv4_mask;
9275                 break;
9276         case RTE_FLOW_ITEM_TYPE_IPV6:
9277                 mask = &rte_flow_item_ipv6_mask;
9278                 break;
9279         case RTE_FLOW_ITEM_TYPE_ICMP:
9280                 mask = &rte_flow_item_icmp_mask;
9281                 break;
9282         case RTE_FLOW_ITEM_TYPE_UDP:
9283                 mask = &rte_flow_item_udp_mask;
9284                 break;
9285         case RTE_FLOW_ITEM_TYPE_TCP:
9286                 mask = &rte_flow_item_tcp_mask;
9287                 break;
9288         case RTE_FLOW_ITEM_TYPE_SCTP:
9289                 mask = &rte_flow_item_sctp_mask;
9290                 break;
9291         case RTE_FLOW_ITEM_TYPE_VXLAN:
9292                 mask = &rte_flow_item_vxlan_mask;
9293                 break;
9294         case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
9295                 mask = &rte_flow_item_vxlan_gpe_mask;
9296                 break;
9297         case RTE_FLOW_ITEM_TYPE_E_TAG:
9298                 mask = &rte_flow_item_e_tag_mask;
9299                 break;
9300         case RTE_FLOW_ITEM_TYPE_NVGRE:
9301                 mask = &rte_flow_item_nvgre_mask;
9302                 break;
9303         case RTE_FLOW_ITEM_TYPE_MPLS:
9304                 mask = &rte_flow_item_mpls_mask;
9305                 break;
9306         case RTE_FLOW_ITEM_TYPE_GRE:
9307                 mask = &rte_flow_item_gre_mask;
9308                 break;
9309         case RTE_FLOW_ITEM_TYPE_GRE_KEY:
9310                 mask = &gre_key_default_mask;
9311                 break;
9312         case RTE_FLOW_ITEM_TYPE_META:
9313                 mask = &rte_flow_item_meta_mask;
9314                 break;
9315         case RTE_FLOW_ITEM_TYPE_FUZZY:
9316                 mask = &rte_flow_item_fuzzy_mask;
9317                 break;
9318         case RTE_FLOW_ITEM_TYPE_GTP:
9319                 mask = &rte_flow_item_gtp_mask;
9320                 break;
9321         case RTE_FLOW_ITEM_TYPE_GTP_PSC:
9322                 mask = &rte_flow_item_gtp_psc_mask;
9323                 break;
9324         case RTE_FLOW_ITEM_TYPE_GENEVE:
9325                 mask = &rte_flow_item_geneve_mask;
9326                 break;
9327         case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
9328                 mask = &rte_flow_item_geneve_opt_mask;
9329                 break;
9330         case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
9331                 mask = &rte_flow_item_pppoe_proto_id_mask;
9332                 break;
9333         case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
9334                 mask = &rte_flow_item_l2tpv3oip_mask;
9335                 break;
9336         case RTE_FLOW_ITEM_TYPE_ESP:
9337                 mask = &rte_flow_item_esp_mask;
9338                 break;
9339         case RTE_FLOW_ITEM_TYPE_AH:
9340                 mask = &rte_flow_item_ah_mask;
9341                 break;
9342         case RTE_FLOW_ITEM_TYPE_PFCP:
9343                 mask = &rte_flow_item_pfcp_mask;
9344                 break;
9345         case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
9346         case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
9347                 mask = &rte_flow_item_ethdev_mask;
9348                 break;
9349         case RTE_FLOW_ITEM_TYPE_L2TPV2:
9350                 mask = &rte_flow_item_l2tpv2_mask;
9351                 break;
9352         case RTE_FLOW_ITEM_TYPE_PPP:
9353                 mask = &rte_flow_item_ppp_mask;
9354                 break;
9355         default:
9356                 break;
9357         }
9358         return mask;
9359 }
9360
9361 /** Dispatch parsed buffer to function calls. */
9362 static void
9363 cmd_set_raw_parsed_sample(const struct buffer *in)
9364 {
9365         uint32_t n = in->args.vc.actions_n;
9366         uint32_t i = 0;
9367         struct rte_flow_action *action = NULL;
9368         struct rte_flow_action *data = NULL;
9369         const struct rte_flow_action_rss *rss = NULL;
9370         size_t size = 0;
9371         uint16_t idx = in->port; /* We borrow port field as index */
9372         uint32_t max_size = sizeof(struct rte_flow_action) *
9373                                                 ACTION_SAMPLE_ACTIONS_NUM;
9374
9375         RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
9376         data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
9377         memset(data, 0x00, max_size);
9378         for (; i <= n - 1; i++) {
9379                 action = in->args.vc.actions + i;
9380                 if (action->type == RTE_FLOW_ACTION_TYPE_END)
9381                         break;
9382                 switch (action->type) {
9383                 case RTE_FLOW_ACTION_TYPE_MARK:
9384                         size = sizeof(struct rte_flow_action_mark);
9385                         rte_memcpy(&sample_mark[idx],
9386                                 (const void *)action->conf, size);
9387                         action->conf = &sample_mark[idx];
9388                         break;
9389                 case RTE_FLOW_ACTION_TYPE_COUNT:
9390                         size = sizeof(struct rte_flow_action_count);
9391                         rte_memcpy(&sample_count[idx],
9392                                 (const void *)action->conf, size);
9393                         action->conf = &sample_count[idx];
9394                         break;
9395                 case RTE_FLOW_ACTION_TYPE_QUEUE:
9396                         size = sizeof(struct rte_flow_action_queue);
9397                         rte_memcpy(&sample_queue[idx],
9398                                 (const void *)action->conf, size);
9399                         action->conf = &sample_queue[idx];
9400                         break;
9401                 case RTE_FLOW_ACTION_TYPE_RSS:
9402                         size = sizeof(struct rte_flow_action_rss);
9403                         rss = action->conf;
9404                         rte_memcpy(&sample_rss_data[idx].conf,
9405                                    (const void *)rss, size);
9406                         if (rss->key_len && rss->key) {
9407                                 sample_rss_data[idx].conf.key =
9408                                                 sample_rss_data[idx].key;
9409                                 rte_memcpy((void *)((uintptr_t)
9410                                            sample_rss_data[idx].conf.key),
9411                                            (const void *)rss->key,
9412                                            sizeof(uint8_t) * rss->key_len);
9413                         }
9414                         if (rss->queue_num && rss->queue) {
9415                                 sample_rss_data[idx].conf.queue =
9416                                                 sample_rss_data[idx].queue;
9417                                 rte_memcpy((void *)((uintptr_t)
9418                                            sample_rss_data[idx].conf.queue),
9419                                            (const void *)rss->queue,
9420                                            sizeof(uint16_t) * rss->queue_num);
9421                         }
9422                         action->conf = &sample_rss_data[idx].conf;
9423                         break;
9424                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
9425                         size = sizeof(struct rte_flow_action_raw_encap);
9426                         rte_memcpy(&sample_encap[idx],
9427                                 (const void *)action->conf, size);
9428                         action->conf = &sample_encap[idx];
9429                         break;
9430                 case RTE_FLOW_ACTION_TYPE_PORT_ID:
9431                         size = sizeof(struct rte_flow_action_port_id);
9432                         rte_memcpy(&sample_port_id[idx],
9433                                 (const void *)action->conf, size);
9434                         action->conf = &sample_port_id[idx];
9435                         break;
9436                 case RTE_FLOW_ACTION_TYPE_PF:
9437                         break;
9438                 case RTE_FLOW_ACTION_TYPE_VF:
9439                         size = sizeof(struct rte_flow_action_vf);
9440                         rte_memcpy(&sample_vf[idx],
9441                                         (const void *)action->conf, size);
9442                         action->conf = &sample_vf[idx];
9443                         break;
9444                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
9445                         size = sizeof(struct rte_flow_action_vxlan_encap);
9446                         parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
9447                         action->conf = &sample_vxlan_encap[idx].conf;
9448                         break;
9449                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
9450                         size = sizeof(struct rte_flow_action_nvgre_encap);
9451                         parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
9452                         action->conf = &sample_nvgre_encap[idx];
9453                         break;
9454                 default:
9455                         fprintf(stderr, "Error - Not supported action\n");
9456                         return;
9457                 }
9458                 rte_memcpy(data, action, sizeof(struct rte_flow_action));
9459                 data++;
9460         }
9461 }
9462
9463 /** Dispatch parsed buffer to function calls. */
9464 static void
9465 cmd_set_raw_parsed(const struct buffer *in)
9466 {
9467         uint32_t n = in->args.vc.pattern_n;
9468         int i = 0;
9469         struct rte_flow_item *item = NULL;
9470         size_t size = 0;
9471         uint8_t *data = NULL;
9472         uint8_t *data_tail = NULL;
9473         size_t *total_size = NULL;
9474         uint16_t upper_layer = 0;
9475         uint16_t proto = 0;
9476         uint16_t idx = in->port; /* We borrow port field as index */
9477         int gtp_psc = -1; /* GTP PSC option index. */
9478
9479         if (in->command == SET_SAMPLE_ACTIONS)
9480                 return cmd_set_raw_parsed_sample(in);
9481         RTE_ASSERT(in->command == SET_RAW_ENCAP ||
9482                    in->command == SET_RAW_DECAP);
9483         if (in->command == SET_RAW_ENCAP) {
9484                 total_size = &raw_encap_confs[idx].size;
9485                 data = (uint8_t *)&raw_encap_confs[idx].data;
9486         } else {
9487                 total_size = &raw_decap_confs[idx].size;
9488                 data = (uint8_t *)&raw_decap_confs[idx].data;
9489         }
9490         *total_size = 0;
9491         memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
9492         /* process hdr from upper layer to low layer (L3/L4 -> L2). */
9493         data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
9494         for (i = n - 1 ; i >= 0; --i) {
9495                 const struct rte_flow_item_gtp *gtp;
9496                 const struct rte_flow_item_geneve_opt *opt;
9497
9498                 item = in->args.vc.pattern + i;
9499                 if (item->spec == NULL)
9500                         item->spec = flow_item_default_mask(item);
9501                 switch (item->type) {
9502                 case RTE_FLOW_ITEM_TYPE_ETH:
9503                         size = sizeof(struct rte_ether_hdr);
9504                         break;
9505                 case RTE_FLOW_ITEM_TYPE_VLAN:
9506                         size = sizeof(struct rte_vlan_hdr);
9507                         proto = RTE_ETHER_TYPE_VLAN;
9508                         break;
9509                 case RTE_FLOW_ITEM_TYPE_IPV4:
9510                         size = sizeof(struct rte_ipv4_hdr);
9511                         proto = RTE_ETHER_TYPE_IPV4;
9512                         break;
9513                 case RTE_FLOW_ITEM_TYPE_IPV6:
9514                         size = sizeof(struct rte_ipv6_hdr);
9515                         proto = RTE_ETHER_TYPE_IPV6;
9516                         break;
9517                 case RTE_FLOW_ITEM_TYPE_UDP:
9518                         size = sizeof(struct rte_udp_hdr);
9519                         proto = 0x11;
9520                         break;
9521                 case RTE_FLOW_ITEM_TYPE_TCP:
9522                         size = sizeof(struct rte_tcp_hdr);
9523                         proto = 0x06;
9524                         break;
9525                 case RTE_FLOW_ITEM_TYPE_VXLAN:
9526                         size = sizeof(struct rte_vxlan_hdr);
9527                         break;
9528                 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
9529                         size = sizeof(struct rte_vxlan_gpe_hdr);
9530                         break;
9531                 case RTE_FLOW_ITEM_TYPE_GRE:
9532                         size = sizeof(struct rte_gre_hdr);
9533                         proto = 0x2F;
9534                         break;
9535                 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
9536                         size = sizeof(rte_be32_t);
9537                         proto = 0x0;
9538                         break;
9539                 case RTE_FLOW_ITEM_TYPE_MPLS:
9540                         size = sizeof(struct rte_mpls_hdr);
9541                         proto = 0x0;
9542                         break;
9543                 case RTE_FLOW_ITEM_TYPE_NVGRE:
9544                         size = sizeof(struct rte_flow_item_nvgre);
9545                         proto = 0x2F;
9546                         break;
9547                 case RTE_FLOW_ITEM_TYPE_GENEVE:
9548                         size = sizeof(struct rte_geneve_hdr);
9549                         break;
9550                 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
9551                         opt = (const struct rte_flow_item_geneve_opt *)
9552                                                                 item->spec;
9553                         size = offsetof(struct rte_flow_item_geneve_opt, data);
9554                         if (opt->option_len && opt->data) {
9555                                 *total_size += opt->option_len *
9556                                                sizeof(uint32_t);
9557                                 rte_memcpy(data_tail - (*total_size),
9558                                            opt->data,
9559                                            opt->option_len * sizeof(uint32_t));
9560                         }
9561                         break;
9562                 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
9563                         size = sizeof(rte_be32_t);
9564                         proto = 0x73;
9565                         break;
9566                 case RTE_FLOW_ITEM_TYPE_ESP:
9567                         size = sizeof(struct rte_esp_hdr);
9568                         proto = 0x32;
9569                         break;
9570                 case RTE_FLOW_ITEM_TYPE_AH:
9571                         size = sizeof(struct rte_flow_item_ah);
9572                         proto = 0x33;
9573                         break;
9574                 case RTE_FLOW_ITEM_TYPE_GTP:
9575                         if (gtp_psc < 0) {
9576                                 size = sizeof(struct rte_gtp_hdr);
9577                                 break;
9578                         }
9579                         if (gtp_psc != i + 1) {
9580                                 fprintf(stderr,
9581                                         "Error - GTP PSC does not follow GTP\n");
9582                                 goto error;
9583                         }
9584                         gtp = item->spec;
9585                         if ((gtp->v_pt_rsv_flags & 0x07) != 0x04) {
9586                                 /* Only E flag should be set. */
9587                                 fprintf(stderr,
9588                                         "Error - GTP unsupported flags\n");
9589                                 goto error;
9590                         } else {
9591                                 struct rte_gtp_hdr_ext_word ext_word = {
9592                                         .next_ext = 0x85
9593                                 };
9594
9595                                 /* We have to add GTP header extra word. */
9596                                 *total_size += sizeof(ext_word);
9597                                 rte_memcpy(data_tail - (*total_size),
9598                                            &ext_word, sizeof(ext_word));
9599                         }
9600                         size = sizeof(struct rte_gtp_hdr);
9601                         break;
9602                 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
9603                         if (gtp_psc >= 0) {
9604                                 fprintf(stderr,
9605                                         "Error - Multiple GTP PSC items\n");
9606                                 goto error;
9607                         } else {
9608                                 const struct rte_flow_item_gtp_psc
9609                                         *opt = item->spec;
9610                                 struct {
9611                                         uint8_t len;
9612                                         uint8_t pdu_type:4;
9613                                         uint8_t qfi:6;
9614                                         uint8_t next;
9615                                 } psc;
9616                                 psc.len = sizeof(psc) / 4;
9617                                 psc.pdu_type = opt->hdr.type;
9618                                 psc.qfi = opt->hdr.qfi;
9619                                 psc.next = 0;
9620                                 *total_size += sizeof(psc);
9621                                 rte_memcpy(data_tail - (*total_size),
9622                                            &psc, sizeof(psc));
9623                                 gtp_psc = i;
9624                                 size = 0;
9625                         }
9626                         break;
9627                 case RTE_FLOW_ITEM_TYPE_PFCP:
9628                         size = sizeof(struct rte_flow_item_pfcp);
9629                         break;
9630                 case RTE_FLOW_ITEM_TYPE_FLEX:
9631                         size = item->spec ?
9632                                 ((const struct rte_flow_item_flex *)
9633                                 item->spec)->length : 0;
9634                         break;
9635                 case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
9636                         size = 0;
9637                         if (item->spec) {
9638                                 const struct rte_flow_item_gre_opt
9639                                         *opt = item->spec;
9640                                 if (opt->checksum_rsvd.checksum) {
9641                                         *total_size +=
9642                                                 sizeof(opt->checksum_rsvd);
9643                                         rte_memcpy(data_tail - (*total_size),
9644                                                    &opt->checksum_rsvd,
9645                                                    sizeof(opt->checksum_rsvd));
9646                                 }
9647                                 if (opt->key.key) {
9648                                         *total_size += sizeof(opt->key.key);
9649                                         rte_memcpy(data_tail - (*total_size),
9650                                                    &opt->key.key,
9651                                                    sizeof(opt->key.key));
9652                                 }
9653                                 if (opt->sequence.sequence) {
9654                                         *total_size += sizeof(opt->sequence.sequence);
9655                                         rte_memcpy(data_tail - (*total_size),
9656                                                    &opt->sequence.sequence,
9657                                                    sizeof(opt->sequence.sequence));
9658                                 }
9659                         }
9660                         proto = 0x2F;
9661                         break;
9662                 default:
9663                         fprintf(stderr, "Error - Not supported item\n");
9664                         goto error;
9665                 }
9666                 *total_size += size;
9667                 rte_memcpy(data_tail - (*total_size), item->spec, size);
9668                 /* update some fields which cannot be set by cmdline */
9669                 update_fields((data_tail - (*total_size)), item,
9670                               upper_layer);
9671                 upper_layer = proto;
9672         }
9673         if (verbose_level & 0x1)
9674                 printf("total data size is %zu\n", (*total_size));
9675         RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
9676         memmove(data, (data_tail - (*total_size)), *total_size);
9677         return;
9678
9679 error:
9680         *total_size = 0;
9681         memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
9682 }
9683
9684 /** Populate help strings for current token (cmdline API). */
9685 static int
9686 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
9687                      unsigned int size)
9688 {
9689         struct context *ctx = &cmd_flow_context;
9690         const struct token *token = &token_list[ctx->prev];
9691
9692         (void)hdr;
9693         if (!size)
9694                 return -1;
9695         /* Set token type and update global help with details. */
9696         snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
9697         if (token->help)
9698                 cmd_set_raw.help_str = token->help;
9699         else
9700                 cmd_set_raw.help_str = token->name;
9701         return 0;
9702 }
9703
9704 /** Token definition template (cmdline API). */
9705 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
9706         .ops = &(struct cmdline_token_ops){
9707                 .parse = cmd_flow_parse,
9708                 .complete_get_nb = cmd_flow_complete_get_nb,
9709                 .complete_get_elt = cmd_flow_complete_get_elt,
9710                 .get_help = cmd_set_raw_get_help,
9711         },
9712         .offset = 0,
9713 };
9714
9715 /** Populate the next dynamic token. */
9716 static void
9717 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
9718              cmdline_parse_token_hdr_t **hdr_inst)
9719 {
9720         struct context *ctx = &cmd_flow_context;
9721
9722         /* Always reinitialize context before requesting the first token. */
9723         if (!(hdr_inst - cmd_set_raw.tokens)) {
9724                 cmd_flow_context_init(ctx);
9725                 ctx->curr = START_SET;
9726         }
9727         /* Return NULL when no more tokens are expected. */
9728         if (!ctx->next_num && (ctx->curr != START_SET)) {
9729                 *hdr = NULL;
9730                 return;
9731         }
9732         /* Determine if command should end here. */
9733         if (ctx->eol && ctx->last && ctx->next_num) {
9734                 const enum index *list = ctx->next[ctx->next_num - 1];
9735                 int i;
9736
9737                 for (i = 0; list[i]; ++i) {
9738                         if (list[i] != END)
9739                                 continue;
9740                         *hdr = NULL;
9741                         return;
9742                 }
9743         }
9744         *hdr = &cmd_set_raw_token_hdr;
9745 }
9746
9747 /** Token generator and output processing callback (cmdline API). */
9748 static void
9749 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
9750 {
9751         if (cl == NULL)
9752                 cmd_set_raw_tok(arg0, arg2);
9753         else
9754                 cmd_set_raw_parsed(arg0);
9755 }
9756
9757 /** Global parser instance (cmdline API). */
9758 cmdline_parse_inst_t cmd_set_raw = {
9759         .f = cmd_set_raw_cb,
9760         .data = NULL, /**< Unused. */
9761         .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
9762         .tokens = {
9763                 NULL,
9764         }, /**< Tokens are returned by cmd_flow_tok(). */
9765 };
9766
9767 /* *** display raw_encap/raw_decap buf */
9768 struct cmd_show_set_raw_result {
9769         cmdline_fixed_string_t cmd_show;
9770         cmdline_fixed_string_t cmd_what;
9771         cmdline_fixed_string_t cmd_all;
9772         uint16_t cmd_index;
9773 };
9774
9775 static void
9776 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
9777 {
9778         struct cmd_show_set_raw_result *res = parsed_result;
9779         uint16_t index = res->cmd_index;
9780         uint8_t all = 0;
9781         uint8_t *raw_data = NULL;
9782         size_t raw_size = 0;
9783         char title[16] = {0};
9784
9785         RTE_SET_USED(cl);
9786         RTE_SET_USED(data);
9787         if (!strcmp(res->cmd_all, "all")) {
9788                 all = 1;
9789                 index = 0;
9790         } else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
9791                 fprintf(stderr, "index should be 0-%u\n",
9792                         RAW_ENCAP_CONFS_MAX_NUM - 1);
9793                 return;
9794         }
9795         do {
9796                 if (!strcmp(res->cmd_what, "raw_encap")) {
9797                         raw_data = (uint8_t *)&raw_encap_confs[index].data;
9798                         raw_size = raw_encap_confs[index].size;
9799                         snprintf(title, 16, "\nindex: %u", index);
9800                         rte_hexdump(stdout, title, raw_data, raw_size);
9801                 } else {
9802                         raw_data = (uint8_t *)&raw_decap_confs[index].data;
9803                         raw_size = raw_decap_confs[index].size;
9804                         snprintf(title, 16, "\nindex: %u", index);
9805                         rte_hexdump(stdout, title, raw_data, raw_size);
9806                 }
9807         } while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
9808 }
9809
9810 cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
9811         TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
9812                         cmd_show, "show");
9813 cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
9814         TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
9815                         cmd_what, "raw_encap#raw_decap");
9816 cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
9817         TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
9818                         cmd_index, RTE_UINT16);
9819 cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
9820         TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
9821                         cmd_all, "all");
9822 cmdline_parse_inst_t cmd_show_set_raw = {
9823         .f = cmd_show_set_raw_parsed,
9824         .data = NULL,
9825         .help_str = "show <raw_encap|raw_decap> <index>",
9826         .tokens = {
9827                 (void *)&cmd_show_set_raw_cmd_show,
9828                 (void *)&cmd_show_set_raw_cmd_what,
9829                 (void *)&cmd_show_set_raw_cmd_index,
9830                 NULL,
9831         },
9832 };
9833 cmdline_parse_inst_t cmd_show_set_raw_all = {
9834         .f = cmd_show_set_raw_parsed,
9835         .data = NULL,
9836         .help_str = "show <raw_encap|raw_decap> all",
9837         .tokens = {
9838                 (void *)&cmd_show_set_raw_cmd_show,
9839                 (void *)&cmd_show_set_raw_cmd_what,
9840                 (void *)&cmd_show_set_raw_cmd_all,
9841                 NULL,
9842         },
9843 };