We can precompute a number of the cubic TCP factors because
SRTT is a constant and most of the other parts come from module
parameters.

Given the history of simple math errors, this patch deserves extra
special attention.

Signed-off-by: Stephen Hemminger <[EMAIL PROTECTED]>


--- net-2.6.16.orig/net/ipv4/tcp_cubic.c
+++ net-2.6.16/net/ipv4/tcp_cubic.c
@@ -27,22 +27,28 @@
                                          */
 #define        BICTCP_HZ               10      /* BIC HZ 2^10 = 1024 */
 
+#define BICTCP_SRTT            ((HZ << 3)/10) /* BIC is now RTT independent */
+
 static int fast_convergence = 1;
 static int max_increment = 16;
 static int beta = 819;         /* = 819/1024 (BICTCP_BETA_SCALE) */
 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 u32 cube_scale;
+static u64 cube_factor;
 
 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,56 +157,10 @@ static u32 cubic_root(u64 x)
                 return (u32)end;
 }
 
-static inline u32 bictcp_K(u32 dist, u32 srtt)
+static inline u32 bictcp_K(u32 dist)
 {
-        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;
+       return cubic_root((cube_factor * dist) >> (cube_scale + 3 - BICTCP_HZ));
 }
 
 /*
@@ -209,7 +169,7 @@ static inline u32 bictcp_K(u32 dist, u32
 static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
 {
        u64 d64;
-       u32 d32, t, srtt, bic_target, min_cnt, max_cnt;
+       u32 d32, t, bic_target, min_cnt, max_cnt;
 
        ca->ack_cnt++;  /* count the number of ACKs */
 
@@ -220,7 +180,6 @@ static inline void bictcp_update(struct 
        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 */
@@ -231,7 +190,7 @@ static inline void bictcp_update(struct 
                        ca->bic_K = 0;
                        ca->bic_origin_point = cwnd;
                } else {
-                       ca->bic_K = bictcp_K(ca->last_max_cwnd-cwnd, srtt);
+                       ca->bic_K = bictcp_K(ca->last_max_cwnd-cwnd);
                        ca->bic_origin_point = ca->last_max_cwnd;
                }
        }
@@ -260,8 +219,7 @@ static inline void bictcp_update(struct 
                 d32 = 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 */
+        d64 = (cube_rtt_scale * d64 * d64 * d64) >> (10+3*BICTCP_HZ);  /* 
c/rtt * (t-K)^3 */
         d32 = (u32)d64;
         if (t < ca->bic_K)                                     /* below 
origin*/
                 bic_target = ca->bic_origin_point - d32;
@@ -288,8 +246,7 @@ static inline void bictcp_update(struct 
 
        /* TCP Friendly */
        if (tcp_friendliness) {
-               u32 scale = 
8*(BICTCP_BETA_SCALE+beta)/3/(BICTCP_BETA_SCALE-beta);
-               d32 = (cwnd * scale) >> 3;
+               d32 = (cwnd * beta_scale) >> 3;
                while (ca->ack_cnt > d32) {             /* update tcp cwnd */
                        ca->ack_cnt -= d32;
                        ca->tcp_cwnd++;
@@ -427,7 +384,51 @@ static struct tcp_congestion_ops cubictc
 
 static int __init cubictcp_register(void)
 {
+       u64 d64;
+       u32 d32;
+
        BUG_ON(sizeof(struct bictcp) > ICSK_CA_PRIV_SIZE);
+
+       /* Precompute a bunch of the scaling factors that are used per-packet */
+       beta_scale = 8*(BICTCP_BETA_SCALE+beta)/3/(BICTCP_BETA_SCALE-beta);
+
+       cube_rtt_scale = (bic_scale << 3) * HZ / BICTCP_SRTT;   /* 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 = (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 */
+       d64 = d32 = (1 << (10+2*BICTCP_HZ)) / bic_scale;
+
+       /* 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 = BICTCP_SRTT;
+       cube_scale = 0;
+
+       while ( !(d32 & 0x80000000) && (cube_scale < BICTCP_HZ)){
+               d32 = d32 << 1;
+               ++cube_scale;
+       }
+       cube_factor = d64 * d32 / HZ;
+
        return tcp_register_congestion_control(&cubictcp);
 }
 
-
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

Reply via email to