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