diff options
author | Stephen Hemminger <shemminger@osdl.org> | 2006-06-05 20:29:39 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-06-18 00:29:27 -0400 |
commit | a4ed25849532728effaa0665c92e08e029e41407 (patch) | |
tree | 812c1da0f0052715ae07e3beb088344115c27daf /net/ipv4 | |
parent | f890f921040fef6a35e39d15b729af1fd1a35f29 (diff) |
[TCP]: TCP Compound quad root function
The original code did a 64 bit divide directly, which won't work on
32 bit platforms. Rather than doing a 64 bit square root twice,
just implement a 4th root function in one pass using Newton's method.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/tcp_compound.c | 90 |
1 files changed, 66 insertions, 24 deletions
diff --git a/net/ipv4/tcp_compound.c b/net/ipv4/tcp_compound.c index 8c1ebfb7659e..ec68cb8081c1 100644 --- a/net/ipv4/tcp_compound.c +++ b/net/ipv4/tcp_compound.c | |||
@@ -52,8 +52,6 @@ | |||
52 | 52 | ||
53 | #define TCP_COMPOUND_ALPHA 3U | 53 | #define TCP_COMPOUND_ALPHA 3U |
54 | #define TCP_COMPOUND_BETA 1U | 54 | #define TCP_COMPOUND_BETA 1U |
55 | #define TCP_COMPOUND_KAPPA_POW 3 | ||
56 | #define TCP_COMPOUND_KAPPA_NSQRT 2 | ||
57 | #define TCP_COMPOUND_GAMMA 30 | 55 | #define TCP_COMPOUND_GAMMA 30 |
58 | #define TCP_COMPOUND_ZETA 1 | 56 | #define TCP_COMPOUND_ZETA 1 |
59 | 57 | ||
@@ -156,6 +154,58 @@ static void tcp_compound_state(struct sock *sk, u8 ca_state) | |||
156 | vegas_disable(sk); | 154 | vegas_disable(sk); |
157 | } | 155 | } |
158 | 156 | ||
157 | |||
158 | /* 64bit divisor, dividend and result. dynamic precision */ | ||
159 | static inline u64 div64_64(u64 dividend, u64 divisor) | ||
160 | { | ||
161 | u32 d = divisor; | ||
162 | |||
163 | if (divisor > 0xffffffffULL) { | ||
164 | unsigned int shift = fls(divisor >> 32); | ||
165 | |||
166 | d = divisor >> shift; | ||
167 | dividend >>= shift; | ||
168 | } | ||
169 | |||
170 | /* avoid 64 bit division if possible */ | ||
171 | if (dividend >> 32) | ||
172 | do_div(dividend, d); | ||
173 | else | ||
174 | dividend = (u32) dividend / d; | ||
175 | |||
176 | return dividend; | ||
177 | } | ||
178 | |||
179 | /* calculate the quartic root of "a" using Newton-Raphson */ | ||
180 | static u32 qroot(u64 a) | ||
181 | { | ||
182 | u32 x, x1; | ||
183 | |||
184 | /* Initial estimate is based on: | ||
185 | * qrt(x) = exp(log(x) / 4) | ||
186 | */ | ||
187 | x = 1u << (fls64(a) >> 2); | ||
188 | |||
189 | /* | ||
190 | * Iteration based on: | ||
191 | * 3 | ||
192 | * x = ( 3 * x + a / x ) / 4 | ||
193 | * k+1 k k | ||
194 | */ | ||
195 | do { | ||
196 | u64 x3 = x; | ||
197 | |||
198 | x1 = x; | ||
199 | x3 *= x; | ||
200 | x3 *= x; | ||
201 | |||
202 | x = (3 * x + (u32) div64_64(a, x3)) / 4; | ||
203 | } while (abs(x1 - x) > 1); | ||
204 | |||
205 | return x; | ||
206 | } | ||
207 | |||
208 | |||
159 | /* | 209 | /* |
160 | * If the connection is idle and we are restarting, | 210 | * If the connection is idle and we are restarting, |
161 | * then we don't want to do any Vegas calculations | 211 | * then we don't want to do any Vegas calculations |
@@ -304,29 +354,21 @@ static void tcp_compound_cong_avoid(struct sock *sk, u32 ack, | |||
304 | dwnd = vegas->dwnd; | 354 | dwnd = vegas->dwnd; |
305 | 355 | ||
306 | if (diff < (TCP_COMPOUND_GAMMA << V_PARAM_SHIFT)) { | 356 | if (diff < (TCP_COMPOUND_GAMMA << V_PARAM_SHIFT)) { |
307 | u32 i, j, x, x2; | ||
308 | u64 v; | 357 | u64 v; |
309 | 358 | u32 x; | |
310 | v = 1; | 359 | |
311 | 360 | /* | |
312 | for (i = 0; i < TCP_COMPOUND_KAPPA_POW; i++) | 361 | * The TCP Compound paper describes the choice |
313 | v *= old_wnd; | 362 | * of "k" determines the agressiveness, |
314 | 363 | * ie. slope of the response function. | |
315 | for (i = 0; i < TCP_COMPOUND_KAPPA_NSQRT; i++) { | 364 | * |
316 | x = 1; | 365 | * For same value as HSTCP would be 0.8 |
317 | for (j = 0; j < 200; j++) { | 366 | * but for computaional reasons, both the |
318 | x2 = (x + v / x) / 2; | 367 | * original authors and this implementation |
319 | 368 | * use 0.75. | |
320 | if (x2 == x || !x2) | 369 | */ |
321 | break; | 370 | v = old_wnd; |
322 | 371 | x = qroot(v * v * v) >> TCP_COMPOUND_ALPHA; | |
323 | x = x2; | ||
324 | } | ||
325 | v = x; | ||
326 | } | ||
327 | |||
328 | x = (u32) v >> TCP_COMPOUND_ALPHA; | ||
329 | |||
330 | if (x > 1) | 372 | if (x > 1) |
331 | dwnd = x - 1; | 373 | dwnd = x - 1; |
332 | else | 374 | else |