[ovs-dev,hwol,RFC,v1,4/5] netdev-dpdk: Add netdev function: flow_stats_get()

Message ID 1546285557-1617-5-git-send-email-ophirmu@mellanox.com
State New
Delegated to: Ian Stokes
Headers show
Series
  • Support hw offloaded flows
Related show

Commit Message

Ophir Munk Dec. 31, 2018, 7:45 p.m.
This function gets the offloaded flow stats. When a flow is fully offloaded
reading the PMD SW stats will result in no updates. In order to reflect the
actual stats accounted for the flow, the hw must be queried.

Signed-off-by: Ophir Munk <ophirmu@mellanox.com>
---
 lib/netdev-dpdk.c     | 35 ++++++++++++++++++++++++++++++++---
 lib/netdev-provider.h |  7 +++++++
 lib/netdev.c          | 11 +++++++++++
 lib/netdev.h          |  2 ++
 4 files changed, 52 insertions(+), 3 deletions(-)

Patch

diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index e1f2331..a78c01c 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -5051,9 +5051,38 @@  netdev_dpdk_flow_del(struct netdev *netdev, const ovs_u128 *ufid,
     return netdev_dpdk_destroy_rte_flow(netdev, ufid, rte_flow);
 }
 
-#define DPDK_FLOW_OFFLOAD_API                   \
-    .flow_put = netdev_dpdk_flow_put,           \
-    .flow_del = netdev_dpdk_flow_del
+static int
+netdev_dpdk_flow_stats_get(struct netdev *netdev, const ovs_u128 *ufid,
+                     struct dpif_flow_stats *stats) {
+
+    int ret = 0;
+    struct rte_flow_error error;
+    struct rte_flow_query_count query;
+    struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
+    struct rte_flow *rte_flow = ufid_to_rte_flow_find(ufid);
+    if (!rte_flow) {
+        return EINVAL;
+    }
+    const struct rte_flow_action action = {
+        .type = RTE_FLOW_ACTION_TYPE_COUNT
+    };
+    memset(&query, 0, sizeof(query));
+    ret = rte_flow_query(dev->port_id, rte_flow, &action, &query, &error);
+    if (ret) {
+        return -ret;
+    }
+
+    stats->n_packets = (query.hits_set) ? query.hits : 0;
+    stats->n_bytes = (query.bytes_set) ? query.bytes : 0;
+    stats->used = 0;
+    stats->tcp_flags = 0;
+    return ret;
+}
+
+#define DPDK_FLOW_OFFLOAD_API                               \
+    .flow_put = netdev_dpdk_flow_put,                       \
+    .flow_del = netdev_dpdk_flow_del,                       \
+    .flow_stats_get = netdev_dpdk_flow_stats_get
 
 #define NETDEV_DPDK_CLASS_COMMON                            \
     .is_pmd = true,                                         \
diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h
index fb0c27e..50b6575 100644
--- a/lib/netdev-provider.h
+++ b/lib/netdev-provider.h
@@ -881,6 +881,13 @@  struct netdev_class {
     int (*flow_del)(struct netdev *, const ovs_u128 *ufid,
                     struct dpif_flow_stats *);
 
+    /* Get offloaded flow stats. When a flow is fully offloaded, reading the
+     * PMD stats will result is no updates. In order to reflect the actual
+     * stats the hardware must be querried.
+     * Return 0 if successful, otherwise returns a positive errno value. */
+    int (*flow_stats_get)(struct netdev *netdev, const ovs_u128 *ufid,
+                struct dpif_flow_stats *stats);
+
     /* Initializies the netdev flow api.
      * Return 0 if successful, otherwise returns a positive errno value. */
     int (*init_flow_api)(struct netdev *);
diff --git a/lib/netdev.c b/lib/netdev.c
index 45b50f2..2cf7ad9 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -2232,6 +2232,17 @@  netdev_flow_del(struct netdev *netdev, const ovs_u128 *ufid,
 }
 
 int
+netdev_flow_stats_get(struct netdev *netdev, const ovs_u128 *ufid,
+                struct dpif_flow_stats *stats)
+{
+    const struct netdev_class *class = netdev->netdev_class;
+
+    return (class->flow_stats_get
+            ? class->flow_stats_get(netdev, ufid, stats)
+            : EOPNOTSUPP);
+}
+
+int
 netdev_init_flow_api(struct netdev *netdev)
 {
     const struct netdev_class *class = netdev->netdev_class;
diff --git a/lib/netdev.h b/lib/netdev.h
index d94817f..1fca859 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
@@ -226,6 +226,8 @@  int netdev_flow_get(struct netdev *, struct match *, struct nlattr **actions,
                     struct dpif_flow_attrs *, struct ofpbuf *wbuffer);
 int netdev_flow_del(struct netdev *, const ovs_u128 *,
                     struct dpif_flow_stats *);
+int netdev_flow_stats_get(struct netdev *, const ovs_u128 *,
+                    struct dpif_flow_stats *);
 int netdev_init_flow_api(struct netdev *);
 uint32_t netdev_get_block_id(struct netdev *);
 int netdev_get_hw_info(struct netdev *, int);