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