Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.a...@intel.com>
---
 app/test-pmd/cmdline_flow.c | 872 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 872 insertions(+)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 5754e78..7d80f2a 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -237,6 +237,44 @@ enum index {
        ACTION_OF_POP_MPLS_ETHERTYPE,
        ACTION_OF_PUSH_MPLS,
        ACTION_OF_PUSH_MPLS_ETHERTYPE,
+       ACTION_VXLAN_ENCAP,
+       ACTION_VXLAN_ENCAP_ETH_DST,
+       ACTION_VXLAN_ENCAP_ETH_DST_VALUE,
+       ACTION_VXLAN_ENCAP_ETH_SRC,
+       ACTION_VXLAN_ENCAP_ETH_SRC_VALUE,
+       ACTION_VXLAN_ENCAP_ETH_TYPE,
+       ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE,
+       ACTION_VXLAN_ENCAP_IPV4_DST,
+       ACTION_VXLAN_ENCAP_IPV4_DST_VALUE,
+       ACTION_VXLAN_ENCAP_IPV4_SRC,
+       ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE,
+       ACTION_VXLAN_ENCAP_IPV4_PROTO,
+       ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE,
+       ACTION_VXLAN_ENCAP_UDP_SRC,
+       ACTION_VXLAN_ENCAP_UDP_SRC_VALUE,
+       ACTION_VXLAN_ENCAP_UDP_DST,
+       ACTION_VXLAN_ENCAP_UDP_DST_VALUE,
+       ACTION_VXLAN_ENCAP_VXLAN_VNI,
+       ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE,
+       ACTION_VXLAN_ENCAP_END,
+       ACTION_VXLAN_DECAP,
+       ACTION_NVGRE_ENCAP,
+       ACTION_NVGRE_ENCAP_ETH_DST,
+       ACTION_NVGRE_ENCAP_ETH_DST_VALUE,
+       ACTION_NVGRE_ENCAP_ETH_SRC,
+       ACTION_NVGRE_ENCAP_ETH_SRC_VALUE,
+       ACTION_NVGRE_ENCAP_ETH_TYPE,
+       ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE,
+       ACTION_NVGRE_ENCAP_IPV4_DST,
+       ACTION_NVGRE_ENCAP_IPV4_DST_VALUE,
+       ACTION_NVGRE_ENCAP_IPV4_SRC,
+       ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE,
+       ACTION_NVGRE_ENCAP_IPV4_PROTO,
+       ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE,
+       ACTION_NVGRE_ENCAP_NVGRE_VSNI,
+       ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE,
+       ACTION_NVGRE_ENCAP_END,
+       ACTION_NVGRE_DECAP,
 };
 
 /** Maximum size for pattern in struct rte_flow_item_raw. */
@@ -256,6 +294,28 @@ struct action_rss_data {
        uint16_t queue[ACTION_RSS_QUEUE_NUM];
 };
 
+#define ACTION_VXLAN_ENCAP_MAX_PATTERN 5
+#define ACTION_NVGRE_ENCAP_MAX_PATTERN 4
+
+struct action_vxlan_encap_data {
+       struct rte_flow_action_vxlan_encap conf;
+       struct rte_flow_item pattern[ACTION_VXLAN_ENCAP_MAX_PATTERN];
+       struct rte_flow_item_eth eth;
+       struct rte_flow_item_ipv4 ipv4;
+       struct rte_flow_item_udp udp;
+       struct rte_flow_item_vxlan vxlan;
+       uint32_t hdr_flags;
+};
+
+struct action_nvgre_encap_data {
+       struct rte_flow_action_nvgre_encap conf;
+       struct rte_flow_item pattern[ACTION_NVGRE_ENCAP_MAX_PATTERN];
+       struct rte_flow_item_eth eth;
+       struct rte_flow_item_ipv4 ipv4;
+       struct rte_flow_item_nvgre nvgre;
+       uint32_t hdr_flags;
+};
+
 /** Maximum number of subsequent tokens and arguments on the stack. */
 #define CTX_STACK_SIZE 16
 
@@ -383,6 +443,13 @@ struct token {
                .size = (s), \
        })
 
+#define ARGS_ENTRY_ARB_HTON(o, s) \
+       (&(const struct arg){ \
+               .hton = 1, \
+               .offset = (o), \
+               .size = (s), \
+       })
+
 /** Same as ARGS_ENTRY_ARB() with bounded values. */
 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
        (&(const struct arg){ \
@@ -773,6 +840,10 @@ static const enum index next_action[] = {
        ACTION_OF_SET_VLAN_PCP,
        ACTION_OF_POP_MPLS,
        ACTION_OF_PUSH_MPLS,
+       ACTION_VXLAN_ENCAP,
+       ACTION_VXLAN_DECAP,
+       ACTION_NVGRE_ENCAP,
+       ACTION_NVGRE_DECAP,
        ZERO,
 };
 
@@ -874,6 +945,44 @@ static const enum index action_jump[] = {
        ZERO,
 };
 
+static const enum index action_vxlan_encap[] = {
+       ACTION_VXLAN_ENCAP_ETH_DST,
+       ACTION_VXLAN_ENCAP_ETH_SRC,
+       ACTION_VXLAN_ENCAP_ETH_TYPE,
+       ACTION_VXLAN_ENCAP_IPV4_DST,
+       ACTION_VXLAN_ENCAP_IPV4_SRC,
+       ACTION_VXLAN_ENCAP_IPV4_PROTO,
+       ACTION_VXLAN_ENCAP_UDP_DST,
+       ACTION_VXLAN_ENCAP_UDP_SRC,
+       ACTION_VXLAN_ENCAP_VXLAN_VNI,
+       ACTION_VXLAN_ENCAP_END,
+       ACTION_NEXT,
+       ZERO,
+};
+
+static const enum index action_vxlan_decap[] = {
+       ACTION_NEXT,
+       ZERO,
+};
+
+static const enum index action_nvgre_encap[] = {
+       ACTION_NVGRE_ENCAP_ETH_DST,
+       ACTION_NVGRE_ENCAP_ETH_SRC,
+       ACTION_NVGRE_ENCAP_ETH_TYPE,
+       ACTION_NVGRE_ENCAP_IPV4_DST,
+       ACTION_NVGRE_ENCAP_IPV4_SRC,
+       ACTION_NVGRE_ENCAP_IPV4_PROTO,
+       ACTION_NVGRE_ENCAP_NVGRE_VSNI,
+       ACTION_NVGRE_ENCAP_END,
+       ACTION_NEXT,
+       ZERO,
+};
+
+static const enum index action_nvgre_decap[] = {
+       ACTION_NEXT,
+       ZERO,
+};
+
 static int parse_init(struct context *, const struct token *,
                      const char *, unsigned int,
                      void *, unsigned int);
@@ -896,6 +1005,42 @@ static int parse_vc_action_rss_type(struct context *, 
const struct token *,
 static int parse_vc_action_rss_queue(struct context *, const struct token *,
                                     const char *, unsigned int, void *,
                                     unsigned int);
+static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
+                                      const char *, unsigned int, void *,
+                                      unsigned int);
+static int parse_vc_action_vxlan_decap(struct context *, const struct token *,
+                                      const char *, unsigned int, void *,
+                                      unsigned int);
+static int parse_vc_action_vxlan_encap_fields(struct context *,
+                                             const struct token *,
+                                             const char *, unsigned int,
+                                             void *, unsigned int);
+static int parse_vc_action_vxlan_encap_fields_value(struct context *,
+                                                   const struct token *,
+                                                   const char *, unsigned int,
+                                                   void *, unsigned int);
+static int parse_vc_action_vxlan_encap_end(struct context *,
+                                          const struct token *,
+                                          const char *, unsigned int,
+                                          void *, unsigned int);
+static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
+                                      const char *, unsigned int, void *,
+                                      unsigned int);
+static int parse_vc_action_nvgre_decap(struct context *, const struct token *,
+                                      const char *, unsigned int, void *,
+                                      unsigned int);
+static int parse_vc_action_nvgre_encap_fields(struct context *,
+                                             const struct token *,
+                                             const char *, unsigned int,
+                                             void *, unsigned int);
+static int parse_vc_action_nvgre_encap_fields_value(struct context *,
+                                                   const struct token *,
+                                                   const char *, unsigned int,
+                                                   void *, unsigned int);
+static int parse_vc_action_nvgre_encap_end(struct context *,
+                                          const struct token *,
+                                          const char *, unsigned int,
+                                          void *, unsigned int);
 static int parse_destroy(struct context *, const struct token *,
                         const char *, unsigned int,
                         void *, unsigned int);
@@ -2362,6 +2507,256 @@ static const struct token token_list[] = {
                              ethertype)),
                .call = parse_vc_conf,
        },
+       [ACTION_VXLAN_ENCAP] = {
+               .name = "vxlan_encap",
+               .help = "encap flow with vxlan tunnel definition",
+               .priv = PRIV_ACTION(VXLAN_ENCAP,
+                                   sizeof(struct action_vxlan_encap_data)),
+               .next = NEXT(action_vxlan_encap,
+                               NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_DST,
+                                       ACTION_VXLAN_ENCAP_ETH_SRC,
+                                       ACTION_VXLAN_ENCAP_ETH_TYPE,
+                                       ACTION_VXLAN_ENCAP_IPV4_DST,
+                                       ACTION_VXLAN_ENCAP_IPV4_SRC,
+                                       ACTION_VXLAN_ENCAP_IPV4_PROTO,
+                                       ACTION_VXLAN_ENCAP_UDP_DST,
+                                       ACTION_VXLAN_ENCAP_UDP_SRC,
+                                       ACTION_VXLAN_ENCAP_VXLAN_VNI,
+                                       ACTION_VXLAN_ENCAP_END)),
+               .call = parse_vc_action_vxlan_encap,
+       },
+       [ACTION_VXLAN_DECAP] = {
+               .name = "vxlan_decap",
+               .help = "decap flow with vxlan tunnel definition",
+               .priv = PRIV_ACTION(VXLAN_DECAP, 0),
+               .next = NEXT(action_vxlan_decap),
+               .call = parse_vc_action_vxlan_decap,
+       },
+       [ACTION_VXLAN_ENCAP_ETH_DST] = {
+               .name = "eth_dst",
+               .help = "destination MAC for vxlan tunnel",
+               .next = NEXT(action_vxlan_encap,
+                            NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_DST_VALUE)),
+               .call = parse_vc_action_vxlan_encap_fields,
+       },
+       [ACTION_VXLAN_ENCAP_ETH_DST_VALUE] = {
+               .name = "eth_dst_value",
+               .help = "destination MAC for vxlan tunnel",
+               .call = parse_vc_action_vxlan_encap_fields_value,
+       },
+       [ACTION_VXLAN_ENCAP_ETH_SRC] = {
+               .name = "eth_src",
+               .help = "source MAC for vxlan tunnel",
+               .next = NEXT(action_vxlan_encap,
+                            NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_SRC_VALUE)),
+               .call = parse_vc_action_vxlan_encap_fields,
+       },
+       [ACTION_VXLAN_ENCAP_ETH_SRC_VALUE] = {
+               .name = "eth_src_value",
+               .help = "source MAC for vxlan tunnel",
+               .call = parse_vc_action_vxlan_encap_fields_value,
+       },
+       [ACTION_VXLAN_ENCAP_ETH_TYPE] = {
+               .name = "eth_type",
+               .help = "eth type for vxlan tunnel",
+               .next = NEXT(action_vxlan_encap,
+                            NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE)),
+               .call = parse_vc_action_vxlan_encap_fields,
+       },
+       [ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE] = {
+               .name = "eth_type_value",
+               .help = "eth type for vxlan tunnel",
+               .call = parse_vc_action_vxlan_encap_fields_value,
+       },
+       [ACTION_VXLAN_ENCAP_IPV4_DST] = {
+               .name = "ipv4_dst",
+               .help = "destination ipv4 IP for vxlan tunnel",
+               .next = NEXT(action_vxlan_encap,
+                            NEXT_ENTRY(ACTION_VXLAN_ENCAP_IPV4_DST_VALUE)),
+               .call = parse_vc_action_vxlan_encap_fields,
+       },
+       [ACTION_VXLAN_ENCAP_IPV4_DST_VALUE] = {
+               .name = "ipv4_dst_value",
+               .help = "destination ipv4 IP for vxlan tunnel",
+               .call = parse_vc_action_vxlan_encap_fields_value,
+       },
+       [ACTION_VXLAN_ENCAP_IPV4_SRC] = {
+               .name = "ipv4_src",
+               .help = "source ipv4 IP for vxlan tunnel",
+               .next = NEXT(action_vxlan_encap,
+                            NEXT_ENTRY(ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE)),
+               .call = parse_vc_action_vxlan_encap_fields,
+       },
+       [ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE] = {
+               .name = "ipv4_src_value",
+               .help = "source ipv4 IP for vxlan tunnel",
+               .call = parse_vc_action_vxlan_encap_fields_value,
+       },
+       [ACTION_VXLAN_ENCAP_IPV4_PROTO] = {
+               .name = "ipv4_proto",
+               .help = "ipv4 proto for vxlan tunnel",
+               .next = NEXT(action_vxlan_encap,
+                            NEXT_ENTRY(ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE)),
+               .call = parse_vc_action_vxlan_encap_fields,
+       },
+       [ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE] = {
+               .name = "ipv4_proto_value",
+               .help = "ipv4 proto for vxlan tunnel",
+               .call = parse_vc_action_vxlan_encap_fields_value,
+       },
+       [ACTION_VXLAN_ENCAP_UDP_DST] = {
+               .name = "udp_dst",
+               .help = "udp destination port for vxlan tunnel",
+               .next = NEXT(action_vxlan_encap,
+                            NEXT_ENTRY(ACTION_VXLAN_ENCAP_UDP_DST_VALUE)),
+               .call = parse_vc_action_vxlan_encap_fields,
+       },
+       [ACTION_VXLAN_ENCAP_UDP_DST_VALUE] = {
+               .name = "udp_dst_value",
+               .help = "udp destination port for vxlan tunnel",
+               .call = parse_vc_action_vxlan_encap_fields_value,
+       },
+       [ACTION_VXLAN_ENCAP_UDP_SRC] = {
+               .name = "udp_src",
+               .help = "udp source port for vxlan tunnel",
+               .next = NEXT(action_vxlan_encap,
+                            NEXT_ENTRY(ACTION_VXLAN_ENCAP_UDP_SRC_VALUE)),
+               .call = parse_vc_action_vxlan_encap_fields,
+       },
+       [ACTION_VXLAN_ENCAP_UDP_SRC_VALUE] = {
+               .name = "udp_src_value",
+               .help = "udp source port for vxlan tunnel",
+               .call = parse_vc_action_vxlan_encap_fields_value,
+       },
+       [ACTION_VXLAN_ENCAP_VXLAN_VNI] = {
+               .name = "vxlan_vni",
+               .help = "vxlan vni for vxlan tunnel",
+               .next = NEXT(action_vxlan_encap,
+                            NEXT_ENTRY(ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE)),
+               .call = parse_vc_action_vxlan_encap_fields,
+       },
+       [ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE] = {
+               .name = "vxlan_vni_value",
+               .help = "vxlan vni for vxlan tunnel",
+               .call = parse_vc_action_vxlan_encap_fields_value,
+       },
+       [ACTION_VXLAN_ENCAP_END] = {
+               .name = "end",
+               .help = "end of the pattern for vxlan encap",
+               .call = parse_vc_action_vxlan_encap_end,
+       },
+       [ACTION_NVGRE_ENCAP] = {
+               .name = "nvgre_encap",
+               .help = "encap flow with nvgre tunnel definition",
+               .priv = PRIV_ACTION(NVGRE_ENCAP,
+                                   sizeof(struct action_nvgre_encap_data)),
+               .next = NEXT(action_nvgre_encap,
+                               NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_DST,
+                                       ACTION_NVGRE_ENCAP_ETH_SRC,
+                                       ACTION_NVGRE_ENCAP_ETH_TYPE,
+                                       ACTION_NVGRE_ENCAP_IPV4_DST,
+                                       ACTION_NVGRE_ENCAP_IPV4_SRC,
+                                       ACTION_NVGRE_ENCAP_IPV4_PROTO,
+                                       ACTION_NVGRE_ENCAP_NVGRE_VSNI,
+                                       ACTION_NVGRE_ENCAP_END)),
+               .call = parse_vc_action_nvgre_encap,
+       },
+       [ACTION_NVGRE_DECAP] = {
+               .name = "nvgre_decap",
+               .help = "decap flow with nvgre tunnel definition",
+               .priv = PRIV_ACTION(NVGRE_DECAP, 0),
+               .next = NEXT(action_nvgre_decap),
+               .call = parse_vc_action_nvgre_decap,
+       },
+       [ACTION_NVGRE_ENCAP_ETH_DST] = {
+               .name = "eth_dst",
+               .help = "destination MAC for nvgre tunnel",
+               .next = NEXT(action_nvgre_encap,
+                            NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_DST_VALUE)),
+               .call = parse_vc_action_nvgre_encap_fields,
+       },
+       [ACTION_NVGRE_ENCAP_ETH_DST_VALUE] = {
+               .name = "eth_dst_value",
+               .help = "destination MAC for nvgre tunnel",
+               .call = parse_vc_action_nvgre_encap_fields_value,
+       },
+       [ACTION_NVGRE_ENCAP_ETH_SRC] = {
+               .name = "eth_src",
+               .help = "source MAC for nvgre tunnel",
+               .next = NEXT(action_nvgre_encap,
+                            NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_SRC_VALUE)),
+               .call = parse_vc_action_nvgre_encap_fields,
+       },
+       [ACTION_NVGRE_ENCAP_ETH_SRC_VALUE] = {
+               .name = "eth_src_value",
+               .help = "source MAC for nvgre tunnel",
+               .call = parse_vc_action_nvgre_encap_fields_value,
+       },
+       [ACTION_NVGRE_ENCAP_ETH_TYPE] = {
+               .name = "eth_type",
+               .help = "eth type for nvgre tunnel",
+               .next = NEXT(action_nvgre_encap,
+                            NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE)),
+               .call = parse_vc_action_nvgre_encap_fields,
+       },
+       [ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE] = {
+               .name = "eth_type_value",
+               .help = "eth type for nvgre tunnel",
+               .call = parse_vc_action_nvgre_encap_fields_value,
+       },
+       [ACTION_NVGRE_ENCAP_IPV4_DST] = {
+               .name = "ipv4_dst",
+               .help = "destination ipv4 IP for nvgre tunnel",
+               .next = NEXT(action_nvgre_encap,
+                            NEXT_ENTRY(ACTION_NVGRE_ENCAP_IPV4_DST_VALUE)),
+               .call = parse_vc_action_nvgre_encap_fields,
+       },
+       [ACTION_NVGRE_ENCAP_IPV4_DST_VALUE] = {
+               .name = "ipv4_dst_value",
+               .help = "destination ipv4 IP for nvgre tunnel",
+               .call = parse_vc_action_nvgre_encap_fields_value,
+       },
+       [ACTION_NVGRE_ENCAP_IPV4_SRC] = {
+               .name = "ipv4_src",
+               .help = "source ipv4 IP for nvgre tunnel",
+               .next = NEXT(action_nvgre_encap,
+                            NEXT_ENTRY(ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE)),
+               .call = parse_vc_action_nvgre_encap_fields,
+       },
+       [ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE] = {
+               .name = "ipv4_src_value",
+               .help = "source ipv4 IP for nvgre tunnel",
+               .call = parse_vc_action_nvgre_encap_fields_value,
+       },
+       [ACTION_NVGRE_ENCAP_IPV4_PROTO] = {
+               .name = "ipv4_proto",
+               .help = "ipv4 proto for nvgre tunnel",
+               .next = NEXT(action_nvgre_encap,
+                            NEXT_ENTRY(ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE)),
+               .call = parse_vc_action_nvgre_encap_fields,
+       },
+       [ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE] = {
+               .name = "ipv4_proto_value",
+               .help = "ipv4 proto for nvgre tunnel",
+               .call = parse_vc_action_nvgre_encap_fields_value,
+       },
+       [ACTION_NVGRE_ENCAP_NVGRE_VSNI] = {
+               .name = "nvgre_vsni",
+               .help = "nvgre vsni for NVGRE tunnel",
+               .next = NEXT(action_nvgre_encap,
+                            NEXT_ENTRY(ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE)),
+               .call = parse_vc_action_nvgre_encap_fields,
+       },
+       [ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE] = {
+               .name = "nvgre_vsni_value",
+               .help = "nvgre vsni for nvgre tunnel",
+               .call = parse_vc_action_nvgre_encap_fields_value,
+       },
+       [ACTION_NVGRE_ENCAP_END] = {
+               .name = "end",
+               .help = "end of the pattern for nvgre encap",
+               .call = parse_vc_action_nvgre_encap_end,
+       },
 };
 
 /** Remove and return last entry from argument stack. */
@@ -2924,6 +3319,482 @@ parse_vc_action_rss_queue(struct context *ctx, const 
struct token *token,
        return len;
 }
 
+/** Parse VXLAN_ENCAP action. */
+static int
+parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
+                           const char *str, unsigned int len,
+                           void *buf, unsigned int size)
+{
+       struct buffer *out = buf;
+       struct rte_flow_action *action;
+       struct action_vxlan_encap_data *data;
+       int ret;
+
+       ret = parse_vc(ctx, token, str, len, buf, size);
+       if (ret < 0)
+               return ret;
+       /* Nothing else to do if there is no buffer. */
+       if (!out)
+               return ret;
+       if (!out->args.vc.actions_n)
+               return -1;
+       action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+       /* Point to selected object. */
+       ctx->object = out->args.vc.data;
+       ctx->objmask = NULL;
+       /* Set up default configuration. */
+       data = ctx->object;
+       data->conf.definition = data->pattern;
+       action->conf = &data->conf;
+
+       return ret;
+}
+
+/** Parse VXLAN_DECAP action. */
+static int
+parse_vc_action_vxlan_decap(struct context *ctx, const struct token *token,
+                           const char *str, unsigned int len,
+                           void *buf, unsigned int size)
+{
+       struct buffer *out = buf;
+       int ret;
+
+       ret = parse_vc(ctx, token, str, len, buf, size);
+       if (ret < 0)
+               return ret;
+       /* Nothing else to do if there is no buffer. */
+       if (!out)
+               return ret;
+       if (!out->args.vc.actions_n)
+               return -1;
+       /* Point to selected object. */
+       ctx->object = out->args.vc.data;
+       ctx->objmask = NULL;
+       return ret;
+}
+
+static uint32_t get_proto_index_using_flag(uint32_t flag)
+{
+       uint32_t c = 0, i = 0;
+       uint32_t supported_ptypes[] = {
+                                       RTE_PTYPE_L2_ETHER,
+                                       RTE_PTYPE_L2_ETHER_VLAN,
+                                       RTE_PTYPE_L3_IPV4,
+                                       RTE_PTYPE_L4_UDP,
+                                       RTE_PTYPE_TUNNEL_VXLAN,
+                                       RTE_PTYPE_TUNNEL_NVGRE
+                                      };
+
+       for (i = 0; i != RTE_DIM(supported_ptypes); i++) {
+               if (supported_ptypes[i] & flag)
+                       c++;
+       }
+       c = (c > 0) ? (c - 1) : 0;
+
+       return c;
+}
+
+/** Parse VXLAN_ENCAP action pattern fields. */
+static int
+parse_vc_action_vxlan_encap_fields(struct context *ctx,
+                                  const struct token *token,
+                                  const char *str, unsigned int len,
+                                  void *buf, unsigned int size)
+{
+       struct action_vxlan_encap_data *data;
+       uint32_t p_index;
+
+       (void)buf;
+       (void)size;
+       /* Token name must match. */
+       if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+               return -1;
+       if (!ctx->object)
+               return len;
+       switch (ctx->curr) {
+       case ACTION_VXLAN_ENCAP_ETH_DST:
+       case ACTION_VXLAN_ENCAP_ETH_SRC:
+       case ACTION_VXLAN_ENCAP_ETH_TYPE:
+               data = ctx->object;
+               data->hdr_flags |= RTE_PTYPE_L2_ETHER;
+               p_index = get_proto_index_using_flag(data->hdr_flags);
+               data->pattern[p_index].spec = &data->eth;
+               data->pattern[p_index].mask = &rte_flow_item_eth_mask;
+               data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_ETH;
+               break;
+       case ACTION_VXLAN_ENCAP_IPV4_DST:
+       case ACTION_VXLAN_ENCAP_IPV4_SRC:
+       case ACTION_VXLAN_ENCAP_IPV4_PROTO:
+               data = ctx->object;
+               data->hdr_flags |= RTE_PTYPE_L3_IPV4;
+               p_index = get_proto_index_using_flag(data->hdr_flags);
+               data->pattern[p_index].spec = &data->ipv4;
+               data->pattern[p_index].mask = &rte_flow_item_ipv4_mask;
+               data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_IPV4;
+               break;
+       case ACTION_VXLAN_ENCAP_UDP_DST:
+       case ACTION_VXLAN_ENCAP_UDP_SRC:
+               data = ctx->object;
+               data->hdr_flags |= RTE_PTYPE_L4_UDP;
+               p_index = get_proto_index_using_flag(data->hdr_flags);
+               data->pattern[p_index].spec = &data->udp;
+               data->pattern[p_index].mask = &rte_flow_item_udp_mask;
+               data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_UDP;
+               break;
+       case ACTION_VXLAN_ENCAP_VXLAN_VNI:
+               data = ctx->object;
+               data->hdr_flags |= RTE_PTYPE_TUNNEL_VXLAN;
+               p_index = get_proto_index_using_flag(data->hdr_flags);
+               data->pattern[p_index].spec = &data->vxlan;
+               data->pattern[p_index].mask = &rte_flow_item_vxlan_mask;
+               data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_VXLAN;
+               break;
+       default:
+               return -1;
+       }
+
+       return len;
+}
+
+/** Parse VXLAN_ENCAP action pattern fields value. */
+static int
+parse_vc_action_vxlan_encap_fields_value(struct context *ctx,
+                                        const struct token *token,
+                                        const char *str, unsigned int len,
+                                        void *buf, unsigned int size)
+{
+       struct action_vxlan_encap_data *data;
+       struct ether_addr mac;
+       char str2[len + 1];
+       struct in_addr ip4;
+       uint16_t val1;
+       uint32_t val2;
+       int ret;
+
+       (void)token;
+       (void)buf;
+       if (!ctx->object)
+               return len;
+       data = ctx->object;
+       switch (ctx->curr) {
+       case ACTION_VXLAN_ENCAP_ETH_DST_VALUE:
+               ret = cmdline_parse_etheraddr(NULL, str, &mac, size);
+               if (ret < 0 || (unsigned int)ret != len)
+                       return -1;
+               memcpy(&data->eth.dst, &mac, sizeof(mac));
+               break;
+       case ACTION_VXLAN_ENCAP_ETH_SRC_VALUE:
+               ret = cmdline_parse_etheraddr(NULL, str, &mac, size);
+               if (ret < 0 || (unsigned int)ret != len)
+                       return -1;
+               memcpy(&data->eth.src, &mac, sizeof(mac));
+               break;
+       case ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE:
+               memcpy(str2, str, len);
+               str2[len] = '\0';
+               val1 = strtoul(str2, NULL, 0);
+               if (val1 == 0)
+                       return -1;
+               data->eth.type = htons(val1);
+               break;
+       case ACTION_VXLAN_ENCAP_IPV4_DST_VALUE:
+               memcpy(str2, str, len);
+               str2[len] = '\0';
+               ret = inet_pton(AF_INET, str2, &ip4);
+               if (ret != 1)
+                       return -1;
+               memcpy(&data->ipv4.hdr.dst_addr, &ip4, sizeof(ip4));
+               break;
+       case ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE:
+               memcpy(str2, str, len);
+               str2[len] = '\0';
+               ret = inet_pton(AF_INET, str2, &ip4);
+               if (ret != 1)
+                       return -1;
+               memcpy(&data->ipv4.hdr.src_addr, &ip4, sizeof(ip4));
+               break;
+       case ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE:
+               memcpy(str2, str, len);
+               str2[len] = '\0';
+               val1 = strtoul(str2, NULL, 0);
+               if (val1 == 0)
+                       return -1;
+               data->ipv4.hdr.next_proto_id = val1;
+               break;
+       case ACTION_VXLAN_ENCAP_UDP_DST_VALUE:
+               memcpy(str2, str, len);
+               str2[len] = '\0';
+               val1 = strtoul(str2, NULL, 0);
+               if (val1 == 0)
+                       return -1;
+               data->udp.hdr.dst_port = htons(val1);
+               break;
+       case ACTION_VXLAN_ENCAP_UDP_SRC_VALUE:
+               memcpy(str2, str, len);
+               str2[len] = '\0';
+               val1 = strtoul(str2, NULL, 0);
+               if (val1 == 0)
+                       return -1;
+               data->udp.hdr.src_port = htons(val1);
+               break;
+       case ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE:
+               memcpy(str2, str, len);
+               str2[len] = '\0';
+               val2 = strtoul(str2, NULL, 0);
+               if (val2 == 0)
+                       return -1;
+               data->vxlan.vni[0] = (uint8_t)((val2 >> 16) & 0xff);
+               data->vxlan.vni[1] = (uint8_t)((val2 >> 8) & 0xff);
+               data->vxlan.vni[2] = (uint8_t)(val2 & 0xff);
+               break;
+       default:
+               return -1;
+       }
+
+       return len;
+}
+
+/** Parse VXLAN_ENCAP action pattern end. */
+static int
+parse_vc_action_vxlan_encap_end(struct context *ctx,
+                               const struct token *token,
+                               const char *str, unsigned int len,
+                               void *buf, unsigned int size)
+{
+       struct action_vxlan_encap_data *data;
+       uint32_t p_index;
+
+       (void)buf;
+       (void)size;
+       /* Token name must match. */
+       if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+               return -1;
+       if (ctx->curr != ACTION_VXLAN_ENCAP_END)
+               return -1;
+       if (!ctx->object)
+               return len;
+       data = ctx->object;
+       p_index = get_proto_index_using_flag(data->hdr_flags);
+       data->pattern[p_index + 1].type = RTE_FLOW_ITEM_TYPE_END;
+
+       return len;
+}
+
+/** Parse NVGRE_ENCAP action. */
+static int
+parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
+                           const char *str, unsigned int len,
+                           void *buf, unsigned int size)
+{
+       struct buffer *out = buf;
+       struct rte_flow_action *action;
+       struct action_nvgre_encap_data *data;
+       int ret;
+
+       ret = parse_vc(ctx, token, str, len, buf, size);
+       if (ret < 0)
+               return ret;
+       /* Nothing else to do if there is no buffer. */
+       if (!out)
+               return ret;
+       if (!out->args.vc.actions_n)
+               return -1;
+       action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+       /* Point to selected object. */
+       ctx->object = out->args.vc.data;
+       ctx->objmask = NULL;
+       /* Set up default configuration. */
+       data = ctx->object;
+       data->conf.definition = data->pattern;
+       action->conf = &data->conf;
+
+       return ret;
+}
+
+/** Parse NVGRE_DECAP action. */
+static int
+parse_vc_action_nvgre_decap(struct context *ctx, const struct token *token,
+                           const char *str, unsigned int len,
+                           void *buf, unsigned int size)
+{
+       struct buffer *out = buf;
+       int ret;
+
+       ret = parse_vc(ctx, token, str, len, buf, size);
+       if (ret < 0)
+               return ret;
+       /* Nothing else to do if there is no buffer. */
+       if (!out)
+               return ret;
+       if (!out->args.vc.actions_n)
+               return -1;
+       /* Point to selected object. */
+       ctx->object = out->args.vc.data;
+       ctx->objmask = NULL;
+       return ret;
+}
+
+/** Parse NVGRE_ENCAP action pattern fields. */
+static int
+parse_vc_action_nvgre_encap_fields(struct context *ctx,
+                                  const struct token *token,
+                                  const char *str, unsigned int len,
+                                  void *buf, unsigned int size)
+{
+       struct action_nvgre_encap_data *data;
+       uint32_t p_index;
+
+       (void)buf;
+       (void)size;
+       /* Token name must match. */
+       if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+               return -1;
+       if (!ctx->object)
+               return len;
+       switch (ctx->curr) {
+       case ACTION_NVGRE_ENCAP_ETH_DST:
+       case ACTION_NVGRE_ENCAP_ETH_SRC:
+       case ACTION_NVGRE_ENCAP_ETH_TYPE:
+               data = ctx->object;
+               data->hdr_flags |= RTE_PTYPE_L2_ETHER;
+               p_index = get_proto_index_using_flag(data->hdr_flags);
+               data->pattern[p_index].spec = &data->eth;
+               data->pattern[p_index].mask = &rte_flow_item_eth_mask;
+               data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_ETH;
+               break;
+       case ACTION_NVGRE_ENCAP_IPV4_DST:
+       case ACTION_NVGRE_ENCAP_IPV4_SRC:
+       case ACTION_NVGRE_ENCAP_IPV4_PROTO:
+               data = ctx->object;
+               data->hdr_flags |= RTE_PTYPE_L3_IPV4;
+               p_index = get_proto_index_using_flag(data->hdr_flags);
+               data->pattern[p_index].spec = &data->ipv4;
+               data->pattern[p_index].mask = &rte_flow_item_ipv4_mask;
+               data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_IPV4;
+               break;
+       case ACTION_NVGRE_ENCAP_NVGRE_VSNI:
+               data = ctx->object;
+               data->hdr_flags |= RTE_PTYPE_TUNNEL_NVGRE;
+               p_index = get_proto_index_using_flag(data->hdr_flags);
+               data->pattern[p_index].spec = &data->nvgre;
+               data->pattern[p_index].mask = &rte_flow_item_nvgre_mask;
+               data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_NVGRE;
+               break;
+       default:
+               return -1;
+       }
+
+       return len;
+}
+
+/** Parse NVGRE_ENCAP action pattern fields value. */
+static int
+parse_vc_action_nvgre_encap_fields_value(struct context *ctx,
+                                        const struct token *token,
+                                        const char *str, unsigned int len,
+                                        void *buf, unsigned int size)
+{
+       struct action_nvgre_encap_data *data;
+       struct ether_addr mac;
+       char str2[len + 1];
+       struct in_addr ip4;
+       uint16_t val1;
+       uint32_t val2;
+       int ret;
+
+       (void)token;
+       (void)buf;
+       if (!ctx->object)
+               return len;
+       data = ctx->object;
+       switch (ctx->curr) {
+       case ACTION_NVGRE_ENCAP_ETH_DST_VALUE:
+               ret = cmdline_parse_etheraddr(NULL, str, &mac, size);
+               if (ret < 0 || (unsigned int)ret != len)
+                       return -1;
+               memcpy(&data->eth.dst, &mac, sizeof(mac));
+               break;
+       case ACTION_NVGRE_ENCAP_ETH_SRC_VALUE:
+               ret = cmdline_parse_etheraddr(NULL, str, &mac, size);
+               if (ret < 0 || (unsigned int)ret != len)
+                       return -1;
+               memcpy(&data->eth.src, &mac, sizeof(mac));
+               break;
+       case ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE:
+               memcpy(str2, str, len);
+               str2[len] = '\0';
+               val1 = strtoul(str2, NULL, 0);
+               if (val1 == 0)
+                       return -1;
+               data->eth.type = htons(val1);
+               break;
+       case ACTION_NVGRE_ENCAP_IPV4_DST_VALUE:
+               memcpy(str2, str, len);
+               str2[len] = '\0';
+               ret = inet_pton(AF_INET, str2, &ip4);
+               if (ret != 1)
+                       return -1;
+               memcpy(&data->ipv4.hdr.dst_addr, &ip4, sizeof(ip4));
+               break;
+       case ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE:
+               memcpy(str2, str, len);
+               str2[len] = '\0';
+               ret = inet_pton(AF_INET, str2, &ip4);
+               if (ret != 1)
+                       return -1;
+               memcpy(&data->ipv4.hdr.src_addr, &ip4, sizeof(ip4));
+               break;
+       case ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE:
+               memcpy(str2, str, len);
+               str2[len] = '\0';
+               val1 = strtoul(str2, NULL, 0);
+               if (val1 == 0)
+                       return -1;
+               data->ipv4.hdr.next_proto_id = val1;
+               break;
+       case ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE:
+               memcpy(str2, str, len);
+               str2[len] = '\0';
+               val2 = strtoul(str2, NULL, 0);
+               if (val2 == 0)
+                       return -1;
+               data->nvgre.tni[0] = (uint8_t)((val2 >> 16) & 0xff);
+               data->nvgre.tni[1] = (uint8_t)((val2 >> 8) & 0xff);
+               data->nvgre.tni[2] = (uint8_t)(val2 & 0xff);
+               break;
+       default:
+               return -1;
+       }
+
+       return len;
+}
+
+/** Parse NVGRE_ENCAP action pattern end. */
+static int
+parse_vc_action_nvgre_encap_end(struct context *ctx,
+                               const struct token *token,
+                               const char *str, unsigned int len,
+                               void *buf, unsigned int size)
+{
+       struct action_nvgre_encap_data *data;
+       uint32_t p_index;
+
+       (void)buf;
+       (void)size;
+       /* Token name must match. */
+       if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+               return -1;
+       if (ctx->curr != ACTION_NVGRE_ENCAP_END)
+               return -1;
+       if (!ctx->object)
+               return len;
+       data = ctx->object;
+       p_index = get_proto_index_using_flag(data->hdr_flags);
+       data->pattern[p_index + 1].type = RTE_FLOW_ITEM_TYPE_END;
+
+       return len;
+}
+
 /** Parse tokens for destroy command. */
 static int
 parse_destroy(struct context *ctx, const struct token *token,
@@ -2961,6 +3832,7 @@ parse_destroy(struct context *ctx, const struct token 
*token,
        return len;
 }
 
+
 /** Parse tokens for flush command. */
 static int
 parse_flush(struct context *ctx, const struct token *token,
-- 
2.7.4

Reply via email to