During a recovery, we should always reduce send window if the host is
notifying a window reduction.

This is needed because in the recovery phase the host requires to
buffer the packets between the beginning of the recovery and the data
we're sending "forward" with ssthresh window and sacked_out count.

So it isn't buffering the in_flight packets, but a number of packets
that could be much higher.

If the host asks a window reduction its buffer is filling up, and if
we ignore the reduction, when the buffer is full all the packets
arriving to the host will be dropped.

When the first packet is dropped the host will begin asking for a zero
window; this request will be eventually granted, however in the
meantime we will have lost a full window of packets.

Anyway we could neither set the FLAG_WIN_UPDATE, otherwise the ack
will not be considered a DUPACK and when using Reno the sacked_out
count will not be updated.

Regards,
Angelo P. Castellani
diff -urd linux-2.6.16-orig/net/ipv4/tcp_input.c linux-2.6.16-winupdate/net/ipv4/tcp_input.c
--- linux-2.6.16-orig/net/ipv4/tcp_input.c	2006-05-16 14:53:02.000000000 +0200
+++ linux-2.6.16-winupdate/net/ipv4/tcp_input.c	2006-07-05 15:38:08.000000000 +0200
@@ -2365,12 +2365,44 @@
 {
 	int flag = 0;
 	u32 nwin = ntohs(skb->h.th->window);
+	struct inet_connection_sock *icsk = inet_csk(sk);
+	int silent_update = 0;
 
 	if (likely(!skb->h.th->syn))
 		nwin <<= tp->rx_opt.snd_wscale;
 
-	if (tcp_may_update_window(tp, ack, ack_seq, nwin)) {
-		flag |= FLAG_WIN_UPDATE;
+	/*
+	 * During a recovery, we should always reduce send window if the host
+	 * is notifying a window reduction.
+	 *
+	 * This is needed because in the recovery phase the host requires
+	 * to buffer the packets between the beginning of the recovery
+	 * and the data we're sending "forward" with ssthresh window and
+	 * sacked_out count.
+	 *
+	 * So it isn't buffering the in_flight packets, but a number of packets
+	 * that could be much higher.
+	 *
+	 * If the host asks a window reduction its buffer is filling up, and if we
+	 * ignore the reduction, when the buffer is full all the packets arriving
+	 * to the host will be dropped.
+	 *
+	 * When the first packet is dropped the host will begin asking for a zero
+	 * window; this request will be eventually granted, however in the
+	 * meantime we will have lost a full window of packets.
+	 *
+	 * Anyway we could neither set the FLAG_WIN_UPDATE, otherwise the
+	 * ack will not be considered a DUPACK and when using Reno the 
+	 * sacked_out count will not be updated.
+	 *
+	 */
+	if (icsk->icsk_ca_state == TCP_CA_Recovery &&
+		    nwin < tp->snd_wnd)
+		silent_update = 1;
+
+	if (silent_update || tcp_may_update_window(tp, ack, ack_seq, nwin)) {
+		if (!silent_update)
+			flag |= FLAG_WIN_UPDATE;
 		tcp_update_wl(tp, ack, ack_seq);
 
 		if (tp->snd_wnd != nwin) {

Reply via email to