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 23 static 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 34 static 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 41 static u32 meter_hash(struct dp_meter_instance *ti, u32 id) 42 { 43 return id % ti->n_meters; 44 } 45 46 static 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. */ 55 static 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 69 static 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 84 static void dp_meter_instance_free(struct dp_meter_instance *ti) 85 { 86 kvfree(ti); 87 } 88 89 static 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 97 static int 98 dp_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 new_ti->dp_meters[i] = 111 rcu_dereference_ovsl(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 119 static 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 128 static 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 137 static 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 166 attach_err: 167 dp_meter_instance_remove(ti, meter); 168 tbl->count--; 169 return err; 170 } 171 172 static 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 203 out: 204 return 0; 205 206 shrink_err: 207 dp_meter_instance_insert(ti, meter); 208 tbl->count++; 209 return -ENOMEM; 210 } 211 212 static struct sk_buff * 213 ovs_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 235 static 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 (!meter) 246 return 0; 247 248 if (nla_put(reply, OVS_METER_ATTR_STATS, 249 sizeof(struct ovs_flow_stats), &meter->stats) || 250 nla_put_u64_64bit(reply, OVS_METER_ATTR_USED, meter->used, 251 OVS_METER_ATTR_PAD)) 252 goto error; 253 254 nla = nla_nest_start_noflag(reply, OVS_METER_ATTR_BANDS); 255 if (!nla) 256 goto error; 257 258 band = meter->bands; 259 260 for (i = 0; i < meter->n_bands; ++i, ++band) { 261 struct nlattr *band_nla; 262 263 band_nla = nla_nest_start_noflag(reply, OVS_BAND_ATTR_UNSPEC); 264 if (!band_nla || nla_put(reply, OVS_BAND_ATTR_STATS, 265 sizeof(struct ovs_flow_stats), 266 &band->stats)) 267 goto error; 268 nla_nest_end(reply, band_nla); 269 } 270 nla_nest_end(reply, nla); 271 272 return 0; 273 error: 274 return -EMSGSIZE; 275 } 276 277 static int ovs_meter_cmd_features(struct sk_buff *skb, struct genl_info *info) 278 { 279 struct ovs_header *ovs_header = info->userhdr; 280 struct ovs_header *ovs_reply_header; 281 struct nlattr *nla, *band_nla; 282 struct sk_buff *reply; 283 struct datapath *dp; 284 int err = -EMSGSIZE; 285 286 reply = ovs_meter_cmd_reply_start(info, OVS_METER_CMD_FEATURES, 287 &ovs_reply_header); 288 if (IS_ERR(reply)) 289 return PTR_ERR(reply); 290 291 ovs_lock(); 292 dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); 293 if (!dp) { 294 err = -ENODEV; 295 goto exit_unlock; 296 } 297 298 if (nla_put_u32(reply, OVS_METER_ATTR_MAX_METERS, 299 dp->meter_tbl.max_meters_allowed)) 300 goto exit_unlock; 301 302 ovs_unlock(); 303 304 if (nla_put_u32(reply, OVS_METER_ATTR_MAX_BANDS, DP_MAX_BANDS)) 305 goto nla_put_failure; 306 307 nla = nla_nest_start_noflag(reply, OVS_METER_ATTR_BANDS); 308 if (!nla) 309 goto nla_put_failure; 310 311 band_nla = nla_nest_start_noflag(reply, OVS_BAND_ATTR_UNSPEC); 312 if (!band_nla) 313 goto nla_put_failure; 314 /* Currently only DROP band type is supported. */ 315 if (nla_put_u32(reply, OVS_BAND_ATTR_TYPE, OVS_METER_BAND_TYPE_DROP)) 316 goto nla_put_failure; 317 nla_nest_end(reply, band_nla); 318 nla_nest_end(reply, nla); 319 320 genlmsg_end(reply, ovs_reply_header); 321 return genlmsg_reply(reply, info); 322 323 exit_unlock: 324 ovs_unlock(); 325 nla_put_failure: 326 nlmsg_free(reply); 327 return err; 328 } 329 330 static struct dp_meter *dp_meter_create(struct nlattr **a) 331 { 332 struct nlattr *nla; 333 int rem; 334 u16 n_bands = 0; 335 struct dp_meter *meter; 336 struct dp_meter_band *band; 337 int err; 338 339 /* Validate attributes, count the bands. */ 340 if (!a[OVS_METER_ATTR_BANDS]) 341 return ERR_PTR(-EINVAL); 342 343 nla_for_each_nested(nla, a[OVS_METER_ATTR_BANDS], rem) 344 if (++n_bands > DP_MAX_BANDS) 345 return ERR_PTR(-EINVAL); 346 347 /* Allocate and set up the meter before locking anything. */ 348 meter = kzalloc(struct_size(meter, bands, n_bands), GFP_KERNEL); 349 if (!meter) 350 return ERR_PTR(-ENOMEM); 351 352 meter->id = nla_get_u32(a[OVS_METER_ATTR_ID]); 353 meter->used = div_u64(ktime_get_ns(), 1000 * 1000); 354 meter->kbps = a[OVS_METER_ATTR_KBPS] ? 1 : 0; 355 meter->keep_stats = !a[OVS_METER_ATTR_CLEAR]; 356 spin_lock_init(&meter->lock); 357 if (meter->keep_stats && a[OVS_METER_ATTR_STATS]) { 358 meter->stats = *(struct ovs_flow_stats *) 359 nla_data(a[OVS_METER_ATTR_STATS]); 360 } 361 meter->n_bands = n_bands; 362 363 /* Set up meter bands. */ 364 band = meter->bands; 365 nla_for_each_nested(nla, a[OVS_METER_ATTR_BANDS], rem) { 366 struct nlattr *attr[OVS_BAND_ATTR_MAX + 1]; 367 u32 band_max_delta_t; 368 369 err = nla_parse_deprecated((struct nlattr **)&attr, 370 OVS_BAND_ATTR_MAX, nla_data(nla), 371 nla_len(nla), band_policy, NULL); 372 if (err) 373 goto exit_free_meter; 374 375 if (!attr[OVS_BAND_ATTR_TYPE] || 376 !attr[OVS_BAND_ATTR_RATE] || 377 !attr[OVS_BAND_ATTR_BURST]) { 378 err = -EINVAL; 379 goto exit_free_meter; 380 } 381 382 band->type = nla_get_u32(attr[OVS_BAND_ATTR_TYPE]); 383 band->rate = nla_get_u32(attr[OVS_BAND_ATTR_RATE]); 384 if (band->rate == 0) { 385 err = -EINVAL; 386 goto exit_free_meter; 387 } 388 389 band->burst_size = nla_get_u32(attr[OVS_BAND_ATTR_BURST]); 390 /* Figure out max delta_t that is enough to fill any bucket. 391 * Keep max_delta_t size to the bucket units: 392 * pkts => 1/1000 packets, kilobits => bits. 393 * 394 * Start with a full bucket. 395 */ 396 band->bucket = (band->burst_size + band->rate) * 1000; 397 band_max_delta_t = band->bucket / band->rate; 398 if (band_max_delta_t > meter->max_delta_t) 399 meter->max_delta_t = band_max_delta_t; 400 band++; 401 } 402 403 return meter; 404 405 exit_free_meter: 406 kfree(meter); 407 return ERR_PTR(err); 408 } 409 410 static int ovs_meter_cmd_set(struct sk_buff *skb, struct genl_info *info) 411 { 412 struct nlattr **a = info->attrs; 413 struct dp_meter *meter, *old_meter; 414 struct sk_buff *reply; 415 struct ovs_header *ovs_reply_header; 416 struct ovs_header *ovs_header = info->userhdr; 417 struct dp_meter_table *meter_tbl; 418 struct datapath *dp; 419 int err; 420 u32 meter_id; 421 bool failed; 422 423 if (!a[OVS_METER_ATTR_ID]) { 424 return -ENODEV; 425 } 426 427 meter = dp_meter_create(a); 428 if (IS_ERR_OR_NULL(meter)) 429 return PTR_ERR(meter); 430 431 reply = ovs_meter_cmd_reply_start(info, OVS_METER_CMD_SET, 432 &ovs_reply_header); 433 if (IS_ERR(reply)) { 434 err = PTR_ERR(reply); 435 goto exit_free_meter; 436 } 437 438 ovs_lock(); 439 dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); 440 if (!dp) { 441 err = -ENODEV; 442 goto exit_unlock; 443 } 444 445 meter_tbl = &dp->meter_tbl; 446 meter_id = nla_get_u32(a[OVS_METER_ATTR_ID]); 447 448 old_meter = lookup_meter(meter_tbl, meter_id); 449 err = detach_meter(meter_tbl, old_meter); 450 if (err) 451 goto exit_unlock; 452 453 err = attach_meter(meter_tbl, meter); 454 if (err) 455 goto exit_unlock; 456 457 ovs_unlock(); 458 459 /* Build response with the meter_id and stats from 460 * the old meter, if any. 461 */ 462 failed = nla_put_u32(reply, OVS_METER_ATTR_ID, meter_id); 463 WARN_ON(failed); 464 if (old_meter) { 465 spin_lock_bh(&old_meter->lock); 466 if (old_meter->keep_stats) { 467 err = ovs_meter_cmd_reply_stats(reply, meter_id, 468 old_meter); 469 WARN_ON(err); 470 } 471 spin_unlock_bh(&old_meter->lock); 472 ovs_meter_free(old_meter); 473 } 474 475 genlmsg_end(reply, ovs_reply_header); 476 return genlmsg_reply(reply, info); 477 478 exit_unlock: 479 ovs_unlock(); 480 nlmsg_free(reply); 481 exit_free_meter: 482 kfree(meter); 483 return err; 484 } 485 486 static int ovs_meter_cmd_get(struct sk_buff *skb, struct genl_info *info) 487 { 488 struct ovs_header *ovs_header = info->userhdr; 489 struct ovs_header *ovs_reply_header; 490 struct nlattr **a = info->attrs; 491 struct dp_meter *meter; 492 struct sk_buff *reply; 493 struct datapath *dp; 494 u32 meter_id; 495 int err; 496 497 if (!a[OVS_METER_ATTR_ID]) 498 return -EINVAL; 499 500 meter_id = nla_get_u32(a[OVS_METER_ATTR_ID]); 501 502 reply = ovs_meter_cmd_reply_start(info, OVS_METER_CMD_GET, 503 &ovs_reply_header); 504 if (IS_ERR(reply)) 505 return PTR_ERR(reply); 506 507 ovs_lock(); 508 509 dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); 510 if (!dp) { 511 err = -ENODEV; 512 goto exit_unlock; 513 } 514 515 /* Locate meter, copy stats. */ 516 meter = lookup_meter(&dp->meter_tbl, meter_id); 517 if (!meter) { 518 err = -ENOENT; 519 goto exit_unlock; 520 } 521 522 spin_lock_bh(&meter->lock); 523 err = ovs_meter_cmd_reply_stats(reply, meter_id, meter); 524 spin_unlock_bh(&meter->lock); 525 if (err) 526 goto exit_unlock; 527 528 ovs_unlock(); 529 530 genlmsg_end(reply, ovs_reply_header); 531 return genlmsg_reply(reply, info); 532 533 exit_unlock: 534 ovs_unlock(); 535 nlmsg_free(reply); 536 return err; 537 } 538 539 static int ovs_meter_cmd_del(struct sk_buff *skb, struct genl_info *info) 540 { 541 struct ovs_header *ovs_header = info->userhdr; 542 struct ovs_header *ovs_reply_header; 543 struct nlattr **a = info->attrs; 544 struct dp_meter *old_meter; 545 struct sk_buff *reply; 546 struct datapath *dp; 547 u32 meter_id; 548 int err; 549 550 if (!a[OVS_METER_ATTR_ID]) 551 return -EINVAL; 552 553 reply = ovs_meter_cmd_reply_start(info, OVS_METER_CMD_DEL, 554 &ovs_reply_header); 555 if (IS_ERR(reply)) 556 return PTR_ERR(reply); 557 558 ovs_lock(); 559 560 dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); 561 if (!dp) { 562 err = -ENODEV; 563 goto exit_unlock; 564 } 565 566 meter_id = nla_get_u32(a[OVS_METER_ATTR_ID]); 567 old_meter = lookup_meter(&dp->meter_tbl, meter_id); 568 if (old_meter) { 569 spin_lock_bh(&old_meter->lock); 570 err = ovs_meter_cmd_reply_stats(reply, meter_id, old_meter); 571 WARN_ON(err); 572 spin_unlock_bh(&old_meter->lock); 573 574 err = detach_meter(&dp->meter_tbl, old_meter); 575 if (err) 576 goto exit_unlock; 577 } 578 579 ovs_unlock(); 580 ovs_meter_free(old_meter); 581 genlmsg_end(reply, ovs_reply_header); 582 return genlmsg_reply(reply, info); 583 584 exit_unlock: 585 ovs_unlock(); 586 nlmsg_free(reply); 587 return err; 588 } 589 590 /* Meter action execution. 591 * 592 * Return true 'meter_id' drop band is triggered. The 'skb' should be 593 * dropped by the caller'. 594 */ 595 bool ovs_meter_execute(struct datapath *dp, struct sk_buff *skb, 596 struct sw_flow_key *key, u32 meter_id) 597 { 598 long long int now_ms = div_u64(ktime_get_ns(), 1000 * 1000); 599 long long int long_delta_ms; 600 struct dp_meter_band *band; 601 struct dp_meter *meter; 602 int i, band_exceeded_max = -1; 603 u32 band_exceeded_rate = 0; 604 u32 delta_ms; 605 u32 cost; 606 607 meter = lookup_meter(&dp->meter_tbl, meter_id); 608 /* Do not drop the packet when there is no meter. */ 609 if (!meter) 610 return false; 611 612 /* Lock the meter while using it. */ 613 spin_lock(&meter->lock); 614 615 long_delta_ms = (now_ms - meter->used); /* ms */ 616 617 /* Make sure delta_ms will not be too large, so that bucket will not 618 * wrap around below. 619 */ 620 delta_ms = (long_delta_ms > (long long int)meter->max_delta_t) 621 ? meter->max_delta_t : (u32)long_delta_ms; 622 623 /* Update meter statistics. 624 */ 625 meter->used = now_ms; 626 meter->stats.n_packets += 1; 627 meter->stats.n_bytes += skb->len; 628 629 /* Bucket rate is either in kilobits per second, or in packets per 630 * second. We maintain the bucket in the units of either bits or 631 * 1/1000th of a packet, correspondingly. 632 * Then, when rate is multiplied with milliseconds, we get the 633 * bucket units: 634 * msec * kbps = bits, and 635 * msec * packets/sec = 1/1000 packets. 636 * 637 * 'cost' is the number of bucket units in this packet. 638 */ 639 cost = (meter->kbps) ? skb->len * 8 : 1000; 640 641 /* Update all bands and find the one hit with the highest rate. */ 642 for (i = 0; i < meter->n_bands; ++i) { 643 long long int max_bucket_size; 644 645 band = &meter->bands[i]; 646 max_bucket_size = (band->burst_size + band->rate) * 1000LL; 647 648 band->bucket += delta_ms * band->rate; 649 if (band->bucket > max_bucket_size) 650 band->bucket = max_bucket_size; 651 652 if (band->bucket >= cost) { 653 band->bucket -= cost; 654 } else if (band->rate > band_exceeded_rate) { 655 band_exceeded_rate = band->rate; 656 band_exceeded_max = i; 657 } 658 } 659 660 if (band_exceeded_max >= 0) { 661 /* Update band statistics. */ 662 band = &meter->bands[band_exceeded_max]; 663 band->stats.n_packets += 1; 664 band->stats.n_bytes += skb->len; 665 666 /* Drop band triggered, let the caller drop the 'skb'. */ 667 if (band->type == OVS_METER_BAND_TYPE_DROP) { 668 spin_unlock(&meter->lock); 669 return true; 670 } 671 } 672 673 spin_unlock(&meter->lock); 674 return false; 675 } 676 677 static struct genl_ops dp_meter_genl_ops[] = { 678 { .cmd = OVS_METER_CMD_FEATURES, 679 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 680 .flags = 0, /* OK for unprivileged users. */ 681 .doit = ovs_meter_cmd_features 682 }, 683 { .cmd = OVS_METER_CMD_SET, 684 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 685 .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN 686 * privilege. 687 */ 688 .doit = ovs_meter_cmd_set, 689 }, 690 { .cmd = OVS_METER_CMD_GET, 691 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 692 .flags = 0, /* OK for unprivileged users. */ 693 .doit = ovs_meter_cmd_get, 694 }, 695 { .cmd = OVS_METER_CMD_DEL, 696 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 697 .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN 698 * privilege. 699 */ 700 .doit = ovs_meter_cmd_del 701 }, 702 }; 703 704 static const struct genl_multicast_group ovs_meter_multicast_group = { 705 .name = OVS_METER_MCGROUP, 706 }; 707 708 struct genl_family dp_meter_genl_family __ro_after_init = { 709 .hdrsize = sizeof(struct ovs_header), 710 .name = OVS_METER_FAMILY, 711 .version = OVS_METER_VERSION, 712 .maxattr = OVS_METER_ATTR_MAX, 713 .policy = meter_policy, 714 .netnsok = true, 715 .parallel_ops = true, 716 .ops = dp_meter_genl_ops, 717 .n_ops = ARRAY_SIZE(dp_meter_genl_ops), 718 .mcgrps = &ovs_meter_multicast_group, 719 .n_mcgrps = 1, 720 .module = THIS_MODULE, 721 }; 722 723 int ovs_meters_init(struct datapath *dp) 724 { 725 struct dp_meter_table *tbl = &dp->meter_tbl; 726 struct dp_meter_instance *ti; 727 unsigned long free_mem_bytes; 728 729 ti = dp_meter_instance_alloc(DP_METER_ARRAY_SIZE_MIN); 730 if (!ti) 731 return -ENOMEM; 732 733 /* Allow meters in a datapath to use ~3.12% of physical memory. */ 734 free_mem_bytes = nr_free_buffer_pages() * (PAGE_SIZE >> 5); 735 tbl->max_meters_allowed = min(free_mem_bytes / sizeof(struct dp_meter), 736 DP_METER_NUM_MAX); 737 if (!tbl->max_meters_allowed) 738 goto out_err; 739 740 rcu_assign_pointer(tbl->ti, ti); 741 tbl->count = 0; 742 743 return 0; 744 745 out_err: 746 dp_meter_instance_free(ti); 747 return -ENOMEM; 748 } 749 750 void ovs_meters_exit(struct datapath *dp) 751 { 752 struct dp_meter_table *tbl = &dp->meter_tbl; 753 struct dp_meter_instance *ti = rcu_dereference_raw(tbl->ti); 754 int i; 755 756 for (i = 0; i < ti->n_meters; i++) 757 ovs_meter_free(ti->dp_meters[i]); 758 759 dp_meter_instance_free(ti); 760 } 761