[tcp] Improve robustness in the presence of duplicated received packets

gPXE responds to duplicated ACKs with an immediate retransmission,
which can lead to a sorceror's apprentice syndrome.  It also responds
to out-of-range (or old duplicate) ACKs with a RST, which can cause
valid connections to be dropped.

Fix the sorceror's apprentice syndrome by leaving the retransmission
timer running (and so inhibiting the immediate retransmission) when we
receive a potential duplicate ACK.  This seems to match the behaviour
of Linux observed via wireshark traces.

Fix the RST issue by sending RST only on out-of-range ACKs that occur
before the connection is fully established, as per RFC 793.

These problems were exposed during development of the 802.11 wireless
link layer; the 802.11 protocol has a failure mode that can easily
cause duplicated packets.  The fixes were tested in a controlled way
by faking large numbers of duplicated packets in the rtl8139 driver.

Originally-fixed-by: Joshua Oreman <oremanj@rwcr.net>
This commit is contained in:
Michael Brown
2009-06-23 01:29:43 +01:00
parent 68973f1c49
commit 558c1a45fe
2 changed files with 38 additions and 13 deletions

View File

@@ -229,6 +229,16 @@ struct tcp_options {
TCP_STATE_SENT ( TCP_FIN ) ) ) \
== TCP_STATE_ACKED ( TCP_SYN ) )
/** Have ever been fully established
*
* We have been fully established if we have both received a SYN and
* had our own SYN acked.
*/
#define TCP_HAS_BEEN_ESTABLISHED(state) \
( ( (state) & ( TCP_STATE_ACKED ( TCP_SYN ) | \
TCP_STATE_RCVD ( TCP_SYN ) ) ) \
== ( TCP_STATE_ACKED ( TCP_SYN ) | TCP_STATE_RCVD ( TCP_SYN ) ) )
/** Have closed gracefully
*
* We have closed gracefully if we have both received a FIN and had