> On Apr 14, 2017, at 12:46 PM, Andy Zhou <az...@ovn.org> wrote: > > Add 'meter_ids', an id-pool object to manage datapath 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 <az...@ovn.org> > --- > lib/dpif-netdev.c | 24 ------------------------ > ofproto/ofproto-dpif.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- > ofproto/ofproto-dpif.h | 4 ++++ > 3 files changed, 46 insertions(+), 26 deletions(-) > > diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c > index a14a2ebb5b2a..d5417162b7af 100644 > --- a/lib/dpif-netdev.c > +++ b/lib/dpif-netdev.c > @@ -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; > } > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c > index 6a5ffb94fa94..a026d4913731 100644 > --- a/ofproto/ofproto-dpif.c > +++ b/ofproto/ofproto-dpif.c > @@ -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. */
->”Datapath" > + 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; > } > > @@ -5385,6 +5395,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; > @@ -5414,12 +5435,31 @@ meter_get(const struct ofproto *ofproto_, > ofproto_meter_id meter_id, > return OFPERR_OFPMMFC_UNKNOWN_METER; > } > > +struct free_meter_id_args { > + struct ofproto_dpif *ofproto; > + ofproto_meter_id meter_id; > +}; > + > +static void > +free_meter_id(struct free_meter_id_args *args) > +{ > + struct ofproto_dpif *ofproto = args->ofproto; > + > + dpif_meter_del(ofproto->backer->dpif, args->meter_id, NULL, 0); > + id_pool_free_id(ofproto->backer->meter_ids, args->meter_id.uint32); > + free(args); > +} > + > static void > meter_del(struct ofproto *ofproto_, ofproto_meter_id meter_id) > { > - struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); > + struct free_meter_id_args *arg = xmalloc(sizeof *arg); > > - dpif_meter_del(ofproto->backer->dpif, meter_id, NULL, 0); > + /* The 'meter_id' may still be in use the xlate code. What about megaflows still using the meter_id, is that a problem? I guess it is OK for the meter to not be found during action execution, but how is situation different from the translation code referring to a stale meter_id? > + * Only safe to delet after RCU grace period. */ ->”delete” > + arg->ofproto = ofproto_dpif_cast(ofproto_); > + arg->meter_id = meter_id; > + ovsrcu_postpone(free_meter_id, arg); > } > > const struct ofproto_class ofproto_dpif_class = { > diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h > index 81a0bdfdad10..d14ab62ae195 100644 > --- a/ofproto/ofproto-dpif.h > +++ b/ofproto/ofproto-dpif.h > @@ -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" > @@ -221,6 +222,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; > > -- > 1.8.3.1 > > _______________________________________________ > dev mailing list > d...@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev