aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2005-12-21 19:32:08 -0800
committerDavid S. Miller <davem@sunset.davemloft.net>2006-01-03 13:11:08 -0800
commit89b3d9aaf46791177c5a5fa07a3ed38a035b5ef5 (patch)
tree161c94fe1060d267de87a6cee04e6dc7838f2816
parent90933fc8ba5cc9034e3c04ee19938a22b0b4fe4e (diff)
[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>
-rw-r--r--net/ipv4/tcp_cubic.c133
1 files changed, 57 insertions, 76 deletions
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
index bb5dc4bfb6b..44fd40891ac 100644
--- a/net/ipv4/tcp_cubic.c
+++ b/net/ipv4/tcp_cubic.c
@@ -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);
}