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