[TCP] cubic: precompute constants

Revised version of patch to pre-compute values for TCP cubic.
  * d32,d64 replaced with descriptive names
  * cube_factor replaces
	 srtt[scaled by count] / HZ * ((1 << (10+2*BICTCP_HZ)) / bic_scale)
  * beta_scale replaces
	8*(BICTCP_BETA_SCALE+beta)/3/(BICTCP_BETA_SCALE-beta);

Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Stephen Hemminger 2005-12-21 19:32:08 -08:00 committed by David S. Miller
parent 90933fc8ba
commit 89b3d9aaf4

View file

@ -16,7 +16,7 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <net/tcp.h>
#include <asm/div64.h>
#define BICTCP_BETA_SCALE 1024 /* Scale factor beta calculation
* max_cwnd = snd_cwnd * beta
@ -34,15 +34,20 @@ static int initial_ssthresh = 100;
static int bic_scale = 41;
static int tcp_friendliness = 1;
static u32 cube_rtt_scale;
static u32 beta_scale;
static u64 cube_factor;
/* Note parameters that are used for precomputing scale factors are read-only */
module_param(fast_convergence, int, 0644);
MODULE_PARM_DESC(fast_convergence, "turn on/off fast convergence");
module_param(max_increment, int, 0644);
MODULE_PARM_DESC(max_increment, "Limit on increment allowed during binary search");
module_param(beta, int, 0644);
module_param(beta, int, 0444);
MODULE_PARM_DESC(beta, "beta for multiplicative increase");
module_param(initial_ssthresh, int, 0644);
MODULE_PARM_DESC(initial_ssthresh, "initial value of slow start threshold");
module_param(bic_scale, int, 0644);
module_param(bic_scale, int, 0444);
MODULE_PARM_DESC(bic_scale, "scale (scaled by 1024) value for bic function (bic_scale/1024)");
module_param(tcp_friendliness, int, 0644);
MODULE_PARM_DESC(tcp_friendliness, "turn on/off tcp friendliness");
@ -151,65 +156,13 @@ static u32 cubic_root(u64 x)
return (u32)end;
}
static inline u32 bictcp_K(u32 dist, u32 srtt)
{
u64 d64;
u32 d32;
u32 count;
u32 result;
/* calculate the "K" for (wmax-cwnd) = c/rtt * K^3
so K = cubic_root( (wmax-cwnd)*rtt/c )
the unit of K is bictcp_HZ=2^10, not HZ
c = bic_scale >> 10
rtt = (tp->srtt >> 3 ) / HZ
the following code has been designed and tested for
cwnd < 1 million packets
RTT < 100 seconds
HZ < 1,000,00 (corresponding to 10 nano-second)
*/
/* 1/c * 2^2*bictcp_HZ */
d32 = (1 << (10+2*BICTCP_HZ)) / bic_scale;
d64 = (__u64)d32;
/* srtt * 2^count / HZ
1) to get a better accuracy of the following d32,
the larger the "count", the better the accuracy
2) and avoid overflow of the following d64
the larger the "count", the high possibility of overflow
3) so find a "count" between bictcp_hz-3 and bictcp_hz
"count" may be less than bictcp_HZ,
then d64 becomes 0. that is OK
*/
d32 = srtt;
count = 0;
while (((d32 & 0x80000000)==0) && (count < BICTCP_HZ)){
d32 = d32 << 1;
count++;
}
d32 = d32 / HZ;
/* (wmax-cwnd) * (srtt>>3 / HZ) / c * 2^(3*bictcp_HZ) */
d64 = (d64 * dist * d32) >> (count+3-BICTCP_HZ);
/* cubic root */
d64 = cubic_root(d64);
result = (u32)d64;
return result;
}
/*
* Compute congestion window to use.
*/
static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
{
u64 d64;
u32 d32, t, srtt, bic_target, min_cnt, max_cnt;
u64 offs;
u32 delta, t, bic_target, min_cnt, max_cnt;
ca->ack_cnt++; /* count the number of ACKs */
@ -220,8 +173,6 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
ca->last_cwnd = cwnd;
ca->last_time = tcp_time_stamp;
srtt = (HZ << 3)/10; /* use real time-based growth function */
if (ca->epoch_start == 0) {
ca->epoch_start = tcp_time_stamp; /* record the beginning of an epoch */
ca->ack_cnt = 1; /* start counting */
@ -231,7 +182,11 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
ca->bic_K = 0;
ca->bic_origin_point = cwnd;
} else {
ca->bic_K = bictcp_K(ca->last_max_cwnd-cwnd, srtt);
/* Compute new K based on
* (wmax-cwnd) * (srtt>>3 / HZ) / c * 2^(3*bictcp_HZ)
*/
ca->bic_K = cubic_root(cube_factor
* (ca->last_max_cwnd - cwnd));
ca->bic_origin_point = ca->last_max_cwnd;
}
}
@ -239,9 +194,9 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
/* cubic function - calc*/
/* calculate c * time^3 / rtt,
* while considering overflow in calculation of time^3
* (so time^3 is done by using d64)
* (so time^3 is done by using 64 bit)
* and without the support of division of 64bit numbers
* (so all divisions are done by using d32)
* (so all divisions are done by using 32 bit)
* also NOTE the unit of those veriables
* time = (t - K) / 2^bictcp_HZ
* c = bic_scale >> 10
@ -255,18 +210,16 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
<< BICTCP_HZ) / HZ;
if (t < ca->bic_K) /* t - K */
d32 = ca->bic_K - t;
offs = ca->bic_K - t;
else
d32 = t - ca->bic_K;
offs = t - ca->bic_K;
d64 = (u64)d32;
d32 = (bic_scale << 3) * HZ / srtt; /* 1024*c/rtt */
d64 = (d32 * d64 * d64 * d64) >> (10+3*BICTCP_HZ); /* c/rtt * (t-K)^3 */
d32 = (u32)d64;
/* c/rtt * (t-K)^3 */
delta = (cube_rtt_scale * offs * offs * offs) >> (10+3*BICTCP_HZ);
if (t < ca->bic_K) /* below origin*/
bic_target = ca->bic_origin_point - d32;
bic_target = ca->bic_origin_point - delta;
else /* above origin*/
bic_target = ca->bic_origin_point + d32;
bic_target = ca->bic_origin_point + delta;
/* cubic function - calc bictcp_cnt*/
if (bic_target > cwnd) {
@ -288,16 +241,16 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
/* TCP Friendly */
if (tcp_friendliness) {
u32 scale = 8*(BICTCP_BETA_SCALE+beta)/3/(BICTCP_BETA_SCALE-beta);
d32 = (cwnd * scale) >> 3;
while (ca->ack_cnt > d32) { /* update tcp cwnd */
ca->ack_cnt -= d32;
u32 scale = beta_scale;
delta = (cwnd * scale) >> 3;
while (ca->ack_cnt > delta) { /* update tcp cwnd */
ca->ack_cnt -= delta;
ca->tcp_cwnd++;
}
if (ca->tcp_cwnd > cwnd){ /* if bic is slower than tcp */
d32 = ca->tcp_cwnd - cwnd;
max_cnt = cwnd / d32;
delta = ca->tcp_cwnd - cwnd;
max_cnt = cwnd / delta;
if (ca->cnt > max_cnt)
ca->cnt = max_cnt;
}
@ -428,6 +381,34 @@ static struct tcp_congestion_ops cubictcp = {
static int __init cubictcp_register(void)
{
BUG_ON(sizeof(struct bictcp) > ICSK_CA_PRIV_SIZE);
/* Precompute a bunch of the scaling factors that are used per-packet
* based on SRTT of 100ms
*/
beta_scale = 8*(BICTCP_BETA_SCALE+beta)/ 3 / (BICTCP_BETA_SCALE - beta);
cube_rtt_scale = (bic_scale << 3) / 10; /* 1024*c/rtt */
/* calculate the "K" for (wmax-cwnd) = c/rtt * K^3
* so K = cubic_root( (wmax-cwnd)*rtt/c )
* the unit of K is bictcp_HZ=2^10, not HZ
*
* c = bic_scale >> 10
* rtt = 100ms
*
* the following code has been designed and tested for
* cwnd < 1 million packets
* RTT < 100 seconds
* HZ < 1,000,00 (corresponding to 10 nano-second)
*/
/* 1/c * 2^2*bictcp_HZ * srtt */
cube_factor = 1ull << (10+3*BICTCP_HZ); /* 2^40 */
/* divide by bic_scale and by constant Srtt (100ms) */
do_div(cube_factor, bic_scale * 10);
return tcp_register_congestion_control(&cubictcp);
}