In case of a flow modification, preserve the HW statistics of the old HW
flow to the new one.
Signed-off-by: Eli Britstein <el...@mellanox.com>
Reviewed-by: Gaetan Rivet <gaet...@mellanox.com>
---
lib/netdev-offload-dpdk.c | 28 +++++++++++++++++++++-------
1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c
index de6101e4d..960acb2da 100644
--- a/lib/netdev-offload-dpdk.c
+++ b/lib/netdev-offload-dpdk.c
@@ -78,7 +78,7 @@ ufid_to_rte_flow_data_find(const ovs_u128 *ufid)
return NULL;
}
-static inline void
+static inline struct ufid_to_rte_flow_data *
ufid_to_rte_flow_associate(const ovs_u128 *ufid,
struct rte_flow *rte_flow, bool actions_offloaded)
{
@@ -103,6 +103,7 @@ ufid_to_rte_flow_associate(const ovs_u128 *ufid,
cmap_insert(&ufid_to_rte_flow,
CONST_CAST(struct cmap_node *, &data->node), hash);
+ return data;
}
static inline void
@@ -1407,7 +1408,7 @@ out:
return flow;
}
-static int
+static struct ufid_to_rte_flow_data *
netdev_offload_dpdk_add_flow(struct netdev *netdev,
struct match *match,
struct nlattr *nl_actions,
@@ -1416,6 +1417,7 @@ netdev_offload_dpdk_add_flow(struct netdev *netdev,
struct offload_info *info)
{
struct flow_patterns patterns = { .items = NULL, .cnt = 0 };
+ struct ufid_to_rte_flow_data *flows_data = NULL;
bool actions_offloaded = true;
struct rte_flow *flow;
int ret = 0;
@@ -1442,13 +1444,13 @@ netdev_offload_dpdk_add_flow(struct netdev *netdev,
ret = -1;
goto out;
}
- ufid_to_rte_flow_associate(ufid, flow, actions_offloaded);
+ flows_data = ufid_to_rte_flow_associate(ufid, flow, actions_offloaded);
VLOG_DBG("%s: installed flow %p by ufid "UUID_FMT,
netdev_get_name(netdev), flow, UUID_ARGS((struct uuid *)ufid));
out:
free_flow_patterns(&patterns);
- return ret;
+ return flows_data;
}
static int
@@ -1482,14 +1484,19 @@ netdev_offload_dpdk_flow_put(struct netdev *netdev,
struct match *match,
struct dpif_flow_stats *stats)
{
struct ufid_to_rte_flow_data *rte_flow_data;
+ struct dpif_flow_stats old_stats;
+ bool modification = false;
int ret;
/*
* If an old rte_flow exists, it means it's a flow modification.
* Here destroy the old rte flow first before adding a new one.
+ * Keep the stats for the newly created rule.
*/
rte_flow_data = ufid_to_rte_flow_data_find(ufid);
if (rte_flow_data && rte_flow_data->rte_flow) {
+ old_stats = rte_flow_data->stats;
+ modification = true;
ret = netdev_offload_dpdk_destroy_flow(netdev, ufid,
rte_flow_data->rte_flow);
if (ret < 0) {
@@ -1497,11 +1504,18 @@ netdev_offload_dpdk_flow_put(struct netdev *netdev,
struct match *match,
}
}
+ rte_flow_data = netdev_offload_dpdk_add_flow(netdev, match, actions,
+ actions_len, ufid, info);
+ if (!rte_flow_data) {
+ return -1;
+ }
+ if (modification) {
+ rte_flow_data->stats = old_stats;
+ }
if (stats) {
- memset(stats, 0, sizeof *stats);
+ *stats = rte_flow_data->stats;
}
- return netdev_offload_dpdk_add_flow(netdev, match, actions,
- actions_len, ufid, info);
+ return 0;
}
static int