On 1/12/26 12:20 PM, Eelco Chaudron wrote:
> This patch moves the hardware packet miss recovery API from the
> netdev-offload to the dpif-offload provider. The API name has been
> changed from hw_miss_packet_recover() to hw_post_process()
> to reflect that it may also be used for other tasks in the future,
> such as conntrack post-processing.
> 
> Acked-by: Eli Britstein <elibr.nvidia.com>
> Signed-off-by: Eelco Chaudron <[email protected]>
> ---
> 
> v3 changes:
>   - Changed API name from hw_miss_packet_postprocess()
>     to hw_post_process()
> ---
>  lib/dpif-netdev.c             | 18 +++++++++++-------
>  lib/dpif-offload-dpdk.c       |  9 +++++++++
>  lib/dpif-offload-provider.h   | 11 +++++++++++
>  lib/dpif-offload.c            | 35 +++++++++++++++++++++++++++++++++++
>  lib/dpif-offload.h            |  1 +
>  lib/netdev-offload-dpdk.c     |  3 +--
>  lib/netdev-offload-dpdk.h     |  2 ++
>  lib/netdev-offload-provider.h |  6 ------
>  lib/netdev-offload.c          | 33 +++------------------------------
>  lib/netdev-offload.h          |  4 ++--
>  lib/netdev.c                  |  3 ++-
>  11 files changed, 77 insertions(+), 48 deletions(-)
> 
> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
> index 82df85823..07e94f5cb 100644
> --- a/lib/dpif-netdev.c
> +++ b/lib/dpif-netdev.c
> @@ -122,7 +122,7 @@ COVERAGE_DEFINE(datapath_drop_invalid_bond);
>  COVERAGE_DEFINE(datapath_drop_invalid_tnl_port);
>  COVERAGE_DEFINE(datapath_drop_rx_invalid_packet);
>  #ifdef ALLOW_EXPERIMENTAL_API /* Packet restoration API required. */
> -COVERAGE_DEFINE(datapath_drop_hw_miss_recover);
> +COVERAGE_DEFINE(datapath_drop_hw_post_process);
>  #endif
>  
>  /* Protects against changes to 'dp_netdevs'. */
> @@ -8423,14 +8423,18 @@ dp_netdev_hw_flow(const struct dp_netdev_pmd_thread 
> *pmd,
>  #ifdef ALLOW_EXPERIMENTAL_API /* Packet restoration API required. */
>      /* Restore the packet if HW processing was terminated before completion. 
> */
>      struct dp_netdev_rxq *rxq = pmd->ctx.last_rxq;
> -    bool miss_api_supported;
> +    bool post_process_api_supported;
> +
> +    
> atomic_read_relaxed(&rxq->port->netdev->hw_info.post_process_api_supported,
> +                        &post_process_api_supported);
> +    if (post_process_api_supported) {
> +        int err = dpif_offload_netdev_hw_post_process(rxq->port->netdev,
> +                                                      packet);
>  
> -    atomic_read_relaxed(&rxq->port->netdev->hw_info.miss_api_supported,
> -                        &miss_api_supported);
> -    if (miss_api_supported) {
> -        int err = netdev_hw_miss_packet_recover(rxq->port->netdev, packet);
>          if (err && err != EOPNOTSUPP) {
> -            COVERAGE_INC(datapath_drop_hw_miss_recover);
> +            if (err != ECANCELED) {
> +                COVERAGE_INC(datapath_drop_hw_post_process);

Should we have a separate counter for the ECANCELED case?

> +            }
>              return -1;
>          }
>      }
> diff --git a/lib/dpif-offload-dpdk.c b/lib/dpif-offload-dpdk.c
> index 2ded4111d..9763e19c6 100644
> --- a/lib/dpif-offload-dpdk.c
> +++ b/lib/dpif-offload-dpdk.c
> @@ -288,6 +288,14 @@ dpif_offload_dpdk_netdev_flow_flush(const struct 
> dpif_offload *offload
>      return netdev_offload_dpdk_flow_flush(netdev);
>  }
>  
> +static int
> +dpif_offload_dpdk_netdev_hw_post_process(
> +    const struct dpif_offload *offload_ OVS_UNUSED, struct netdev *netdev,
> +    struct dp_packet *packet)
> +{
> +    return netdev_offload_dpdk_hw_miss_packet_recover(netdev, packet);
> +}
> +
>  struct dpif_offload_class dpif_offload_dpdk_class = {
>      .type = "dpdk",
>      .supported_dpif_types = (const char *const[]) {
> @@ -302,6 +310,7 @@ struct dpif_offload_class dpif_offload_dpdk_class = {
>      .port_del = dpif_offload_dpdk_port_del,
>      .flow_get_n_offloaded = dpif_offload_dpdk_get_n_offloaded,
>      .netdev_flow_flush = dpif_offload_dpdk_netdev_flow_flush,
> +    .netdev_hw_post_process = dpif_offload_dpdk_netdev_hw_post_process,
>  };
>  
>  /* 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 5e403894e..8da7b12cd 100644
> --- a/lib/dpif-offload-provider.h
> +++ b/lib/dpif-offload-provider.h
> @@ -169,6 +169,17 @@ struct dpif_offload_class {
>      /* 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 *);
> +
> +    /* Recover and/or set the packet state (contents and metadata) for
> +     * continued processing in software, and/or perform any additional
> +     * post-processing required by the offload provider.
> +     *
> +     * Return 0 if successful and the packet requires further processing;
> +     * otherwise, return a positive errno value and take ownership of the
> +     * packet if errno != EOPNOTSUPP.  Return ECANCELED if the packet was
> +     * fully consumed by the provider for non-error conditions. */
> +    int (*netdev_hw_post_process)(const struct dpif_offload *, struct netdev 
> *,
> +                                  struct dp_packet *);
>  };
>  
>  
> diff --git a/lib/dpif-offload.c b/lib/dpif-offload.c
> index 1c5494d8e..544744c88 100644
> --- a/lib/dpif-offload.c
> +++ b/lib/dpif-offload.c
> @@ -852,6 +852,41 @@ dpif_offload_netdev_flush_flows(struct netdev *netdev)
>      return EOPNOTSUPP;
>  }
>  
> +int
> +dpif_offload_netdev_hw_post_process(struct netdev *netdev,
> +                                    struct dp_packet *packet)
> +{
> +    const struct dpif_offload *offload;
> +    bool post_process_api_supported;
> +    int rc;
> +
> +    atomic_read_relaxed(&netdev->hw_info.post_process_api_supported,
> +                        &post_process_api_supported);
> +    if (!post_process_api_supported) {
> +        return EOPNOTSUPP;
> +    }
> +
> +    offload = ovsrcu_get(const struct dpif_offload *, &netdev->dpif_offload);
> +
> +    if (!offload || !offload->class->netdev_hw_post_process) {
> +        if (offload) {
> +            /* Offload is configured and API unsupported by the port;
> +             * avoid subsequent calls. */
> +            atomic_store_relaxed(&netdev->hw_info.post_process_api_supported,
> +                                 false);
> +        }
> +        return EOPNOTSUPP;
> +    }
> +
> +    rc = offload->class->netdev_hw_post_process(offload, netdev, packet);
> +    if (rc == EOPNOTSUPP) {
> +        /* API unsupported by the port; avoid subsequent calls. */
> +        atomic_store_relaxed(&netdev->hw_info.post_process_api_supported,
> +                             false);
> +    }
> +    return rc;
> +}
> +
>  
>  struct dpif_offload_port_mgr *
>  dpif_offload_port_mgr_init(void)
> diff --git a/lib/dpif-offload.h b/lib/dpif-offload.h
> index fb7edf269..acef15832 100644
> --- a/lib/dpif-offload.h
> +++ b/lib/dpif-offload.h
> @@ -75,5 +75,6 @@ void dpif_offload_meter_del(const struct dpif *dpif, 
> ofproto_meter_id meter_id,
>  
>  /* Netdev specific function, which can be used in the fast path. */
>  int dpif_offload_netdev_flush_flows(struct netdev *);
> +int dpif_offload_netdev_hw_post_process(struct netdev *, struct dp_packet *);
>  
>  #endif /* DPIF_OFFLOAD_H */
> diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c
> index d1781d8e4..c3d5e83f5 100644
> --- a/lib/netdev-offload-dpdk.c
> +++ b/lib/netdev-offload-dpdk.c
> @@ -2685,7 +2685,7 @@ get_vport_netdev(const char *dpif_type,
>      return aux.vport;
>  }
>  
> -static int
> +int
>  netdev_offload_dpdk_hw_miss_packet_recover(struct netdev *netdev,
>                                             struct dp_packet *packet)
>  {
> @@ -2803,5 +2803,4 @@ 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,
> -    .hw_miss_packet_recover = netdev_offload_dpdk_hw_miss_packet_recover,
>  };
> diff --git a/lib/netdev-offload-dpdk.h b/lib/netdev-offload-dpdk.h
> index d5061b40c..475822e1b 100644
> --- a/lib/netdev-offload-dpdk.h
> +++ b/lib/netdev-offload-dpdk.h
> @@ -24,5 +24,7 @@ struct netdev;
>   * associated dpif offload provider. */
>  int netdev_offload_dpdk_flow_flush(struct netdev *);
>  uint64_t netdev_offload_dpdk_flow_get_n_offloaded(struct netdev *);
> +int netdev_offload_dpdk_hw_miss_packet_recover(struct netdev *,
> +                                               struct dp_packet *);
>  
>  #endif /* NETDEV_OFFLOAD_DPDK_H */
> diff --git a/lib/netdev-offload-provider.h b/lib/netdev-offload-provider.h
> index 898df8333..f762af19a 100644
> --- a/lib/netdev-offload-provider.h
> +++ b/lib/netdev-offload-provider.h
> @@ -80,12 +80,6 @@ struct netdev_flow_api {
>      int (*flow_del)(struct netdev *, const ovs_u128 *ufid,
>                      struct dpif_flow_stats *);
>  
> -    /* Recover the packet state (contents and data) for continued processing
> -     * in software.
> -     * Return 0 if successful, otherwise returns a positive errno value and
> -     * takes ownership of a packet if errno != EOPNOTSUPP. */
> -    int (*hw_miss_packet_recover)(struct netdev *, struct dp_packet *);
> -
>      /* Initializies the netdev flow api.
>       * Return 0 if successful, otherwise returns a positive errno value. */
>      int (*init_flow_api)(struct netdev *);
> diff --git a/lib/netdev-offload.c b/lib/netdev-offload.c
> index 0c4209290..453bb20a0 100644
> --- a/lib/netdev-offload.c
> +++ b/lib/netdev-offload.c
> @@ -186,7 +186,8 @@ netdev_assign_flow_api(struct netdev *netdev)
>      CMAP_FOR_EACH (rfa, cmap_node, &netdev_flow_apis) {
>          if (!rfa->flow_api->init_flow_api(netdev)) {
>              ovs_refcount_ref(&rfa->refcnt);
> -            atomic_store_relaxed(&netdev->hw_info.miss_api_supported, true);
> +            atomic_store_relaxed(&netdev->hw_info.post_process_api_supported,
> +                                 true);
>              ovsrcu_set(&netdev->flow_api, rfa->flow_api);
>              VLOG_INFO("%s: Assigned flow API '%s'.",
>                        netdev_get_name(netdev), rfa->flow_api->type);
> @@ -195,7 +196,7 @@ netdev_assign_flow_api(struct netdev *netdev)
>          VLOG_DBG("%s: flow API '%s' is not suitable.",
>                   netdev_get_name(netdev), rfa->flow_api->type);
>      }
> -    atomic_store_relaxed(&netdev->hw_info.miss_api_supported, false);
> +    atomic_store_relaxed(&netdev->hw_info.post_process_api_supported, false);
>      VLOG_INFO("%s: No suitable flow API found.", netdev_get_name(netdev));
>  
>      return -1;
> @@ -254,34 +255,6 @@ netdev_flow_put(struct netdev *netdev, struct match 
> *match,
>             : EOPNOTSUPP;
>  }
>  
> -int
> -netdev_hw_miss_packet_recover(struct netdev *netdev,
> -                              struct dp_packet *packet)
> -{
> -    const struct netdev_flow_api *flow_api;
> -    bool miss_api_supported;
> -    int rv;
> -
> -    atomic_read_relaxed(&netdev->hw_info.miss_api_supported,
> -                        &miss_api_supported);
> -    if (!miss_api_supported) {
> -        return EOPNOTSUPP;
> -    }
> -
> -    flow_api = ovsrcu_get(const struct netdev_flow_api *, &netdev->flow_api);
> -    if (!flow_api || !flow_api->hw_miss_packet_recover) {
> -        return EOPNOTSUPP;
> -    }
> -
> -    rv = flow_api->hw_miss_packet_recover(netdev, packet);
> -    if (rv == EOPNOTSUPP) {
> -        /* API unsupported by the port; avoid subsequent calls. */
> -        atomic_store_relaxed(&netdev->hw_info.miss_api_supported, false);
> -    }
> -
> -    return rv;
> -}
> -
>  int
>  netdev_flow_get(struct netdev *netdev, struct match *match,
>                  struct nlattr **actions, const ovs_u128 *ufid,
> diff --git a/lib/netdev-offload.h b/lib/netdev-offload.h
> index 2b32179ec..6939fcd35 100644
> --- a/lib/netdev-offload.h
> +++ b/lib/netdev-offload.h
> @@ -47,7 +47,8 @@ struct ovs_action_push_tnl;
>  /* Offload-capable (HW) netdev information */
>  struct netdev_hw_info {
>      bool oor;                         /* Out of Offload Resources ? */
> -    atomic_bool miss_api_supported;   /* hw_miss_packet_recover() 
> supported.*/
> +    /* Is hw_post_process() supported. */
> +    atomic_bool post_process_api_supported;
>      int offload_count;                /* Offloaded flow count */
>      int pending_count;                /* Pending (non-offloaded) flow count 
> */
>      OVSRCU_TYPE(void *) offload_data; /* Offload metadata. */
> @@ -110,7 +111,6 @@ bool netdev_flow_dump_next(struct netdev_flow_dump *, 
> struct match *,
>  int netdev_flow_put(struct netdev *, struct match *, struct nlattr *actions,
>                      size_t actions_len, const ovs_u128 *,
>                      struct offload_info *, struct dpif_flow_stats *);
> -int netdev_hw_miss_packet_recover(struct netdev *, struct dp_packet *);
>  int netdev_flow_get(struct netdev *, struct match *, struct nlattr **actions,
>                      const ovs_u128 *, struct dpif_flow_stats *,
>                      struct dpif_flow_attrs *, struct ofpbuf *wbuffer);
> diff --git a/lib/netdev.c b/lib/netdev.c
> index 5413ca61d..c5182fe8f 100644
> --- a/lib/netdev.c
> +++ b/lib/netdev.c
> @@ -435,7 +435,8 @@ netdev_open(const char *name, const char *type, struct 
> netdev **netdevp)
>                      seq_read(netdev->reconfigure_seq);
>                  ovsrcu_set(&netdev->flow_api, NULL);
>                  netdev->hw_info.oor = false;
> -                atomic_init(&netdev->hw_info.miss_api_supported, false);
> +                atomic_init(&netdev->hw_info.post_process_api_supported,
> +                            false);
>                  netdev->node = shash_add(&netdev_shash, name, netdev);
>  
>                  /* By default enable one tx and rx queue per netdev. */

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

Reply via email to