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 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 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 (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; 272 error: 273 return -EMSGSIZE; 274 } 275 276 static 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 322 exit_unlock: 323 ovs_unlock(); 324 nla_put_failure: 325 nlmsg_free(reply); 326 return err; 327 } 328 329 static 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 404 exit_free_meter: 405 kfree(meter); 406 return ERR_PTR(err); 407 } 408 409 static 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 476 exit_unlock: 477 ovs_unlock(); 478 nlmsg_free(reply); 479 exit_free_meter: 480 kfree(meter); 481 return err; 482 } 483 484 static 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 531 exit_unlock: 532 ovs_unlock(); 533 nlmsg_free(reply); 534 return err; 535 } 536 537 static 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 582 exit_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 */ 593 bool 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 683 static 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 710 static const struct genl_multicast_group ovs_meter_multicast_group = { 711 .name = OVS_METER_MCGROUP, 712 }; 713 714 struct 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 729 int 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 751 out_err: 752 dp_meter_instance_free(ti); 753 return -ENOMEM; 754 } 755 756 void 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