This allows configuring hardware offload on/off.  The ct_sweep
expiration is always trying to fill the ops batch anyway, so it
doesn't need an actual check for enabled / disabled.  Wrapping that
code in a check may also be harmful in the event that offload is
disabled with offloaded connections.

Assisted-by: Claude Sonnet 4.6 <[email protected]>
Signed-off-by: Aaron Conole <[email protected]>
---
 lib/conntrack.c    |  5 +++--
 lib/ct-offload.c   | 46 +++++++++++++++++++++++++++++++++++++++++++---
 lib/ct-offload.h   |  9 +++++++++
 lib/dpif-offload.c | 16 ++++++++++++++++
 lib/dpif-offload.h |  1 +
 5 files changed, 72 insertions(+), 5 deletions(-)

diff --git a/lib/conntrack.c b/lib/conntrack.c
index fbc7e43dc6..eb22039372 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -1396,7 +1396,7 @@ process_one(struct conntrack *ct, struct dp_packet *pkt,
         }
         ovs_mutex_unlock(&ct->ct_lock);
 
-        if (conn) {
+        if (conn && ct_offload_enabled()) {
             struct ct_offload_ctx offload_ctx = {
                 .conn          = conn,
                 .netdev_in     = NULL,
@@ -1410,7 +1410,8 @@ process_one(struct conntrack *ct, struct dp_packet *pkt,
     }
 
     if (!create_new_conn && conn && ctx->reply &&
-        (pkt->md.ct_state & CS_ESTABLISHED)) {
+        (pkt->md.ct_state & CS_ESTABLISHED) &&
+        ct_offload_enabled()) {
         /* Notify offload providers that the connection is established.
          * We use the reply bit to detect that the connection has
          * transitioned and give us the input port, which should be the
diff --git a/lib/ct-offload.c b/lib/ct-offload.c
index 58afef7203..8c9c98e805 100644
--- a/lib/ct-offload.c
+++ b/lib/ct-offload.c
@@ -22,14 +22,22 @@
 
 #include "conntrack.h"
 #include "conntrack-private.h"
+#include "dpif-offload.h"
 #include "ovs-thread.h"
 #include "util.h"
+#include "vswitch-idl.h"
 
 #include "openvswitch/list.h"
 #include "openvswitch/vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(ct_offload);
 
+/* Built-in CT offload provider classes.  Only those whose name matches a
+ * registered dpif offload class will be activated by ct_offload_module_init().
+ * Populated by downstream patches as concrete providers are added. */
+static const struct ct_offload_class *base_ct_offload_classes[] OVS_UNUSED = {
+};
+
 /* Private slot for storing per-connection offload state. */
 static ct_private_id_t ct_offload_private_id = CT_PRIVATE_ID_INVALID;
 
@@ -140,13 +148,16 @@ ct_offload_alloc_private_slot(void)
 
 /* ct_offload_module_init() - register built-in CT offload providers.
  *
- * Must be called once before any connections are created. */
+ * Only registers providers whose name matches a currently-registered dpif
+ * offload class, so CT offload is automatically tied to the active hardware
+ * offload provider.  Safe to call multiple times; subsequent calls are
+ * no-ops (duplicate registration is detected and skipped). */
 void
 ct_offload_module_init(void)
 {
     ct_offload_alloc_private_slot();
-    /* No built-in providers yet; third parties call ct_offload_register()
-     * directly from their own module-init routines. */
+    /* No built-in providers yet; base_ct_offload_classes[] is populated as
+     * concrete providers are added in downstream patches. */
 }
 
 /* ct_offload_init_for_tests() - allocate the internal private slot for tests.
@@ -159,6 +170,35 @@ ct_offload_init_for_tests(void)
     ct_offload_alloc_private_slot();
 }
 
+/* ct_offload_enabled() - returns true when hardware offload is active.
+ *
+ * Delegates to dpif_offload_enabled() so CT offload shares the same global
+ * enable/disable knob as datapath hardware offload. */
+bool
+ct_offload_enabled(void)
+{
+    return dpif_offload_enabled();
+}
+
+/* ct_offload_set_global_cfg() - configure CT offload from OVSDB.
+ *
+ * Called internally by dpif_offload_set_global_cfg() once hardware offload
+ * has been enabled and the appropriate dpif offload classes are known. */
+void
+ct_offload_set_global_cfg(const struct ovsrec_open_vswitch *cfg OVS_UNUSED)
+{
+    static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
+
+    if (!dpif_offload_enabled()) {
+        return;
+    }
+
+    if (ovsthread_once_start(&once)) {
+        ct_offload_module_init();
+        ovsthread_once_done(&once);
+    }
+}
+
 /* Internal helpers -- callers must hold ct_offload_classes_rwlock (rdlock).
  *
  * When 'batched' is true the helper skips providers that implement
diff --git a/lib/ct-offload.h b/lib/ct-offload.h
index 4971a61e53..1496fc2b7e 100644
--- a/lib/ct-offload.h
+++ b/lib/ct-offload.h
@@ -23,6 +23,7 @@
 #include "util.h"
 
 struct netdev;
+struct ovsrec_open_vswitch;
 
 /* Context for offload as part of the callbacks that all connection
  * offload APIs receive. */
@@ -103,6 +104,14 @@ void ct_offload_module_init(void);
  * production use; call ct_offload_module_init() instead. */
 void ct_offload_init_for_tests(void);
 
+/* Global configuration: called internally by dpif_offload_set_global_cfg()
+ * to enable CT offload once hardware offload is active. */
+void ct_offload_set_global_cfg(const struct ovsrec_open_vswitch *);
+
+/* Returns true when CT offload is enabled (delegates to
+ * dpif_offload_enabled()). */
+bool ct_offload_enabled(void);
+
 /* Per-connection offload API that dispatches to all registered providers.
  * conn_add, conn_del, and conn_established require conn->lock to be held by
  * the caller; conn_update, can_offload, and flush do not. */
diff --git a/lib/dpif-offload.c b/lib/dpif-offload.c
index 04dabc42c7..37e4465931 100644
--- a/lib/dpif-offload.c
+++ b/lib/dpif-offload.c
@@ -18,6 +18,7 @@
 #include <errno.h>
 
 #include "dpif-offload.h"
+#include "ct-offload.h"
 #include "dpif-offload-provider.h"
 #include "dpif-provider.h"
 #include "netdev-provider.h"
@@ -516,6 +517,19 @@ dpif_offload_enabled(void)
     return enabled;
 }
 
+/* dpif_offload_class_is_registered() - returns true if a dpif offload class
+ * with the given name has been successfully registered. */
+bool
+dpif_offload_class_is_registered(const char *name)
+{
+    bool found;
+
+    ovs_mutex_lock(&dpif_offload_mutex);
+    found = shash_find(&dpif_offload_classes, name) != NULL;
+    ovs_mutex_unlock(&dpif_offload_mutex);
+    return found;
+}
+
 bool
 dpif_offload_rebalance_policy_enabled(void)
 {
@@ -828,6 +842,8 @@ dpif_offload_set_global_cfg(const struct 
ovsrec_open_vswitch *cfg)
             }
         }
     }
+
+    ct_offload_set_global_cfg(cfg);
 }
 
 void
diff --git a/lib/dpif-offload.h b/lib/dpif-offload.h
index bf76433200..c008a40c46 100644
--- a/lib/dpif-offload.h
+++ b/lib/dpif-offload.h
@@ -45,6 +45,7 @@ enum dpif_offload_impl_type {
 void dpif_offload_set_global_cfg(const struct ovsrec_open_vswitch *);
 bool dpif_offload_enabled(void);
 bool dpif_offload_rebalance_policy_enabled(void);
+bool dpif_offload_class_is_registered(const char *name);
 
 
 /* Per dpif specific functions. */
-- 
2.51.0

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to