linux/net/openvswitch/meter.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2017 Nicira, Inc.
   4 */
   5
   6#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   7
   8#include <linux/if.h>
   9#include <linux/skbuff.h>
  10#include <linux/ip.h>
  11#include <linux/kernel.h>
  12#include <linux/openvswitch.h>
  13#include <linux/netlink.h>
  14#include <linux/rculist.h>
  15#include <linux/swap.h>
  16
  17#include <net/netlink.h>
  18#include <net/genetlink.h>
  19
  20#include "datapath.h"
  21#include "meter.h"
  22
  23static const struct nla_policy meter_policy[OVS_METER_ATTR_MAX + 1] = {
  24        [OVS_METER_ATTR_ID] = { .type = NLA_U32, },
  25        [OVS_METER_ATTR_KBPS] = { .type = NLA_FLAG },
  26        [OVS_METER_ATTR_STATS] = { .len = sizeof(struct ovs_flow_stats) },
  27        [OVS_METER_ATTR_BANDS] = { .type = NLA_NESTED },
  28        [OVS_METER_ATTR_USED] = { .type = NLA_U64 },
  29        [OVS_METER_ATTR_CLEAR] = { .type = NLA_FLAG },
  30        [OVS_METER_ATTR_MAX_METERS] = { .type = NLA_U32 },
  31        [OVS_METER_ATTR_MAX_BANDS] = { .type = NLA_U32 },
  32};
  33
  34static const struct nla_policy band_policy[OVS_BAND_ATTR_MAX + 1] = {
  35        [OVS_BAND_ATTR_TYPE] = { .type = NLA_U32, },
  36        [OVS_BAND_ATTR_RATE] = { .type = NLA_U32, },
  37        [OVS_BAND_ATTR_BURST] = { .type = NLA_U32, },
  38        [OVS_BAND_ATTR_STATS] = { .len = sizeof(struct ovs_flow_stats) },
  39};
  40
  41static u32 meter_hash(struct dp_meter_instance *ti, u32 id)
  42{
  43        return id % ti->n_meters;
  44}
  45
  46static void ovs_meter_free(struct dp_meter *meter)
  47{
  48        if (!meter)
  49                return;
  50
  51        kfree_rcu(meter, rcu);
  52}
  53
  54/* Call with ovs_mutex or RCU read lock. */
  55static struct dp_meter *lookup_meter(const struct dp_meter_table *tbl,
  56                                     u32 meter_id)
  57{
  58        struct dp_meter_instance *ti = rcu_dereference_ovsl(tbl->ti);
  59        u32 hash = meter_hash(ti, meter_id);
  60        struct dp_meter *meter;
  61
  62        meter = rcu_dereference_ovsl(ti->dp_meters[hash]);
  63        if (meter && likely(meter->id == meter_id))
  64                return meter;
  65
  66        return NULL;
  67}
  68
  69static struct dp_meter_instance *dp_meter_instance_alloc(const u32 size)
  70{
  71        struct dp_meter_instance *ti;
  72
  73        ti = kvzalloc(sizeof(*ti) +
  74                      sizeof(struct dp_meter *) * size,
  75                      GFP_KERNEL);
  76        if (!ti)
  77                return NULL;
  78
  79        ti->n_meters = size;
  80
  81        return ti;
  82}
  83
  84static void dp_meter_instance_free(struct dp_meter_instance *ti)
  85{
  86        kvfree(ti);
  87}
  88
  89static void dp_meter_instance_free_rcu(struct rcu_head *rcu)
  90{
  91        struct dp_meter_instance *ti;
  92
  93        ti = container_of(rcu, struct dp_meter_instance, rcu);
  94        kvfree(ti);
  95}
  96
  97static int
  98dp_meter_instance_realloc(struct dp_meter_table *tbl, u32 size)
  99{
 100        struct dp_meter_instance *ti = rcu_dereference_ovsl(tbl->ti);
 101        int n_meters = min(size, ti->n_meters);
 102        struct dp_meter_instance *new_ti;
 103        int i;
 104
 105        new_ti = dp_meter_instance_alloc(size);
 106        if (!new_ti)
 107                return -ENOMEM;
 108
 109        for (i = 0; i < n_meters; i++)
 110                if (rcu_dereference_ovsl(ti->dp_meters[i]))
 111                        new_ti->dp_meters[i] = ti->dp_meters[i];
 112
 113        rcu_assign_pointer(tbl->ti, new_ti);
 114        call_rcu(&ti->rcu, dp_meter_instance_free_rcu);
 115
 116        return 0;
 117}
 118
 119static void dp_meter_instance_insert(struct dp_meter_instance *ti,
 120                                     struct dp_meter *meter)
 121{
 122        u32 hash;
 123
 124        hash = meter_hash(ti, meter->id);
 125        rcu_assign_pointer(ti->dp_meters[hash], meter);
 126}
 127
 128static void dp_meter_instance_remove(struct dp_meter_instance *ti,
 129                                     struct dp_meter *meter)
 130{
 131        u32 hash;
 132
 133        hash = meter_hash(ti, meter->id);
 134        RCU_INIT_POINTER(ti->dp_meters[hash], NULL);
 135}
 136
 137static int attach_meter(struct dp_meter_table *tbl, struct dp_meter *meter)
 138{
 139        struct dp_meter_instance *ti = rcu_dereference_ovsl(tbl->ti);
 140        u32 hash = meter_hash(ti, meter->id);
 141        int err;
 142
 143        /* In generally, slots selected should be empty, because
 144         * OvS uses id-pool to fetch a available id.
 145         */
 146        if (unlikely(rcu_dereference_ovsl(ti->dp_meters[hash])))
 147                return -EBUSY;
 148
 149        dp_meter_instance_insert(ti, meter);
 150
 151        /* That function is thread-safe. */
 152        tbl->count++;
 153        if (tbl->count >= tbl->max_meters_allowed) {
 154                err = -EFBIG;
 155                goto attach_err;
 156        }
 157
 158        if (tbl->count >= ti->n_meters &&
 159            dp_meter_instance_realloc(tbl, ti->n_meters * 2)) {
 160                err = -ENOMEM;
 161                goto attach_err;
 162        }
 163
 164        return 0;
 165
 166attach_err:
 167        dp_meter_instance_remove(ti, meter);
 168        tbl->count--;
 169        return err;
 170}
 171
 172static int detach_meter(struct dp_meter_table *tbl, struct dp_meter *meter)
 173{
 174        struct dp_meter_instance *ti;
 175
 176        ASSERT_OVSL();
 177        if (!meter)
 178                return 0;
 179
 180        ti = rcu_dereference_ovsl(tbl->ti);
 181        dp_meter_instance_remove(ti, meter);
 182
 183        tbl->count--;
 184
 185        /* Shrink the meter array if necessary. */
 186        if (ti->n_meters > DP_METER_ARRAY_SIZE_MIN &&
 187            tbl->count <= (ti->n_meters / 4)) {
 188                int half_size = ti->n_meters / 2;
 189                int i;
 190
 191                /* Avoid hash collision, don't move slots to other place.
 192                 * Make sure there are no references of meters in array
 193                 * which will be released.
 194                 */
 195                for (i = half_size; i < ti->n_meters; i++)
 196                        if (rcu_dereference_ovsl(ti->dp_meters[i]))
 197                                goto out;
 198
 199                if (dp_meter_instance_realloc(tbl, half_size))
 200                        goto shrink_err;
 201        }
 202
 203out:
 204        return 0;
 205
 206shrink_err:
 207        dp_meter_instance_insert(ti, meter);
 208        tbl->count++;
 209        return -ENOMEM;
 210}
 211
 212static struct sk_buff *
 213ovs_meter_cmd_reply_start(struct genl_info *info, u8 cmd,
 214                          struct ovs_header **ovs_reply_header)
 215{
 216        struct sk_buff *skb;
 217        struct ovs_header *ovs_header = info->userhdr;
 218
 219        skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
 220        if (!skb)
 221                return ERR_PTR(-ENOMEM);
 222
 223        *ovs_reply_header = genlmsg_put(skb, info->snd_portid,
 224                                        info->snd_seq,
 225                                        &dp_meter_genl_family, 0, cmd);
 226        if (!*ovs_reply_header) {
 227                nlmsg_free(skb);
 228                return ERR_PTR(-EMSGSIZE);
 229        }
 230        (*ovs_reply_header)->dp_ifindex = ovs_header->dp_ifindex;
 231
 232        return skb;
 233}
 234
 235static int ovs_meter_cmd_reply_stats(struct sk_buff *reply, u32 meter_id,
 236                                     struct dp_meter *meter)
 237{
 238        struct nlattr *nla;
 239        struct dp_meter_band *band;
 240        u16 i;
 241
 242        if (nla_put_u32(reply, OVS_METER_ATTR_ID, meter_id))
 243                goto error;
 244
 245        if (nla_put(reply, OVS_METER_ATTR_STATS,
 246                    sizeof(struct ovs_flow_stats), &meter->stats))
 247                goto error;
 248
 249        if (nla_put_u64_64bit(reply, OVS_METER_ATTR_USED, meter->used,
 250                              OVS_METER_ATTR_PAD))
 251                goto error;
 252
 253        nla = nla_nest_start_noflag(reply, OVS_METER_ATTR_BANDS);
 254        if (!nla)
 255                goto error;
 256
 257        band = meter->bands;
 258
 259        for (i = 0; i < meter->n_bands; ++i, ++band) {
 260                struct nlattr *band_nla;
 261
 262                band_nla = nla_nest_start_noflag(reply, OVS_BAND_ATTR_UNSPEC);
 263                if (!band_nla || nla_put(reply, OVS_BAND_ATTR_STATS,
 264                                         sizeof(struct ovs_flow_stats),
 265                                         &band->stats))
 266                        goto error;
 267                nla_nest_end(reply, band_nla);
 268        }
 269        nla_nest_end(reply, nla);
 270
 271        return 0;
 272error:
 273        return -EMSGSIZE;
 274}
 275
 276static int ovs_meter_cmd_features(struct sk_buff *skb, struct genl_info *info)
 277{
 278        struct ovs_header *ovs_header = info->userhdr;
 279        struct ovs_header *ovs_reply_header;
 280        struct nlattr *nla, *band_nla;
 281        struct sk_buff *reply;
 282        struct datapath *dp;
 283        int err = -EMSGSIZE;
 284
 285        reply = ovs_meter_cmd_reply_start(info, OVS_METER_CMD_FEATURES,
 286                                          &ovs_reply_header);
 287        if (IS_ERR(reply))
 288                return PTR_ERR(reply);
 289
 290        ovs_lock();
 291        dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
 292        if (!dp) {
 293                err = -ENODEV;
 294                goto exit_unlock;
 295        }
 296
 297        if (nla_put_u32(reply, OVS_METER_ATTR_MAX_METERS,
 298                        dp->meter_tbl.max_meters_allowed))
 299                goto exit_unlock;
 300
 301        ovs_unlock();
 302
 303        if (nla_put_u32(reply, OVS_METER_ATTR_MAX_BANDS, DP_MAX_BANDS))
 304                goto nla_put_failure;
 305
 306        nla = nla_nest_start_noflag(reply, OVS_METER_ATTR_BANDS);
 307        if (!nla)
 308                goto nla_put_failure;
 309
 310        band_nla = nla_nest_start_noflag(reply, OVS_BAND_ATTR_UNSPEC);
 311        if (!band_nla)
 312                goto nla_put_failure;
 313        /* Currently only DROP band type is supported. */
 314        if (nla_put_u32(reply, OVS_BAND_ATTR_TYPE, OVS_METER_BAND_TYPE_DROP))
 315                goto nla_put_failure;
 316        nla_nest_end(reply, band_nla);
 317        nla_nest_end(reply, nla);
 318
 319        genlmsg_end(reply, ovs_reply_header);
 320        return genlmsg_reply(reply, info);
 321
 322exit_unlock:
 323        ovs_unlock();
 324nla_put_failure:
 325        nlmsg_free(reply);
 326        return err;
 327}
 328
 329static struct dp_meter *dp_meter_create(struct nlattr **a)
 330{
 331        struct nlattr *nla;
 332        int rem;
 333        u16 n_bands = 0;
 334        struct dp_meter *meter;
 335        struct dp_meter_band *band;
 336        int err;
 337
 338        /* Validate attributes, count the bands. */
 339        if (!a[OVS_METER_ATTR_BANDS])
 340                return ERR_PTR(-EINVAL);
 341
 342        nla_for_each_nested(nla, a[OVS_METER_ATTR_BANDS], rem)
 343                if (++n_bands > DP_MAX_BANDS)
 344                        return ERR_PTR(-EINVAL);
 345
 346        /* Allocate and set up the meter before locking anything. */
 347        meter = kzalloc(struct_size(meter, bands, n_bands), GFP_KERNEL);
 348        if (!meter)
 349                return ERR_PTR(-ENOMEM);
 350
 351        meter->id = nla_get_u32(a[OVS_METER_ATTR_ID]);
 352        meter->used = div_u64(ktime_get_ns(), 1000 * 1000);
 353        meter->kbps = a[OVS_METER_ATTR_KBPS] ? 1 : 0;
 354        meter->keep_stats = !a[OVS_METER_ATTR_CLEAR];
 355        spin_lock_init(&meter->lock);
 356        if (meter->keep_stats && a[OVS_METER_ATTR_STATS]) {
 357                meter->stats = *(struct ovs_flow_stats *)
 358                        nla_data(a[OVS_METER_ATTR_STATS]);
 359        }
 360        meter->n_bands = n_bands;
 361
 362        /* Set up meter bands. */
 363        band = meter->bands;
 364        nla_for_each_nested(nla, a[OVS_METER_ATTR_BANDS], rem) {
 365                struct nlattr *attr[OVS_BAND_ATTR_MAX + 1];
 366                u32 band_max_delta_t;
 367
 368                err = nla_parse_deprecated((struct nlattr **)&attr,
 369                                           OVS_BAND_ATTR_MAX, nla_data(nla),
 370                                           nla_len(nla), band_policy, NULL);
 371                if (err)
 372                        goto exit_free_meter;
 373
 374                if (!attr[OVS_BAND_ATTR_TYPE] ||
 375                    !attr[OVS_BAND_ATTR_RATE] ||
 376                    !attr[OVS_BAND_ATTR_BURST]) {
 377                        err = -EINVAL;
 378                        goto exit_free_meter;
 379                }
 380
 381                band->type = nla_get_u32(attr[OVS_BAND_ATTR_TYPE]);
 382                band->rate = nla_get_u32(attr[OVS_BAND_ATTR_RATE]);
 383                if (band->rate == 0) {
 384                        err = -EINVAL;
 385                        goto exit_free_meter;
 386                }
 387
 388                band->burst_size = nla_get_u32(attr[OVS_BAND_ATTR_BURST]);
 389                /* Figure out max delta_t that is enough to fill any bucket.
 390                 * Keep max_delta_t size to the bucket units:
 391                 * pkts => 1/1000 packets, kilobits => bits.
 392                 *
 393                 * Start with a full bucket.
 394                 */
 395                band->bucket = band->burst_size * 1000ULL;
 396                band_max_delta_t = div_u64(band->bucket, band->rate);
 397                if (band_max_delta_t > meter->max_delta_t)
 398                        meter->max_delta_t = band_max_delta_t;
 399                band++;
 400        }
 401
 402        return meter;
 403
 404exit_free_meter:
 405        kfree(meter);
 406        return ERR_PTR(err);
 407}
 408
 409static int ovs_meter_cmd_set(struct sk_buff *skb, struct genl_info *info)
 410{
 411        struct nlattr **a = info->attrs;
 412        struct dp_meter *meter, *old_meter;
 413        struct sk_buff *reply;
 414        struct ovs_header *ovs_reply_header;
 415        struct ovs_header *ovs_header = info->userhdr;
 416        struct dp_meter_table *meter_tbl;
 417        struct datapath *dp;
 418        int err;
 419        u32 meter_id;
 420        bool failed;
 421
 422        if (!a[OVS_METER_ATTR_ID])
 423                return -EINVAL;
 424
 425        meter = dp_meter_create(a);
 426        if (IS_ERR(meter))
 427                return PTR_ERR(meter);
 428
 429        reply = ovs_meter_cmd_reply_start(info, OVS_METER_CMD_SET,
 430                                          &ovs_reply_header);
 431        if (IS_ERR(reply)) {
 432                err = PTR_ERR(reply);
 433                goto exit_free_meter;
 434        }
 435
 436        ovs_lock();
 437        dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
 438        if (!dp) {
 439                err = -ENODEV;
 440                goto exit_unlock;
 441        }
 442
 443        meter_tbl = &dp->meter_tbl;
 444        meter_id = nla_get_u32(a[OVS_METER_ATTR_ID]);
 445
 446        old_meter = lookup_meter(meter_tbl, meter_id);
 447        err = detach_meter(meter_tbl, old_meter);
 448        if (err)
 449                goto exit_unlock;
 450
 451        err = attach_meter(meter_tbl, meter);
 452        if (err)
 453                goto exit_unlock;
 454
 455        ovs_unlock();
 456
 457        /* Build response with the meter_id and stats from
 458         * the old meter, if any.
 459         */
 460        failed = nla_put_u32(reply, OVS_METER_ATTR_ID, meter_id);
 461        WARN_ON(failed);
 462        if (old_meter) {
 463                spin_lock_bh(&old_meter->lock);
 464                if (old_meter->keep_stats) {
 465                        err = ovs_meter_cmd_reply_stats(reply, meter_id,
 466                                                        old_meter);
 467                        WARN_ON(err);
 468                }
 469                spin_unlock_bh(&old_meter->lock);
 470                ovs_meter_free(old_meter);
 471        }
 472
 473        genlmsg_end(reply, ovs_reply_header);
 474        return genlmsg_reply(reply, info);
 475
 476exit_unlock:
 477        ovs_unlock();
 478        nlmsg_free(reply);
 479exit_free_meter:
 480        kfree(meter);
 481        return err;
 482}
 483
 484static int ovs_meter_cmd_get(struct sk_buff *skb, struct genl_info *info)
 485{
 486        struct ovs_header *ovs_header = info->userhdr;
 487        struct ovs_header *ovs_reply_header;
 488        struct nlattr **a = info->attrs;
 489        struct dp_meter *meter;
 490        struct sk_buff *reply;
 491        struct datapath *dp;
 492        u32 meter_id;
 493        int err;
 494
 495        if (!a[OVS_METER_ATTR_ID])
 496                return -EINVAL;
 497
 498        meter_id = nla_get_u32(a[OVS_METER_ATTR_ID]);
 499
 500        reply = ovs_meter_cmd_reply_start(info, OVS_METER_CMD_GET,
 501                                          &ovs_reply_header);
 502        if (IS_ERR(reply))
 503                return PTR_ERR(reply);
 504
 505        ovs_lock();
 506
 507        dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
 508        if (!dp) {
 509                err = -ENODEV;
 510                goto exit_unlock;
 511        }
 512
 513        /* Locate meter, copy stats. */
 514        meter = lookup_meter(&dp->meter_tbl, meter_id);
 515        if (!meter) {
 516                err = -ENOENT;
 517                goto exit_unlock;
 518        }
 519
 520        spin_lock_bh(&meter->lock);
 521        err = ovs_meter_cmd_reply_stats(reply, meter_id, meter);
 522        spin_unlock_bh(&meter->lock);
 523        if (err)
 524                goto exit_unlock;
 525
 526        ovs_unlock();
 527
 528        genlmsg_end(reply, ovs_reply_header);
 529        return genlmsg_reply(reply, info);
 530
 531exit_unlock:
 532        ovs_unlock();
 533        nlmsg_free(reply);
 534        return err;
 535}
 536
 537static int ovs_meter_cmd_del(struct sk_buff *skb, struct genl_info *info)
 538{
 539        struct ovs_header *ovs_header = info->userhdr;
 540        struct ovs_header *ovs_reply_header;
 541        struct nlattr **a = info->attrs;
 542        struct dp_meter *old_meter;
 543        struct sk_buff *reply;
 544        struct datapath *dp;
 545        u32 meter_id;
 546        int err;
 547
 548        if (!a[OVS_METER_ATTR_ID])
 549                return -EINVAL;
 550
 551        reply = ovs_meter_cmd_reply_start(info, OVS_METER_CMD_DEL,
 552                                          &ovs_reply_header);
 553        if (IS_ERR(reply))
 554                return PTR_ERR(reply);
 555
 556        ovs_lock();
 557
 558        dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
 559        if (!dp) {
 560                err = -ENODEV;
 561                goto exit_unlock;
 562        }
 563
 564        meter_id = nla_get_u32(a[OVS_METER_ATTR_ID]);
 565        old_meter = lookup_meter(&dp->meter_tbl, meter_id);
 566        if (old_meter) {
 567                spin_lock_bh(&old_meter->lock);
 568                err = ovs_meter_cmd_reply_stats(reply, meter_id, old_meter);
 569                WARN_ON(err);
 570                spin_unlock_bh(&old_meter->lock);
 571
 572                err = detach_meter(&dp->meter_tbl, old_meter);
 573                if (err)
 574                        goto exit_unlock;
 575        }
 576
 577        ovs_unlock();
 578        ovs_meter_free(old_meter);
 579        genlmsg_end(reply, ovs_reply_header);
 580        return genlmsg_reply(reply, info);
 581
 582exit_unlock:
 583        ovs_unlock();
 584        nlmsg_free(reply);
 585        return err;
 586}
 587
 588/* Meter action execution.
 589 *
 590 * Return true 'meter_id' drop band is triggered. The 'skb' should be
 591 * dropped by the caller'.
 592 */
 593bool ovs_meter_execute(struct datapath *dp, struct sk_buff *skb,
 594                       struct sw_flow_key *key, u32 meter_id)
 595{
 596        long long int now_ms = div_u64(ktime_get_ns(), 1000 * 1000);
 597        long long int long_delta_ms;
 598        struct dp_meter_band *band;
 599        struct dp_meter *meter;
 600        int i, band_exceeded_max = -1;
 601        u32 band_exceeded_rate = 0;
 602        u32 delta_ms;
 603        u32 cost;
 604
 605        meter = lookup_meter(&dp->meter_tbl, meter_id);
 606        /* Do not drop the packet when there is no meter. */
 607        if (!meter)
 608                return false;
 609
 610        /* Lock the meter while using it. */
 611        spin_lock(&meter->lock);
 612
 613        long_delta_ms = (now_ms - meter->used); /* ms */
 614        if (long_delta_ms < 0) {
 615                /* This condition means that we have several threads fighting
 616                 * for a meter lock, and the one who received the packets a
 617                 * bit later wins. Assuming that all racing threads received
 618                 * packets at the same time to avoid overflow.
 619                 */
 620                long_delta_ms = 0;
 621        }
 622
 623        /* Make sure delta_ms will not be too large, so that bucket will not
 624         * wrap around below.
 625         */
 626        delta_ms = (long_delta_ms > (long long int)meter->max_delta_t)
 627                   ? meter->max_delta_t : (u32)long_delta_ms;
 628
 629        /* Update meter statistics.
 630         */
 631        meter->used = now_ms;
 632        meter->stats.n_packets += 1;
 633        meter->stats.n_bytes += skb->len;
 634
 635        /* Bucket rate is either in kilobits per second, or in packets per
 636         * second.  We maintain the bucket in the units of either bits or
 637         * 1/1000th of a packet, correspondingly.
 638         * Then, when rate is multiplied with milliseconds, we get the
 639         * bucket units:
 640         * msec * kbps = bits, and
 641         * msec * packets/sec = 1/1000 packets.
 642         *
 643         * 'cost' is the number of bucket units in this packet.
 644         */
 645        cost = (meter->kbps) ? skb->len * 8 : 1000;
 646
 647        /* Update all bands and find the one hit with the highest rate. */
 648        for (i = 0; i < meter->n_bands; ++i) {
 649                long long int max_bucket_size;
 650
 651                band = &meter->bands[i];
 652                max_bucket_size = band->burst_size * 1000LL;
 653
 654                band->bucket += delta_ms * band->rate;
 655                if (band->bucket > max_bucket_size)
 656                        band->bucket = max_bucket_size;
 657
 658                if (band->bucket >= cost) {
 659                        band->bucket -= cost;
 660                } else if (band->rate > band_exceeded_rate) {
 661                        band_exceeded_rate = band->rate;
 662                        band_exceeded_max = i;
 663                }
 664        }
 665
 666        if (band_exceeded_max >= 0) {
 667                /* Update band statistics. */
 668                band = &meter->bands[band_exceeded_max];
 669                band->stats.n_packets += 1;
 670                band->stats.n_bytes += skb->len;
 671
 672                /* Drop band triggered, let the caller drop the 'skb'.  */
 673                if (band->type == OVS_METER_BAND_TYPE_DROP) {
 674                        spin_unlock(&meter->lock);
 675                        return true;
 676                }
 677        }
 678
 679        spin_unlock(&meter->lock);
 680        return false;
 681}
 682
 683static const struct genl_small_ops dp_meter_genl_ops[] = {
 684        { .cmd = OVS_METER_CMD_FEATURES,
 685                .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
 686                .flags = 0,               /* OK for unprivileged users. */
 687                .doit = ovs_meter_cmd_features
 688        },
 689        { .cmd = OVS_METER_CMD_SET,
 690                .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
 691                .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN
 692                                           *  privilege.
 693                                           */
 694                .doit = ovs_meter_cmd_set,
 695        },
 696        { .cmd = OVS_METER_CMD_GET,
 697                .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
 698                .flags = 0,               /* OK for unprivileged users. */
 699                .doit = ovs_meter_cmd_get,
 700        },
 701        { .cmd = OVS_METER_CMD_DEL,
 702                .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
 703                .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN
 704                                           *  privilege.
 705                                           */
 706                .doit = ovs_meter_cmd_del
 707        },
 708};
 709
 710static const struct genl_multicast_group ovs_meter_multicast_group = {
 711        .name = OVS_METER_MCGROUP,
 712};
 713
 714struct genl_family dp_meter_genl_family __ro_after_init = {
 715        .hdrsize = sizeof(struct ovs_header),
 716        .name = OVS_METER_FAMILY,
 717        .version = OVS_METER_VERSION,
 718        .maxattr = OVS_METER_ATTR_MAX,
 719        .policy = meter_policy,
 720        .netnsok = true,
 721        .parallel_ops = true,
 722        .small_ops = dp_meter_genl_ops,
 723        .n_small_ops = ARRAY_SIZE(dp_meter_genl_ops),
 724        .mcgrps = &ovs_meter_multicast_group,
 725        .n_mcgrps = 1,
 726        .module = THIS_MODULE,
 727};
 728
 729int ovs_meters_init(struct datapath *dp)
 730{
 731        struct dp_meter_table *tbl = &dp->meter_tbl;
 732        struct dp_meter_instance *ti;
 733        unsigned long free_mem_bytes;
 734
 735        ti = dp_meter_instance_alloc(DP_METER_ARRAY_SIZE_MIN);
 736        if (!ti)
 737                return -ENOMEM;
 738
 739        /* Allow meters in a datapath to use ~3.12% of physical memory. */
 740        free_mem_bytes = nr_free_buffer_pages() * (PAGE_SIZE >> 5);
 741        tbl->max_meters_allowed = min(free_mem_bytes / sizeof(struct dp_meter),
 742                                      DP_METER_NUM_MAX);
 743        if (!tbl->max_meters_allowed)
 744                goto out_err;
 745
 746        rcu_assign_pointer(tbl->ti, ti);
 747        tbl->count = 0;
 748
 749        return 0;
 750
 751out_err:
 752        dp_meter_instance_free(ti);
 753        return -ENOMEM;
 754}
 755
 756void ovs_meters_exit(struct datapath *dp)
 757{
 758        struct dp_meter_table *tbl = &dp->meter_tbl;
 759        struct dp_meter_instance *ti = rcu_dereference_raw(tbl->ti);
 760        int i;
 761
 762        for (i = 0; i < ti->n_meters; i++)
 763                ovs_meter_free(rcu_dereference_raw(ti->dp_meters[i]));
 764
 765        dp_meter_instance_free(ti);
 766}
 767