On 1/12/26 12:20 PM, Eelco Chaudron wrote:
> This patch adds an API to retrieve the netdev by port_id from either
> the dpif or a specific offload provider.
> 
> Acked-by: Eli Britstein <elibr.nvidia.com>
> Signed-off-by: Eelco Chaudron <[email protected]>
> ---
> 
> v2 changes:
>   - netdev reference issue in upcall handling.
> ---
>  lib/dpif-offload-dpdk.c       | 15 +++++++++++++
>  lib/dpif-offload-dummy.c      | 19 ++++++++++++++++
>  lib/dpif-offload-provider.h   |  8 +++++++
>  lib/dpif-offload-tc.c         | 17 +++++++++++++++
>  lib/dpif-offload.c            | 41 ++++++++++++++++++++++++++++++++++-
>  lib/dpif-offload.h            |  5 +++++
>  ofproto/ofproto-dpif-upcall.c |  5 ++---
>  7 files changed, 106 insertions(+), 4 deletions(-)
> 
> diff --git a/lib/dpif-offload-dpdk.c b/lib/dpif-offload-dpdk.c
> index 9763e19c6..b361da81a 100644
> --- a/lib/dpif-offload-dpdk.c
> +++ b/lib/dpif-offload-dpdk.c
> @@ -109,6 +109,20 @@ dpif_offload_dpdk_port_del(struct dpif_offload 
> *offload_, odp_port_t port_no)
>      return ret;
>  }
>  
> +static struct netdev *
> +dpif_offload_dpdk_get_netdev(struct dpif_offload *offload_, odp_port_t 
> port_no)
> +{
> +    struct dpif_offload_dpdk *offload = dpif_offload_dpdk_cast(offload_);
> +    struct dpif_offload_port_mgr_port *port;
> +
> +    port = dpif_offload_port_mgr_find_by_odp_port(offload->port_mgr, 
> port_no);
> +    if (!port) {
> +        return NULL;
> +    }
> +
> +    return port->netdev;
> +}
> +
>  static int
>  dpif_offload_dpdk_open(const struct dpif_offload_class *offload_class,
>                         struct dpif *dpif, struct dpif_offload **offload_)
> @@ -309,6 +323,7 @@ struct dpif_offload_class dpif_offload_dpdk_class = {
>      .port_add = dpif_offload_dpdk_port_add,
>      .port_del = dpif_offload_dpdk_port_del,
>      .flow_get_n_offloaded = dpif_offload_dpdk_get_n_offloaded,
> +    .get_netdev = dpif_offload_dpdk_get_netdev,
>      .netdev_flow_flush = dpif_offload_dpdk_netdev_flow_flush,
>      .netdev_hw_post_process = dpif_offload_dpdk_netdev_hw_post_process,
>  };
> diff --git a/lib/dpif-offload-dummy.c b/lib/dpif-offload-dummy.c
> index 33f89599a..ac1a69b7f 100644
> --- a/lib/dpif-offload-dummy.c
> +++ b/lib/dpif-offload-dummy.c
> @@ -101,6 +101,24 @@ dpif_offload_dummy_port_del(struct dpif_offload 
> *dpif_offload,
>      return 0;
>  }
>  
> +static struct netdev *
> +dpif_offload_dummy_get_netdev(struct dpif_offload *dpif_offload,
> +                              odp_port_t port_no)
> +{
> +    struct dpif_offload_dummy *offload_dummy;
> +    struct dpif_offload_port_mgr_port *port;
> +
> +    offload_dummy = dpif_offload_dummy_cast(dpif_offload);
> +
> +    port = dpif_offload_port_mgr_find_by_odp_port(offload_dummy->port_mgr,
> +                                                  port_no);
> +    if (!port) {
> +        return NULL;
> +    }
> +
> +    return port->netdev;
> +}
> +
>  static int
>  dpif_offload_dummy_open(const struct dpif_offload_class *offload_class,
>                          struct dpif *dpif, struct dpif_offload 
> **dpif_offload)
> @@ -248,6 +266,7 @@ dpif_offload_dummy_can_offload(struct dpif_offload 
> *dpif_offload OVS_UNUSED,
>          .can_offload = dpif_offload_dummy_can_offload,          \
>          .port_add = dpif_offload_dummy_port_add,                \
>          .port_del = dpif_offload_dummy_port_del,                \
> +        .get_netdev = dpif_offload_dummy_get_netdev,            \
>      }
>  
>  DEFINE_DPIF_DUMMY_CLASS(dpif_offload_dummy_class, "dummy");
> diff --git a/lib/dpif-offload-provider.h b/lib/dpif-offload-provider.h
> index 8840441c0..3235ed79c 100644
> --- a/lib/dpif-offload-provider.h
> +++ b/lib/dpif-offload-provider.h
> @@ -225,6 +225,14 @@ struct dpif_offload_class {
>      int (*meter_del)(const struct dpif_offload *, ofproto_meter_id meter_id,
>                       struct ofputil_meter_stats *);
>  
> +    /* Return the 'netdev' associated with the port_no if this offload
> +     * provider is handling offload for this port/netdev.  The returned
> +     * netdev is owned by the port manager and its reference count is
> +     * NOT incremented.  Callers needing to hold a reference must call
> +     * netdev_ref() on the returned netdev.  Returns NULL if port_no is
> +     * not found. */
> +    struct netdev *(*get_netdev)(struct dpif_offload *, odp_port_t port_no);
> +
>  
>      /* These APIs operate directly on the provided netdev for performance
>       * reasons.  They are intended for use in fast path processing and should
> diff --git a/lib/dpif-offload-tc.c b/lib/dpif-offload-tc.c
> index 0e7e7ae42..d09571583 100644
> --- a/lib/dpif-offload-tc.c
> +++ b/lib/dpif-offload-tc.c
> @@ -133,6 +133,22 @@ dpif_offload_tc_port_del(struct dpif_offload 
> *dpif_offload,
>      return ret;
>  }
>  
> +static struct netdev *
> +dpif_offload_tc_get_netdev(struct dpif_offload *dpif_offload,
> +                           odp_port_t port_no)
> +{
> +    struct dpif_offload_tc *offload_tc = dpif_offload_tc_cast(dpif_offload);
> +    struct dpif_offload_port_mgr_port *port;
> +
> +    port = dpif_offload_port_mgr_find_by_odp_port(offload_tc->port_mgr,
> +                                                  port_no);
> +    if (!port) {
> +        return NULL;
> +    }
> +
> +    return port->netdev;
> +}
> +
>  static int
>  dpif_offload_tc_open(const struct dpif_offload_class *offload_class,
>                       struct dpif *dpif, struct dpif_offload **dpif_offload)
> @@ -566,5 +582,6 @@ struct dpif_offload_class dpif_offload_tc_class = {
>      .meter_set = dpif_offload_tc_meter_set,
>      .meter_get = dpif_offload_tc_meter_get,
>      .meter_del = dpif_offload_tc_meter_del,
> +    .get_netdev = dpif_offload_tc_get_netdev,
>      .netdev_flow_flush = dpif_offload_tc_netdev_flow_flush,
>  };
> diff --git a/lib/dpif-offload.c b/lib/dpif-offload.c
> index 9fb684390..88aefd868 100644
> --- a/lib/dpif-offload.c
> +++ b/lib/dpif-offload.c
> @@ -158,7 +158,8 @@ dp_offload_initialize(void)
>                     && base_dpif_offload_classes[i]->close
>                     && base_dpif_offload_classes[i]->can_offload
>                     && base_dpif_offload_classes[i]->port_add
> -                   && base_dpif_offload_classes[i]->port_del);
> +                   && base_dpif_offload_classes[i]->port_del
> +                   && base_dpif_offload_classes[i]->get_netdev);
>  
>          ovs_assert((base_dpif_offload_classes[i]->flow_dump_create &&
>                      base_dpif_offload_classes[i]->flow_dump_next &&
> @@ -1026,6 +1027,44 @@ dpif_offload_flow_dump_thread_destroy(struct 
> dpif_flow_dump_thread *thread)
>      free(thread->offload_threads);
>  }
>  
> +struct netdev *
> +dpif_offload_offload_get_netdev_by_port_id(struct dpif_offload *offload,

offload_offload

> +                                           odp_port_t port_no)
> +{
> +    if (!dpif_offload_is_offload_enabled() || !offload) {
> +        return NULL;
> +    }
> +
> +    return offload->class->get_netdev(offload, port_no);
> +}
> +
> +struct netdev *
> +dpif_offload_get_netdev_by_port_id(struct dpif *dpif,
> +                                   struct dpif_offload **offload,
> +                                   odp_port_t port_no)
> +{
> +    struct dp_offload *dp_offload = dpif_offload_get_dp_offload(dpif);
> +    struct dpif_offload *tmp_offload;
> +    struct netdev *netdev = NULL;
> +
> +    if (!dp_offload || !dpif_offload_is_offload_enabled()) {
> +        return NULL;
> +    }
> +
> +    LIST_FOR_EACH (tmp_offload, dpif_list_node,
> +                   &dp_offload->offload_providers) {
> +        netdev = tmp_offload->class->get_netdev(tmp_offload, port_no);
> +        if (netdev) {
> +            if (offload) {
> +                *offload = tmp_offload;
> +            }
> +            break;
> +        }
> +    }
> +
> +    return netdev;
> +}
> +
>  
>  int
>  dpif_offload_netdev_flush_flows(struct netdev *netdev)
> diff --git a/lib/dpif-offload.h b/lib/dpif-offload.h
> index acef15832..5f6942fbd 100644
> --- a/lib/dpif-offload.h
> +++ b/lib/dpif-offload.h
> @@ -58,6 +58,11 @@ void dpif_offload_meter_get(const struct dpif *dpif, 
> ofproto_meter_id meter_id,
>                              struct ofputil_meter_stats *);
>  void dpif_offload_meter_del(const struct dpif *dpif, ofproto_meter_id 
> meter_id,
>                              struct ofputil_meter_stats *);
> +struct netdev *dpif_offload_get_netdev_by_port_id(struct dpif *,
> +                                                  struct dpif_offload **,
> +                                                  odp_port_t);
> +struct netdev *dpif_offload_offload_get_netdev_by_port_id(
> +    struct dpif_offload *, odp_port_t);
>  
>  /* Iterates through each DPIF_OFFLOAD in DPIF, using DUMP as state.
>   *
> diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
> index 3fa96b673..363314ad9 100644
> --- a/ofproto/ofproto-dpif-upcall.c
> +++ b/ofproto/ofproto-dpif-upcall.c
> @@ -2710,7 +2710,6 @@ ukey_netdev_unref(struct udpif_key *ukey)
>  static void
>  ukey_to_flow_netdev(struct udpif *udpif, struct udpif_key *ukey)
>  {
> -    const char *dpif_type_str = dpif_normalize_type(dpif_type(udpif->dpif));
>      const struct nlattr *k;
>      unsigned int left;
>  
> @@ -2722,8 +2721,8 @@ ukey_to_flow_netdev(struct udpif *udpif, struct 
> udpif_key *ukey)
>          enum ovs_key_attr type = nl_attr_type(k);
>  
>          if (type == OVS_KEY_ATTR_IN_PORT) {
> -            ukey->in_netdev = netdev_ports_get(nl_attr_get_odp_port(k),
> -                                               dpif_type_str);
> +            ukey->in_netdev = netdev_ref(dpif_offload_get_netdev_by_port_id(
> +                udpif->dpif, NULL, nl_attr_get_odp_port(k)));
>          } else if (type == OVS_KEY_ATTR_TUNNEL) {
>              struct flow_tnl tnl;
>              enum odp_key_fitness res;

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

Reply via email to