On 1/12/26 12:20 PM, Eelco Chaudron wrote:
> 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.
> 
> Acked-by: Eli Britstein <elibr.nvidia.com>
> Signed-off-by: Eelco Chaudron <[email protected]>
> ---
> 
> v2 changes:
>   - Added missing newline at end of netdev-offload-tc.h.
>   - Fixed some indentation issues.
> 
> v3 changes:
>   - Fixed some newline issues.
>   - 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            | 37 ++++++++++++++++++++++++++++++
>  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, 171 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 e54b41f25..ed0b5bec9 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"
> @@ -254,6 +255,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[]) {
> @@ -266,6 +274,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 50d2da19e..3855add8f 100644
> --- a/lib/dpif-offload-provider.h
> +++ b/lib/dpif-offload-provider.h
> @@ -127,6 +127,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 fb9db9433..200685fa8 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 "tc.h"
> @@ -238,6 +239,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);
> +}

This is only used in two functions below.  Can we instead call
the netdev_offload_tc_flow_flush() inside them directly?

> +
> +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[]) {
> @@ -250,4 +291,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 b6d057ec1..bab811554 100644
> --- a/lib/dpif-offload.c
> +++ b/lib/dpif-offload.c
> @@ -717,6 +717,43 @@ 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 20bf578d6..bac2faa64 100644
> --- a/lib/dpif.c
> +++ b/lib/dpif.c
> @@ -957,6 +957,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

Reply via email to