From 8453d35f2443156ae75b913e573019c05a7442d2 Mon Sep 17 00:00:00 2001 From: ps Date: Mon, 14 Feb 2005 21:01:08 +0000 Subject: - Retransmit just one segment on initiation of SACK recovery. Remove the SACK "initburst" sysctl. - Fix bugs in SACK dupack and partialack handling that can cause large bursts while in SACK recovery. Submitted by: Mohan Srinivasan --- sys/netinet/tcp_input.c | 12 +----------- sys/netinet/tcp_reass.c | 12 +----------- sys/netinet/tcp_sack.c | 36 ++++++++++++++++-------------------- 3 files changed, 18 insertions(+), 42 deletions(-) diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 37405c1..1784551 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -159,12 +159,6 @@ SYSCTL_INT(_net_inet_tcp_reass, OID_AUTO, overflows, CTLFLAG_RD, &tcp_reass_overflows, 0, "Global number of TCP Segment Reassembly Queue Overflows"); -static int tcp_sack_recovery_initburst = 3; -SYSCTL_INT(_net_inet_tcp_sack, OID_AUTO, - initburst, CTLFLAG_RW, - &tcp_sack_recovery_initburst, 0, - "Initial Number of Rexmits when sack recovery is set up"); - struct inpcbhead tcb; #define tcb6 tcb /* for KAME src sync over BSD*'s */ struct inpcbinfo tcbinfo; @@ -1870,14 +1864,10 @@ trimthenstep6: if (tp->sack_enable) { tcpstat.tcps_sack_recovery_episode++; tp->sack_newdata = tp->snd_nxt; - tp->snd_cwnd = - tp->t_maxseg * tcp_sack_recovery_initburst; + tp->snd_cwnd = tp->t_maxseg; (void) tcp_output(tp); - tp->snd_cwnd += - tp->snd_ssthresh; goto drop; } - tp->snd_nxt = th->th_ack; tp->snd_cwnd = tp->t_maxseg; (void) tcp_output(tp); diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index 37405c1..1784551 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -159,12 +159,6 @@ SYSCTL_INT(_net_inet_tcp_reass, OID_AUTO, overflows, CTLFLAG_RD, &tcp_reass_overflows, 0, "Global number of TCP Segment Reassembly Queue Overflows"); -static int tcp_sack_recovery_initburst = 3; -SYSCTL_INT(_net_inet_tcp_sack, OID_AUTO, - initburst, CTLFLAG_RW, - &tcp_sack_recovery_initburst, 0, - "Initial Number of Rexmits when sack recovery is set up"); - struct inpcbhead tcb; #define tcb6 tcb /* for KAME src sync over BSD*'s */ struct inpcbinfo tcbinfo; @@ -1870,14 +1864,10 @@ trimthenstep6: if (tp->sack_enable) { tcpstat.tcps_sack_recovery_episode++; tp->sack_newdata = tp->snd_nxt; - tp->snd_cwnd = - tp->t_maxseg * tcp_sack_recovery_initburst; + tp->snd_cwnd = tp->t_maxseg; (void) tcp_output(tp); - tp->snd_cwnd += - tp->snd_ssthresh; goto drop; } - tp->snd_nxt = th->th_ack; tp->snd_cwnd = tp->t_maxseg; (void) tcp_output(tp); diff --git a/sys/netinet/tcp_sack.c b/sys/netinet/tcp_sack.c index 6230ff2..8637fa2 100644 --- a/sys/netinet/tcp_sack.c +++ b/sys/netinet/tcp_sack.c @@ -481,9 +481,14 @@ tcp_free_sackholes(struct tcpcb *tp) } /* - * Checks for partial ack. If partial ack arrives, turn off retransmission - * timer, deflate the window, do not clear tp->t_dupacks, and return 1. - * If the ack advances at least to tp->snd_recover, return 0. + * 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 better 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. */ void tcp_sack_partialack(tp, th) @@ -491,28 +496,19 @@ tcp_sack_partialack(tp, th) struct tcphdr *th; { INP_LOCK_ASSERT(tp->t_inpcb); - u_long ocwnd = tp->snd_cwnd; - int sack_bytes_rexmt = 0; + int num_segs = 1; + int sack_bytes_rxmt = 0; callout_stop(tp->tt_rexmt); tp->t_rtttime = 0; - /* - * Set cwnd so we can send one more segment (either rexmit based on - * scoreboard or new segment). Set cwnd to the amount of data - * rexmitted from scoreboard plus the amount of new data transmitted - * in this sack recovery episode plus one segment. - */ - (void)tcp_sack_output(tp, &sack_bytes_rexmt); - tp->snd_cwnd = sack_bytes_rexmt + (tp->snd_nxt - tp->sack_newdata) + - tp->t_maxseg; + /* send one or 2 segments based on how much new data was acked */ + if (((th->th_ack - tp->snd_una) / tp->t_maxseg) > 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_maxseg; tp->t_flags |= TF_ACKNOW; (void) tcp_output(tp); - tp->snd_cwnd = ocwnd; - /* - * Partial window deflation. Relies on fact that tp->snd_una - * not updated yet. - */ - tp->snd_cwnd -= (th->th_ack - tp->snd_una - tp->t_maxseg); } #ifdef TCP_SACK_DEBUG -- cgit v1.1