diff mbox series

[ovs-dev,v2,2/6] netdev-offload: Add DPDK meter offload API

Message ID 20230309130252.356289-3-simon.horman@corigine.com
State Changes Requested
Headers show
Series Add support for DPDK meter HW offload | expand

Checks

Context Check Description
ovsrobot/apply-robot warning apply and check: warning
ovsrobot/github-robot-_Build_and_Test success github build: passed
ovsrobot/intel-ovs-compilation success test: success

Commit Message

Simon Horman March 9, 2023, 1:02 p.m. UTC
From: Peng Zhang <peng.zhang@corigine.com>

Add API to offload DPDK meter to HW, and the corresponding functions to call
the DPDK meter callbacks from all the registered flow API providers.
The interfaces are like those related to DPDK meter in dpif_class, in order
to pass necessary info to HW.

Signed-off-by: Peng Zhang <peng.zhang@corigine.com>
Signed-off-by: Jin Liu <jin.liu@corigine.com>
Signed-off-by: Simon Horman <simon.horman@corigine.com>
---
 Documentation/howto/dpdk.rst  |  5 +-
 lib/netdev-offload-provider.h | 30 +++++++++++
 lib/netdev-offload.c          | 99 +++++++++++++++++++++++++++++++++++
 lib/netdev-offload.h          |  9 ++++
 4 files changed, 141 insertions(+), 2 deletions(-)

Comments

0-day Robot March 9, 2023, 2:21 p.m. UTC | #1
References:  <20230309130252.356289-3-simon.horman@corigine.com>
 

Bleep bloop.  Greetings Simon Horman, I am a robot and I have tried out your patch.
Thanks for your contribution.

I encountered some error that I wasn't expecting.  See the details below.


checkpatch:
WARNING: Unexpected sign-offs from developers who are not authors or co-authors or committers: Jin Liu <jin.liu@corigine.com>, Simon Horman <simon.horman@corigine.com>
Lines checked: 224, Warnings: 1, Errors: 0


Please check this out.  If you feel there has been an error, please email aconole@redhat.com

Thanks,
0-day Robot
Ilya Maximets March 22, 2023, 8:35 p.m. UTC | #2
On 3/9/23 14:02, Simon Horman wrote:
> From: Peng Zhang <peng.zhang@corigine.com>
> 
> Add API to offload DPDK meter to HW, and the corresponding functions to call
> the DPDK meter callbacks from all the registered flow API providers.
> The interfaces are like those related to DPDK meter in dpif_class, in order
> to pass necessary info to HW.
> 
> Signed-off-by: Peng Zhang <peng.zhang@corigine.com>
> Signed-off-by: Jin Liu <jin.liu@corigine.com>
> Signed-off-by: Simon Horman <simon.horman@corigine.com>
> ---
>  Documentation/howto/dpdk.rst  |  5 +-
>  lib/netdev-offload-provider.h | 30 +++++++++++
>  lib/netdev-offload.c          | 99 +++++++++++++++++++++++++++++++++++
>  lib/netdev-offload.h          |  9 ++++
>  4 files changed, 141 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/howto/dpdk.rst b/Documentation/howto/dpdk.rst
> index 04609b20bd21..02fc568770ee 100644
> --- a/Documentation/howto/dpdk.rst
> +++ b/Documentation/howto/dpdk.rst
> @@ -401,10 +401,11 @@ Supported actions for hardware offload are:
>  - Modification of IPv6 (set_field:<ADDR>->ipv6_src/ipv6_dst/mod_nw_ttl).
>  - Clone/output (tnl_push and output) for encapsulating over a tunnel.
>  - Tunnel pop, for packets received on physical ports.
> +- Meter.
>  
>  .. note::
> -  Tunnel offloads are experimental APIs in DPDK. In order to enable it,
> -  compile with -DALLOW_EXPERIMENTAL_API.
> +  Tunnel offloads and Meter offloads are experimental APIs in DPDK. To enable
> +  these features, compile with -DALLOW_EXPERIMENTAL_API.
>  
>  Multiprocess
>  ------------
> diff --git a/lib/netdev-offload-provider.h b/lib/netdev-offload-provider.h
> index 9108856d18d1..7ecbb8d026f1 100644
> --- a/lib/netdev-offload-provider.h
> +++ b/lib/netdev-offload-provider.h
> @@ -102,6 +102,16 @@ struct netdev_flow_api {
>      int (*meter_set)(ofproto_meter_id meter_id,
>                       struct ofputil_meter_config *config);
>  
> +    /* Offloads or modifies the offloaded meter on the netdev with the given
> +     * 'meter_id' and the configuration in 'config'. On failure, a non-zero
> +     * error code is returned.
> +     *
> +     * The meter id specified through 'config->meter_id' is converted as an
> +     * internal meter id. */
> +    int (*dpdk_meter_set)(struct netdev *,
> +                          ofproto_meter_id meter_id,
> +                          struct ofputil_meter_config *);

Hi.

This looks strange.  We do already have the meter API here.
There is no need to create a separate set of APIs for each
offload provider.  This breaks the abstraction.

If there is something missing in existing meter_* callbacks,
modify them, so they can be suitable for both implementations.
If you need to iterate over all the ports, we have a special
netdev_ports_traverse() function that can be used from the
netdev-offload-dpdk.

Also, In my reply for v1 I mentioned that this patch set
should be sent for dpdk-latest branch, not master.  i.e.,
it should have 'dpdk-latest' in the subject prefix.

CC: Ian.

dpdk-latest branch may need a rebase though.  Ian, may I ask
you to rebase it on the latest master?  Or I can do that
myself, if necessary.

Best regards, Ilya Maximets.
Simon Horman March 30, 2023, 8:53 a.m. UTC | #3
On Wed, Mar 22, 2023 at 09:35:29PM +0100, Ilya Maximets wrote:
> On 3/9/23 14:02, Simon Horman wrote:
> > From: Peng Zhang <peng.zhang@corigine.com>

...

> > diff --git a/lib/netdev-offload-provider.h b/lib/netdev-offload-provider.h
> > index 9108856d18d1..7ecbb8d026f1 100644
> > --- a/lib/netdev-offload-provider.h
> > +++ b/lib/netdev-offload-provider.h
> > @@ -102,6 +102,16 @@ struct netdev_flow_api {
> >      int (*meter_set)(ofproto_meter_id meter_id,
> >                       struct ofputil_meter_config *config);
> >  
> > +    /* Offloads or modifies the offloaded meter on the netdev with the given
> > +     * 'meter_id' and the configuration in 'config'. On failure, a non-zero
> > +     * error code is returned.
> > +     *
> > +     * The meter id specified through 'config->meter_id' is converted as an
> > +     * internal meter id. */
> > +    int (*dpdk_meter_set)(struct netdev *,
> > +                          ofproto_meter_id meter_id,
> > +                          struct ofputil_meter_config *);
> 
> Hi.
> 
> This looks strange.  We do already have the meter API here.
> There is no need to create a separate set of APIs for each
> offload provider.  This breaks the abstraction.
> 
> If there is something missing in existing meter_* callbacks,
> modify them, so they can be suitable for both implementations.
> If you need to iterate over all the ports, we have a special
> netdev_ports_traverse() function that can be used from the
> netdev-offload-dpdk.

Thanks, we are working on revising this accordingly.

> Also, In my reply for v1 I mentioned that this patch set
> should be sent for dpdk-latest branch, not master.  i.e.,
> it should have 'dpdk-latest' in the subject prefix.

Sorry about that. This series is based on dpdk-latest.
But I omitted dpdk-latest from the subject prefix.

> CC: Ian.
> 
> dpdk-latest branch may need a rebase though.  Ian, may I ask
> you to rebase it on the latest master?  Or I can do that
> myself, if necessary.
> 
> Best regards, Ilya Maximets.
diff mbox series

Patch

diff --git a/Documentation/howto/dpdk.rst b/Documentation/howto/dpdk.rst
index 04609b20bd21..02fc568770ee 100644
--- a/Documentation/howto/dpdk.rst
+++ b/Documentation/howto/dpdk.rst
@@ -401,10 +401,11 @@  Supported actions for hardware offload are:
 - Modification of IPv6 (set_field:<ADDR>->ipv6_src/ipv6_dst/mod_nw_ttl).
 - Clone/output (tnl_push and output) for encapsulating over a tunnel.
 - Tunnel pop, for packets received on physical ports.
+- Meter.
 
 .. note::
-  Tunnel offloads are experimental APIs in DPDK. In order to enable it,
-  compile with -DALLOW_EXPERIMENTAL_API.
+  Tunnel offloads and Meter offloads are experimental APIs in DPDK. To enable
+  these features, compile with -DALLOW_EXPERIMENTAL_API.
 
 Multiprocess
 ------------
diff --git a/lib/netdev-offload-provider.h b/lib/netdev-offload-provider.h
index 9108856d18d1..7ecbb8d026f1 100644
--- a/lib/netdev-offload-provider.h
+++ b/lib/netdev-offload-provider.h
@@ -102,6 +102,16 @@  struct netdev_flow_api {
     int (*meter_set)(ofproto_meter_id meter_id,
                      struct ofputil_meter_config *config);
 
+    /* Offloads or modifies the offloaded meter on the netdev with the given
+     * 'meter_id' and the configuration in 'config'. On failure, a non-zero
+     * error code is returned.
+     *
+     * The meter id specified through 'config->meter_id' is converted as an
+     * internal meter id. */
+    int (*dpdk_meter_set)(struct netdev *,
+                          ofproto_meter_id meter_id,
+                          struct ofputil_meter_config *);
+
     /* Queries HW for meter stats with the given 'meter_id'. Store the stats
      * of dropped packets to band 0. On failure, a non-zero error code is
      * returned.
@@ -113,6 +123,18 @@  struct netdev_flow_api {
     int (*meter_get)(ofproto_meter_id meter_id,
                      struct ofputil_meter_stats *stats);
 
+    /* Queries netdev for meter stats with the given 'meter_id'. Store the
+     * stats of dropped packets to band 0. On failure, a non-zero error code
+     * is returned.
+     *
+     * Note that the 'stats' structure is already initialized, and only the
+     * available statistics should be incremented, not replaced. Those fields
+     * are packet_in_count, byte_in_count and band[]->byte_count and
+     * band[]->packet_count. */
+    int (*dpdk_meter_get)(struct netdev *,
+                          ofproto_meter_id meter_id,
+                          struct ofputil_meter_stats *);
+
     /* Removes meter 'meter_id' from HW. Store the stats of dropped packets to
      * band 0. On failure, a non-zero error code is returned.
      *
@@ -121,6 +143,14 @@  struct netdev_flow_api {
     int (*meter_del)(ofproto_meter_id meter_id,
                      struct ofputil_meter_stats *stats);
 
+    /* Removes meter 'meter_id' from netdev. Store the stats of dropped packets
+     * to band 0. On failure, a non-zero error code is returned.
+     *
+     * If del success, 'stats' will be set zero. */
+    int (*dpdk_meter_del)(struct netdev *,
+                          ofproto_meter_id meter_id,
+                          struct ofputil_meter_stats *stats);
+
     /* 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 4592262bd34e..44cab0c4ee79 100644
--- a/lib/netdev-offload.c
+++ b/lib/netdev-offload.c
@@ -895,3 +895,102 @@  netdev_set_flow_api_enabled(const struct smap *ovs_other_config)
         }
     }
 }
+
+void
+dpdk_meter_offload_set(const char *dpif_type,
+                       ofproto_meter_id meter_id,
+                       struct ofputil_meter_config *config)
+{
+    struct netdev_registered_flow_api *rfa;
+    struct port_to_netdev_data *data;
+    struct netdev *dev;
+    int ret;
+
+    ovs_rwlock_rdlock(&netdev_hmap_rwlock);
+    HMAP_FOR_EACH (data, portno_node, &port_to_netdev) {
+        dev = data->netdev;
+        if (netdev_get_dpif_type(dev) == dpif_type) {
+            /* Offload APIs could fail, for example, because the offload is not
+             * supported. This is fine, as the offload API should take care of
+             * this. */
+            CMAP_FOR_EACH (rfa, cmap_node, &netdev_flow_apis) {
+                if (rfa->flow_api->dpdk_meter_set) {
+                    ret = rfa->flow_api->dpdk_meter_set(dev, meter_id, config);
+                    if (ret) {
+                        VLOG_DBG_RL(&rl, "Failed setting meter %u for flow api"
+                                    " %s, error %d", meter_id.uint32,
+                                    rfa->flow_api->type, ret);
+                    }
+                }
+            }
+        }
+    }
+    ovs_rwlock_unlock(&netdev_hmap_rwlock);
+}
+
+void
+dpdk_meter_offload_get(const char *dpif_type,
+                       ofproto_meter_id meter_id,
+                       struct ofputil_meter_stats *stats)
+{
+    struct netdev_registered_flow_api *rfa;
+    struct ofputil_meter_stats offload_stats;
+    struct port_to_netdev_data *data;
+    struct netdev *dev;
+    int ret;
+
+    ovs_rwlock_rdlock(&netdev_hmap_rwlock);
+    HMAP_FOR_EACH (data, portno_node, &port_to_netdev) {
+        memset(&offload_stats, 0, sizeof(struct ofputil_meter_stats));
+        dev = data->netdev;
+        if (netdev_get_dpif_type(dev) == dpif_type) {
+            CMAP_FOR_EACH (rfa, cmap_node, &netdev_flow_apis) {
+                if (rfa->flow_api->dpdk_meter_get) {
+                    ret = rfa->flow_api->dpdk_meter_get(dev, meter_id, stats);
+                    if (ret) {
+                        VLOG_DBG_RL(&rl, "Failed getting meter %u for flow "
+                                    "api %s, error %d", meter_id.uint32,
+                                    rfa->flow_api->type, ret);
+                    }
+                }
+            }
+
+            if (!offload_stats.byte_in_count &&
+                       !offload_stats.packet_in_count) {
+                continue;
+            }
+            stats->byte_in_count += offload_stats.byte_in_count;
+            stats->packet_in_count += offload_stats.packet_in_count;
+        }
+    }
+    ovs_rwlock_unlock(&netdev_hmap_rwlock);
+}
+
+void
+dpdk_meter_offload_del(const char *dpif_type,
+                       ofproto_meter_id meter_id,
+                       struct ofputil_meter_stats *stats)
+{
+    struct netdev_registered_flow_api *rfa;
+    struct port_to_netdev_data *data;
+    struct netdev *dev;
+    int ret;
+
+    ovs_rwlock_rdlock(&netdev_hmap_rwlock);
+    HMAP_FOR_EACH (data, portno_node, &port_to_netdev) {
+        dev = data->netdev;
+        if (netdev_get_dpif_type(dev) == dpif_type) {
+            CMAP_FOR_EACH (rfa, cmap_node, &netdev_flow_apis) {
+                if (rfa->flow_api->dpdk_meter_del) {
+                    ret = rfa->flow_api->dpdk_meter_del(dev, meter_id, stats);
+                    if (ret) {
+                        VLOG_DBG_RL(&rl, "Failed deleting meter %u for flow "
+                                    "api %s, error %d", meter_id.uint32,
+                                    rfa->flow_api->type, ret);
+                    }
+                }
+            }
+        }
+    }
+    ovs_rwlock_unlock(&netdev_hmap_rwlock);
+}
diff --git a/lib/netdev-offload.h b/lib/netdev-offload.h
index edc843cd99a3..e53f70a277b3 100644
--- a/lib/netdev-offload.h
+++ b/lib/netdev-offload.h
@@ -161,6 +161,15 @@  int netdev_ports_get_n_flows(const char *dpif_type,
 void meter_offload_set(ofproto_meter_id, struct ofputil_meter_config *);
 int meter_offload_get(ofproto_meter_id, struct ofputil_meter_stats *);
 int meter_offload_del(ofproto_meter_id, struct ofputil_meter_stats *);
+void dpdk_meter_offload_set(const char *dpif_type,
+                            ofproto_meter_id meter_id,
+                            struct ofputil_meter_config *config);
+void dpdk_meter_offload_del(const char *dpif_type,
+                            ofproto_meter_id meter_id_,
+                            struct ofputil_meter_stats *stats);
+void dpdk_meter_offload_get(const char *dpif_type,
+                            ofproto_meter_id meter_id_,
+                            struct ofputil_meter_stats *stats);
 
 #ifdef  __cplusplus
 }