Lines Matching +full:in +full:- +full:band

1 // SPDX-License-Identifier: GPL-2.0-only
53 return &dp->meters[meter_id & (METER_HASH_BUCKETS - 1)]; in meter_hash_bucket()
65 if (meter->id == meter_id) in lookup_meter()
73 struct hlist_head *head = meter_hash_bucket(dp, meter->id); in attach_meter()
75 hlist_add_head_rcu(&meter->dp_hash_node, head); in attach_meter()
82 hlist_del_rcu(&meter->dp_hash_node); in detach_meter()
90 struct ovs_header *ovs_header = info->userhdr; in ovs_meter_cmd_reply_start()
94 return ERR_PTR(-ENOMEM); in ovs_meter_cmd_reply_start()
96 *ovs_reply_header = genlmsg_put(skb, info->snd_portid, in ovs_meter_cmd_reply_start()
97 info->snd_seq, in ovs_meter_cmd_reply_start()
101 return ERR_PTR(-EMSGSIZE); in ovs_meter_cmd_reply_start()
103 (*ovs_reply_header)->dp_ifindex = ovs_header->dp_ifindex; in ovs_meter_cmd_reply_start()
112 struct dp_meter_band *band; in ovs_meter_cmd_reply_stats() local
122 sizeof(struct ovs_flow_stats), &meter->stats) || in ovs_meter_cmd_reply_stats()
123 nla_put_u64_64bit(reply, OVS_METER_ATTR_USED, meter->used, in ovs_meter_cmd_reply_stats()
131 band = meter->bands; in ovs_meter_cmd_reply_stats()
133 for (i = 0; i < meter->n_bands; ++i, ++band) { in ovs_meter_cmd_reply_stats()
139 &band->stats)) in ovs_meter_cmd_reply_stats()
147 return -EMSGSIZE; in ovs_meter_cmd_reply_stats()
173 /* Currently only DROP band type is supported. */ in ovs_meter_cmd_features()
184 err = -EMSGSIZE; in ovs_meter_cmd_features()
194 struct dp_meter_band *band; in dp_meter_create() local
199 return ERR_PTR(-EINVAL); in dp_meter_create()
203 return ERR_PTR(-EINVAL); in dp_meter_create()
208 return ERR_PTR(-ENOMEM); in dp_meter_create()
210 meter->id = nla_get_u32(a[OVS_METER_ATTR_ID]); in dp_meter_create()
211 meter->used = div_u64(ktime_get_ns(), 1000 * 1000); in dp_meter_create()
212 meter->kbps = a[OVS_METER_ATTR_KBPS] ? 1 : 0; in dp_meter_create()
213 meter->keep_stats = !a[OVS_METER_ATTR_CLEAR]; in dp_meter_create()
214 spin_lock_init(&meter->lock); in dp_meter_create()
215 if (meter->keep_stats && a[OVS_METER_ATTR_STATS]) { in dp_meter_create()
216 meter->stats = *(struct ovs_flow_stats *) in dp_meter_create()
219 meter->n_bands = n_bands; in dp_meter_create()
222 band = meter->bands; in dp_meter_create()
236 err = -EINVAL; in dp_meter_create()
240 band->type = nla_get_u32(attr[OVS_BAND_ATTR_TYPE]); in dp_meter_create()
241 band->rate = nla_get_u32(attr[OVS_BAND_ATTR_RATE]); in dp_meter_create()
242 if (band->rate == 0) { in dp_meter_create()
243 err = -EINVAL; in dp_meter_create()
247 band->burst_size = nla_get_u32(attr[OVS_BAND_ATTR_BURST]); in dp_meter_create()
254 band->bucket = (band->burst_size + band->rate) * 1000; in dp_meter_create()
255 band_max_delta_t = band->bucket / band->rate; in dp_meter_create()
256 if (band_max_delta_t > meter->max_delta_t) in dp_meter_create()
257 meter->max_delta_t = band_max_delta_t; in dp_meter_create()
258 band++; in dp_meter_create()
270 struct nlattr **a = info->attrs; in ovs_meter_cmd_set()
274 struct ovs_header *ovs_header = info->userhdr; in ovs_meter_cmd_set()
281 return -ENODEV; in ovs_meter_cmd_set()
296 dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); in ovs_meter_cmd_set()
298 err = -ENODEV; in ovs_meter_cmd_set()
316 spin_lock_bh(&old_meter->lock); in ovs_meter_cmd_set()
317 if (old_meter->keep_stats) { in ovs_meter_cmd_set()
322 spin_unlock_bh(&old_meter->lock); in ovs_meter_cmd_set()
339 struct nlattr **a = info->attrs; in ovs_meter_cmd_get()
341 struct ovs_header *ovs_header = info->userhdr; in ovs_meter_cmd_get()
349 return -EINVAL; in ovs_meter_cmd_get()
360 dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); in ovs_meter_cmd_get()
362 err = -ENODEV; in ovs_meter_cmd_get()
369 err = -ENOENT; in ovs_meter_cmd_get()
373 spin_lock_bh(&meter->lock); in ovs_meter_cmd_get()
375 spin_unlock_bh(&meter->lock); in ovs_meter_cmd_get()
392 struct nlattr **a = info->attrs; in ovs_meter_cmd_del()
394 struct ovs_header *ovs_header = info->userhdr; in ovs_meter_cmd_del()
402 return -EINVAL; in ovs_meter_cmd_del()
412 dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); in ovs_meter_cmd_del()
414 err = -ENODEV; in ovs_meter_cmd_del()
420 spin_lock_bh(&old_meter->lock); in ovs_meter_cmd_del()
423 spin_unlock_bh(&old_meter->lock); in ovs_meter_cmd_del()
439 * Return true 'meter_id' drop band is triggered. The 'skb' should be
446 struct dp_meter_band *band; in ovs_meter_execute() local
451 int i, band_exceeded_max = -1; in ovs_meter_execute()
460 spin_lock(&meter->lock); in ovs_meter_execute()
462 long_delta_ms = (now_ms - meter->used); /* ms */ in ovs_meter_execute()
467 delta_ms = (long_delta_ms > (long long int)meter->max_delta_t) in ovs_meter_execute()
468 ? meter->max_delta_t : (u32)long_delta_ms; in ovs_meter_execute()
472 meter->used = now_ms; in ovs_meter_execute()
473 meter->stats.n_packets += 1; in ovs_meter_execute()
474 meter->stats.n_bytes += skb->len; in ovs_meter_execute()
476 /* Bucket rate is either in kilobits per second, or in packets per in ovs_meter_execute()
477 * second. We maintain the bucket in the units of either bits or in ovs_meter_execute()
484 * 'cost' is the number of bucket units in this packet. in ovs_meter_execute()
486 cost = (meter->kbps) ? skb->len * 8 : 1000; in ovs_meter_execute()
489 for (i = 0; i < meter->n_bands; ++i) { in ovs_meter_execute()
492 band = &meter->bands[i]; in ovs_meter_execute()
493 max_bucket_size = (band->burst_size + band->rate) * 1000LL; in ovs_meter_execute()
495 band->bucket += delta_ms * band->rate; in ovs_meter_execute()
496 if (band->bucket > max_bucket_size) in ovs_meter_execute()
497 band->bucket = max_bucket_size; in ovs_meter_execute()
499 if (band->bucket >= cost) { in ovs_meter_execute()
500 band->bucket -= cost; in ovs_meter_execute()
501 } else if (band->rate > band_exceeded_rate) { in ovs_meter_execute()
502 band_exceeded_rate = band->rate; in ovs_meter_execute()
508 /* Update band statistics. */ in ovs_meter_execute()
509 band = &meter->bands[band_exceeded_max]; in ovs_meter_execute()
510 band->stats.n_packets += 1; in ovs_meter_execute()
511 band->stats.n_bytes += skb->len; in ovs_meter_execute()
513 /* Drop band triggered, let the caller drop the 'skb'. */ in ovs_meter_execute()
514 if (band->type == OVS_METER_BAND_TYPE_DROP) { in ovs_meter_execute()
515 spin_unlock(&meter->lock); in ovs_meter_execute()
520 spin_unlock(&meter->lock); in ovs_meter_execute()
574 dp->meters = kmalloc_array(METER_HASH_BUCKETS, in ovs_meters_init()
577 if (!dp->meters) in ovs_meters_init()
578 return -ENOMEM; in ovs_meters_init()
581 INIT_HLIST_HEAD(&dp->meters[i]); in ovs_meters_init()
591 struct hlist_head *head = &dp->meters[i]; in ovs_meters_exit()
599 kfree(dp->meters); in ovs_meters_exit()