On 10 Dec 2025, at 17:39, Eli Britstein wrote:
>> -----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
ACK
>> + 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
ACK
>> + 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