On 10 Dec 2025, at 18:00, 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 13/41] dpif-offload: Call flow-flush netdev-
>> offload APIs via dpif-offload.
>>
>> Start using the new dpif-offload API by avoiding direct calls to
>> netdev-offload.
>> This is the first step towards removing netdev-offload as an API layer.
>>
>> Signed-off-by: Eelco Chaudron <[email protected]>
>> ---
>>
>> v2 changes:
>> - Added missing newline at end of netdev-offload-tc.h.
>> - Fixed some indentation issues.
>> ---
>> lib/automake.mk | 4 +++-
>> lib/dpif-netdev.c | 2 +-
>> lib/dpif-netlink.c | 5 ----
>> lib/dpif-offload-dpdk.c | 9 ++++++++
>> lib/dpif-offload-provider.h | 13 +++++++++++
>> lib/dpif-offload-tc.c | 43 +++++++++++++++++++++++++++++++++++
>> lib/dpif-offload.c | 36 +++++++++++++++++++++++++++++
>> lib/dpif-offload.h | 5 ++++
>> lib/dpif.c | 1 +
>> lib/netdev-offload-dpdk.c | 4 ++--
>> lib/netdev-offload-dpdk.h | 27 ++++++++++++++++++++++
>> lib/netdev-offload-provider.h | 3 ---
>> lib/netdev-offload-tc.c | 6 ++---
>> lib/netdev-offload-tc.h | 27 ++++++++++++++++++++++
>> lib/netdev-offload.c | 25 --------------------
>> lib/netdev-offload.h | 2 --
>> 16 files changed, 170 insertions(+), 42 deletions(-) create mode 100644
>> lib/netdev-offload-dpdk.h create mode 100644 lib/netdev-offload-tc.h
>>
>> diff --git a/lib/automake.mk b/lib/automake.mk index 6db7daa9f..229064716
>> 100644
>> --- a/lib/automake.mk
>> +++ b/lib/automake.mk
>> @@ -481,6 +481,7 @@ lib_libopenvswitch_la_SOURCES += \
>> lib/netdev-linux.h \
>> lib/netdev-linux-private.h \
>> lib/netdev-offload-tc.c \
>> + lib/netdev-offload-tc.h \
>> lib/netlink-conntrack.c \
>> lib/netlink-conntrack.h \
>> lib/netlink-notifier.c \
>> @@ -509,7 +510,8 @@ lib_libopenvswitch_la_SOURCES += \
>> lib/dpdk.c \
>> lib/dpif-offload-dpdk.c \
>> lib/netdev-dpdk.c \
>> - lib/netdev-offload-dpdk.c
>> + lib/netdev-offload-dpdk.c \
>> + lib/netdev-offload-dpdk.h
>> else
>> lib_libopenvswitch_la_SOURCES += \
>> lib/dpdk-stub.c
>> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 2e31041ef..79b05bc0d
>> 100644
>> --- a/lib/dpif-netdev.c
>> +++ b/lib/dpif-netdev.c
>> @@ -2911,7 +2911,7 @@ dp_offload_flush(struct dp_offload_thread_item
>> *item)
>> struct dp_offload_flush_item *flush = &item->data->flush;
>>
>> ovs_rwlock_rdlock(&item->dp->port_rwlock);
>> - netdev_flow_flush(flush->netdev);
>> + dpif_offload_netdev_flush_flows(flush->netdev);
>> ovs_rwlock_unlock(&item->dp->port_rwlock);
>>
>> ovs_barrier_block(flush->barrier);
>> diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index
>> e7e55bc05..6241ba8f7
>> 100644
>> --- a/lib/dpif-netlink.c
>> +++ b/lib/dpif-netlink.c
>> @@ -1309,7 +1309,6 @@ dpif_netlink_port_get_pid(const struct dpif *dpif_,
>> odp_port_t port_no) static int dpif_netlink_flow_flush(struct dpif *dpif_)
>> {
>> - const char *dpif_type_str = dpif_normalize_type(dpif_type(dpif_));
>> const struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
>> struct dpif_netlink_flow flow;
>>
>> @@ -1317,10 +1316,6 @@ dpif_netlink_flow_flush(struct dpif *dpif_)
>> flow.cmd = OVS_FLOW_CMD_DEL;
>> flow.dp_ifindex = dpif->dp_ifindex;
>>
>> - if (dpif_offload_is_offload_enabled()) {
>> - netdev_ports_flow_flush(dpif_type_str);
>> - }
>> -
>> return dpif_netlink_flow_transact(&flow, NULL, NULL); }
>>
>> diff --git a/lib/dpif-offload-dpdk.c b/lib/dpif-offload-dpdk.c index
>> 1f097bfc9..f231a1c68 100644
>> --- a/lib/dpif-offload-dpdk.c
>> +++ b/lib/dpif-offload-dpdk.c
>> @@ -19,6 +19,7 @@
>>
>> #include "dpif-offload.h"
>> #include "dpif-offload-provider.h"
>> +#include "netdev-offload-dpdk.h"
>> #include "netdev-provider.h"
>> #include "netdev-vport.h"
>> #include "util.h"
>> @@ -252,6 +253,13 @@ dpif_offload_dpdk_can_offload(struct dpif_offload
>> *offload OVS_UNUSED,
>> return netdev_dpdk_flow_api_supported(netdev, true); }
>>
>> +static int
>> +dpif_offload_dpdk_netdev_flow_flush(const struct dpif_offload *offload
>> + OVS_UNUSED, struct netdev *netdev)
>> +{
>> + return netdev_offload_dpdk_flow_flush(netdev);
>> +}
>> +
>> struct dpif_offload_class dpif_offload_dpdk_class = {
>> .type = "dpdk",
>> .supported_dpif_types = (const char *const[]) { @@ -264,6 +272,7 @@
>> struct dpif_offload_class dpif_offload_dpdk_class = {
>> .can_offload = dpif_offload_dpdk_can_offload,
>> .port_add = dpif_offload_dpdk_port_add,
>> .port_del = dpif_offload_dpdk_port_del,
>> + .netdev_flow_flush = dpif_offload_dpdk_netdev_flow_flush,
>> };
>>
>> /* XXX: Temporary functions below, which will be removed once fully diff
>> --git
>> a/lib/dpif-offload-provider.h b/lib/dpif-offload-provider.h index
>> 50f9a53c2..4439e9f71 100644
>> --- a/lib/dpif-offload-provider.h
>> +++ b/lib/dpif-offload-provider.h
>> @@ -126,6 +126,19 @@ struct dpif_offload_class {
>> * as above in 'port_deleted' applies here.*/
>> void (*port_set_config)(struct dpif_offload *, odp_port_t port_no,
>> const struct smap *cfg);
>> +
>> + /* Deletes all offloaded flows for this offload_provider. Return 0 if
>> + * successful, otherwise returns a positive errno value. */
>> + int (*flow_flush)(const struct dpif_offload *);
>> +
>> +
>> + /* These APIs operate directly on the provided netdev for performance
>> + * reasons. They are intended for use in fast path processing and
>> should
>> + * be designed with speed and efficiency in mind. */
>> +
>> + /* Deletes all offloaded flows on this netdev. Return 0 if successful,
>> + * otherwise returns a positive errno value. */
>> + int (*netdev_flow_flush)(const struct dpif_offload *, struct netdev
>> + *);
>> };
>>
>>
>> diff --git a/lib/dpif-offload-tc.c b/lib/dpif-offload-tc.c index
>> 66d52851a..63ce789c6 100644
>> --- a/lib/dpif-offload-tc.c
>> +++ b/lib/dpif-offload-tc.c
>> @@ -19,6 +19,7 @@
>>
>> #include "dpif-offload.h"
>> #include "dpif-offload-provider.h"
>> +#include "netdev-offload-tc.h"
>> #include "netdev-provider.h"
>> #include "netdev-vport.h"
>> #include "util.h"
>> @@ -236,6 +237,46 @@ dpif_offload_tc_can_offload(struct dpif_offload
>> *dpif_offload OVS_UNUSED,
>> return true;
>> }
>>
>> +static int
>> +dpif_offload_tc_netdev_flow_flush_(struct netdev *netdev) {
>> + return netdev_offload_tc_flow_flush(netdev);
>> +}
>> +
>> +static int
>> +dpif_offload_tc_netdev_flow_flush(const struct dpif_offload *offload
>> + OVS_UNUSED, struct netdev *netdev) {
>> + return dpif_offload_tc_netdev_flow_flush_(netdev);
>> +}
>> +
>> +static bool
>> +dpif_offload_tc_flow_flush_cb(struct dpif_offload_port_mgr_port *port,
>> + void *aux) {
>> + int *err_ptr = aux;
>> + int err;
>> +
>> + err = dpif_offload_tc_netdev_flow_flush_(port->netdev);
>> + if (err && *err_ptr == 0) {
>> + *err_ptr = err;
>> + }
>> +
>> + return false;
>> +}
>> +
>> +static int
>> +dpif_offload_tc_flow_flush(const struct dpif_offload *offload) {
>> + struct dpif_offload_tc *offload_tc = dpif_offload_tc_cast(offload);
>> + int err = 0;
>> +
>> + dpif_offload_port_mgr_traverse_ports(
>> + offload_tc->port_mgr, dpif_offload_tc_flow_flush_cb, &err);
>> +
>> + return err;
>> +}
>> +
>> struct dpif_offload_class dpif_offload_tc_class = {
>> .type = "tc",
>> .supported_dpif_types = (const char *const[]) { @@ -248,4 +289,6 @@
>> struct dpif_offload_class dpif_offload_tc_class = {
>> .can_offload = dpif_offload_tc_can_offload,
>> .port_add = dpif_offload_tc_port_add,
>> .port_del = dpif_offload_tc_port_del,
>> + .flow_flush = dpif_offload_tc_flow_flush,
>> + .netdev_flow_flush = dpif_offload_tc_netdev_flow_flush,
>> };
>> diff --git a/lib/dpif-offload.c b/lib/dpif-offload.c index
>> bfaa953b5..5f2be95ee
>> 100644
>> --- a/lib/dpif-offload.c
>> +++ b/lib/dpif-offload.c
>> @@ -713,6 +713,42 @@ dpif_offload_set_global_cfg(const struct
>> ovsrec_open_vswitch *cfg)
>> }
>> }
>>
>> +void
>> +dpif_offload_flow_flush(struct dpif *dpif) {
>> + struct dp_offload *dp_offload = dpif_offload_get_dp_offload(dpif);
>> + const struct dpif_offload *offload;
>> +
>> + if (!dp_offload) {
>> + return;
>> + }
>> +
>> + LIST_FOR_EACH (offload, dpif_list_node, &dp_offload->offload_providers)
>> {
>> + if (offload->class->flow_flush) {
>> + int err = offload->class->flow_flush(offload);
> Blank line
>> + if (err) {
>> + VLOG_ERR("Failed flow flush on dpif-offload provider "
>> + "%s, error %s", dpif_offload_name(offload),
>> + ovs_strerror(err));
> indentation
ACK on both.
>> + }
>> + }
>> + }
>> +}
>> +
>> +
>>
>>
>> +int
>> +dpif_offload_netdev_flush_flows(struct netdev *netdev) {
>> + const struct dpif_offload *offload;
>> +
>> + offload = ovsrcu_get(const struct dpif_offload *,
>> + &netdev->dpif_offload);
>> +
>> + if (offload && offload->class->netdev_flow_flush) {
>> + return offload->class->netdev_flow_flush(offload, netdev);
>> + }
>> + return EOPNOTSUPP;
>> +}
>> +
>>
>>
>>
>> struct dpif_offload_port_mgr *
>> dpif_offload_port_mgr_init(void)
>> diff --git a/lib/dpif-offload.h b/lib/dpif-offload.h index
>> 5b6c3038e..2d8778f7b
>> 100644
>> --- a/lib/dpif-offload.h
>> +++ b/lib/dpif-offload.h
>> @@ -46,6 +46,7 @@ const char *dpif_offload_name(const struct dpif_offload
>> *); const char *dpif_offload_class_type(const struct dpif_offload *); bool
>> dpif_offload_get_debug(const struct dpif_offload *, struct ds *,
>> struct json *);
>> +void dpif_offload_flow_flush(struct dpif *);
>> void dpif_offload_dump_start(struct dpif_offload_dump *, const struct dpif
>> *);
>> bool dpif_offload_dump_next(struct dpif_offload_dump *,
>> struct dpif_offload **); @@ -64,4 +65,8 @@ int
>> dpif_offload_dump_done(struct dpif_offload_dump *);
>> : (dpif_offload_dump_done(DUMP), false)); \
>> )
>>
>> +
>>
>>
>> +/* Netdev specific function, which can be used in the fast path. */ int
>> +dpif_offload_netdev_flush_flows(struct netdev *);
>> +
>> #endif /* DPIF_OFFLOAD_H */
>> diff --git a/lib/dpif.c b/lib/dpif.c
>> index fb889322a..4e6f13255 100644
>> --- a/lib/dpif.c
>> +++ b/lib/dpif.c
>> @@ -958,6 +958,7 @@ dpif_flow_flush(struct dpif *dpif)
>>
>> error = dpif->dpif_class->flow_flush(dpif);
>> log_operation(dpif, "flow_flush", error);
>> + dpif_offload_flow_flush(dpif);
>> return error;
>> }
>>
>> diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c index
>> c4f97be70..072103596 100644
>> --- a/lib/netdev-offload-dpdk.c
>> +++ b/lib/netdev-offload-dpdk.c
>> @@ -25,6 +25,7 @@
>>
>> #include "cmap.h"
>> #include "dpif-netdev.h"
>> +#include "netdev-offload-dpdk.h"
>> #include "netdev-offload-provider.h"
>> #include "netdev-provider.h"
>> #include "netdev-vport.h"
>> @@ -2609,7 +2610,7 @@ flush_in_vport_cb(struct netdev *vport,
>> return false;
>> }
>>
>> -static int
>> +int
>> netdev_offload_dpdk_flow_flush(struct netdev *netdev) {
>> flush_netdev_flows_in_related(netdev, netdev); @@ -2802,7 +2803,6 @@
>> const struct netdev_flow_api netdev_offload_dpdk = {
>> .init_flow_api = netdev_offload_dpdk_init_flow_api,
>> .uninit_flow_api = netdev_offload_dpdk_uninit_flow_api,
>> .flow_get = netdev_offload_dpdk_flow_get,
>> - .flow_flush = netdev_offload_dpdk_flow_flush,
>> .hw_miss_packet_recover =
>> netdev_offload_dpdk_hw_miss_packet_recover,
>> .flow_get_n_flows = netdev_offload_dpdk_get_n_flows, }; diff --git
>> a/lib/netdev-offload-dpdk.h b/lib/netdev-offload-dpdk.h new file mode
>> 100644 index 000000000..feded432f
>> --- /dev/null
>> +++ b/lib/netdev-offload-dpdk.h
>> @@ -0,0 +1,27 @@
>> +/*
>> + * Copyright (c) 2025 Red Hat, Inc.
>> + *
>> + * Licensed under the Apache License, Version 2.0 (the "License");
>> + * you may not use this file except in compliance with the License.
>> + * You may obtain a copy of the License at:
>> + *
>> + * http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * Unless required by applicable law or agreed to in writing, software
>> + * distributed under the License is distributed on an "AS IS" BASIS,
>> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>> implied.
>> + * See the License for the specific language governing permissions and
>> + * limitations under the License.
>> + */
>> +
>> + #ifndef NETDEV_OFFLOAD_DPDK_H
>> + #define NETDEV_OFFLOAD_DPDK_H
>> +
>> +/* Forward declarations of private structures. */ struct netdev;
>> +
>> +/* Netdev-specific offload functions. These should only be used by the
>> + * associated dpif offload provider. */ int
>> +netdev_offload_dpdk_flow_flush(struct netdev *);
>> +
>> +#endif /* NETDEV_OFFLOAD_DPDK_H */
>> diff --git a/lib/netdev-offload-provider.h b/lib/netdev-offload-provider.h
>> index
>> 9108856d1..6e36ed4c8 100644
>> --- a/lib/netdev-offload-provider.h
>> +++ b/lib/netdev-offload-provider.h
>> @@ -30,9 +30,6 @@ extern "C" {
>>
>> struct netdev_flow_api {
>> char *type;
>> - /* Flush all offloaded flows from a netdev.
>> - * Return 0 if successful, otherwise returns a positive errno value. */
>> - int (*flow_flush)(struct netdev *);
>>
>> /* Flow dumping interface.
>> *
>> diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c index
>> 9491dc90e..1c554416c 100644
>> --- a/lib/netdev-offload-tc.c
>> +++ b/lib/netdev-offload-tc.c
>> @@ -32,6 +32,7 @@
>> #include "openvswitch/vlog.h"
>> #include "netdev-linux.h"
>> #include "netdev-offload-provider.h"
>> +#include "netdev-offload-tc.h"
>> #include "netdev-provider.h"
>> #include "netdev-vport.h"
>> #include "netlink.h"
>> @@ -562,8 +563,8 @@ delete_chains_from_netdev(struct netdev *netdev,
>> struct tcf_id *id)
>> return error;
>> }
>>
>> -static int
>> -netdev_tc_flow_flush(struct netdev *netdev)
>> +int
>> +netdev_offload_tc_flow_flush(struct netdev *netdev)
>> {
>> struct ufid_tc_data *data;
>> int err;
>> @@ -3426,7 +3427,6 @@ meter_tc_del_policer(ofproto_meter_id meter_id,
>>
>> const struct netdev_flow_api netdev_offload_tc = {
>> .type = "linux_tc",
>> - .flow_flush = netdev_tc_flow_flush,
>> .flow_dump_create = netdev_tc_flow_dump_create,
>> .flow_dump_destroy = netdev_tc_flow_dump_destroy,
>> .flow_dump_next = netdev_tc_flow_dump_next, diff --git a/lib/netdev-
>> offload-tc.h b/lib/netdev-offload-tc.h new file mode 100644 index
>> 000000000..964559728
>> --- /dev/null
>> +++ b/lib/netdev-offload-tc.h
>> @@ -0,0 +1,27 @@
>> +/*
>> + * Copyright (c) 2025 Red Hat, Inc.
>> + *
>> + * Licensed under the Apache License, Version 2.0 (the "License");
>> + * you may not use this file except in compliance with the License.
>> + * You may obtain a copy of the License at:
>> + *
>> + * http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * Unless required by applicable law or agreed to in writing, software
>> + * distributed under the License is distributed on an "AS IS" BASIS,
>> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>> implied.
>> + * See the License for the specific language governing permissions and
>> + * limitations under the License.
>> + */
>> +
>> +#ifndef NETDEV_OFFLOAD_TC_H
>> +#define NETDEV_OFFLOAD_TC_H
>> +
>> +/* Forward declarations of private structures. */ struct netdev;
>> +
>> +/* Netdev-specific offload functions. These should only be used by the
>> + * associated dpif offload provider. */ int
>> +netdev_offload_tc_flow_flush(struct netdev *);
>> +
>> +#endif /* NETDEV_OFFLOAD_TC_H */
>> diff --git a/lib/netdev-offload.c b/lib/netdev-offload.c index
>> 0fad1b983..2b1c99fb6 100644
>> --- a/lib/netdev-offload.c
>> +++ b/lib/netdev-offload.c
>> @@ -262,17 +262,6 @@ meter_offload_del(ofproto_meter_id meter_id,
>> struct ofputil_meter_stats *stats)
>> return 0;
>> }
>>
>> -int
>> -netdev_flow_flush(struct netdev *netdev) -{
>> - const struct netdev_flow_api *flow_api =
>> - ovsrcu_get(const struct netdev_flow_api *, &netdev->flow_api);
>> -
>> - return (flow_api && flow_api->flow_flush)
>> - ? flow_api->flow_flush(netdev)
>> - : EOPNOTSUPP;
>> -}
>> -
>> int
>> netdev_flow_dump_create(struct netdev *netdev, struct netdev_flow_dump
>> **dump,
>> bool terse)
>> @@ -591,20 +580,6 @@ netdev_offload_thread_init(void)
>> }
>> }
>>
>> -void
>> -netdev_ports_flow_flush(const char *dpif_type) -{
>> - struct port_to_netdev_data *data;
>> -
>> - ovs_rwlock_rdlock(&port_to_netdev_rwlock);
>> - HMAP_FOR_EACH (data, portno_node, &port_to_netdev) {
>> - if (netdev_get_dpif_type(data->netdev) == dpif_type) {
>> - netdev_flow_flush(data->netdev);
>> - }
>> - }
>> - ovs_rwlock_unlock(&port_to_netdev_rwlock);
>> -}
>> -
>> void
>> netdev_ports_traverse(const char *dpif_type,
>> bool (*cb)(struct netdev *, odp_port_t, void *), diff
>> --git
>> a/lib/netdev-offload.h b/lib/netdev-offload.h index 5a18727eb..0bee005fd
>> 100644
>> --- a/lib/netdev-offload.h
>> +++ b/lib/netdev-offload.h
>> @@ -100,7 +100,6 @@ netdev_offload_thread_id(void)
>> return id;
>> }
>>
>> -int netdev_flow_flush(struct netdev *); int netdev_flow_dump_create(struct
>> netdev *, struct netdev_flow_dump **dump,
>> bool terse); int netdev_flow_dump_destroy(struct
>> netdev_flow_dump *); @@ -144,7 +143,6 @@ struct netdev_flow_dump
>> **netdev_ports_flow_dump_create(
>> const char *dpif_type,
>> int *ports,
>> bool terse); -void
>> netdev_ports_flow_flush(const char
>> *dpif_type); int netdev_ports_flow_del(const char *dpif_type, const ovs_u128
>> *ufid,
>> struct dpif_flow_stats *stats); int
>> netdev_ports_flow_get(const
>> char *dpif_type, struct match *match,
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev