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