@@ -260,7 +260,6 @@ struct dp_netdev {
/* Meters. */
struct ovs_mutex meter_locks[N_METER_LOCKS];
struct dp_meter *meters[MAX_METERS]; /* Meter bands. */
- uint32_t meter_free; /* Next free meter. */
/* Protects access to ofproto-dpif-upcall interface during revalidator
* thread synchronization. */
@@ -3896,9 +3895,6 @@ dpif_netdev_meter_set(struct dpif *dpif, ofproto_meter_id *meter_id,
struct dp_meter *meter;
int i;
- if (mid == UINT32_MAX) {
- mid = dp->meter_free;
- }
if (mid >= MAX_METERS) {
return EFBIG; /* Meter_id out of range. */
}
@@ -3958,21 +3954,6 @@ dpif_netdev_meter_set(struct dpif *dpif, ofproto_meter_id *meter_id,
dp->meters[mid] = meter;
meter_unlock(dp, mid);
- meter_id->uint32 = mid; /* Store on success. */
-
- /* Find next free meter */
- if (dp->meter_free == mid) { /* Now taken. */
- do {
- if (++mid >= MAX_METERS) { /* Wrap around */
- mid = 0;
- }
- if (mid == dp->meter_free) { /* Full circle */
- mid = MAX_METERS;
- break;
- }
- } while (dp->meters[mid]);
- dp->meter_free = mid; /* Next free meter or MAX_METERS */
- }
return 0;
}
return ENOMEM;
@@ -4027,11 +4008,6 @@ dpif_netdev_meter_del(struct dpif *dpif,
meter_lock(dp, meter_id);
dp_delete_meter(dp, meter_id);
meter_unlock(dp, meter_id);
-
- /* Keep free meter index as low as possible */
- if (meter_id < dp->meter_free) {
- dp->meter_free = meter_id;
- }
}
return error;
}
@@ -662,6 +662,7 @@ close_dpif_backer(struct dpif_backer *backer)
free(backer->type);
free(backer->dp_version_string);
dpif_close(backer->dpif);
+ id_pool_destroy(backer->meter_ids);
free(backer);
}
@@ -787,6 +788,15 @@ open_dpif_backer(const char *type, struct dpif_backer **backerp)
= check_variable_length_userdata(backer);
backer->dp_version_string = dpif_get_dp_version(backer->dpif);
+ /* Manage Datpath meter IDs if supported. */
+ struct ofputil_meter_features features;
+ dpif_meter_get_features(backer->dpif, &features);
+ if (features.max_meters) {
+ backer->meter_ids = id_pool_create(0, features.max_meters);
+ } else {
+ backer->meter_ids = NULL;
+ }
+
return error;
}
@@ -5391,6 +5401,17 @@ meter_set(struct ofproto *ofproto_, ofproto_meter_id *meter_id,
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
+ /* Provider ID unknown. Use backer to allocate a new DP meter */
+ if (meter_id->uint32 == UINT32_MAX) {
+ if (!ofproto->backer->meter_ids) {
+ return EFBIG; /* Datapath does not support meter. */
+ }
+
+ if(!id_pool_alloc_id(ofproto->backer->meter_ids, &meter_id->uint32)) {
+ return ENOMEM; /* Can't allocate a DP meter. */
+ }
+ }
+
switch (dpif_meter_set(ofproto->backer->dpif, meter_id, config)) {
case 0:
return 0;
@@ -5426,6 +5447,7 @@ meter_del(struct ofproto *ofproto_, ofproto_meter_id meter_id)
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
dpif_meter_del(ofproto->backer->dpif, meter_id, NULL, 0);
+ id_pool_free_id(ofproto->backer->meter_ids, meter_id.uint32);
}
const struct ofproto_class ofproto_dpif_class = {
@@ -51,6 +51,7 @@
#include "hmapx.h"
#include "odp-util.h"
#include "openvswitch/ofp-util.h"
+#include "id-pool.h"
#include "ovs-thread.h"
#include "ofproto-provider.h"
#include "util.h"
@@ -208,6 +209,9 @@ struct dpif_backer {
bool recv_set_enable; /* Enables or disables receiving packets. */
+ /* Meter. */
+ struct id_pool *meter_ids; /* Datapath meter allocation. */
+
/* Version string of the datapath stored in OVSDB. */
char *dp_version_string;
Add 'meter_ids', an id-pool object to manage datapath meter id, i.e. provider_meter_id. Currently, only userspace datapath supports meter, and it implements the provider_meter_id management. Moving this function to 'backer' allows other datapath implementation to share the same logic. Signed-off-by: Andy Zhou <azhou@ovn.org> --- lib/dpif-netdev.c | 24 ------------------------ ofproto/ofproto-dpif.c | 22 ++++++++++++++++++++++ ofproto/ofproto-dpif.h | 4 ++++ 3 files changed, 26 insertions(+), 24 deletions(-)