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
