On Fri, Apr 28, 2017 at 12:47 PM, Jarno Rajahalme <[email protected]> wrote:
> With a note below:
>
> Acked-by: Jarno Rajahalme <[email protected]>
>
>> On Apr 28, 2017, at 2:01 AM, Andy Zhou <[email protected]> wrote:
>>
>> 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 <[email protected]>
>>
>> ---
>> v1-v2: fix typos
>> ---
>> 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 b3a080628d2b..f4de737e3751 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 c73c2738c91c..30f18b302a77 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 Datapath 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;
>> }
>>
>> @@ -5439,6 +5449,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;
>> @@ -5468,12 +5489,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.
>> +     * Only safe to delete after RCU grace period. */
>
> I’d like to see this comment expanded a bit, e.g., “Even when rules referring 
> to a meter are deleted, those rules, and their actions, remain accessible to 
> upcall translation for upcalls whose processing started before the meter was 
> deleted."

Thanks. I expended the comment, and fixed other minor issues
mentioned, and pushed the series to master.
>
> Also, in the future we may want to sync id recycling with the revalidation 
> cycle so that we know the ID to be freed is not used by datapath flows any 
> more.
>
Yes, sync with datapath needs more work. Noted.
>   Jarno
>
>> +    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
>> [email protected]
>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to