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