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