* [dpdk-dev] [PATCH] app/testpmd: enabled vxlan and nvgre encap/decap support for rte_flow
@ 2018-05-09 16:56 Mohammad Abdul Awal
2018-05-10 12:47 ` Iremonger, Bernard
0 siblings, 1 reply; 3+ messages in thread
From: Mohammad Abdul Awal @ 2018-05-09 16:56 UTC (permalink / raw)
To: dev; +Cc: Mohammad Abdul Awal
Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.awal@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
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [dpdk-dev] [PATCH] app/testpmd: enabled vxlan and nvgre encap/decap support for rte_flow
2018-05-09 16:56 [dpdk-dev] [PATCH] app/testpmd: enabled vxlan and nvgre encap/decap support for rte_flow Mohammad Abdul Awal
@ 2018-05-10 12:47 ` Iremonger, Bernard
2018-05-11 10:45 ` Mohammad Abdul Awal
0 siblings, 1 reply; 3+ messages in thread
From: Iremonger, Bernard @ 2018-05-10 12:47 UTC (permalink / raw)
To: Awal, Mohammad Abdul, dev, Adrien Mazarguil; +Cc: Awal, Mohammad Abdul
Hi Awal,
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Mohammad Abdul
> Awal
> Sent: Wednesday, May 9, 2018 5:57 PM
> To: dev@dpdk.org
> Cc: Awal, Mohammad Abdul <mohammad.abdul.awal@intel.com>
> Subject: [dpdk-dev] [PATCH] app/testpmd: enabled vxlan and nvgre encap/decap
> support for rte_flow
The commit message should not be empty, it should contain a description of the changes
>
> Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.awal@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,
Is ACTION_VXLAN_ENCAP_END necessary, could ACTION_END be used instead?
> + 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,
Is ACTION_NVGRE_ENCAP_END necessary, could ACTION_END be used instead?
> + 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,
"end" only is being parsed, could ACTION_END be used instead?
> + },
> + [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,
"end" only is being parsed, could ACTION_END be used instead?
> + },
> };
>
> /** 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)
> +{
This function should not be necessary if ACTION_END be used instead?
> + 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)
> +{
This function should not be necessary if ACTION_END be used instead?
> + 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;
> }
>
> +
Extra blank line should be removed.
> /** Parse tokens for flush command. */
> static int
> parse_flush(struct context *ctx, const struct token *token,
> --
> 2.7.4
In the Testpmd Application/User Guide, there is section 4.12. Flow rules management.
dpdk/build/doc/html/guides/testpmd_app_ug/index.html
As the encap and decap flows are fairly complex, It might be worth adding sections on Sample Encap flow rules and Sample Decap flow rules.
Regards,
Bernard.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [dpdk-dev] [PATCH] app/testpmd: enabled vxlan and nvgre encap/decap support for rte_flow
2018-05-10 12:47 ` Iremonger, Bernard
@ 2018-05-11 10:45 ` Mohammad Abdul Awal
0 siblings, 0 replies; 3+ messages in thread
From: Mohammad Abdul Awal @ 2018-05-11 10:45 UTC (permalink / raw)
To: Iremonger, Bernard, dev, Adrien Mazarguil
Hi Bernard,
On 10/05/2018 13:47, Iremonger, Bernard wrote:
> Hi Awal,
>
>> -----Original Message-----
>> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Mohammad Abdul
>> Awal
>> Sent: Wednesday, May 9, 2018 5:57 PM
>> To: dev@dpdk.org
>> Cc: Awal, Mohammad Abdul <mohammad.abdul.awal@intel.com>
>> Subject: [dpdk-dev] [PATCH] app/testpmd: enabled vxlan and nvgre encap/decap
>> support for rte_flow
> The commit message should not be empty, it should contain a description of the changes
I will add some message here.
>
>> Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.awal@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,
> Is ACTION_VXLAN_ENCAP_END necessary, could ACTION_END be used instead?
Actually, ACTION_VXLAN_ENCAP_END is different than ACTION_END.
ACTION_END creates the RTE_FLOW_ACTION_TYPE_END.
On the other hand, ACTION_VXLAN_ENCAP_END created RTE_FLOW_ITEM_TYPE_END
at the end pf patterns in the encap definition which is pattern of items
end by item_end.
So, to treat the two situations separately we need
ACTION_VXLAN_ENCAP_END, unless there is a clever way present.
>
>> + 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,
> Is ACTION_NVGRE_ENCAP_END necessary, could ACTION_END be used instead?
Please see my related comment above.
>
>> + 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,
> "end" only is being parsed, could ACTION_END be used instead?
Please see my related comment above.
>
>> + },
>> + [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,
> "end" only is being parsed, could ACTION_END be used instead?
Please see my related comment above.
>
>> + },
>> };
>>
>> /** 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)
>> +{
> This function should not be necessary if ACTION_END be used instead?
Please see my related comment above.
>
>> + 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)
>> +{
> This function should not be necessary if ACTION_END be used instead?
Please see my related comment above.
>
>> + 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;
>> }
>>
>> +
> Extra blank line should be removed.
Removed.
>
>> /** Parse tokens for flush command. */
>> static int
>> parse_flush(struct context *ctx, const struct token *token,
>> --
>> 2.7.4
> In the Testpmd Application/User Guide, there is section 4.12. Flow rules management.
> dpdk/build/doc/html/guides/testpmd_app_ug/index.html
>
> As the encap and decap flows are fairly complex, It might be worth adding sections on Sample Encap flow rules and Sample Decap flow rules.
I will add some documentation in the flow guide.
Regards,
Awal.
>
> Regards,
>
> Bernard.
>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2018-05-11 10:45 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-09 16:56 [dpdk-dev] [PATCH] app/testpmd: enabled vxlan and nvgre encap/decap support for rte_flow Mohammad Abdul Awal
2018-05-10 12:47 ` Iremonger, Bernard
2018-05-11 10:45 ` Mohammad Abdul Awal
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).