Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2017 Nicira, Inc.
0004  */
0005 
0006 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0007 
0008 #include <linux/if.h>
0009 #include <linux/skbuff.h>
0010 #include <linux/ip.h>
0011 #include <linux/kernel.h>
0012 #include <linux/openvswitch.h>
0013 #include <linux/netlink.h>
0014 #include <linux/rculist.h>
0015 
0016 #include <net/netlink.h>
0017 #include <net/genetlink.h>
0018 
0019 #include "datapath.h"
0020 #include "meter.h"
0021 
0022 static const struct nla_policy meter_policy[OVS_METER_ATTR_MAX + 1] = {
0023     [OVS_METER_ATTR_ID] = { .type = NLA_U32, },
0024     [OVS_METER_ATTR_KBPS] = { .type = NLA_FLAG },
0025     [OVS_METER_ATTR_STATS] = { .len = sizeof(struct ovs_flow_stats) },
0026     [OVS_METER_ATTR_BANDS] = { .type = NLA_NESTED },
0027     [OVS_METER_ATTR_USED] = { .type = NLA_U64 },
0028     [OVS_METER_ATTR_CLEAR] = { .type = NLA_FLAG },
0029     [OVS_METER_ATTR_MAX_METERS] = { .type = NLA_U32 },
0030     [OVS_METER_ATTR_MAX_BANDS] = { .type = NLA_U32 },
0031 };
0032 
0033 static const struct nla_policy band_policy[OVS_BAND_ATTR_MAX + 1] = {
0034     [OVS_BAND_ATTR_TYPE] = { .type = NLA_U32, },
0035     [OVS_BAND_ATTR_RATE] = { .type = NLA_U32, },
0036     [OVS_BAND_ATTR_BURST] = { .type = NLA_U32, },
0037     [OVS_BAND_ATTR_STATS] = { .len = sizeof(struct ovs_flow_stats) },
0038 };
0039 
0040 static u32 meter_hash(struct dp_meter_instance *ti, u32 id)
0041 {
0042     return id % ti->n_meters;
0043 }
0044 
0045 static void ovs_meter_free(struct dp_meter *meter)
0046 {
0047     if (!meter)
0048         return;
0049 
0050     kfree_rcu(meter, rcu);
0051 }
0052 
0053 /* Call with ovs_mutex or RCU read lock. */
0054 static struct dp_meter *lookup_meter(const struct dp_meter_table *tbl,
0055                      u32 meter_id)
0056 {
0057     struct dp_meter_instance *ti = rcu_dereference_ovsl(tbl->ti);
0058     u32 hash = meter_hash(ti, meter_id);
0059     struct dp_meter *meter;
0060 
0061     meter = rcu_dereference_ovsl(ti->dp_meters[hash]);
0062     if (meter && likely(meter->id == meter_id))
0063         return meter;
0064 
0065     return NULL;
0066 }
0067 
0068 static struct dp_meter_instance *dp_meter_instance_alloc(const u32 size)
0069 {
0070     struct dp_meter_instance *ti;
0071 
0072     ti = kvzalloc(sizeof(*ti) +
0073               sizeof(struct dp_meter *) * size,
0074               GFP_KERNEL);
0075     if (!ti)
0076         return NULL;
0077 
0078     ti->n_meters = size;
0079 
0080     return ti;
0081 }
0082 
0083 static void dp_meter_instance_free(struct dp_meter_instance *ti)
0084 {
0085     kvfree(ti);
0086 }
0087 
0088 static void dp_meter_instance_free_rcu(struct rcu_head *rcu)
0089 {
0090     struct dp_meter_instance *ti;
0091 
0092     ti = container_of(rcu, struct dp_meter_instance, rcu);
0093     kvfree(ti);
0094 }
0095 
0096 static int
0097 dp_meter_instance_realloc(struct dp_meter_table *tbl, u32 size)
0098 {
0099     struct dp_meter_instance *ti = rcu_dereference_ovsl(tbl->ti);
0100     int n_meters = min(size, ti->n_meters);
0101     struct dp_meter_instance *new_ti;
0102     int i;
0103 
0104     new_ti = dp_meter_instance_alloc(size);
0105     if (!new_ti)
0106         return -ENOMEM;
0107 
0108     for (i = 0; i < n_meters; i++)
0109         if (rcu_dereference_ovsl(ti->dp_meters[i]))
0110             new_ti->dp_meters[i] = ti->dp_meters[i];
0111 
0112     rcu_assign_pointer(tbl->ti, new_ti);
0113     call_rcu(&ti->rcu, dp_meter_instance_free_rcu);
0114 
0115     return 0;
0116 }
0117 
0118 static void dp_meter_instance_insert(struct dp_meter_instance *ti,
0119                      struct dp_meter *meter)
0120 {
0121     u32 hash;
0122 
0123     hash = meter_hash(ti, meter->id);
0124     rcu_assign_pointer(ti->dp_meters[hash], meter);
0125 }
0126 
0127 static void dp_meter_instance_remove(struct dp_meter_instance *ti,
0128                      struct dp_meter *meter)
0129 {
0130     u32 hash;
0131 
0132     hash = meter_hash(ti, meter->id);
0133     RCU_INIT_POINTER(ti->dp_meters[hash], NULL);
0134 }
0135 
0136 static int attach_meter(struct dp_meter_table *tbl, struct dp_meter *meter)
0137 {
0138     struct dp_meter_instance *ti = rcu_dereference_ovsl(tbl->ti);
0139     u32 hash = meter_hash(ti, meter->id);
0140     int err;
0141 
0142     /* In generally, slots selected should be empty, because
0143      * OvS uses id-pool to fetch a available id.
0144      */
0145     if (unlikely(rcu_dereference_ovsl(ti->dp_meters[hash])))
0146         return -EBUSY;
0147 
0148     dp_meter_instance_insert(ti, meter);
0149 
0150     /* That function is thread-safe. */
0151     tbl->count++;
0152     if (tbl->count >= tbl->max_meters_allowed) {
0153         err = -EFBIG;
0154         goto attach_err;
0155     }
0156 
0157     if (tbl->count >= ti->n_meters &&
0158         dp_meter_instance_realloc(tbl, ti->n_meters * 2)) {
0159         err = -ENOMEM;
0160         goto attach_err;
0161     }
0162 
0163     return 0;
0164 
0165 attach_err:
0166     dp_meter_instance_remove(ti, meter);
0167     tbl->count--;
0168     return err;
0169 }
0170 
0171 static int detach_meter(struct dp_meter_table *tbl, struct dp_meter *meter)
0172 {
0173     struct dp_meter_instance *ti;
0174 
0175     ASSERT_OVSL();
0176     if (!meter)
0177         return 0;
0178 
0179     ti = rcu_dereference_ovsl(tbl->ti);
0180     dp_meter_instance_remove(ti, meter);
0181 
0182     tbl->count--;
0183 
0184     /* Shrink the meter array if necessary. */
0185     if (ti->n_meters > DP_METER_ARRAY_SIZE_MIN &&
0186         tbl->count <= (ti->n_meters / 4)) {
0187         int half_size = ti->n_meters / 2;
0188         int i;
0189 
0190         /* Avoid hash collision, don't move slots to other place.
0191          * Make sure there are no references of meters in array
0192          * which will be released.
0193          */
0194         for (i = half_size; i < ti->n_meters; i++)
0195             if (rcu_dereference_ovsl(ti->dp_meters[i]))
0196                 goto out;
0197 
0198         if (dp_meter_instance_realloc(tbl, half_size))
0199             goto shrink_err;
0200     }
0201 
0202 out:
0203     return 0;
0204 
0205 shrink_err:
0206     dp_meter_instance_insert(ti, meter);
0207     tbl->count++;
0208     return -ENOMEM;
0209 }
0210 
0211 static struct sk_buff *
0212 ovs_meter_cmd_reply_start(struct genl_info *info, u8 cmd,
0213               struct ovs_header **ovs_reply_header)
0214 {
0215     struct sk_buff *skb;
0216     struct ovs_header *ovs_header = info->userhdr;
0217 
0218     skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
0219     if (!skb)
0220         return ERR_PTR(-ENOMEM);
0221 
0222     *ovs_reply_header = genlmsg_put(skb, info->snd_portid,
0223                     info->snd_seq,
0224                     &dp_meter_genl_family, 0, cmd);
0225     if (!*ovs_reply_header) {
0226         nlmsg_free(skb);
0227         return ERR_PTR(-EMSGSIZE);
0228     }
0229     (*ovs_reply_header)->dp_ifindex = ovs_header->dp_ifindex;
0230 
0231     return skb;
0232 }
0233 
0234 static int ovs_meter_cmd_reply_stats(struct sk_buff *reply, u32 meter_id,
0235                      struct dp_meter *meter)
0236 {
0237     struct nlattr *nla;
0238     struct dp_meter_band *band;
0239     u16 i;
0240 
0241     if (nla_put_u32(reply, OVS_METER_ATTR_ID, meter_id))
0242         goto error;
0243 
0244     if (nla_put(reply, OVS_METER_ATTR_STATS,
0245             sizeof(struct ovs_flow_stats), &meter->stats))
0246         goto error;
0247 
0248     if (nla_put_u64_64bit(reply, OVS_METER_ATTR_USED, meter->used,
0249                   OVS_METER_ATTR_PAD))
0250         goto error;
0251 
0252     nla = nla_nest_start_noflag(reply, OVS_METER_ATTR_BANDS);
0253     if (!nla)
0254         goto error;
0255 
0256     band = meter->bands;
0257 
0258     for (i = 0; i < meter->n_bands; ++i, ++band) {
0259         struct nlattr *band_nla;
0260 
0261         band_nla = nla_nest_start_noflag(reply, OVS_BAND_ATTR_UNSPEC);
0262         if (!band_nla || nla_put(reply, OVS_BAND_ATTR_STATS,
0263                      sizeof(struct ovs_flow_stats),
0264                      &band->stats))
0265             goto error;
0266         nla_nest_end(reply, band_nla);
0267     }
0268     nla_nest_end(reply, nla);
0269 
0270     return 0;
0271 error:
0272     return -EMSGSIZE;
0273 }
0274 
0275 static int ovs_meter_cmd_features(struct sk_buff *skb, struct genl_info *info)
0276 {
0277     struct ovs_header *ovs_header = info->userhdr;
0278     struct ovs_header *ovs_reply_header;
0279     struct nlattr *nla, *band_nla;
0280     struct sk_buff *reply;
0281     struct datapath *dp;
0282     int err = -EMSGSIZE;
0283 
0284     reply = ovs_meter_cmd_reply_start(info, OVS_METER_CMD_FEATURES,
0285                       &ovs_reply_header);
0286     if (IS_ERR(reply))
0287         return PTR_ERR(reply);
0288 
0289     ovs_lock();
0290     dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
0291     if (!dp) {
0292         err = -ENODEV;
0293         goto exit_unlock;
0294     }
0295 
0296     if (nla_put_u32(reply, OVS_METER_ATTR_MAX_METERS,
0297             dp->meter_tbl.max_meters_allowed))
0298         goto exit_unlock;
0299 
0300     ovs_unlock();
0301 
0302     if (nla_put_u32(reply, OVS_METER_ATTR_MAX_BANDS, DP_MAX_BANDS))
0303         goto nla_put_failure;
0304 
0305     nla = nla_nest_start_noflag(reply, OVS_METER_ATTR_BANDS);
0306     if (!nla)
0307         goto nla_put_failure;
0308 
0309     band_nla = nla_nest_start_noflag(reply, OVS_BAND_ATTR_UNSPEC);
0310     if (!band_nla)
0311         goto nla_put_failure;
0312     /* Currently only DROP band type is supported. */
0313     if (nla_put_u32(reply, OVS_BAND_ATTR_TYPE, OVS_METER_BAND_TYPE_DROP))
0314         goto nla_put_failure;
0315     nla_nest_end(reply, band_nla);
0316     nla_nest_end(reply, nla);
0317 
0318     genlmsg_end(reply, ovs_reply_header);
0319     return genlmsg_reply(reply, info);
0320 
0321 exit_unlock:
0322     ovs_unlock();
0323 nla_put_failure:
0324     nlmsg_free(reply);
0325     return err;
0326 }
0327 
0328 static struct dp_meter *dp_meter_create(struct nlattr **a)
0329 {
0330     struct nlattr *nla;
0331     int rem;
0332     u16 n_bands = 0;
0333     struct dp_meter *meter;
0334     struct dp_meter_band *band;
0335     int err;
0336 
0337     /* Validate attributes, count the bands. */
0338     if (!a[OVS_METER_ATTR_BANDS])
0339         return ERR_PTR(-EINVAL);
0340 
0341     nla_for_each_nested(nla, a[OVS_METER_ATTR_BANDS], rem)
0342         if (++n_bands > DP_MAX_BANDS)
0343             return ERR_PTR(-EINVAL);
0344 
0345     /* Allocate and set up the meter before locking anything. */
0346     meter = kzalloc(struct_size(meter, bands, n_bands), GFP_KERNEL);
0347     if (!meter)
0348         return ERR_PTR(-ENOMEM);
0349 
0350     meter->id = nla_get_u32(a[OVS_METER_ATTR_ID]);
0351     meter->used = div_u64(ktime_get_ns(), 1000 * 1000);
0352     meter->kbps = a[OVS_METER_ATTR_KBPS] ? 1 : 0;
0353     meter->keep_stats = !a[OVS_METER_ATTR_CLEAR];
0354     spin_lock_init(&meter->lock);
0355     if (meter->keep_stats && a[OVS_METER_ATTR_STATS]) {
0356         meter->stats = *(struct ovs_flow_stats *)
0357             nla_data(a[OVS_METER_ATTR_STATS]);
0358     }
0359     meter->n_bands = n_bands;
0360 
0361     /* Set up meter bands. */
0362     band = meter->bands;
0363     nla_for_each_nested(nla, a[OVS_METER_ATTR_BANDS], rem) {
0364         struct nlattr *attr[OVS_BAND_ATTR_MAX + 1];
0365         u32 band_max_delta_t;
0366 
0367         err = nla_parse_deprecated((struct nlattr **)&attr,
0368                        OVS_BAND_ATTR_MAX, nla_data(nla),
0369                        nla_len(nla), band_policy, NULL);
0370         if (err)
0371             goto exit_free_meter;
0372 
0373         if (!attr[OVS_BAND_ATTR_TYPE] ||
0374             !attr[OVS_BAND_ATTR_RATE] ||
0375             !attr[OVS_BAND_ATTR_BURST]) {
0376             err = -EINVAL;
0377             goto exit_free_meter;
0378         }
0379 
0380         band->type = nla_get_u32(attr[OVS_BAND_ATTR_TYPE]);
0381         band->rate = nla_get_u32(attr[OVS_BAND_ATTR_RATE]);
0382         if (band->rate == 0) {
0383             err = -EINVAL;
0384             goto exit_free_meter;
0385         }
0386 
0387         band->burst_size = nla_get_u32(attr[OVS_BAND_ATTR_BURST]);
0388         /* Figure out max delta_t that is enough to fill any bucket.
0389          * Keep max_delta_t size to the bucket units:
0390          * pkts => 1/1000 packets, kilobits => bits.
0391          *
0392          * Start with a full bucket.
0393          */
0394         band->bucket = band->burst_size * 1000ULL;
0395         band_max_delta_t = div_u64(band->bucket, band->rate);
0396         if (band_max_delta_t > meter->max_delta_t)
0397             meter->max_delta_t = band_max_delta_t;
0398         band++;
0399     }
0400 
0401     return meter;
0402 
0403 exit_free_meter:
0404     kfree(meter);
0405     return ERR_PTR(err);
0406 }
0407 
0408 static int ovs_meter_cmd_set(struct sk_buff *skb, struct genl_info *info)
0409 {
0410     struct nlattr **a = info->attrs;
0411     struct dp_meter *meter, *old_meter;
0412     struct sk_buff *reply;
0413     struct ovs_header *ovs_reply_header;
0414     struct ovs_header *ovs_header = info->userhdr;
0415     struct dp_meter_table *meter_tbl;
0416     struct datapath *dp;
0417     int err;
0418     u32 meter_id;
0419     bool failed;
0420 
0421     if (!a[OVS_METER_ATTR_ID])
0422         return -EINVAL;
0423 
0424     meter = dp_meter_create(a);
0425     if (IS_ERR(meter))
0426         return PTR_ERR(meter);
0427 
0428     reply = ovs_meter_cmd_reply_start(info, OVS_METER_CMD_SET,
0429                       &ovs_reply_header);
0430     if (IS_ERR(reply)) {
0431         err = PTR_ERR(reply);
0432         goto exit_free_meter;
0433     }
0434 
0435     ovs_lock();
0436     dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
0437     if (!dp) {
0438         err = -ENODEV;
0439         goto exit_unlock;
0440     }
0441 
0442     meter_tbl = &dp->meter_tbl;
0443     meter_id = nla_get_u32(a[OVS_METER_ATTR_ID]);
0444 
0445     old_meter = lookup_meter(meter_tbl, meter_id);
0446     err = detach_meter(meter_tbl, old_meter);
0447     if (err)
0448         goto exit_unlock;
0449 
0450     err = attach_meter(meter_tbl, meter);
0451     if (err)
0452         goto exit_unlock;
0453 
0454     ovs_unlock();
0455 
0456     /* Build response with the meter_id and stats from
0457      * the old meter, if any.
0458      */
0459     failed = nla_put_u32(reply, OVS_METER_ATTR_ID, meter_id);
0460     WARN_ON(failed);
0461     if (old_meter) {
0462         spin_lock_bh(&old_meter->lock);
0463         if (old_meter->keep_stats) {
0464             err = ovs_meter_cmd_reply_stats(reply, meter_id,
0465                             old_meter);
0466             WARN_ON(err);
0467         }
0468         spin_unlock_bh(&old_meter->lock);
0469         ovs_meter_free(old_meter);
0470     }
0471 
0472     genlmsg_end(reply, ovs_reply_header);
0473     return genlmsg_reply(reply, info);
0474 
0475 exit_unlock:
0476     ovs_unlock();
0477     nlmsg_free(reply);
0478 exit_free_meter:
0479     kfree(meter);
0480     return err;
0481 }
0482 
0483 static int ovs_meter_cmd_get(struct sk_buff *skb, struct genl_info *info)
0484 {
0485     struct ovs_header *ovs_header = info->userhdr;
0486     struct ovs_header *ovs_reply_header;
0487     struct nlattr **a = info->attrs;
0488     struct dp_meter *meter;
0489     struct sk_buff *reply;
0490     struct datapath *dp;
0491     u32 meter_id;
0492     int err;
0493 
0494     if (!a[OVS_METER_ATTR_ID])
0495         return -EINVAL;
0496 
0497     meter_id = nla_get_u32(a[OVS_METER_ATTR_ID]);
0498 
0499     reply = ovs_meter_cmd_reply_start(info, OVS_METER_CMD_GET,
0500                       &ovs_reply_header);
0501     if (IS_ERR(reply))
0502         return PTR_ERR(reply);
0503 
0504     ovs_lock();
0505 
0506     dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
0507     if (!dp) {
0508         err = -ENODEV;
0509         goto exit_unlock;
0510     }
0511 
0512     /* Locate meter, copy stats. */
0513     meter = lookup_meter(&dp->meter_tbl, meter_id);
0514     if (!meter) {
0515         err = -ENOENT;
0516         goto exit_unlock;
0517     }
0518 
0519     spin_lock_bh(&meter->lock);
0520     err = ovs_meter_cmd_reply_stats(reply, meter_id, meter);
0521     spin_unlock_bh(&meter->lock);
0522     if (err)
0523         goto exit_unlock;
0524 
0525     ovs_unlock();
0526 
0527     genlmsg_end(reply, ovs_reply_header);
0528     return genlmsg_reply(reply, info);
0529 
0530 exit_unlock:
0531     ovs_unlock();
0532     nlmsg_free(reply);
0533     return err;
0534 }
0535 
0536 static int ovs_meter_cmd_del(struct sk_buff *skb, struct genl_info *info)
0537 {
0538     struct ovs_header *ovs_header = info->userhdr;
0539     struct ovs_header *ovs_reply_header;
0540     struct nlattr **a = info->attrs;
0541     struct dp_meter *old_meter;
0542     struct sk_buff *reply;
0543     struct datapath *dp;
0544     u32 meter_id;
0545     int err;
0546 
0547     if (!a[OVS_METER_ATTR_ID])
0548         return -EINVAL;
0549 
0550     reply = ovs_meter_cmd_reply_start(info, OVS_METER_CMD_DEL,
0551                       &ovs_reply_header);
0552     if (IS_ERR(reply))
0553         return PTR_ERR(reply);
0554 
0555     ovs_lock();
0556 
0557     dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
0558     if (!dp) {
0559         err = -ENODEV;
0560         goto exit_unlock;
0561     }
0562 
0563     meter_id = nla_get_u32(a[OVS_METER_ATTR_ID]);
0564     old_meter = lookup_meter(&dp->meter_tbl, meter_id);
0565     if (old_meter) {
0566         spin_lock_bh(&old_meter->lock);
0567         err = ovs_meter_cmd_reply_stats(reply, meter_id, old_meter);
0568         WARN_ON(err);
0569         spin_unlock_bh(&old_meter->lock);
0570 
0571         err = detach_meter(&dp->meter_tbl, old_meter);
0572         if (err)
0573             goto exit_unlock;
0574     }
0575 
0576     ovs_unlock();
0577     ovs_meter_free(old_meter);
0578     genlmsg_end(reply, ovs_reply_header);
0579     return genlmsg_reply(reply, info);
0580 
0581 exit_unlock:
0582     ovs_unlock();
0583     nlmsg_free(reply);
0584     return err;
0585 }
0586 
0587 /* Meter action execution.
0588  *
0589  * Return true 'meter_id' drop band is triggered. The 'skb' should be
0590  * dropped by the caller'.
0591  */
0592 bool ovs_meter_execute(struct datapath *dp, struct sk_buff *skb,
0593                struct sw_flow_key *key, u32 meter_id)
0594 {
0595     long long int now_ms = div_u64(ktime_get_ns(), 1000 * 1000);
0596     long long int long_delta_ms;
0597     struct dp_meter_band *band;
0598     struct dp_meter *meter;
0599     int i, band_exceeded_max = -1;
0600     u32 band_exceeded_rate = 0;
0601     u32 delta_ms;
0602     u32 cost;
0603 
0604     meter = lookup_meter(&dp->meter_tbl, meter_id);
0605     /* Do not drop the packet when there is no meter. */
0606     if (!meter)
0607         return false;
0608 
0609     /* Lock the meter while using it. */
0610     spin_lock(&meter->lock);
0611 
0612     long_delta_ms = (now_ms - meter->used); /* ms */
0613     if (long_delta_ms < 0) {
0614         /* This condition means that we have several threads fighting
0615          * for a meter lock, and the one who received the packets a
0616          * bit later wins. Assuming that all racing threads received
0617          * packets at the same time to avoid overflow.
0618          */
0619         long_delta_ms = 0;
0620     }
0621 
0622     /* Make sure delta_ms will not be too large, so that bucket will not
0623      * wrap around below.
0624      */
0625     delta_ms = (long_delta_ms > (long long int)meter->max_delta_t)
0626            ? meter->max_delta_t : (u32)long_delta_ms;
0627 
0628     /* Update meter statistics.
0629      */
0630     meter->used = now_ms;
0631     meter->stats.n_packets += 1;
0632     meter->stats.n_bytes += skb->len;
0633 
0634     /* Bucket rate is either in kilobits per second, or in packets per
0635      * second.  We maintain the bucket in the units of either bits or
0636      * 1/1000th of a packet, correspondingly.
0637      * Then, when rate is multiplied with milliseconds, we get the
0638      * bucket units:
0639      * msec * kbps = bits, and
0640      * msec * packets/sec = 1/1000 packets.
0641      *
0642      * 'cost' is the number of bucket units in this packet.
0643      */
0644     cost = (meter->kbps) ? skb->len * 8 : 1000;
0645 
0646     /* Update all bands and find the one hit with the highest rate. */
0647     for (i = 0; i < meter->n_bands; ++i) {
0648         long long int max_bucket_size;
0649 
0650         band = &meter->bands[i];
0651         max_bucket_size = band->burst_size * 1000LL;
0652 
0653         band->bucket += delta_ms * band->rate;
0654         if (band->bucket > max_bucket_size)
0655             band->bucket = max_bucket_size;
0656 
0657         if (band->bucket >= cost) {
0658             band->bucket -= cost;
0659         } else if (band->rate > band_exceeded_rate) {
0660             band_exceeded_rate = band->rate;
0661             band_exceeded_max = i;
0662         }
0663     }
0664 
0665     if (band_exceeded_max >= 0) {
0666         /* Update band statistics. */
0667         band = &meter->bands[band_exceeded_max];
0668         band->stats.n_packets += 1;
0669         band->stats.n_bytes += skb->len;
0670 
0671         /* Drop band triggered, let the caller drop the 'skb'.  */
0672         if (band->type == OVS_METER_BAND_TYPE_DROP) {
0673             spin_unlock(&meter->lock);
0674             return true;
0675         }
0676     }
0677 
0678     spin_unlock(&meter->lock);
0679     return false;
0680 }
0681 
0682 static const struct genl_small_ops dp_meter_genl_ops[] = {
0683     { .cmd = OVS_METER_CMD_FEATURES,
0684         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
0685         .flags = 0,       /* OK for unprivileged users. */
0686         .doit = ovs_meter_cmd_features
0687     },
0688     { .cmd = OVS_METER_CMD_SET,
0689         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
0690         .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN
0691                        *  privilege.
0692                        */
0693         .doit = ovs_meter_cmd_set,
0694     },
0695     { .cmd = OVS_METER_CMD_GET,
0696         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
0697         .flags = 0,       /* OK for unprivileged users. */
0698         .doit = ovs_meter_cmd_get,
0699     },
0700     { .cmd = OVS_METER_CMD_DEL,
0701         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
0702         .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN
0703                        *  privilege.
0704                        */
0705         .doit = ovs_meter_cmd_del
0706     },
0707 };
0708 
0709 static const struct genl_multicast_group ovs_meter_multicast_group = {
0710     .name = OVS_METER_MCGROUP,
0711 };
0712 
0713 struct genl_family dp_meter_genl_family __ro_after_init = {
0714     .hdrsize = sizeof(struct ovs_header),
0715     .name = OVS_METER_FAMILY,
0716     .version = OVS_METER_VERSION,
0717     .maxattr = OVS_METER_ATTR_MAX,
0718     .policy = meter_policy,
0719     .netnsok = true,
0720     .parallel_ops = true,
0721     .small_ops = dp_meter_genl_ops,
0722     .n_small_ops = ARRAY_SIZE(dp_meter_genl_ops),
0723     .mcgrps = &ovs_meter_multicast_group,
0724     .n_mcgrps = 1,
0725     .module = THIS_MODULE,
0726 };
0727 
0728 int ovs_meters_init(struct datapath *dp)
0729 {
0730     struct dp_meter_table *tbl = &dp->meter_tbl;
0731     struct dp_meter_instance *ti;
0732     unsigned long free_mem_bytes;
0733 
0734     ti = dp_meter_instance_alloc(DP_METER_ARRAY_SIZE_MIN);
0735     if (!ti)
0736         return -ENOMEM;
0737 
0738     /* Allow meters in a datapath to use ~3.12% of physical memory. */
0739     free_mem_bytes = nr_free_buffer_pages() * (PAGE_SIZE >> 5);
0740     tbl->max_meters_allowed = min(free_mem_bytes / sizeof(struct dp_meter),
0741                       DP_METER_NUM_MAX);
0742     if (!tbl->max_meters_allowed)
0743         goto out_err;
0744 
0745     rcu_assign_pointer(tbl->ti, ti);
0746     tbl->count = 0;
0747 
0748     return 0;
0749 
0750 out_err:
0751     dp_meter_instance_free(ti);
0752     return -ENOMEM;
0753 }
0754 
0755 void ovs_meters_exit(struct datapath *dp)
0756 {
0757     struct dp_meter_table *tbl = &dp->meter_tbl;
0758     struct dp_meter_instance *ti = rcu_dereference_raw(tbl->ti);
0759     int i;
0760 
0761     for (i = 0; i < ti->n_meters; i++)
0762         ovs_meter_free(rcu_dereference_raw(ti->dp_meters[i]));
0763 
0764     dp_meter_instance_free(ti);
0765 }