Add API to offload meter to HW, and the corresponding functions to be
called from dpif by the type.
The interfaces are like those related to meter in dpif_class, in order
to pass necessary info to HW.

Signed-off-by: Jianbo Liu <[email protected]>
---
 lib/netdev-offload-provider.h |  16 +++++
 lib/netdev-offload.c          | 119 ++++++++++++++++++++++++++++++++++
 lib/netdev-offload.h          |  10 +++
 3 files changed, 145 insertions(+)

diff --git a/lib/netdev-offload-provider.h b/lib/netdev-offload-provider.h
index 8ff2de983..4c34d3f7f 100644
--- a/lib/netdev-offload-provider.h
+++ b/lib/netdev-offload-provider.h
@@ -102,10 +102,26 @@ struct netdev_flow_api {
     void (*uninit_flow_api)(struct netdev *);
 };
 
+struct meter_offload_api {
+    char *type;
+    int (*meter_offload_init)(void);
+    int (*meter_offload_destroy)(void);
+    int (*meter_offload_set)(ofproto_meter_id meter_id,
+                             struct ofputil_meter_config *config);
+    int (*meter_offload_get)(ofproto_meter_id meter_id,
+                             struct ofputil_meter_stats *stats,
+                             uint16_t max_bands);
+    int (*meter_offload_del)(ofproto_meter_id meter_id,
+                             struct ofputil_meter_stats *stats,
+                             uint16_t max_bands);
+};
+
 int netdev_register_flow_api_provider(const struct netdev_flow_api *);
 int netdev_unregister_flow_api_provider(const char *type);
 bool netdev_flow_api_equals(const struct netdev *, const struct netdev *);
 
+int meter_register_offload_api_provider(const struct meter_offload_api *);
+
 #ifdef __linux__
 extern const struct netdev_flow_api netdev_offload_tc;
 #endif
diff --git a/lib/netdev-offload.c b/lib/netdev-offload.c
index fb108c0d5..9787c16c0 100644
--- a/lib/netdev-offload.c
+++ b/lib/netdev-offload.c
@@ -195,6 +195,125 @@ netdev_assign_flow_api(struct netdev *netdev)
     return -1;
 }
 
+/* Protects 'meter_offload_apis'.  */
+static struct ovs_mutex meter_offload_api_provider_mtx = OVS_MUTEX_INITIALIZER;
+
+/* Contains 'struct meter_registered_offload_api's. */
+static struct cmap meter_offload_apis = CMAP_INITIALIZER;
+
+struct meter_registered_offload_api {
+    /* In 'meter_offload_apis', by meter_offload_api->type. */
+    struct cmap_node cmap_node;
+    const struct meter_offload_api *meter_api;
+};
+
+static struct meter_registered_offload_api *
+meter_lookup_offload_api(const char *type)
+{
+    struct meter_registered_offload_api *r;
+    CMAP_FOR_EACH_WITH_HASH (r, cmap_node, hash_string(type, 0),
+                             &meter_offload_apis) {
+        if (!strcmp(type, r->meter_api->type)) {
+            return r;
+        }
+    }
+    return NULL;
+}
+
+int
+meter_register_offload_api_provider(const struct meter_offload_api *new_api)
+    OVS_EXCLUDED(meter_offload_api_provider_mtx)
+{
+    int error = 0;
+
+    ovs_mutex_lock(&meter_offload_api_provider_mtx);
+    if (meter_lookup_offload_api(new_api->type)) {
+        VLOG_WARN("fail to register duplicate meter offload api provider: %s",
+                   new_api->type);
+        error = EEXIST;
+    } else {
+        struct meter_registered_offload_api *r;
+
+        r = xmalloc(sizeof *r);
+        cmap_insert(&meter_offload_apis, &r->cmap_node,
+                    hash_string(new_api->type, 0));
+        r->meter_api = new_api;
+        VLOG_DBG("meter offload API '%s' registered.", new_api->type);
+    }
+    ovs_mutex_unlock(&meter_offload_api_provider_mtx);
+
+    return error;
+}
+
+static const struct meter_offload_api *
+meter_offload_get_api(const char *type)
+    OVS_EXCLUDED(meter_offload_api_provider_mtx)
+{
+    struct meter_registered_offload_api *r;
+
+    ovs_mutex_lock(&meter_offload_api_provider_mtx);
+    r = meter_lookup_offload_api(type);
+    ovs_mutex_unlock(&meter_offload_api_provider_mtx);
+
+    return r ? r->meter_api : NULL;
+}
+
+int
+meter_offload_set(const char *type, ofproto_meter_id meter_id,
+                  struct ofputil_meter_config *config)
+{
+    const struct meter_offload_api *meter_api;
+
+    meter_api = meter_offload_get_api(type);
+
+    return meter_api ? meter_api->meter_offload_set(meter_id, config)
+                     : EOPNOTSUPP;
+}
+
+int
+meter_offload_get(const char *type, ofproto_meter_id meter_id,
+                  struct ofputil_meter_stats *stats, uint16_t max_bands)
+{
+    const struct meter_offload_api *meter_api;
+
+    meter_api = meter_offload_get_api(type);
+
+    return meter_api ? meter_api->meter_offload_get(meter_id, stats, max_bands)
+                     : EOPNOTSUPP;
+}
+
+int
+meter_offload_del(const char *type, ofproto_meter_id meter_id,
+                  struct ofputil_meter_stats *stats, uint16_t max_bands)
+{
+    const struct meter_offload_api *meter_api;
+
+    meter_api = meter_offload_get_api(type);
+
+    return meter_api ? meter_api->meter_offload_del(meter_id, stats, max_bands)
+                     : EOPNOTSUPP;
+}
+
+int
+meter_offload_init(const char *type)
+{
+    const struct meter_offload_api *meter_api;
+
+    meter_api = meter_offload_get_api(type);
+
+    return meter_api ? meter_api->meter_offload_init() : EOPNOTSUPP;
+}
+
+int
+meter_offload_destroy(const char *type)
+{
+    const struct meter_offload_api *meter_api;
+
+    meter_api = meter_offload_get_api(type);
+
+    return meter_api ? meter_api->meter_offload_destroy() : EOPNOTSUPP;
+}
+
 int
 netdev_flow_flush(struct netdev *netdev)
 {
diff --git a/lib/netdev-offload.h b/lib/netdev-offload.h
index 8237a85dd..54100748b 100644
--- a/lib/netdev-offload.h
+++ b/lib/netdev-offload.h
@@ -22,6 +22,7 @@
 #include "openvswitch/types.h"
 #include "ovs-rcu.h"
 #include "ovs-thread.h"
+#include "openvswitch/ofp-meter.h"
 #include "packets.h"
 #include "flow.h"
 
@@ -158,6 +159,15 @@ int netdev_ports_flow_get(const char *dpif_type, struct 
match *match,
 int netdev_ports_get_n_flows(const char *dpif_type,
                              odp_port_t port_no, uint64_t *n_flows);
 
+int meter_offload_set(const char *, ofproto_meter_id,
+                      struct ofputil_meter_config *);
+int meter_offload_get(const char *, ofproto_meter_id,
+                      struct ofputil_meter_stats *, uint16_t);
+int meter_offload_del(const char *, ofproto_meter_id,
+                      struct ofputil_meter_stats *, uint16_t);
+int meter_offload_init(const char *);
+int meter_offload_destroy(const char *);
+
 #ifdef  __cplusplus
 }
 #endif
-- 
2.26.2

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

Reply via email to