We have observed meters working unexpected if traffic is 3+Gbit/s
with multiple connections.
now_ms is not pretected by meter->lock, we may get a negative
long_delta_ms when another cpu updated meter->used, then:
delta_ms = (u32)long_delta_ms;
which will be a large value.
band->bucket += delta_ms * band->rate;
then we get a wrong band->bucket.
OpenVswitch userspace datapath has fixed the same issue[1] some
time ago, and we port the implementation to kernel datapath.
[1] https://patchwork.ozlabs.org/project/openvswitch/patch/20191025114436.9746-1-i.maximets@ovn.org/
Fixes: 96fbc13d7e77 ("openvswitch: Add meter infrastructure")
Signed-off-by: Tao Liu <redacted>
Suggested-by: Ilya Maximets <i.maximets@ovn.org>
---
Changelog:
v2: just set negative long_delta_ms to zero in case of race for meter lock.
v1: make now_ms protected by meter lock.
---
net/openvswitch/meter.c | 8 ++++++++
1 file changed, 8 insertions(+)
@@ -611,6 +611,14 @@ bool ovs_meter_execute(struct datapath *dp, struct sk_buff *skb,spin_lock(&meter->lock);long_delta_ms=(now_ms-meter->used);/* ms */+if(long_delta_ms<0){+/* This condition means that we have several threads fighting+*forameterlock,andtheonewhoreceivedthepacketsa+*bitlaterwins.Assumingthatallracingthreadsreceived+*packetsatthesametimetoavoidoverflow.+*/+long_delta_ms=0;+}/* Make sure delta_ms will not be too large, so that bucket will not*wraparoundbelow.
We have observed meters working unexpected if traffic is 3+Gbit/s
with multiple connections.
now_ms is not pretected by meter->lock, we may get a negative
long_delta_ms when another cpu updated meter->used, then:
delta_ms = (u32)long_delta_ms;
which will be a large value.
band->bucket += delta_ms * band->rate;
then we get a wrong band->bucket.
OpenVswitch userspace datapath has fixed the same issue[1] some
time ago, and we port the implementation to kernel datapath.
[1] https://patchwork.ozlabs.org/project/openvswitch/patch/20191025114436.9746-1-i.maximets@ovn.org/
Fixes: 96fbc13d7e77 ("openvswitch: Add meter infrastructure")
Signed-off-by: Tao Liu <redacted>
Suggested-by: Ilya Maximets <i.maximets@ovn.org>
---
Changelog:
v2: just set negative long_delta_ms to zero in case of race for meter lock.
v1: make now_ms protected by meter lock.
---
Thanks!
I didn't test it, but the change looks good to me.
Reviewed-by: Ilya Maximets <i.maximets@ovn.org>
@@ -611,6 +611,14 @@ bool ovs_meter_execute(struct datapath *dp, struct sk_buff *skb,spin_lock(&meter->lock);long_delta_ms=(now_ms-meter->used);/* ms */+if(long_delta_ms<0){+/* This condition means that we have several threads fighting+*forameterlock,andtheonewhoreceivedthepacketsa+*bitlaterwins.Assumingthatallracingthreadsreceived+*packetsatthesametimetoavoidoverflow.+*/+long_delta_ms=0;+}/* Make sure delta_ms will not be too large, so that bucket will not*wraparoundbelow.
Hello:
This patch was applied to netdev/net.git (refs/heads/master):
On Thu, 13 May 2021 21:08:00 +0800 you wrote:
We have observed meters working unexpected if traffic is 3+Gbit/s
with multiple connections.
now_ms is not pretected by meter->lock, we may get a negative
long_delta_ms when another cpu updated meter->used, then:
delta_ms = (u32)long_delta_ms;
which will be a large value.
[...]