@@ -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
@@ -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);
@@ -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);
}
@@ -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
@@ -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 *);
};
@@ -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,
};
@@ -702,6 +702,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)
@@ -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 */
@@ -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;
}
@@ -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,
};
new file mode 100644
@@ -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 */
@@ -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.
*
@@ -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,
new file mode 100644
@@ -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 */
\ No newline at end of file
@@ -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 *),
@@ -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,
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 <echaudro@redhat.com> --- 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