From: Peng Zhang <[email protected]>

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 <[email protected]>
Signed-off-by: Jin Liu <[email protected]>
---
 Documentation/howto/dpdk.rst  |  5 +--
 lib/netdev-offload-provider.h | 30 ++++++++++++++++++
 lib/netdev-offload.c          | 59 +++++++++++++++++++++++++++++++++++
 lib/netdev-offload.h          |  9 ++++++
 4 files changed, 101 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 *);
+
     /* 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..6aedf2e5c5e9 100644
--- a/lib/netdev-offload.c
+++ b/lib/netdev-offload.c
@@ -256,6 +256,65 @@ meter_offload_del(ofproto_meter_id meter_id, struct 
ofputil_meter_stats *stats)
     return 0;
 }
 
+void
+dpdk_meter_offload_set(struct netdev *dev,
+                       ofproto_meter_id meter_id,
+                       struct ofputil_meter_config *config)
+{
+    struct netdev_registered_flow_api *rfa;
+
+    /* 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) {
+            int 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);
+           }
+        }
+    }
+}
+
+void
+dpdk_meter_offload_get(struct netdev *dev,
+                       ofproto_meter_id meter_id,
+                       struct ofputil_meter_stats *stats)
+{
+    struct netdev_registered_flow_api *rfa;
+
+    CMAP_FOR_EACH (rfa, cmap_node, &netdev_flow_apis) {
+        if (rfa->flow_api->dpdk_meter_get) {
+            int 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);
+           }
+        }
+    }
+}
+
+void
+dpdk_meter_offload_del(struct netdev *dev,
+                       ofproto_meter_id meter_id,
+                       struct ofputil_meter_stats *stats)
+{
+    struct netdev_registered_flow_api *rfa;
+
+    CMAP_FOR_EACH (rfa, cmap_node, &netdev_flow_apis) {
+        if (rfa->flow_api->dpdk_meter_del) {
+            int 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);
+            }
+        }
+    }
+}
+
 int
 netdev_flow_flush(struct netdev *netdev)
 {
diff --git a/lib/netdev-offload.h b/lib/netdev-offload.h
index edc843cd99a3..f1907d2db0c0 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(struct netdev *,
+                            ofproto_meter_id,
+                            struct ofputil_meter_config *);
+void dpdk_meter_offload_get(struct netdev *,
+                            ofproto_meter_id,
+                            struct ofputil_meter_stats *);
+void dpdk_meter_offload_del(struct netdev *,
+                            ofproto_meter_id,
+                            struct ofputil_meter_stats *);
 
 #ifdef  __cplusplus
 }
-- 
2.30.2

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

Reply via email to