Module Name: src Committed By: kefren Date: Tue Nov 12 09:02:05 UTC 2013
Modified Files: src/sys/netinet: tcp_congctl.c tcp_congctl.h tcp_input.c tcp_sack.c tcp_subr.c tcp_var.h Log Message: * implement TCP CUBIC congestion control algorithm * move tcp_sack_newack bits inside reno and newreno_fast_retransmit_newack * notify ECN peer about cwnd shrink in [new]reno_slow_retransmit Based on the patch proposed on tech-net@ on Nov 7 with minor improvments: * adapt wmax for no-fast convergence case * correct cbrt calculation for big window sizes (>750KB) To generate a diff of this commit: cvs rdiff -u -r1.17 -r1.18 src/sys/netinet/tcp_congctl.c cvs rdiff -u -r1.6 -r1.7 src/sys/netinet/tcp_congctl.h cvs rdiff -u -r1.329 -r1.330 src/sys/netinet/tcp_input.c cvs rdiff -u -r1.28 -r1.29 src/sys/netinet/tcp_sack.c cvs rdiff -u -r1.250 -r1.251 src/sys/netinet/tcp_subr.c cvs rdiff -u -r1.170 -r1.171 src/sys/netinet/tcp_var.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/netinet/tcp_congctl.c diff -u src/sys/netinet/tcp_congctl.c:1.17 src/sys/netinet/tcp_congctl.c:1.18 --- src/sys/netinet/tcp_congctl.c:1.17 Fri Oct 25 16:29:20 2013 +++ src/sys/netinet/tcp_congctl.c Tue Nov 12 09:02:05 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: tcp_congctl.c,v 1.17 2013/10/25 16:29:20 martin Exp $ */ +/* $NetBSD: tcp_congctl.c,v 1.18 2013/11/12 09:02:05 kefren Exp $ */ /*- * Copyright (c) 1997, 1998, 1999, 2001, 2005, 2006 The NetBSD Foundation, Inc. @@ -135,7 +135,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tcp_congctl.c,v 1.17 2013/10/25 16:29:20 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tcp_congctl.c,v 1.18 2013/11/12 09:02:05 kefren Exp $"); #include "opt_inet.h" #include "opt_tcp_debug.h" @@ -194,6 +194,9 @@ __KERNEL_RCSID(0, "$NetBSD: tcp_congctl. * consider separating the actual implementations in another file. */ +static void tcp_common_congestion_exp(struct tcpcb *, int, int); + +static int tcp_reno_do_fast_retransmit(struct tcpcb *, const struct tcphdr *); static int tcp_reno_fast_retransmit(struct tcpcb *, const struct tcphdr *); static void tcp_reno_slow_retransmit(struct tcpcb *); static void tcp_reno_fast_retransmit_newack(struct tcpcb *, @@ -206,6 +209,10 @@ static void tcp_newreno_fast_retransmit_ const struct tcphdr *); static void tcp_newreno_newack(struct tcpcb *, const struct tcphdr *); +static int tcp_cubic_fast_retransmit(struct tcpcb *, const struct tcphdr *); +static void tcp_cubic_slow_retransmit(struct tcpcb *tp); +static void tcp_cubic_newack(struct tcpcb *, const struct tcphdr *); +static void tcp_cubic_congestion_exp(struct tcpcb *); static void tcp_congctl_fillnames(void); @@ -241,6 +248,8 @@ tcp_congctl_init(void) KASSERT(r == 0); r = tcp_congctl_register("newreno", &tcp_newreno_ctl); KASSERT(r == 0); + r = tcp_congctl_register("cubic", &tcp_cubic_ctl); + KASSERT(r == 0); /* NewReno is the default. */ #ifndef TCP_CONGCTL_DEFAULT @@ -406,18 +415,28 @@ tcp_congctl_fillnames(void) /* ------------------------------------------------------------------------ */ /* - * TCP/Reno congestion control. + * Common stuff */ + +/* Window reduction (1-beta) for [New]Reno: 0.5 */ +#define RENO_BETAA 1 +#define RENO_BETAB 2 +/* Window reduction (1-beta) for Cubic: 0.8 */ +#define CUBIC_BETAA 4 +#define CUBIC_BETAB 5 +/* Draft Rhee Section 4.1 */ +#define CUBIC_CA 4 +#define CUBIC_CB 10 + static void -tcp_reno_congestion_exp(struct tcpcb *tp) +tcp_common_congestion_exp(struct tcpcb *tp, int betaa, int betab) { u_int win; /* - * Halve the congestion window and reduce the - * slow start threshold. + * Reduce the congestion window and the slow start threshold. */ - win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_segsz; + win = min(tp->snd_wnd, tp->snd_cwnd) * betaa / betab / tp->t_segsz; if (win < 2) win = 2; @@ -434,9 +453,20 @@ tcp_reno_congestion_exp(struct tcpcb *tp } +/* ------------------------------------------------------------------------ */ + +/* + * TCP/Reno congestion control. + */ +static void +tcp_reno_congestion_exp(struct tcpcb *tp) +{ + + tcp_common_congestion_exp(tp, RENO_BETAA, RENO_BETAB); +} static int -tcp_reno_fast_retransmit(struct tcpcb *tp, const struct tcphdr *th) +tcp_reno_do_fast_retransmit(struct tcpcb *tp, const struct tcphdr *th) { /* * We know we're losing at the current @@ -458,10 +488,8 @@ tcp_reno_fast_retransmit(struct tcpcb *t * irrespective of the number of DupAcks. */ - tcp_seq onxt; - - onxt = tp->snd_nxt; - tcp_reno_congestion_exp(tp); + tcp_seq onxt = tp->snd_nxt; + tp->t_partialacks = 0; TCP_TIMER_DISARM(tp, TCPT_REXMT); tp->t_rtttime = 0; @@ -482,6 +510,14 @@ tcp_reno_fast_retransmit(struct tcpcb *t return 0; } +static int +tcp_reno_fast_retransmit(struct tcpcb *tp, const struct tcphdr *th) +{ + + tcp_reno_congestion_exp(tp); + return tcp_reno_do_fast_retransmit(tp, th); +} + static void tcp_reno_slow_retransmit(struct tcpcb *tp) { @@ -521,6 +557,9 @@ tcp_reno_slow_retransmit(struct tcpcb *t tp->t_partialacks = -1; tp->t_dupacks = 0; tp->t_bytes_acked = 0; + + if (TCP_ECN_ALLOWED(tp)) + tp->t_flags |= TF_ECN_SND_CWR; } static void @@ -543,6 +582,8 @@ tcp_reno_fast_retransmit_newack(struct t tp->t_partialacks = -1; tp->t_dupacks = 0; tp->t_bytes_acked = 0; + if (TCP_SACK_ENABLED(tp) && SEQ_GT(th->th_ack, tp->snd_fack)) + tp->snd_fack = th->th_ack; } } @@ -653,6 +694,7 @@ tcp_newreno_fast_retransmit_newack(struc */ tcp_seq onxt = tp->snd_nxt; u_long ocwnd = tp->snd_cwnd; + int sack_num_segs = 1, sack_bytes_rxmt = 0; /* * snd_una has not yet been updated and the socket's send @@ -660,24 +702,52 @@ tcp_newreno_fast_retransmit_newack(struc * have to leave snd_una as it was to get the correct data * offset in tcp_output(). */ - if (++tp->t_partialacks == 1) - TCP_TIMER_DISARM(tp, TCPT_REXMT); + tp->t_partialacks++; + TCP_TIMER_DISARM(tp, TCPT_REXMT); tp->t_rtttime = 0; tp->snd_nxt = th->th_ack; - /* - * Set snd_cwnd to one segment beyond ACK'd offset. snd_una - * is not yet updated when we're called. - */ - tp->snd_cwnd = tp->t_segsz + (th->th_ack - tp->snd_una); - (void) tcp_output(tp); - tp->snd_cwnd = ocwnd; - if (SEQ_GT(onxt, tp->snd_nxt)) - tp->snd_nxt = onxt; - /* - * Partial window deflation. Relies on fact that tp->snd_una - * not updated yet. - */ - tp->snd_cwnd -= (th->th_ack - tp->snd_una - tp->t_segsz); + + if (TCP_SACK_ENABLED(tp)) { + /* + * Partial ack handling within a sack recovery episode. + * Keeping this very simple for now. When a partial ack + * is received, force snd_cwnd to a value that will + * allow the sender to transmit no more than 2 segments. + * If necessary, a fancier scheme can be adopted at a + * later point, but for now, the goal is to prevent the + * sender from bursting a large amount of data in the + * midst of sack recovery. + */ + + /* + * send one or 2 segments based on how much + * new data was acked + */ + if (((th->th_ack - tp->snd_una) / tp->t_segsz) > 2) + sack_num_segs = 2; + (void)tcp_sack_output(tp, &sack_bytes_rxmt); + tp->snd_cwnd = sack_bytes_rxmt + + (tp->snd_nxt - tp->sack_newdata) + + sack_num_segs * tp->t_segsz; + tp->t_flags |= TF_ACKNOW; + (void) tcp_output(tp); + } else { + /* + * Set snd_cwnd to one segment beyond ACK'd offset + * snd_una is not yet updated when we're called + */ + tp->snd_cwnd = tp->t_segsz + (th->th_ack - tp->snd_una); + (void) tcp_output(tp); + tp->snd_cwnd = ocwnd; + if (SEQ_GT(onxt, tp->snd_nxt)) + tp->snd_nxt = onxt; + /* + * Partial window deflation. Relies on fact that + * tp->snd_una not updated yet. + */ + tp->snd_cwnd -= (th->th_ack - tp->snd_una - + tp->t_segsz); + } } else { /* * Complete ack. Inflate the congestion window to ssthresh @@ -696,6 +766,8 @@ tcp_newreno_fast_retransmit_newack(struc tp->t_partialacks = -1; tp->t_dupacks = 0; tp->t_bytes_acked = 0; + if (TCP_SACK_ENABLED(tp) && SEQ_GT(th->th_ack, tp->snd_fack)) + tp->snd_fack = th->th_ack; } } @@ -720,4 +792,179 @@ const struct tcp_congctl tcp_newreno_ctl .cong_exp = tcp_reno_congestion_exp, }; +/* + * CUBIC - http://tools.ietf.org/html/draft-rhee-tcpm-cubic-02 + */ + +/* Cubic prototypes */ +static void tcp_cubic_update_ctime(struct tcpcb *tp); +static uint32_t tcp_cubic_diff_ctime(struct tcpcb *); +static uint32_t tcp_cubic_cbrt(uint32_t); +static uint32_t tcp_cubic_getW(struct tcpcb *); + +/* Cubic TIME functions - XXX I don't like using timevals and microuptime */ +/* + * Set congestion timer to now + */ +static void +tcp_cubic_update_ctime(struct tcpcb *tp) +{ + struct timeval now_timeval; + + getmicrouptime(&now_timeval); + tp->snd_cubic_ctime = now_timeval.tv_sec * 1000 + + now_timeval.tv_usec / 1000; +} + +/* + * miliseconds from last congestion + */ +static uint32_t +tcp_cubic_diff_ctime(struct tcpcb *tp) +{ + struct timeval now_timeval; + + getmicrouptime(&now_timeval); + return now_timeval.tv_sec * 1000 + now_timeval.tv_usec / 1000 - + tp->snd_cubic_ctime; +} +/* + * Approximate cubic root + */ +#define CBRT_ROUNDS 30 +static uint32_t +tcp_cubic_cbrt(uint32_t v) +{ + int i, rounds = CBRT_ROUNDS; + uint64_t x = v / 3; + + /* We fail to calculate correct for small numbers */ + if (v == 0) + return 0; + else if (v < 4) + return 1; + + /* + * largest x that 2*x^3+3*x fits 64bit + * Avoid overflow for a time cost + */ + if (x > 2097151) + rounds += 10; + + for (i = 0; i < rounds; i++) + if (rounds == CBRT_ROUNDS) + x = (v + 2 * x * x * x) / (3 * x * x); + else + /* Avoid overflow */ + x = v / (3 * x * x) + 2 * x / 3; + + return (uint32_t)x; +} + +/* Draft Rhee Section 3.1 - get W(t) */ +static uint32_t +tcp_cubic_getW(struct tcpcb *tp) +{ + uint32_t ms_elapsed = tcp_cubic_diff_ctime(tp); + uint32_t K, CtK; + + K = tcp_cubic_cbrt(tp->snd_cubic_wmax * CUBIC_BETAA / CUBIC_BETAB * + CUBIC_CB / CUBIC_CA); + /* C*(t-K) */ + CtK = CUBIC_CA * (ms_elapsed - K) / CUBIC_CB; + + return CtK * CtK * CtK + tp->snd_cubic_wmax; +} + +static void +tcp_cubic_congestion_exp(struct tcpcb *tp) +{ + + tcp_cubic_update_ctime(tp); + + /* Section 3.6 - Fast Convergence */ + if (tp->snd_cubic_wmax < tp->snd_cubic_wmax_last) { + tp->snd_cubic_wmax_last = tp->snd_cubic_wmax; + tp->snd_cubic_wmax = tp->snd_cubic_wmax / 2 + + tp->snd_cubic_wmax * CUBIC_BETAA / CUBIC_BETAB / 2; + } else { + tp->snd_cubic_wmax_last = tp->snd_cubic_wmax; + tp->snd_cubic_wmax = tp->snd_cwnd; + } + tcp_common_congestion_exp(tp, CUBIC_BETAA, CUBIC_BETAB); +} + +static int +tcp_cubic_fast_retransmit(struct tcpcb *tp, const struct tcphdr *th) +{ + + if (SEQ_LT(th->th_ack, tp->snd_high)) { + /* See newreno */ + tp->t_dupacks = 0; + return 1; + } + + /* + * do CUBIC if not in fast recovery + */ + if (tp->t_partialacks < 0) { + /* Adjust W_max, W_max_last, cwnd and ssthresh */ + tcp_cubic_congestion_exp(tp); + /* Reno and NewReno FR */ + return tcp_reno_do_fast_retransmit(tp, th); + } else + return tcp_reno_fast_retransmit(tp, th); +} + +static void +tcp_cubic_newack(struct tcpcb *tp, const struct tcphdr *th) +{ + uint32_t ms_elapsed, rtt; + u_long w_tcp; + + /* Congestion avoidance and not in fast recovery */ + if (tp->snd_cwnd > tp->snd_ssthresh && tp->t_partialacks < 0) { + ms_elapsed = tcp_cubic_diff_ctime(tp); + + rtt = max(hztoms(1), hztoms((tp->t_srtt >> TCP_RTT_SHIFT))); + + /* Compute W_tcp(t) - XXX should use BETA defines */ + w_tcp = tp->snd_cubic_wmax * 4 / 5 + + ms_elapsed / rtt / 3; + + if (tp->snd_cwnd > w_tcp) { + /* Not in TCP mode */ + tp->snd_cwnd += (tcp_cubic_getW(tp) - tp->snd_cwnd) / + tp->snd_cwnd; + } else { + /* friendly TCP mode */ + tp->snd_cwnd = w_tcp; + } + + /* Make sure we are within limits */ + tp->snd_cwnd = max(tp->snd_cwnd, tp->t_segsz); + tp->snd_cwnd = min(tp->snd_cwnd, TCP_MAXWIN << tp->snd_scale); + } else { + /* Use New Reno */ + tcp_newreno_newack(tp, th); + } +} + +static void +tcp_cubic_slow_retransmit(struct tcpcb *tp) +{ + + /* Reset */ + tp->snd_cubic_wmax = tp->snd_cubic_wmax_last = tp->snd_cubic_ctime = 0; + + tcp_reno_slow_retransmit(tp); +} + +const struct tcp_congctl tcp_cubic_ctl = { + .fast_retransmit = tcp_cubic_fast_retransmit, + .slow_retransmit = tcp_cubic_slow_retransmit, + .fast_retransmit_newack = tcp_newreno_fast_retransmit_newack, + .newack = tcp_cubic_newack, + .cong_exp = tcp_cubic_congestion_exp, +}; Index: src/sys/netinet/tcp_congctl.h diff -u src/sys/netinet/tcp_congctl.h:1.6 src/sys/netinet/tcp_congctl.h:1.7 --- src/sys/netinet/tcp_congctl.h:1.6 Thu Apr 14 15:57:02 2011 +++ src/sys/netinet/tcp_congctl.h Tue Nov 12 09:02:05 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: tcp_congctl.h,v 1.6 2011/04/14 15:57:02 yamt Exp $ */ +/* $NetBSD: tcp_congctl.h,v 1.7 2013/11/12 09:02:05 kefren Exp $ */ /* * Copyright (c) 2006 The NetBSD Foundation, Inc. @@ -78,6 +78,7 @@ struct tcp_congctl { extern const struct tcp_congctl tcp_reno_ctl; extern const struct tcp_congctl tcp_newreno_ctl; +extern const struct tcp_congctl tcp_cubic_ctl; /* currently selected global congestion control */ extern char tcp_congctl_global_name[TCPCC_MAXLEN]; Index: src/sys/netinet/tcp_input.c diff -u src/sys/netinet/tcp_input.c:1.329 src/sys/netinet/tcp_input.c:1.330 --- src/sys/netinet/tcp_input.c:1.329 Sun Sep 15 14:42:38 2013 +++ src/sys/netinet/tcp_input.c Tue Nov 12 09:02:05 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: tcp_input.c,v 1.329 2013/09/15 14:42:38 martin Exp $ */ +/* $NetBSD: tcp_input.c,v 1.330 2013/11/12 09:02:05 kefren Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -148,7 +148,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tcp_input.c,v 1.329 2013/09/15 14:42:38 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tcp_input.c,v 1.330 2013/11/12 09:02:05 kefren Exp $"); #include "opt_inet.h" #include "opt_ipsec.h" @@ -2655,12 +2655,8 @@ after_listen: * If the congestion window was inflated to account * for the other side's cached packets, retract it. */ - /* XXX: make SACK have his own congestion control - * struct -- rpaulo */ - if (TCP_SACK_ENABLED(tp)) - tcp_sack_newack(tp, th); - else - tp->t_congctl->fast_retransmit_newack(tp, th); + tp->t_congctl->fast_retransmit_newack(tp, th); + if (SEQ_GT(th->th_ack, tp->snd_max)) { TCP_STATINC(TCP_STAT_RCVACKTOOMUCH); goto dropafterack; Index: src/sys/netinet/tcp_sack.c diff -u src/sys/netinet/tcp_sack.c:1.28 src/sys/netinet/tcp_sack.c:1.29 --- src/sys/netinet/tcp_sack.c:1.28 Mon Jan 30 23:31:27 2012 +++ src/sys/netinet/tcp_sack.c Tue Nov 12 09:02:05 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: tcp_sack.c,v 1.28 2012/01/30 23:31:27 matt Exp $ */ +/* $NetBSD: tcp_sack.c,v 1.29 2013/11/12 09:02:05 kefren Exp $ */ /* * Copyright (c) 2005 The NetBSD Foundation, Inc. @@ -102,7 +102,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tcp_sack.c,v 1.28 2012/01/30 23:31:27 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tcp_sack.c,v 1.29 2013/11/12 09:02:05 kefren Exp $"); #include "opt_inet.h" #include "opt_ipsec.h" @@ -443,69 +443,6 @@ tcp_free_sackholes(struct tcpcb *tp) } /* - * Implements the SACK response to a new ack, checking for partial acks - * in fast recovery. - */ -void -tcp_sack_newack(struct tcpcb *tp, const struct tcphdr *th) -{ - if (tp->t_partialacks < 0) { - /* - * Not in fast recovery. Reset the duplicate ack - * counter. - */ - tp->t_dupacks = 0; - } else if (SEQ_LT(th->th_ack, tp->snd_recover)) { - /* - * Partial ack handling within a sack recovery episode. - * Keeping this very simple for now. When a partial ack - * is received, force snd_cwnd to a value that will allow - * the sender to transmit no more than 2 segments. - * If necessary, a fancier scheme can be adopted at a - * later point, but for now, the goal is to prevent the - * sender from bursting a large amount of data in the midst - * of sack recovery. - */ - int num_segs = 1; - int sack_bytes_rxmt = 0; - - tp->t_partialacks++; - TCP_TIMER_DISARM(tp, TCPT_REXMT); - tp->t_rtttime = 0; - - /* - * send one or 2 segments based on how much new data was acked - */ - if (((th->th_ack - tp->snd_una) / tp->t_segsz) > 2) - num_segs = 2; - (void)tcp_sack_output(tp, &sack_bytes_rxmt); - tp->snd_cwnd = sack_bytes_rxmt + - (tp->snd_nxt - tp->sack_newdata) + num_segs * tp->t_segsz; - tp->t_flags |= TF_ACKNOW; - (void) tcp_output(tp); - } else { - /* - * Complete ack, inflate the congestion window to - * ssthresh and exit fast recovery. - * - * Window inflation should have left us with approx. - * snd_ssthresh outstanding data. But in case we - * would be inclined to send a burst, better to do - * it via the slow start mechanism. - */ - if (SEQ_SUB(tp->snd_max, th->th_ack) < tp->snd_ssthresh) - tp->snd_cwnd = SEQ_SUB(tp->snd_max, th->th_ack) - + tp->t_segsz; - else - tp->snd_cwnd = tp->snd_ssthresh; - tp->t_partialacks = -1; - tp->t_dupacks = 0; - if (SEQ_GT(th->th_ack, tp->snd_fack)) - tp->snd_fack = th->th_ack; - } -} - -/* * Returns pointer to a sackhole if there are any pending retransmissions; * NULL otherwise. */ Index: src/sys/netinet/tcp_subr.c diff -u src/sys/netinet/tcp_subr.c:1.250 src/sys/netinet/tcp_subr.c:1.251 --- src/sys/netinet/tcp_subr.c:1.250 Wed Jun 5 19:01:26 2013 +++ src/sys/netinet/tcp_subr.c Tue Nov 12 09:02:05 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: tcp_subr.c,v 1.250 2013/06/05 19:01:26 christos Exp $ */ +/* $NetBSD: tcp_subr.c,v 1.251 2013/11/12 09:02:05 kefren Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -91,7 +91,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tcp_subr.c,v 1.250 2013/06/05 19:01:26 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tcp_subr.c,v 1.251 2013/11/12 09:02:05 kefren Exp $"); #include "opt_inet.h" #include "opt_ipsec.h" @@ -963,6 +963,9 @@ static struct tcpcb tcpcb_template = { .snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT, .snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT, .snd_numholes = 0, + .snd_cubic_wmax = 0, + .snd_cubic_wmax_last = 0, + .snd_cubic_ctime = 0, .t_partialacks = -1, .t_bytes_acked = 0, Index: src/sys/netinet/tcp_var.h diff -u src/sys/netinet/tcp_var.h:1.170 src/sys/netinet/tcp_var.h:1.171 --- src/sys/netinet/tcp_var.h:1.170 Wed Apr 10 00:16:04 2013 +++ src/sys/netinet/tcp_var.h Tue Nov 12 09:02:05 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: tcp_var.h,v 1.170 2013/04/10 00:16:04 christos Exp $ */ +/* $NetBSD: tcp_var.h,v 1.171 2013/11/12 09:02:05 kefren Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -328,6 +328,11 @@ struct tcpcb { tcp_seq snd_fack; /* FACK TCP. Forward-most data held by peer. */ +/* CUBIC variables */ + ulong snd_cubic_wmax; /* W_max */ + ulong snd_cubic_wmax_last; /* Used for fast convergence */ + ulong snd_cubic_ctime; /* Last congestion time */ + /* pointer for syn cache entries*/ LIST_HEAD(, syn_cache) t_sc; /* list of entries by this tcb */ @@ -966,7 +971,6 @@ void tcp_del_sackholes(struct tcpcb *, void tcp_free_sackholes(struct tcpcb *); void tcp_sack_adjust(struct tcpcb *tp); struct sackhole *tcp_sack_output(struct tcpcb *tp, int *sack_bytes_rexmt); -void tcp_sack_newack(struct tcpcb *, const struct tcphdr *); int tcp_sack_numblks(const struct tcpcb *); #define TCP_SACK_OPTLEN(nblks) ((nblks) * 8 + 2 + 2)