diff options
Diffstat (limited to 'net/ipv4/tcp_input.c')
| -rw-r--r-- | net/ipv4/tcp_input.c | 24 | 
1 files changed, 8 insertions, 16 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 575d3c1fb6e8..9a1b3c1c1c14 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1971,11 +1971,6 @@ void tcp_enter_loss(struct sock *sk)  	/* F-RTO RFC5682 sec 3.1 step 1: retransmit SND.UNA if no previous  	 * loss recovery is underway except recurring timeout(s) on  	 * the same SND.UNA (sec 3.2). Disable F-RTO on path MTU probing -	 * -	 * In theory F-RTO can be used repeatedly during loss recovery. -	 * In practice this interacts badly with broken middle-boxes that -	 * falsely raise the receive window, which results in repeated -	 * timeouts and stop-and-go behavior.  	 */  	tp->frto = net->ipv4.sysctl_tcp_frto &&  		   (new_recovery || icsk->icsk_retransmits) && @@ -2631,18 +2626,14 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack,  	    tcp_try_undo_loss(sk, false))  		return; -	/* The ACK (s)acks some never-retransmitted data meaning not all -	 * the data packets before the timeout were lost. Therefore we -	 * undo the congestion window and state. This is essentially -	 * the operation in F-RTO (RFC5682 section 3.1 step 3.b). Since -	 * a retransmitted skb is permantly marked, we can apply such an -	 * operation even if F-RTO was not used. -	 */ -	if ((flag & FLAG_ORIG_SACK_ACKED) && -	    tcp_try_undo_loss(sk, tp->undo_marker)) -		return; -  	if (tp->frto) { /* F-RTO RFC5682 sec 3.1 (sack enhanced version). */ +		/* Step 3.b. A timeout is spurious if not all data are +		 * lost, i.e., never-retransmitted data are (s)acked. +		 */ +		if ((flag & FLAG_ORIG_SACK_ACKED) && +		    tcp_try_undo_loss(sk, true)) +			return; +  		if (after(tp->snd_nxt, tp->high_seq)) {  			if (flag & FLAG_DATA_SACKED || is_dupack)  				tp->frto = 0; /* Step 3.a. loss was real */ @@ -4001,6 +3992,7 @@ void tcp_reset(struct sock *sk)  	/* This barrier is coupled with smp_rmb() in tcp_poll() */  	smp_wmb(); +	tcp_write_queue_purge(sk);  	tcp_done(sk);  	if (!sock_flag(sk, SOCK_DEAD))  | 
