From c8e4aa1cd58a20597b74285a3cc35ea24ba5c47c Mon Sep 17 00:00:00 2001 From: ps Date: Tue, 5 Oct 2004 18:36:24 +0000 Subject: - Estimate the amount of data in flight in sack recovery and use it to control the packets injected while in sack recovery (for both retransmissions and new data). - Cleanups to the sack codepaths in tcp_output.c and tcp_sack.c. - Add a new sysctl (net.inet.tcp.sack.initburst) that controls the number of sack retransmissions done upon initiation of sack recovery. Submitted by: Mohan Srinivasan --- sys/netinet/tcp_output.c | 66 +++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 26 deletions(-) (limited to 'sys/netinet/tcp_output.c') diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index cd09097..18da2cd 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -124,6 +124,7 @@ tcp_output(struct tcpcb *tp) unsigned ipoptlen, optlen, hdrlen; int idle, sendalot; int i, sack_rxmit; + int sack_bytes_rxmt; struct sackhole *p; #if 0 int maxburst = TCP_MAXBURST; @@ -198,12 +199,16 @@ again: * Still in sack recovery , reset rxmit flag to zero. */ sack_rxmit = 0; + sack_bytes_rxmt = 0; len = 0; p = NULL; if (tp->sack_enable && IN_FASTRECOVERY(tp) && - (p = tcp_sack_output(tp))) { - KASSERT(tp->snd_cwnd >= 0, - ("%s: CWIN is negative : %ld", __func__, tp->snd_cwnd)); + (p = tcp_sack_output(tp, &sack_bytes_rxmt))) { + long cwin; + + cwin = min(tp->snd_wnd, tp->snd_cwnd) - sack_bytes_rxmt; + if (cwin < 0) + cwin = 0; /* Do not retransmit SACK segments beyond snd_recover */ if (SEQ_GT(p->end, tp->snd_recover)) { /* @@ -222,10 +227,10 @@ again: goto after_sack_rexmit; } else /* Can rexmit part of the current hole */ - len = ((long)ulmin(tp->snd_cwnd, - tp->snd_recover - p->rxmit)); + len = ((long)ulmin(cwin, + tp->snd_recover - p->rxmit)); } else - len = ((long)ulmin(tp->snd_cwnd, p->end - p->rxmit)); + len = ((long)ulmin(cwin, p->end - p->rxmit)); sack_rxmit = 1; sendalot = 1; off = p->rxmit - tp->snd_una; @@ -295,8 +300,25 @@ after_sack_rexmit: * If sack_rxmit is true we are retransmitting from the scoreboard * in which case len is already set. */ - if (!sack_rxmit) - len = ((long)ulmin(so->so_snd.sb_cc, sendwin) - off); + if (sack_rxmit == 0) { + if (sack_bytes_rxmt == 0) + len = ((long)ulmin(so->so_snd.sb_cc, sendwin) - off); + else { + long cwin; + + /* + * We are inside of a SACK recovery episode and are + * sending new data, having retransmitted all the + * data possible in the scoreboard. + */ + len = so->so_snd.sb_cc - off; + cwin = sendwin - (tp->snd_nxt - tp->sack_newdata) - + sack_bytes_rxmt; + if (cwin < 0) + cwin = 0; + len = lmin(len, cwin); + } + } /* * Lop off SYN bit if it has already been sent. However, if this @@ -850,12 +872,13 @@ send: * case, since we know we aren't doing a retransmission. * (retransmit and persist are mutually exclusive...) */ - if (len || (flags & (TH_SYN|TH_FIN)) - || callout_active(tp->tt_persist)) - th->th_seq = htonl(tp->snd_nxt); - else - th->th_seq = htonl(tp->snd_max); - if (sack_rxmit) { + if (sack_rxmit == 0) { + if (len || (flags & (TH_SYN|TH_FIN)) + || callout_active(tp->tt_persist)) + th->th_seq = htonl(tp->snd_nxt); + else + th->th_seq = htonl(tp->snd_max); + } else { th->th_seq = htonl(p->rxmit); p->rxmit += len; } @@ -956,7 +979,7 @@ send: tp->t_flags |= TF_SENTFIN; } } - if (tp->sack_enable && sack_rxmit) + if (sack_rxmit) goto timer; tp->snd_nxt += len; if (SEQ_GT(tp->snd_nxt, tp->snd_max)) { @@ -981,18 +1004,9 @@ send: * of retransmit time. */ timer: - if (tp->sack_enable && sack_rxmit && - !callout_active(tp->tt_rexmt) && - tp->snd_nxt != tp->snd_max) { - callout_reset(tp->tt_rexmt, tp->t_rxtcur, - tcp_timer_rexmt, tp); - if (callout_active(tp->tt_persist)) { - callout_stop(tp->tt_persist); - tp->t_rxtshift = 0; - } - } if (!callout_active(tp->tt_rexmt) && - tp->snd_nxt != tp->snd_una) { + ((sack_rxmit && tp->snd_nxt != tp->snd_max) || + (tp->snd_nxt != tp->snd_una))) { if (callout_active(tp->tt_persist)) { callout_stop(tp->tt_persist); tp->t_rxtshift = 0; -- cgit v1.1