panic in TCP Limited Transmit after RTO

Noritoshi Demizu demizu at
Sat Mar 12 19:49:46 PST 2005

> Limited Transmit is supposed to send new data,

In normal cases, Limited Transmit sends new data.  But in my
experiences, the difference between snd_una and snd_max becomes
about 500KB.  After an RTO, sender has to send 500KB.  So it is
possible or likely to receive duplicate ACKs before snd_nxt reaches
snd_max.  In such case, Limited Transmit has to send old data.
And Limited Transmit of DragonFlyBSD does this well.
(I assume "new data" here means data higher than snd_max.)

> and, we are out of SACK recovery at this point,

Retransmission timeout is an internal event of a sender.  A receiver
does not know of it.  So, even just after a retransmission timeout, a
sender receives ACKs with SACK blocks.

If DragonFlyBSD receives SACK blocks after RTO, it avoids sending such
SACKed data by the effect of tcp_sack_skip_sacked().  When a SACKed
block is skipped by this function, snd_nxt advances more than t_maxseg.
In such case, the following line calculates larger value than t_maxseg.

	sent = tp->snd_nxt - oldsndnxt;

But if it is the first duplicate ACK, the following KASSERT() will fail.
(Note: in such case, t_dupacks=1, snd_limited=0, FIN has not been sent.)

	KASSERT((tp->t_dupacks == 2 && tp->snd_limited == 0) ||
		(sent == tp->t_maxseg + 1 && tp->t_flags & TF_SENTFIN),
		("sent too much"));

> so I think we can safely ignore any old SACK blocks.

Yes, we can ignore old SACK blocks that are discarded on an RTO.
But I think we cannot ignore new SACK blocks received after an RTO,
especially when calculating for a variable "sent" above.

> Please try this patch.

I will try this patch on Monday in Japan time.
But could you reconsider about SACKed bytes?

Thank you.

Noritoshi Demizu

More information about the Bugs mailing list