diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/dccp/ccids/ccid3.h | 19 | ||||
-rw-r--r-- | net/dccp/ccids/lib/tfrc.h | 23 | ||||
-rw-r--r-- | net/dccp/ccids/lib/tfrc_equation.c | 28 |
3 files changed, 35 insertions, 35 deletions
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index cd4fc542f73e..da0ca3c0a7b3 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h | |||
@@ -171,23 +171,4 @@ static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk) | |||
171 | return ccid_priv(dccp_sk(sk)->dccps_hc_rx_ccid); | 171 | return ccid_priv(dccp_sk(sk)->dccps_hc_rx_ccid); |
172 | } | 172 | } |
173 | 173 | ||
174 | static inline u64 scaled_div(u64 a, u32 b) | ||
175 | { | ||
176 | BUG_ON(b==0); | ||
177 | a *= 1000000; | ||
178 | do_div(a, b); | ||
179 | return a; | ||
180 | } | ||
181 | |||
182 | static inline u32 scaled_div32(u64 a, u32 b) | ||
183 | { | ||
184 | u64 result = scaled_div(a, b); | ||
185 | |||
186 | if (result > UINT_MAX) { | ||
187 | DCCP_CRIT("Overflow: a(%llu)/b(%u) > ~0U", | ||
188 | (unsigned long long)a, b); | ||
189 | return UINT_MAX; | ||
190 | } | ||
191 | return result; | ||
192 | } | ||
193 | #endif /* _DCCP_CCID3_H_ */ | 174 | #endif /* _DCCP_CCID3_H_ */ |
diff --git a/net/dccp/ccids/lib/tfrc.h b/net/dccp/ccids/lib/tfrc.h index 45f30f59ea2a..faf5f7e219e3 100644 --- a/net/dccp/ccids/lib/tfrc.h +++ b/net/dccp/ccids/lib/tfrc.h | |||
@@ -13,8 +13,29 @@ | |||
13 | * the Free Software Foundation; either version 2 of the License, or | 13 | * the Free Software Foundation; either version 2 of the License, or |
14 | * (at your option) any later version. | 14 | * (at your option) any later version. |
15 | */ | 15 | */ |
16 | |||
17 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | #include <asm/div64.h> | ||
18 | |||
19 | /* integer-arithmetic divisions of type (a * 1000000)/b */ | ||
20 | static inline u64 scaled_div(u64 a, u32 b) | ||
21 | { | ||
22 | BUG_ON(b==0); | ||
23 | a *= 1000000; | ||
24 | do_div(a, b); | ||
25 | return a; | ||
26 | } | ||
27 | |||
28 | static inline u32 scaled_div32(u64 a, u32 b) | ||
29 | { | ||
30 | u64 result = scaled_div(a, b); | ||
31 | |||
32 | if (result > UINT_MAX) { | ||
33 | DCCP_CRIT("Overflow: a(%llu)/b(%u) > ~0U", | ||
34 | (unsigned long long)a, b); | ||
35 | return UINT_MAX; | ||
36 | } | ||
37 | return result; | ||
38 | } | ||
18 | 39 | ||
19 | extern u32 tfrc_calc_x(u16 s, u32 R, u32 p); | 40 | extern u32 tfrc_calc_x(u16 s, u32 R, u32 p); |
20 | extern u32 tfrc_calc_x_reverse_lookup(u32 fvalue); | 41 | extern u32 tfrc_calc_x_reverse_lookup(u32 fvalue); |
diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c index ddac2c511e2f..90009fd77e15 100644 --- a/net/dccp/ccids/lib/tfrc_equation.c +++ b/net/dccp/ccids/lib/tfrc_equation.c | |||
@@ -13,7 +13,6 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <asm/div64.h> | ||
17 | #include "../../dccp.h" | 16 | #include "../../dccp.h" |
18 | #include "tfrc.h" | 17 | #include "tfrc.h" |
19 | 18 | ||
@@ -616,15 +615,12 @@ static inline u32 tfrc_binsearch(u32 fval, u8 small) | |||
616 | * @R: RTT scaled by 1000000 (i.e., microseconds) | 615 | * @R: RTT scaled by 1000000 (i.e., microseconds) |
617 | * @p: loss ratio estimate scaled by 1000000 | 616 | * @p: loss ratio estimate scaled by 1000000 |
618 | * Returns X_calc in bytes per second (not scaled). | 617 | * Returns X_calc in bytes per second (not scaled). |
619 | * | ||
620 | * Note: DO NOT alter this code unless you run test cases against it, | ||
621 | * as the code has been optimized to stop underflow/overflow. | ||
622 | */ | 618 | */ |
623 | u32 tfrc_calc_x(u16 s, u32 R, u32 p) | 619 | u32 tfrc_calc_x(u16 s, u32 R, u32 p) |
624 | { | 620 | { |
625 | int index; | 621 | u16 index; |
626 | u32 f; | 622 | u32 f; |
627 | u64 tmp1, tmp2; | 623 | u64 result; |
628 | 624 | ||
629 | /* check against invalid parameters and divide-by-zero */ | 625 | /* check against invalid parameters and divide-by-zero */ |
630 | BUG_ON(p > 1000000); /* p must not exceed 100% */ | 626 | BUG_ON(p > 1000000); /* p must not exceed 100% */ |
@@ -650,15 +646,17 @@ u32 tfrc_calc_x(u16 s, u32 R, u32 p) | |||
650 | f = tfrc_calc_x_lookup[index][0]; | 646 | f = tfrc_calc_x_lookup[index][0]; |
651 | } | 647 | } |
652 | 648 | ||
653 | /* The following computes X = s/(R*f(p)) in bytes per second. Since f(p) | 649 | /* |
654 | * and R are both scaled by 1000000, we need to multiply by 1000000^2. | 650 | * Compute X = s/(R*f(p)) in bytes per second. |
655 | * ==> DO NOT alter this unless you test against overflow on 32 bit */ | 651 | * Since f(p) and R are both scaled by 1000000, we need to multiply by |
656 | tmp1 = ((u64)s * 100000000); | 652 | * 1000000^2. To avoid overflow, the result is computed in two stages. |
657 | tmp2 = ((u64)R * (u64)f); | 653 | * This works under almost all reasonable operational conditions, for a |
658 | do_div(tmp2, 10000); | 654 | * wide range of parameters. Yet, should some strange combination of |
659 | do_div(tmp1, tmp2); | 655 | * parameters result in overflow, the use of scaled_div32 will catch |
660 | 656 | * this and return UINT_MAX - which is a logically adequate consequence. | |
661 | return (u32)tmp1; | 657 | */ |
658 | result = scaled_div(s, R); | ||
659 | return scaled_div32(result, f); | ||
662 | } | 660 | } |
663 | 661 | ||
664 | EXPORT_SYMBOL_GPL(tfrc_calc_x); | 662 | EXPORT_SYMBOL_GPL(tfrc_calc_x); |