Index: sys/netinet/cc/cc_cubic.h =================================================================== --- sys/netinet/cc/cc_cubic.h +++ sys/netinet/cc/cc_cubic.h @@ -41,6 +41,8 @@ #ifndef _NETINET_CC_CUBIC_H_ #define _NETINET_CC_CUBIC_H_ +#include + /* Number of bits of precision for fixed point math calcs. */ #define CUBIC_SHIFT 8 @@ -174,6 +176,13 @@ /* t - K, with CUBIC_SHIFT worth of precision. */ cwnd = ((int64_t)(ticks_since_cong << CUBIC_SHIFT) - (K * hz)) / hz; + /* + * (2^21)^3 is long max. Dividing (2^21) by Max IP MSS + * and Cubic_C_factor yields 11060 as the effective useful limit + */ + if (cwnd > 11060) + return INT_MAX; + /* (t - K)^3, with CUBIC_SHIFT^3 worth of precision. */ cwnd *= (cwnd * cwnd); @@ -223,8 +232,10 @@ { /* Equation 4 of I-D. */ - return (((wmax * CUBIC_BETA) + (((THREE_X_PT3 * ticks_since_cong * - smss) << CUBIC_SHIFT) / TWO_SUB_PT3 / rtt_ticks)) >> CUBIC_SHIFT); + return (((wmax * CUBIC_BETA) + + (((THREE_X_PT3 * (unsigned long)ticks_since_cong * + (unsigned long)smss) << CUBIC_SHIFT) / TWO_SUB_PT3 / rtt_ticks)) + >> CUBIC_SHIFT); } #endif /* _NETINET_CC_CUBIC_H_ */ Index: sys/netinet/cc/cc_cubic.c =================================================================== --- sys/netinet/cc/cc_cubic.c +++ sys/netinet/cc/cc_cubic.c @@ -52,6 +52,7 @@ #include #include +#include #include #include #include @@ -78,6 +79,7 @@ static void cubic_post_recovery(struct cc_var *ccv); static void cubic_record_rtt(struct cc_var *ccv); static void cubic_ssthresh_update(struct cc_var *ccv); +static void cubic_after_idle(struct cc_var *ccv); struct cubic { /* Cubic K in fixed point form with CUBIC_SHIFT worth of precision. */ @@ -112,6 +114,7 @@ .conn_init = cubic_conn_init, .mod_init = cubic_mod_init, .post_recovery = cubic_post_recovery, + .after_idle = cubic_after_idle, }; static void @@ -138,7 +141,14 @@ cubic_data->min_rtt_ticks == TCPTV_SRTTBASE) newreno_cc_algo.ack_received(ccv, type); else { - ticks_since_cong = ticks - cubic_data->t_last_cong; + if ((ticks_since_cong = + ticks - cubic_data->t_last_cong) < 0) { + /* + * dragging t_last_cong along + */ + ticks_since_cong = INT_MAX; + cubic_data->t_last_cong = ticks - INT_MAX; + } /* * The mean RTT is used to best reflect the equations in @@ -157,12 +167,14 @@ ccv->flags &= ~CCF_ABC_SENTAWND; - if (w_cubic_next < w_tf) + if (w_cubic_next < w_tf) { /* * TCP-friendly region, follow tf * cwnd growth. */ - CCV(ccv, snd_cwnd) = w_tf; + if (CCV(ccv, snd_cwnd) < w_tf) + CCV(ccv, snd_cwnd) = ulmin(w_tf, INT_MAX); + } else if (CCV(ccv, snd_cwnd) < w_cubic_next) { /* @@ -170,12 +182,14 @@ * cwnd growth. */ if (V_tcp_do_rfc3465) - CCV(ccv, snd_cwnd) = w_cubic_next; + CCV(ccv, snd_cwnd) = ulmin(w_cubic_next, + INT_MAX); else - CCV(ccv, snd_cwnd) += ((w_cubic_next - + CCV(ccv, snd_cwnd) += ulmax(1, + ((ulmin(w_cubic_next, INT_MAX) - CCV(ccv, snd_cwnd)) * CCV(ccv, t_maxseg)) / - CCV(ccv, snd_cwnd); + CCV(ccv, snd_cwnd)); } /* @@ -192,6 +206,23 @@ } } +/* + * This is a Cubic specific implementation of after_idle. + * - Reset cwnd by calling New Reno implementation of after_idle. + * - Reset t_last_cong. + */ +static void +cubic_after_idle(struct cc_var *ccv) +{ + struct cubic *cubic_data; + + cubic_data = ccv->cc_data; + + newreno_cc_algo.after_idle(ccv); + cubic_data->t_last_cong = ticks; +} + + static void cubic_cb_destroy(struct cc_var *ccv) { @@ -287,9 +318,6 @@ static int cubic_mod_init(void) { - - cubic_cc_algo.after_idle = newreno_cc_algo.after_idle; - return (0); }