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);
+            if (err) {
+                VLOG_ERR("Failed flow flush on dpif-offload provider "
+                    "%s, error %s", dpif_offload_name(offload),
+                    ovs_strerror(err));
+            }
+        }
+    }
+}
+
+
+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,
-- 
2.50.1

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

Reply via email to