The existing code did a 64 bit divide directly, which won't work on 32 bit platforms. This is what I am testing, it uses math similar to TCP CUBIC to do a quad root. It seemed more efficient to just do one operation rather than two square roots.
--------- diff --git a/net/ipv4/tcp_compound.c b/net/ipv4/tcp_compound.c index 01048e2..74c26a0 100644 --- a/net/ipv4/tcp_compound.c +++ b/net/ipv4/tcp_compound.c @@ -52,8 +52,6 @@ #define TCP_COMPOUND_ALPHA 3U #define TCP_COMPOUND_BETA 1U -#define TCP_COMPOUND_KAPPA_POW 3 -#define TCP_COMPOUND_KAPPA_NSQRT 2 #define TCP_COMPOUND_GAMMA 30 #define TCP_COMPOUND_ZETA 1 @@ -156,6 +154,58 @@ static void tcp_compound_state(struct so vegas_disable(sk); } + +/* 64bit divisor, dividend and result. dynamic precision */ +static inline u64 div64_64(u64 dividend, u64 divisor) +{ + u32 d = divisor; + + if (divisor > 0xffffffffULL) { + unsigned int shift = fls(divisor >> 32); + + d = divisor >> shift; + dividend >>= shift; + } + + /* avoid 64 bit division if possible */ + if (dividend >> 32) + do_div(dividend, d); + else + dividend = (u32) dividend / d; + + return dividend; +} + +/* calculate the quartic root of "a" using Newton-Raphson */ +static u32 qroot(u64 a) +{ + u32 x, x1; + + /* Initial estimate is based on: + * qrt(x) = exp(log(x) / 4) + */ + x = 1u << (fls64(a) >> 2); + + /* + * Iteration based on: + * 3 + * x = ( 3 * x + a / x ) / 4 + * k+1 k k + */ + do { + u64 x3 = x; + + x1 = x; + x3 *= x; + x3 *= x; + + x = (3 * x + (u32) div64_64(a, x3)) / 4; + } while (abs(x1 - x) > 1); + + return x; +} + + /* * If the connection is idle and we are restarting, * then we don't want to do any Vegas calculations @@ -307,29 +357,23 @@ static void tcp_compound_cong_avoid(stru dwnd = vegas->dwnd; if (diff < (TCP_COMPOUND_GAMMA << V_PARAM_SHIFT)) { - u32 i, j, x, x2; - u64 v; - - v = 1; - - for (i = 0; i < TCP_COMPOUND_KAPPA_POW; i++) - v *= old_wnd; - - for (i = 0; i < TCP_COMPOUND_KAPPA_NSQRT; i++) { - x = 1; - for (j = 0; j < 200; j++) { - x2 = (x + v / x) / 2; - - if (x2 == x || !x2) - break; - - x = x2; - } - v = x; - } + u64 win3; - x = (u32) v >> TCP_COMPOUND_ALPHA; + /* + * The TCP Compound paper describes the choice + * of "k" determines the agressiveness, + * ie. slope of the response function. + * + * For same value as HSTCP would be 0.8 + * but for computaional reasons, both the + * original authors and this implementation + * use 0.75. + */ + win3 = old_wnd; + win3 *= old_wnd; + win3 *= old_wnd; + x = qroot(win3) >> TCP_COMPOUND_ALPHA; if (x > 1) dwnd = x - 1; else - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html