>-----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
>+ }
>+ }
>+ }
>+}
>+
>+
>
>
>+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