>-----Original Message-----
>From: dev <[email protected]> On Behalf Of Eelco Chaudron
>Sent: Tuesday, 2 December 2025 16:05
>To: [email protected]
>Subject: [ovs-dev] [PATCH v2 11/41] dpif-offload: Allow per-port offload
>provider priority config.
>
>This patch adds support for configuring the priority of offload providers at a 
>port
>level.  When multiple providers exist and support the same port, the 'hw-
>offload-priority'
>option allows specifying the order in which they are tried.
>
>Signed-off-by: Eelco Chaudron <[email protected]>
>---
>
>v2 changes:
>  - Fixed indentation problem in bridge_run().
>---
> lib/dpif-offload.c   | 104 ++++++++++++++++++++++++++++++++++++-------
> lib/dpif-offload.h   |   2 +-
> vswitchd/bridge.c    |   5 ++-
> vswitchd/vswitch.xml |  24 ++++++++++
> 4 files changed, 116 insertions(+), 19 deletions(-)
>
>diff --git a/lib/dpif-offload.c b/lib/dpif-offload.c index 5c6b827c3..42055008e
>100644
>--- a/lib/dpif-offload.c
>+++ b/lib/dpif-offload.c
>@@ -23,6 +23,8 @@
> #include "netdev-provider.h"
> #include "unixctl.h"
> #include "util.h"
>+#include "vswitch-idl.h"
>+
> #include "openvswitch/dynamic-string.h"
> #include "openvswitch/shash.h"
> #include "openvswitch/vlog.h"
>@@ -55,6 +57,7 @@ static const struct dpif_offload_class
>*base_dpif_offload_classes[] = {  static char
>*dpif_offload_provider_priority_list = NULL;  static atomic_bool
>dpif_offload_global_enabled = false;  static atomic_bool
>dpif_offload_rebalance_policy = false;
>+static struct smap port_order_cfg = SMAP_INITIALIZER(&port_order_cfg);
>
> static int
> dpif_offload_register_provider__(const struct dpif_offload_class *class) @@ -
>428,34 +431,79 @@ dpif_offload_set_netdev_offload(struct netdev *netdev,
>     ovsrcu_set(&netdev->dpif_offload, offload);  }
>
>+static bool
>+dpif_offload_try_port_add(struct dpif_offload *offload, struct netdev
>*netdev,
>+                          odp_port_t port_no) {
>+    if (offload->class->can_offload(offload, netdev)) {
>+        int err = offload->class->port_add(offload, netdev, port_no);
Blank line
>+        if (!err) {
>+            VLOG_DBG("netdev %s added to dpif-offload provider %s",
>+                     netdev_get_name(netdev), dpif_offload_name(offload));
>+            return true;
>+        } else {
>+            VLOG_ERR("Failed adding netdev %s to dpif-offload provider "
>+                     "%s, error %s",
>+                     netdev_get_name(netdev), dpif_offload_name(offload),
>+                     ovs_strerror(err));
>+        }
>+    } else {
>+        VLOG_DBG("netdev %s failed can_offload for dpif-offload provider %s",
>+                 netdev_get_name(netdev), dpif_offload_name(offload));
>+    }
>+    return false;
>+}
>+
> void
> dpif_offload_port_add(struct dpif *dpif, struct netdev *netdev,
>                       odp_port_t port_no)  {
>     struct dp_offload *dp_offload = dpif_offload_get_dp_offload(dpif);
>+    const char *port_priority = smap_get(&port_order_cfg,
>+                                         netdev_get_name(netdev));
>     struct dpif_offload *offload;
>
>     if (!dp_offload) {
>         return;
>     }
>
>-    LIST_FOR_EACH (offload, dpif_list_node, &dp_offload->offload_providers) {
>-        if (offload->class->can_offload(offload, netdev)) {
>-            int err = offload->class->port_add(offload, netdev, port_no);
>-            if (!err) {
>-                VLOG_DBG("netdev %s added to dpif-offload provider %s",
>-                         netdev_get_name(netdev), dpif_offload_name(offload));
>+    if (port_priority) {
>+        char *tokens = xstrdup(port_priority);
>+        char *saveptr;
>+
>+        VLOG_DBG("for netdev %s using port priority %s",
>+                 netdev_get_name(netdev), port_priority);
>+
>+        for (char *name = strtok_r(tokens, ",", &saveptr);
>+             name;
>+             name = strtok_r(NULL, ",", &saveptr)) {
>+            bool provider_added = false;
>+
>+            if (!strcmp("none", name)) {
>+                break;
>+            }
>+
>+            LIST_FOR_EACH (offload, dpif_list_node,
>+                           &dp_offload->offload_providers) {
>+                if (!strcmp(name, offload->class->type)) {
>+
Remove blank line
>+                    provider_added = dpif_offload_try_port_add(offload, 
>netdev,
>+                                                               port_no);
>+                    break;
>+                }
>+            }
>+
>+            if (provider_added) {
>+                break;
>+            }
>+        }
>+        free(tokens);
>+    } else {
>+        LIST_FOR_EACH (offload, dpif_list_node,
>+                       &dp_offload->offload_providers) {
>+            if (dpif_offload_try_port_add(offload, netdev, port_no)) {
>                 break;
>-            } else {
>-                VLOG_ERR("Failed adding netdev %s to dpif-offload provider "
>-                         "%s, error %s",
>-                         netdev_get_name(netdev), dpif_offload_name(offload),
>-                         ovs_strerror(err));
>             }
>-        } else {
>-            VLOG_DBG(
>-                "netdev %s failed can_offload for dpif-offload provider %s",
>-                netdev_get_name(netdev), dpif_offload_name(offload));
>         }
>     }
> }
>@@ -569,13 +617,16 @@ dpif_offload_dump_done(struct dpif_offload_dump
>*dump)  }
>
> void
>-dpif_offload_set_global_cfg(const struct smap *other_cfg)
>+dpif_offload_set_global_cfg(const struct ovsrec_open_vswitch *cfg)
> {
>     static struct ovsthread_once init_once = OVSTHREAD_ONCE_INITIALIZER;
>-    const char *priority = smap_get(other_cfg, "hw-offload-priority");
>+    const struct smap *other_cfg = &cfg->other_config;
>+    const char *priority;
>
>     /* The 'hw-offload-priority' parameter can only be set at startup,
>      * any successive change needs a restart. */
>+    priority = smap_get(other_cfg, "hw-offload-priority");
>+
>     if (ovsthread_once_start(&init_once)) {
>         /* Initialize the dpif-offload layer in case it's not yet initialized
>          * at the first invocation of setting the configuration. */ @@ -629,6
>+680,25 @@ dpif_offload_set_global_cfg(const struct smap *other_cfg)
>             ovsthread_once_done(&once_enable);
>         }
>     }
>+
>+    /* Filter out the 'hw-offload-priority' per port setting we need it before
>+     * ports are added, so we can assign the correct offload-provider.
>+     * Note that we can safely rebuild the map here, as we only access this
>+     * from the same (main) thread. */
>+    smap_clear(&port_order_cfg);
>+    for (int i = 0; i < cfg->n_bridges; i++) {
>+        const struct ovsrec_bridge *br_cfg = cfg->bridges[i];
>+
>+        for (int j = 0; j < br_cfg->n_ports; j++) {
>+            const struct ovsrec_port *port_cfg = br_cfg->ports[j];
>+
>+            priority = smap_get(&port_cfg->other_config,
>+                                "hw-offload-priority");
>+            if (priority) {
>+                smap_add(&port_order_cfg, port_cfg->name, priority);
>+            }
>+        }
>+    }
> }
>
>
>
>
>diff --git a/lib/dpif-offload.h b/lib/dpif-offload.h index f35f9b8a8..9cee3a8f4
>100644
>--- a/lib/dpif-offload.h
>+++ b/lib/dpif-offload.h
>@@ -32,7 +32,7 @@ struct dpif_offload_dump {
>
>
>
>
> /* Global functions. */
>-void dpif_offload_set_global_cfg(const struct smap *other_cfg);
>+void dpif_offload_set_global_cfg(const struct ovsrec_open_vswitch *);
> bool dpif_offload_is_offload_enabled(void);
> bool dpif_offload_is_offload_rebalance_policy_enabled(void);
>
>diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 62dec1391..10fcc49a7
>100644
>--- a/vswitchd/bridge.c
>+++ b/vswitchd/bridge.c
>@@ -3395,8 +3395,11 @@ bridge_run(void)
>     }
>     cfg = ovsrec_open_vswitch_first(idl);
>
>+    if (cfg && ovsdb_idl_get_seqno(idl) != idl_seqno) {
>+        dpif_offload_set_global_cfg(cfg);
>+    }
>+
>     if (cfg) {
>-        dpif_offload_set_global_cfg(&cfg->other_config);
>         netdev_set_flow_api_enabled(&cfg->other_config);
>         dpdk_init(&cfg->other_config);
>         userspace_tso_init(&cfg->other_config);
>diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index
>061d0a568..1c53a2859 100644
>--- a/vswitchd/vswitch.xml
>+++ b/vswitchd/vswitch.xml
>@@ -2600,6 +2600,30 @@
>         e.g. <code>fake-bridge-bridge-id</code>.
>       </column>
>
>+      <column name="other_config" key="hw-offload-priority"
>+              type='{"type": "string"}'>
>+        <p>
>+          This configuration sets an explicit list of hardware offload
>+          providers to try on this port.  The argument should be a
>+          comma-separated list of hardware offload provider names, or the
>+          word <code>none</code>.
>+        </p>
>+        <p>
>+          If <code>none</code> is encountered in the list, further trying of
>+          offload providers is stopped. For example, if the list only contains
>+          <code>none</code>, hardware offload is disabled on this port even if
>+          it is globally enabled. Note that unknown hardware offload provider
>+          names are ignored.
>+        </p>
>+        <p>
>+          The default value is <code>none</code>, i.e., not set, which uses 
>the
>+          global
>+          <ref table="Open_vSwitch" column="other_config" key="hw-offload-
>priority"/>
>+          configuration. Changing this value after offload enablement requires
>+          restarting the daemon.
>+        </p>
>+      </column>
>+
>       <column name="other_config" key="transient"
>               type='{"type": "boolean"}'>
>         <p>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to