diff options
author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2008-06-11 06:19:10 -0400 |
---|---|---|
committer | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2008-06-11 06:19:10 -0400 |
commit | 7deb0f851003287d7e259bf6b33548b144c0f2d5 (patch) | |
tree | 8ede694c4b6cd41224f7165d09d3f5935d889fd1 /net | |
parent | 1e8a287c79f64226541f5c44aa52d4698bb84cf5 (diff) |
dccp ccid-3: X truncated due to type conversion
This fixes a bug in computing the inter-packet-interval t_ipi = s/X:
scaled_div32(a, b) uses u32 for b, but in "scaled_div32(s, X)" the type of the
sending rate `X' is u64. Since X is scaled by 2^6, this truncates rates greater
than 2^26 Bps (~537 Mbps).
Using full 64-bit division now.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Diffstat (limited to 'net')
-rw-r--r-- | net/dccp/ccids/lib/tfrc.h | 14 |
1 files changed, 6 insertions, 8 deletions
diff --git a/net/dccp/ccids/lib/tfrc.h b/net/dccp/ccids/lib/tfrc.h index ddd8107b927f..ed9857527acf 100644 --- a/net/dccp/ccids/lib/tfrc.h +++ b/net/dccp/ccids/lib/tfrc.h | |||
@@ -15,7 +15,7 @@ | |||
15 | * (at your option) any later version. | 15 | * (at your option) any later version. |
16 | */ | 16 | */ |
17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
18 | #include <asm/div64.h> | 18 | #include <linux/math64.h> |
19 | #include "../../dccp.h" | 19 | #include "../../dccp.h" |
20 | /* internal includes that this module exports: */ | 20 | /* internal includes that this module exports: */ |
21 | #include "loss_interval.h" | 21 | #include "loss_interval.h" |
@@ -29,21 +29,19 @@ extern int tfrc_debug; | |||
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | /* integer-arithmetic divisions of type (a * 1000000)/b */ | 31 | /* integer-arithmetic divisions of type (a * 1000000)/b */ |
32 | static inline u64 scaled_div(u64 a, u32 b) | 32 | static inline u64 scaled_div(u64 a, u64 b) |
33 | { | 33 | { |
34 | BUG_ON(b==0); | 34 | BUG_ON(b==0); |
35 | a *= 1000000; | 35 | return div64_u64(a * 1000000, b); |
36 | do_div(a, b); | ||
37 | return a; | ||
38 | } | 36 | } |
39 | 37 | ||
40 | static inline u32 scaled_div32(u64 a, u32 b) | 38 | static inline u32 scaled_div32(u64 a, u64 b) |
41 | { | 39 | { |
42 | u64 result = scaled_div(a, b); | 40 | u64 result = scaled_div(a, b); |
43 | 41 | ||
44 | if (result > UINT_MAX) { | 42 | if (result > UINT_MAX) { |
45 | DCCP_CRIT("Overflow: a(%llu)/b(%u) > ~0U", | 43 | DCCP_CRIT("Overflow: %llu/%llu > UINT_MAX", |
46 | (unsigned long long)a, b); | 44 | (unsigned long long)a, (unsigned long long)b); |
47 | return UINT_MAX; | 45 | return UINT_MAX; |
48 | } | 46 | } |
49 | return result; | 47 | return result; |