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/tcp_compound.c | |
| 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/tcp_compound.c')
| -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 | 
