[ovs-dev] [PATCH V2 03/19] netdev-offload-dpdk-flow: Dynamically allocate pattern items
Eli Britstein
elibr at mellanox.com
Mon Dec 2 08:41:37 UTC 2019
Instead of statically allocated pattern items on the stack, dynamically
allocate only the required items while parsing the required matches, to
simplify the parsing and make it self-contained, without need of
external types.
Signed-off-by: Eli Britstein <elibr at mellanox.com>
Reviewed-by: Oz Shlomo <ozsh at mellanox.com>
---
lib/netdev-offload-dpdk-flow.c | 163 +++++++++++++++++++++-----------------
lib/netdev-offload-dpdk-private.h | 14 ----
lib/netdev-offload-dpdk.c | 6 +-
3 files changed, 90 insertions(+), 93 deletions(-)
diff --git a/lib/netdev-offload-dpdk-flow.c b/lib/netdev-offload-dpdk-flow.c
index d1d5ce2c6..c8c3e28ea 100644
--- a/lib/netdev-offload-dpdk-flow.c
+++ b/lib/netdev-offload-dpdk-flow.c
@@ -29,6 +29,16 @@ void
netdev_dpdk_flow_patterns_free(struct flow_patterns *patterns)
{
/* When calling this function 'patterns' must be valid */
+ int i;
+
+ for (i = 0; i < patterns->cnt; i++) {
+ if (patterns->items[i].spec) {
+ free((void *)patterns->items[i].spec);
+ }
+ if (patterns->items[i].mask) {
+ free((void *)patterns->items[i].mask);
+ }
+ }
free(patterns->items);
patterns->items = NULL;
patterns->cnt = 0;
@@ -333,8 +343,6 @@ netdev_dpdk_flow_actions_add_mark_rss(struct flow_actions *actions,
int
netdev_dpdk_flow_patterns_add(struct flow_patterns *patterns,
- struct flow_pattern_items *spec,
- struct flow_pattern_items *mask,
const struct match *match)
{
uint8_t proto = 0;
@@ -342,16 +350,20 @@ netdev_dpdk_flow_patterns_add(struct flow_patterns *patterns,
/* Eth */
if (!eth_addr_is_zero(match->wc.masks.dl_src) ||
!eth_addr_is_zero(match->wc.masks.dl_dst)) {
- memcpy(&spec->eth.dst, &match->flow.dl_dst, sizeof spec->eth.dst);
- memcpy(&spec->eth.src, &match->flow.dl_src, sizeof spec->eth.src);
- spec->eth.type = match->flow.dl_type;
+ struct rte_flow_item_eth *spec, *mask;
+
+ spec = xzalloc(sizeof *spec);
+ mask = xzalloc(sizeof *mask);
- memcpy(&mask->eth.dst, &match->wc.masks.dl_dst, sizeof mask->eth.dst);
- memcpy(&mask->eth.src, &match->wc.masks.dl_src, sizeof mask->eth.src);
- mask->eth.type = match->wc.masks.dl_type;
+ memcpy(&spec->dst, &match->flow.dl_dst, sizeof spec->dst);
+ memcpy(&spec->src, &match->flow.dl_src, sizeof spec->src);
+ spec->type = match->flow.dl_type;
- add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_ETH,
- &spec->eth, &mask->eth);
+ memcpy(&mask->dst, &match->wc.masks.dl_dst, sizeof mask->dst);
+ memcpy(&mask->src, &match->wc.masks.dl_src, sizeof mask->src);
+ mask->type = match->wc.masks.dl_type;
+
+ add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_ETH, spec, mask);
} else {
/*
* If user specifies a flow (like UDP flow) without L2 patterns,
@@ -365,36 +377,43 @@ netdev_dpdk_flow_patterns_add(struct flow_patterns *patterns,
/* VLAN */
if (match->wc.masks.vlans[0].tci && match->flow.vlans[0].tci) {
- spec->vlan.tci = match->flow.vlans[0].tci & ~htons(VLAN_CFI);
- mask->vlan.tci = match->wc.masks.vlans[0].tci & ~htons(VLAN_CFI);
+ struct rte_flow_item_vlan *spec, *mask;
+
+ spec = xzalloc(sizeof *spec);
+ mask = xzalloc(sizeof *mask);
+
+ spec->tci = match->flow.vlans[0].tci & ~htons(VLAN_CFI);
+ mask->tci = match->wc.masks.vlans[0].tci & ~htons(VLAN_CFI);
/* Match any protocols. */
- mask->vlan.inner_type = 0;
+ mask->inner_type = 0;
- add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_VLAN,
- &spec->vlan, &mask->vlan);
+ add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_VLAN, spec, mask);
}
/* IP v4 */
if (match->flow.dl_type == htons(ETH_TYPE_IP)) {
- spec->ipv4.hdr.type_of_service = match->flow.nw_tos;
- spec->ipv4.hdr.time_to_live = match->flow.nw_ttl;
- spec->ipv4.hdr.next_proto_id = match->flow.nw_proto;
- spec->ipv4.hdr.src_addr = match->flow.nw_src;
- spec->ipv4.hdr.dst_addr = match->flow.nw_dst;
+ struct rte_flow_item_ipv4 *spec, *mask;
- mask->ipv4.hdr.type_of_service = match->wc.masks.nw_tos;
- mask->ipv4.hdr.time_to_live = match->wc.masks.nw_ttl;
- mask->ipv4.hdr.next_proto_id = match->wc.masks.nw_proto;
- mask->ipv4.hdr.src_addr = match->wc.masks.nw_src;
- mask->ipv4.hdr.dst_addr = match->wc.masks.nw_dst;
+ spec = xzalloc(sizeof *spec);
+ mask = xzalloc(sizeof *mask);
- add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_IPV4,
- &spec->ipv4, &mask->ipv4);
+ spec->hdr.type_of_service = match->flow.nw_tos;
+ spec->hdr.time_to_live = match->flow.nw_ttl;
+ spec->hdr.next_proto_id = match->flow.nw_proto;
+ spec->hdr.src_addr = match->flow.nw_src;
+ spec->hdr.dst_addr = match->flow.nw_dst;
+
+ mask->hdr.type_of_service = match->wc.masks.nw_tos;
+ mask->hdr.time_to_live = match->wc.masks.nw_ttl;
+ mask->hdr.next_proto_id = match->wc.masks.nw_proto;
+ mask->hdr.src_addr = match->wc.masks.nw_src;
+ mask->hdr.dst_addr = match->wc.masks.nw_dst;
+
+ add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_IPV4, spec, mask);
/* Save proto for L4 protocol setup. */
- proto = spec->ipv4.hdr.next_proto_id &
- mask->ipv4.hdr.next_proto_id;
+ proto = spec->hdr.next_proto_id & mask->hdr.next_proto_id;
}
if (proto != IPPROTO_ICMP && proto != IPPROTO_UDP &&
@@ -411,66 +430,62 @@ netdev_dpdk_flow_patterns_add(struct flow_patterns *patterns,
return -1;
}
- switch (proto) {
- case IPPROTO_TCP:
- spec->tcp.hdr.src_port = match->flow.tp_src;
- spec->tcp.hdr.dst_port = match->flow.tp_dst;
- spec->tcp.hdr.data_off = ntohs(match->flow.tcp_flags) >> 8;
- spec->tcp.hdr.tcp_flags = ntohs(match->flow.tcp_flags) & 0xff;
+ if (proto == IPPROTO_TCP) {
+ struct rte_flow_item_tcp *spec, *mask;
+
+ spec = xzalloc(sizeof *spec);
+ mask = xzalloc(sizeof *mask);
- mask->tcp.hdr.src_port = match->wc.masks.tp_src;
- mask->tcp.hdr.dst_port = match->wc.masks.tp_dst;
- mask->tcp.hdr.data_off = ntohs(match->wc.masks.tcp_flags) >> 8;
- mask->tcp.hdr.tcp_flags = ntohs(match->wc.masks.tcp_flags) & 0xff;
+ spec->hdr.src_port = match->flow.tp_src;
+ spec->hdr.dst_port = match->flow.tp_dst;
+ spec->hdr.data_off = ntohs(match->flow.tcp_flags) >> 8;
+ spec->hdr.tcp_flags = ntohs(match->flow.tcp_flags) & 0xff;
- add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_TCP,
- &spec->tcp, &mask->tcp);
+ mask->hdr.src_port = match->wc.masks.tp_src;
+ mask->hdr.dst_port = match->wc.masks.tp_dst;
+ mask->hdr.data_off = ntohs(match->wc.masks.tcp_flags) >> 8;
+ mask->hdr.tcp_flags = ntohs(match->wc.masks.tcp_flags) & 0xff;
- /* proto == TCP and ITEM_TYPE_TCP, thus no need for proto match. */
- mask->ipv4.hdr.next_proto_id = 0;
- break;
+ add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_TCP, spec, mask);
+ } else if (proto == IPPROTO_UDP) {
+ struct rte_flow_item_udp *spec, *mask;
- case IPPROTO_UDP:
- spec->udp.hdr.src_port = match->flow.tp_src;
- spec->udp.hdr.dst_port = match->flow.tp_dst;
+ spec = xzalloc(sizeof *spec);
+ mask = xzalloc(sizeof *mask);
- mask->udp.hdr.src_port = match->wc.masks.tp_src;
- mask->udp.hdr.dst_port = match->wc.masks.tp_dst;
+ spec->hdr.src_port = match->flow.tp_src;
+ spec->hdr.dst_port = match->flow.tp_dst;
- add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_UDP,
- &spec->udp, &mask->udp);
+ mask->hdr.src_port = match->wc.masks.tp_src;
+ mask->hdr.dst_port = match->wc.masks.tp_dst;
- /* proto == UDP and ITEM_TYPE_UDP, thus no need for proto match. */
- mask->ipv4.hdr.next_proto_id = 0;
- break;
+ add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_UDP, spec, mask);
+ } else if (proto == IPPROTO_SCTP) {
+ struct rte_flow_item_sctp *spec, *mask;
- case IPPROTO_SCTP:
- spec->sctp.hdr.src_port = match->flow.tp_src;
- spec->sctp.hdr.dst_port = match->flow.tp_dst;
+ spec = xzalloc(sizeof *spec);
+ mask = xzalloc(sizeof *mask);
- mask->sctp.hdr.src_port = match->wc.masks.tp_src;
- mask->sctp.hdr.dst_port = match->wc.masks.tp_dst;
+ spec->hdr.src_port = match->flow.tp_src;
+ spec->hdr.dst_port = match->flow.tp_dst;
- add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_SCTP,
- &spec->sctp, &mask->sctp);
+ mask->hdr.src_port = match->wc.masks.tp_src;
+ mask->hdr.dst_port = match->wc.masks.tp_dst;
- /* proto == SCTP and ITEM_TYPE_SCTP, thus no need for proto match. */
- mask->ipv4.hdr.next_proto_id = 0;
- break;
+ add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_SCTP, spec, mask);
+ } else if (proto == IPPROTO_ICMP) {
+ struct rte_flow_item_icmp *spec, *mask;
- case IPPROTO_ICMP:
- spec->icmp.hdr.icmp_type = (uint8_t) ntohs(match->flow.tp_src);
- spec->icmp.hdr.icmp_code = (uint8_t) ntohs(match->flow.tp_dst);
+ spec = xzalloc(sizeof *spec);
+ mask = xzalloc(sizeof *mask);
- mask->icmp.hdr.icmp_type = (uint8_t) ntohs(match->wc.masks.tp_src);
- mask->icmp.hdr.icmp_code = (uint8_t) ntohs(match->wc.masks.tp_dst);
+ spec->hdr.icmp_type = (uint8_t) ntohs(match->flow.tp_src);
+ spec->hdr.icmp_code = (uint8_t) ntohs(match->flow.tp_dst);
- add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_ICMP,
- &spec->icmp, &mask->icmp);
+ mask->hdr.icmp_type = (uint8_t) ntohs(match->wc.masks.tp_src);
+ mask->hdr.icmp_code = (uint8_t) ntohs(match->wc.masks.tp_dst);
- /* proto == ICMP and ITEM_TYPE_ICMP, thus no need for proto match. */
- mask->ipv4.hdr.next_proto_id = 0;
- break;
+ add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_ICMP, spec, mask);
}
add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_END, NULL, NULL);
diff --git a/lib/netdev-offload-dpdk-private.h b/lib/netdev-offload-dpdk-private.h
index 397384cb0..e9c9e602a 100644
--- a/lib/netdev-offload-dpdk-private.h
+++ b/lib/netdev-offload-dpdk-private.h
@@ -40,24 +40,10 @@ struct flow_actions {
int current_max;
};
-struct flow_pattern_items {
- struct rte_flow_item_eth eth;
- struct rte_flow_item_vlan vlan;
- struct rte_flow_item_ipv4 ipv4;
- union {
- struct rte_flow_item_tcp tcp;
- struct rte_flow_item_udp udp;
- struct rte_flow_item_sctp sctp;
- struct rte_flow_item_icmp icmp;
- };
-};
-
void
netdev_dpdk_flow_patterns_free(struct flow_patterns *patterns);
int
netdev_dpdk_flow_patterns_add(struct flow_patterns *patterns,
- struct flow_pattern_items *spec,
- struct flow_pattern_items *mask,
const struct match *match);
void
netdev_dpdk_flow_actions_free(struct flow_actions *actions);
diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c
index d6bbb7166..9882e1d23 100644
--- a/lib/netdev-offload-dpdk.c
+++ b/lib/netdev-offload-dpdk.c
@@ -131,15 +131,11 @@ netdev_offload_dpdk_add_flow(struct netdev *netdev,
};
struct flow_patterns patterns = { .items = NULL, .cnt = 0 };
struct flow_actions actions = { .actions = NULL, .cnt = 0 };
- struct flow_pattern_items spec, mask;
struct rte_flow_error error;
struct rte_flow *flow;
int ret = 0;
- memset(&spec, 0, sizeof spec);
- memset(&mask, 0, sizeof mask);
-
- ret = netdev_dpdk_flow_patterns_add(&patterns, &spec, &mask, match);
+ ret = netdev_dpdk_flow_patterns_add(&patterns, match);
if (ret) {
VLOG_WARN("Adding rte match patterns for flow ufid"UUID_FMT" failed",
UUID_ARGS((struct uuid *)ufid));
--
2.14.5
More information about the dev
mailing list