This patch introduces an API that allows offload providers to
manage global configurations. It also moves the 'n-offload-threads'
and 'tc-policy' setting to the appropriate providers using
this new API.

Signed-off-by: Eelco Chaudron <echau...@redhat.com>
---
 lib/dpif-offload-provider.h | 18 +++++++-
 lib/dpif-offload-rte_flow.c | 82 +++++++++++++++++++++++++++++++++++--
 lib/dpif-offload-tc.c       | 52 +++++++++++++++++++++--
 lib/dpif-offload.c          | 18 ++++++++
 lib/dpif.c                  |  1 +
 lib/netdev-offload.c        | 36 +++++-----------
 tests/dpif-netdev.at        |  6 +--
 tests/ofproto-macros.at     |  2 +-
 8 files changed, 177 insertions(+), 38 deletions(-)

diff --git a/lib/dpif-offload-provider.h b/lib/dpif-offload-provider.h
index 89889271e..ae92a6f74 100644
--- a/lib/dpif-offload-provider.h
+++ b/lib/dpif-offload-provider.h
@@ -19,6 +19,8 @@
 
 #include "dpif-provider.h"
 #include "ovs-thread.h"
+#include "smap.h"
+#include "util.h"
 #include "openvswitch/list.h"
 
 /* The DPIF Offload Provider introduces an abstraction layer for hardware
@@ -84,6 +86,11 @@ struct dpif_offload_class {
      * open() above.  If your implementation accesses this provider using
      * RCU pointers, it's responsible for handling deferred deallocation. */
     void (*close)(struct dpif_offload *);
+    /* Pass custom configuration options to the offload provider.  The
+     * implementation might postpone applying the changes until run() is
+     * called. */
+    void (*set_config)(struct dpif_offload *,
+                       const struct smap *other_config);
 };
 
 
@@ -92,8 +99,17 @@ extern struct dpif_offload_class dpif_offload_dummy_x_class;
 extern struct dpif_offload_class dpif_offload_rte_flow_class;
 extern struct dpif_offload_class dpif_offload_tc_class;
 
-/* Global function, called by the dpif layer. */
+
+/* Global functions, called by the dpif layer or offload providers. */
 void dp_offload_initialize(void);
+void dpif_offload_set_config(struct dpif *, const struct smap *other_cfg);
+
+static inline void dpif_offload_assert_class(
+    const struct dpif_offload *dpif_offload,
+    const struct dpif_offload_class *dpif_offload_class)
+{
+    ovs_assert(dpif_offload->class == dpif_offload_class);
+}
 
 
 #endif /* DPIF_OFFLOAD_PROVIDER_H */
diff --git a/lib/dpif-offload-rte_flow.c b/lib/dpif-offload-rte_flow.c
index 4c3ccea4a..3cfe0f3d3 100644
--- a/lib/dpif-offload-rte_flow.c
+++ b/lib/dpif-offload-rte_flow.c
@@ -20,21 +20,86 @@
 #include "dpif-offload-provider.h"
 #include "util.h"
 
+#include "openvswitch/vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(dpif_offload_rte_flow);
+
+#define DEFAULT_OFFLOAD_THREAD_NB 1
+#define MAX_OFFLOAD_THREAD_NB 10
+
+static unsigned int offload_thread_nb = DEFAULT_OFFLOAD_THREAD_NB;
+
+/* dpif offload interface for the rte implementation. */
+struct dpif_offload_rte_flow {
+    struct dpif_offload offload;
+
+    /* Configuration specific variables. */
+    struct ovsthread_once once_enable; /* Track first-time enablement. */
+};
+
+static struct dpif_offload_rte_flow *
+dpif_offload_rte_cast(const struct dpif_offload *offload)
+{
+    dpif_offload_assert_class(offload, &dpif_offload_rte_flow_class);
+    return CONTAINER_OF(offload, struct dpif_offload_rte_flow, offload);
+}
+
 static int
 dpif_offload_rte_open(const struct dpif_offload_class *offload_class,
                       struct dpif *dpif, struct dpif_offload **dpif_offload)
 {
-    struct dpif_offload *offload = xmalloc(sizeof(struct dpif_offload));
+    struct dpif_offload_rte_flow *offload_rte;
+
+    offload_rte = xmalloc(sizeof(struct dpif_offload_rte_flow));
+
+    dpif_offload_init(&offload_rte->offload, offload_class, dpif);
+    offload_rte->once_enable = (struct ovsthread_once)
+        OVSTHREAD_ONCE_INITIALIZER;
 
-    dpif_offload_init(offload, offload_class, dpif);
-    *dpif_offload = offload;
+    *dpif_offload = &offload_rte->offload;
     return 0;
 }
 
 static void
 dpif_offload_rte_close(struct dpif_offload *dpif_offload)
 {
-    free(dpif_offload);
+    struct dpif_offload_rte_flow *offload_rte;
+
+    offload_rte = dpif_offload_rte_cast(dpif_offload);
+    free(offload_rte);
+}
+
+static void
+dpif_offload_rte_set_config(struct dpif_offload *offload,
+                           const struct smap *other_cfg)
+{
+    struct dpif_offload_rte_flow *offload_rte = dpif_offload_rte_cast(offload);
+
+    /* We maintain the existing behavior where global configurations
+     * are only accepted when hardware offload is initially enabled.
+     * Once enabled, they cannot be updated or reconfigured. */
+    if (smap_get_bool(other_cfg, "hw-offload", false)) {
+        if (ovsthread_once_start(&offload_rte->once_enable)) {
+
+            offload_thread_nb = smap_get_ullong(other_cfg,
+                                                "n-offload-threads",
+                                                DEFAULT_OFFLOAD_THREAD_NB);
+            if (offload_thread_nb == 0 ||
+                offload_thread_nb > MAX_OFFLOAD_THREAD_NB) {
+                VLOG_WARN("netdev: Invalid number of threads requested: %u",
+                          offload_thread_nb);
+                offload_thread_nb = DEFAULT_OFFLOAD_THREAD_NB;
+            }
+
+            if (smap_get(other_cfg, "n-offload-threads")) {
+                VLOG_INFO("Flow API using %u thread%s",
+                          offload_thread_nb,
+                          offload_thread_nb > 1 ? "s" : "");
+            }
+
+            ovsthread_once_done(&offload_rte->once_enable);
+        }
+    }
 }
 
 struct dpif_offload_class dpif_offload_rte_flow_class = {
@@ -44,4 +109,13 @@ struct dpif_offload_class dpif_offload_rte_flow_class = {
         NULL},
     .open = dpif_offload_rte_open,
     .close = dpif_offload_rte_close,
+    .set_config = dpif_offload_rte_set_config,
 };
+
+/* XXX: Temporary functions below, which will be removed once fully
+ *      refactored. */
+unsigned int dpif_offload_rte_get_thread_nb(void);
+unsigned int dpif_offload_rte_get_thread_nb(void)
+{
+    return offload_thread_nb;
+}
diff --git a/lib/dpif-offload-tc.c b/lib/dpif-offload-tc.c
index f5d62566e..c09530daa 100644
--- a/lib/dpif-offload-tc.c
+++ b/lib/dpif-offload-tc.c
@@ -19,22 +19,65 @@
 #include "dpif-offload.h"
 #include "dpif-offload-provider.h"
 #include "util.h"
+#include "tc.h"
+
+/* dpif offload interface for the tc implementation. */
+struct dpif_offload_tc {
+    struct dpif_offload offload;
+
+    /* Configuration specific variables. */
+    struct ovsthread_once once_enable; /* Track first-time enablement. */
+};
+
+static struct dpif_offload_tc *
+dpif_offload_tc_cast(const struct dpif_offload *offload)
+{
+    dpif_offload_assert_class(offload, &dpif_offload_tc_class);
+    return CONTAINER_OF(offload, struct dpif_offload_tc, offload);
+}
 
 static int
 dpif_offload_tc_open(const struct dpif_offload_class *offload_class,
                      struct dpif *dpif, struct dpif_offload **dpif_offload)
 {
-    struct dpif_offload *offload = xmalloc(sizeof(struct dpif_offload));
+    struct dpif_offload_tc *offload_tc;
+
+    offload_tc = xmalloc(sizeof(struct dpif_offload_tc));
+
+    dpif_offload_init(&offload_tc->offload, offload_class, dpif);
+    offload_tc->once_enable = (struct ovsthread_once) \
+                              OVSTHREAD_ONCE_INITIALIZER;
 
-    dpif_offload_init(offload, offload_class, dpif);
-    *dpif_offload = offload;
+    *dpif_offload = &offload_tc->offload;
     return 0;
 }
 
 static void
 dpif_offload_tc_close(struct dpif_offload *dpif_offload)
 {
-    free(dpif_offload);
+    struct dpif_offload_tc *offload_tc = dpif_offload_tc_cast(dpif_offload);
+
+    free(offload_tc);
+}
+
+static void
+dpif_offload_tc_set_config(struct dpif_offload *offload,
+                           const struct smap *other_cfg)
+{
+    struct dpif_offload_tc *offload_tc = dpif_offload_tc_cast(offload);
+
+    /* We maintain the existing behavior where global configurations
+     * are only accepted when hardware offload is initially enabled.
+     * Once enabled, they cannot be updated or reconfigured. */
+    if (smap_get_bool(other_cfg, "hw-offload", false)) {
+        if (ovsthread_once_start(&offload_tc->once_enable)) {
+
+            tc_set_policy(smap_get_def(other_cfg, "tc-policy",
+                                       TC_POLICY_DEFAULT));
+
+            ovsthread_once_done(&offload_tc->once_enable);
+        }
+    }
 }
 
 struct dpif_offload_class dpif_offload_tc_class = {
@@ -44,4 +87,5 @@ struct dpif_offload_class dpif_offload_tc_class = {
         NULL},
     .open = dpif_offload_tc_open,
     .close = dpif_offload_tc_close,
+    .set_config = dpif_offload_tc_set_config,
 };
diff --git a/lib/dpif-offload.c b/lib/dpif-offload.c
index aac87d955..c91b7dd25 100644
--- a/lib/dpif-offload.c
+++ b/lib/dpif-offload.c
@@ -348,6 +348,23 @@ dpif_offload_detach_providers(struct dpif *dpif)
     }
 }
 
+void
+dpif_offload_set_config(struct dpif *dpif, const struct smap *other_cfg)
+{
+    struct dp_offload *dp_offload = dpif_offload_get_dp_offload(dpif);
+    struct dpif_offload *offload;
+
+    if (!dp_offload) {
+        return;
+    }
+
+    LIST_FOR_EACH (offload, dpif_list_node, &dp_offload->offload_providers) {
+        if (offload->class->set_config) {
+            offload->class->set_config(offload, other_cfg);
+        }
+    }
+}
+
 
 void
 dpif_offload_init(struct dpif_offload *offload,
@@ -507,6 +524,7 @@ dpif_offload_set_global_cfg(const struct smap *other_cfg)
 
         if (ovsthread_once_start(&once_enable)) {
             atomic_store_relaxed(&dpif_offload_global_enabled, true);
+            VLOG_INFO("hw-offload API Enabled");
 
             if (smap_get_bool(other_cfg, "offload-rebalance", false)) {
                 atomic_store_relaxed(&dpif_offload_rebalance_policy, true);
diff --git a/lib/dpif.c b/lib/dpif.c
index eaf845b6a..a173d643a 100644
--- a/lib/dpif.c
+++ b/lib/dpif.c
@@ -1597,6 +1597,7 @@ dpif_set_config(struct dpif *dpif, const struct smap *cfg)
         if (error) {
             log_operation(dpif, "set_config", error);
         }
+        dpif_offload_set_config(dpif, cfg);
     }
 
     return error;
diff --git a/lib/netdev-offload.c b/lib/netdev-offload.c
index 01fdadbc3..b83bfb864 100644
--- a/lib/netdev-offload.c
+++ b/lib/netdev-offload.c
@@ -61,10 +61,15 @@ VLOG_DEFINE_THIS_MODULE(netdev_offload);
 
 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
 
-#define DEFAULT_OFFLOAD_THREAD_NB 1
+/* XXX: Temporarily duplicates definition in dpif-offload-rte_flow.c. */
 #define MAX_OFFLOAD_THREAD_NB 10
-
+#define DEFAULT_OFFLOAD_THREAD_NB 1
 static unsigned int offload_thread_nb = DEFAULT_OFFLOAD_THREAD_NB;
+
+unsigned int dpif_offload_rte_get_thread_nb(void); /* XXX: Temporarily external
+                                                    * declaration until fully
+                                                    * refactored. */
+
 DEFINE_EXTERN_PER_THREAD_DATA(netdev_offload_thread_id, OVSTHREAD_ID_UNSET);
 
 /* Protects 'netdev_flow_apis'.  */
@@ -853,37 +858,18 @@ netdev_ports_flow_init(void)
 }
 
 void
-netdev_set_flow_api_enabled(const struct smap *ovs_other_config)
+netdev_set_flow_api_enabled(const struct smap *ovs_other_config OVS_UNUSED)
 {
     if (dpif_offload_is_offload_enabled()) {
         static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
 
         if (ovsthread_once_start(&once)) {
 
-            offload_thread_nb = smap_get_ullong(ovs_other_config,
-                                                "n-offload-threads",
-                                                DEFAULT_OFFLOAD_THREAD_NB);
-            if (offload_thread_nb == 0 ||
-                offload_thread_nb > MAX_OFFLOAD_THREAD_NB) {
-                VLOG_WARN("netdev: Invalid number of threads requested: %u",
-                          offload_thread_nb);
-                offload_thread_nb = DEFAULT_OFFLOAD_THREAD_NB;
-            }
-
-            if (smap_get(ovs_other_config, "n-offload-threads")) {
-                VLOG_INFO("netdev: Flow API Enabled, using %u thread%s",
-                          offload_thread_nb,
-                          offload_thread_nb > 1 ? "s" : "");
-            } else {
-                VLOG_INFO("netdev: Flow API Enabled");
-            }
-
-#ifdef __linux__
-            tc_set_policy(smap_get_def(ovs_other_config, "tc-policy",
-                                       TC_POLICY_DEFAULT));
+#ifdef DPDK_NETDEV
+            offload_thread_nb = dpif_offload_rte_get_thread_nb();
 #endif
-            netdev_ports_flow_init();
 
+            netdev_ports_flow_init();
             ovsthread_once_done(&once);
         }
     }
diff --git a/tests/dpif-netdev.at b/tests/dpif-netdev.at
index 6804a9c5c..0304df895 100644
--- a/tests/dpif-netdev.at
+++ b/tests/dpif-netdev.at
@@ -414,7 +414,7 @@ m4_define([DPIF_NETDEV_FLOW_HW_OFFLOAD],
    AT_CHECK([ovs-appctl vlog/set dpif:file:dbg dpif_netdev:file:dbg 
netdev_dummy:file:dbg])
 
    AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:hw-offload=true])
-   OVS_WAIT_UNTIL([grep "netdev: Flow API Enabled" ovs-vswitchd.log])
+   OVS_WAIT_UNTIL([grep "hw-offload API Enabled" ovs-vswitchd.log])
 
    AT_CHECK([ovs-ofctl del-flows br0])
    AT_CHECK([ovs-ofctl add-flow br0 in_port=1,actions=IN_PORT])
@@ -477,7 +477,7 @@ m4_define([DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS],
    AT_CHECK([ovs-appctl vlog/set dpif:file:dbg dpif_netdev:file:dbg 
netdev_dummy:file:dbg])
 
    AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:hw-offload=true])
-   OVS_WAIT_UNTIL([grep "netdev: Flow API Enabled" ovs-vswitchd.log])
+   OVS_WAIT_UNTIL([grep "hw-offload API Enabled" ovs-vswitchd.log])
 
    AT_CHECK([ovs-ofctl del-flows br0])
 
@@ -554,7 +554,7 @@ m4_define([DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS_VID_ARP],
    AT_CHECK([ovs-appctl vlog/set dpif:file:dbg dpif_netdev:file:dbg 
netdev_dummy:file:dbg])
 
    AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:hw-offload=true])
-   OVS_WAIT_UNTIL([grep "netdev: Flow API Enabled" ovs-vswitchd.log])
+   OVS_WAIT_UNTIL([grep "hw-offload API Enabled" ovs-vswitchd.log])
 
    AT_CHECK([ovs-ofctl del-flows br0])
 
diff --git a/tests/ofproto-macros.at b/tests/ofproto-macros.at
index 71cd2aed0..8894dd711 100644
--- a/tests/ofproto-macros.at
+++ b/tests/ofproto-macros.at
@@ -224,7 +224,7 @@ m4_define([_OVS_VSWITCHD_START],
 /ofproto|INFO|datapath ID changed to fedcba9876543210/d
 /dpdk|INFO|DPDK Disabled - Use other_config:dpdk-init to enable/d
 /netlink_socket|INFO|netlink: could not enable listening to all nsid/d
-/netdev_offload|INFO|netdev: Flow API Enabled/d
+/dpif_offload|INFO|hw-offload API Enabled/d
 /probe tc:/d
 /setting extended ack support failed/d
 /tc: Using policy/d
-- 
2.50.1

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

Reply via email to