Subject: Q: window shrinking in BSD

From: "[email-masked]" <[email-masked]>
Date: Tue, 29 Oct 2002 14:06:43 +0200

I have a question regarding the code fragment below. It belongs  to 
tcp_output function of many BSD versions. In this fragment, the 
function check for a window shrinking. 

if (len < 0) {
		/*
		 * If FIN has been sent but not acked,
		 * but we haven't been called to retransmit,
		 * len will be < 0.  Otherwise, window shrank
		 * after we sent into it.  If window shrank to 0,
		 * cancel pending retransmit, pull snd_nxt back
		 * to (closed) window, and set the persist timer
		 * if it isn't already going.  If the window didn't
		 * close completely, just wait for an ACK.
		 */
		len = 0;
		if (win == 0) {
			callout_stop(tp->tt_rexmt);
			tp->t_rxtshift = 0;
			tp->snd_nxt = tp->snd_una;
			if (!callout_active(tp->tt_persist))
				tcp_setpersist(tp);
		}
	}

“If window shrank to 0, cancel pending retransmit, pull snd_nxt back to 
(closed) window, and set the persist timer if it isn't already going.”

So, sender set tp->snd_nxt to tp->snd_una as soon as it enter in 
persist mode.

Now consider this scenario:
Sender has sent segment [1] [2] [3] when receiver send back an ack for 
segment [2] and zero advertised window. Then, sender set snd_nxt to 
snd_una and enter persist mode. In the meantime, if segment [3] reaches 
receiver and is processed (receiver buffer could be empty now), 
receiver could reopen window with an ack for segment [3]. But this ack 
is discarded by sender because snd_nxt < seg_ack. 
Even if sender sends probes repeatedly, receiver could respond with the 
same ack. So, does connection remain in a stall situation for an 
indefinite time?   

Tanks in advance,
Pierluigi