Introduce per-offload-provider implementation types and remove the
synced_dp abstraction from the dpif level. The new API allows
querying the offload implementation type and which provider offloads
a given port.

Signed-off-by: Eelco Chaudron <echau...@redhat.com>
---
 lib/dpif-netdev.c             |  1 -
 lib/dpif-netlink.c            |  1 -
 lib/dpif-offload-dummy.c      |  1 +
 lib/dpif-offload-provider.h   |  4 ++
 lib/dpif-offload-rte_flow.c   |  1 +
 lib/dpif-offload-tc.c         |  1 +
 lib/dpif-offload.c            | 73 +++++++++++++++++++++++++++++++++++
 lib/dpif-offload.h            | 25 ++++++++++++
 lib/dpif-provider.h           |  8 ----
 lib/dpif.c                    |  6 ---
 lib/dpif.h                    |  1 -
 ofproto/ofproto-dpif-upcall.c | 28 +++++++++-----
 12 files changed, 124 insertions(+), 26 deletions(-)

diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 710c14447..45dcd569a 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -9953,7 +9953,6 @@ dpif_netdev_bond_stats_get(struct dpif *dpif, uint32_t 
bond_id,
 const struct dpif_class dpif_netdev_class = {
     "netdev",
     true,                       /* cleanup_required */
-    true,                       /* synced_dp_layers */
     dpif_netdev_init,
     dpif_netdev_enumerate,
     dpif_netdev_port_open_type,
diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
index 2df91a98e..0515f4ebd 100644
--- a/lib/dpif-netlink.c
+++ b/lib/dpif-netlink.c
@@ -4330,7 +4330,6 @@ dpif_netlink_cache_set_size(struct dpif *dpif_, uint32_t 
level, uint32_t size)
 const struct dpif_class dpif_netlink_class = {
     "system",
     false,                      /* cleanup_required */
-    false,                      /* synced_dp_layers */
     NULL,                       /* init */
     dpif_netlink_enumerate,
     NULL,
diff --git a/lib/dpif-offload-dummy.c b/lib/dpif-offload-dummy.c
index b15d2192d..546a4f8d5 100644
--- a/lib/dpif-offload-dummy.c
+++ b/lib/dpif-offload-dummy.c
@@ -254,6 +254,7 @@ dpif_offload_dummy_can_offload(struct dpif_offload 
*dpif_offload OVS_UNUSED,
 #define DEFINE_DPIF_DUMMY_CLASS(NAME, TYPE_STR)         \
     struct dpif_offload_class NAME = {                  \
         .type = TYPE_STR,                               \
+        .impl_type = DPIF_OFFLOAD_IMPL_HW_ONLY,         \
         .supported_dpif_types = (const char *const[]) { \
             "dummy",                                    \
             NULL},                                      \
diff --git a/lib/dpif-offload-provider.h b/lib/dpif-offload-provider.h
index 68e13843c..abb3e2469 100644
--- a/lib/dpif-offload-provider.h
+++ b/lib/dpif-offload-provider.h
@@ -18,6 +18,7 @@
 #define DPIF_OFFLOAD_PROVIDER_H
 
 #include "cmap.h"
+#include "dpif-offload.h"
 #include "dpif-provider.h"
 #include "ovs-thread.h"
 #include "smap.h"
@@ -96,6 +97,9 @@ struct dpif_offload_class {
      * 'struct dpif_class' definition. */
     const char *const *supported_dpif_types;
 
+    /* Type of implementation for this DPIF offload provider. */
+    enum dpif_offload_impl_type impl_type;
+
     /* Called when the dpif offload provider class is registered.  Note that
      * this is the global initialization, not the per dpif one. */
     int (*init)(void);
diff --git a/lib/dpif-offload-rte_flow.c b/lib/dpif-offload-rte_flow.c
index e5c40fb12..fead1f3ef 100644
--- a/lib/dpif-offload-rte_flow.c
+++ b/lib/dpif-offload-rte_flow.c
@@ -314,6 +314,7 @@ dpif_offload_rte_netdev_hw_miss_packet_recover(
 
 struct dpif_offload_class dpif_offload_rte_flow_class = {
     .type = "rte_flow",
+    .impl_type = DPIF_OFFLOAD_IMPL_SYNC,
     .supported_dpif_types = (const char *const[]) {
         "netdev",
         NULL},
diff --git a/lib/dpif-offload-tc.c b/lib/dpif-offload-tc.c
index 961953961..e0358d091 100644
--- a/lib/dpif-offload-tc.c
+++ b/lib/dpif-offload-tc.c
@@ -560,6 +560,7 @@ dpif_offload_tc_flow_dump_thread_destroy(
 
 struct dpif_offload_class dpif_offload_tc_class = {
     .type = "tc",
+    .impl_type = DPIF_OFFLOAD_IMPL_HW_ONLY,
     .supported_dpif_types = (const char *const[]) {
         "system",
         NULL},
diff --git a/lib/dpif-offload.c b/lib/dpif-offload.c
index b2967b754..6fb4c66e1 100644
--- a/lib/dpif-offload.c
+++ b/lib/dpif-offload.c
@@ -560,6 +560,26 @@ dpif_offload_port_set_config(struct dpif *dpif, odp_port_t 
port_no,
     }
 }
 
+struct dpif_offload *
+dpif_offload_port_offloaded_by(const struct dpif *dpif, odp_port_t port_no)
+{
+    struct dp_offload *dp_offload = dpif_offload_get_dp_offload(dpif);
+    struct dpif_offload *offload, *offload_return = NULL;
+
+    if (!dp_offload || !dpif_offload_is_offload_enabled()) {
+        return NULL;
+    }
+
+    LIST_FOR_EACH (offload, dpif_list_node, &dp_offload->offload_providers) {
+        if (offload->class->get_netdev(offload, port_no)) {
+            offload_return = offload;
+            break;
+        }
+    }
+
+    return offload_return;
+}
+
 void
 dpif_offload_dump_start(struct dpif_offload_dump *dump,
                         const struct dpif *dpif)
@@ -732,6 +752,37 @@ dpif_offload_flow_flush(struct dpif *dpif)
     }
 }
 
+enum dpif_offload_impl_type
+dpif_offload_get_impl_type(const struct dpif_offload *offload)
+{
+    return offload->class->impl_type;
+}
+
+enum dpif_offload_impl_type
+dpif_offload_get_impl_type_by_class(const char *type)
+{
+    enum dpif_offload_impl_type impl_type = DPIF_OFFLOAD_IMPL_NONE;
+    struct shash_node *node;
+
+    /* For backwards compatibility 'dpdk' is the same as 'rte_flow'. */
+    if (!strcmp(type, "dpdk")) {
+        type = "rte_flow";
+    }
+
+    ovs_mutex_lock(&dpif_offload_mutex);
+    SHASH_FOR_EACH (node, &dpif_offload_classes) {
+        const struct dpif_offload_class *class = node->data;
+
+        if (!strcmp(type, class->type)) {
+            impl_type = class->impl_type;
+            break;
+        }
+    }
+    ovs_mutex_unlock(&dpif_offload_mutex);
+
+    return impl_type;
+}
+
 uint64_t
 dpif_offload_flow_get_n_offloaded(const struct dpif *dpif)
 {
@@ -752,6 +803,28 @@ dpif_offload_flow_get_n_offloaded(const struct dpif *dpif)
     return flow_count;
 }
 
+uint64_t
+dpif_offload_flow_get_n_offloaded_by_impl(const struct dpif *dpif,
+                                          enum dpif_offload_impl_type type)
+{
+    struct dp_offload *dp_offload = dpif_offload_get_dp_offload(dpif);
+    const struct dpif_offload *offload;
+    uint64_t flow_count = 0;
+
+    if (!dp_offload || !dpif_offload_is_offload_enabled()) {
+        return 0;
+    }
+
+    LIST_FOR_EACH (offload, dpif_list_node, &dp_offload->offload_providers) {
+        if (offload->class->flow_get_n_offloaded
+            && type == dpif_offload_get_impl_type(offload)) {
+            flow_count += offload->class->flow_get_n_offloaded(offload);
+        }
+    }
+
+    return flow_count;
+}
+
 void
 dpif_offload_meter_set(const struct dpif *dpif, ofproto_meter_id meter_id,
                        struct ofputil_meter_config *config)
diff --git a/lib/dpif-offload.h b/lib/dpif-offload.h
index 265585c49..8409323f7 100644
--- a/lib/dpif-offload.h
+++ b/lib/dpif-offload.h
@@ -30,6 +30,23 @@ struct dpif_offload_dump {
     void *state;
 };
 
+/* Definition of the DPIF offload implementation type.
+ *
+ * The 'DPIF_OFFLOAD_IMPL_SYNC' implementation has a single view, the offload
+ * provider is responsible for synchronizing flows and statistics through the
+ * dpif flow operations.  An example of this is rte_flow (DPDK offload).
+ *
+ * The 'DPIF_OFFLOAD_IMPL_HW_ONLY' implementation tries to install a hardware
+ * flow first. If successful, no dpif-layer software flow will be installed.
+ * Offload-specific callbacks are then used to manage the flow and query
+ * statistics. An example of this is kernel TC.
+ */
+enum dpif_offload_impl_type {
+    DPIF_OFFLOAD_IMPL_NONE,
+    DPIF_OFFLOAD_IMPL_SYNC,
+    DPIF_OFFLOAD_IMPL_HW_ONLY,
+};
+
 
 /* Global functions. */
 void dpif_offload_set_global_cfg(const struct ovsrec_open_vswitch *);
@@ -52,6 +69,8 @@ bool dpif_offload_dump_next(struct dpif_offload_dump *,
                             struct dpif_offload **);
 int dpif_offload_dump_done(struct dpif_offload_dump *);
 uint64_t dpif_offload_flow_get_n_offloaded(const struct dpif *);
+uint64_t dpif_offload_flow_get_n_offloaded_by_impl(
+    const struct dpif *, enum dpif_offload_impl_type);
 void dpif_offload_meter_set(const struct dpif *dpif, ofproto_meter_id meter_id,
                             struct ofputil_meter_config *);
 void dpif_offload_meter_get(const struct dpif *dpif, ofproto_meter_id meter_id,
@@ -63,6 +82,12 @@ struct netdev *dpif_offload_get_netdev_by_port_id(struct 
dpif *,
                                                   odp_port_t);
 struct netdev *dpif_offload_offload_get_netdev_by_port_id(
     struct dpif_offload *, odp_port_t);
+struct dpif_offload *dpif_offload_port_offloaded_by(const struct dpif *,
+                                                    odp_port_t);
+enum dpif_offload_impl_type dpif_offload_get_impl_type(
+    const struct dpif_offload *);
+enum dpif_offload_impl_type dpif_offload_get_impl_type_by_class(
+    const char *type);
 
 /* Iterates through each DPIF_OFFLOAD in DPIF, using DUMP as state.
  *
diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h
index 91e7ddcfa..02bcae12f 100644
--- a/lib/dpif-provider.h
+++ b/lib/dpif-provider.h
@@ -164,14 +164,6 @@ struct dpif_class {
      * datapaths that can not exist without it (e.g. netdev datapath).  */
     bool cleanup_required;
 
-    /* If 'true' the specific dpif implementation synchronizes the various
-     * datapath implementation layers, i.e., the dpif's layer in combination
-     * with the underlying netdev offload layers. For example, dpif-netlink
-     * does not sync its kernel flows with the tc ones, i.e., only one gets
-     * installed. On the other hand, dpif-netdev installs both flows,
-     * internally keeps track of both, and represents them as one. */
-    bool synced_dp_layers;
-
     /* Called when the dpif provider is registered, typically at program
      * startup.  Returning an error from this function will prevent any
      * datapath with this class from being created.
diff --git a/lib/dpif.c b/lib/dpif.c
index 721f6afc7..8c40bec18 100644
--- a/lib/dpif.c
+++ b/lib/dpif.c
@@ -2135,9 +2135,3 @@ dpif_cache_set_size(struct dpif *dpif, uint32_t level, 
uint32_t size)
            ? dpif->dpif_class->cache_set_size(dpif, level, size)
            : EOPNOTSUPP;
 }
-
-bool
-dpif_synced_dp_layers(struct dpif *dpif)
-{
-    return dpif->dpif_class->synced_dp_layers;
-}
diff --git a/lib/dpif.h b/lib/dpif.h
index 473eacb2f..f3301ae85 100644
--- a/lib/dpif.h
+++ b/lib/dpif.h
@@ -943,7 +943,6 @@ char *dpif_get_dp_version(const struct dpif *);
 bool dpif_supports_tnl_push_pop(const struct dpif *);
 bool dpif_may_support_explicit_drop_action(const struct dpif *);
 bool dpif_may_support_psample(const struct dpif *);
-bool dpif_synced_dp_layers(struct dpif *);
 
 /* Log functions. */
 struct vlog_module;
diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
index d0c537bc9..b324793f0 100644
--- a/ofproto/ofproto-dpif-upcall.c
+++ b/ofproto/ofproto-dpif-upcall.c
@@ -826,12 +826,8 @@ udpif_get_n_flows(struct udpif *udpif)
         atomic_store_relaxed(&udpif->n_flows_timestamp, now);
         dpif_get_dp_stats(udpif->dpif, &stats);
         flow_count = stats.n_flows;
-
-        if (!dpif_synced_dp_layers(udpif->dpif)) {
-            /* If the dpif layer does not sync the flows, we need to include
-             * the hardware offloaded flows separately. */
-            flow_count += dpif_offload_flow_get_n_offloaded(udpif->dpif);
-        }
+        flow_count += dpif_offload_flow_get_n_offloaded_by_impl(
+            udpif->dpif, DPIF_OFFLOAD_IMPL_HW_ONLY);
 
         atomic_store_relaxed(&udpif->n_flows, flow_count);
         ovs_mutex_unlock(&udpif->n_flows_mutex);
@@ -2802,6 +2798,21 @@ udpif_update_used(struct udpif *udpif, struct udpif_key 
*ukey,
     return stats->used;
 }
 
+static bool
+did_dp_hw_only_offload_change(const char *old_type, const char *new_type)
+{
+    enum dpif_offload_impl_type old_impl = old_type ?
+        dpif_offload_get_impl_type_by_class(old_type) : DPIF_OFFLOAD_IMPL_NONE;
+    enum dpif_offload_impl_type new_impl = new_type ?
+        dpif_offload_get_impl_type_by_class(new_type) : DPIF_OFFLOAD_IMPL_NONE;
+
+    if (old_impl != new_impl && (old_impl == DPIF_OFFLOAD_IMPL_HW_ONLY ||
+                                 new_impl == DPIF_OFFLOAD_IMPL_HW_ONLY)) {
+        return true;
+    }
+    return false;
+}
+
 static void
 revalidate(struct revalidator *revalidator)
 {
@@ -2900,9 +2911,8 @@ revalidate(struct revalidator *revalidator)
 
             ukey->offloaded = f->attrs.offloaded;
             if (!ukey->dp_layer
-                || (!dpif_synced_dp_layers(udpif->dpif)
-                    && strcmp(ukey->dp_layer, f->attrs.dp_layer))) {
-
+                || did_dp_hw_only_offload_change(ukey->dp_layer,
+                                                 f->attrs.dp_layer)) {
                 if (ukey->dp_layer) {
                     /* The dp_layer has changed this is probably due to an
                      * earlier revalidate cycle moving it to/from hw offload.
-- 
2.50.1

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to