Skip to content

Commit 9c76a02

Browse files
committed
Faster recovery from retransmission
Limit the number of dup-ACKs to 3, and send fast-ACKs after each retransmitted segment.
1 parent a70f756 commit 9c76a02

File tree

2 files changed

+30
-4
lines changed

2 files changed

+30
-4
lines changed

src/tcp_fsm.c

+27-3
Original file line numberDiff line numberDiff line change
@@ -366,9 +366,18 @@ static int tcp_estab_state (_tcp_Socket **sp, const in_Header *ip,
366366
len = tcp_process_data (s, tcp, len, &flags);
367367
if (len < 0)
368368
{
369-
TCP_SEND (s); /* An out-of-order or missing segment; do fast ACK */
369+
/* An out-of-order or missing segment; do fast ACK.
370+
* Three should be enough. If those get dropped,
371+
* retransmitter will send more eventually.
372+
*/
373+
if (s->dup_acks < 3)
374+
{
375+
TCP_SEND (s);
376+
++s->dup_acks;
377+
}
370378
return (1);
371379
}
380+
s->dup_acks = 0;
372381

373382
if (s->state != tcp_StateCLOSWT &&
374383
(flags & tcp_FlagFIN) &&
@@ -402,6 +411,14 @@ static int tcp_estab_state (_tcp_Socket **sp, const in_Header *ip,
402411
}
403412
}
404413

414+
/* Send fast-ACK after retransmission.
415+
*/
416+
if (len > 0 && s->missed_seq[0] != s->missed_seq[1])
417+
{
418+
TCP_SEND (s);
419+
return (0);
420+
}
421+
405422
/* Peer ACKed some of our data, continue sending more.
406423
*/
407424
if (ldiff > 0 && s->tx_datalen > (unsigned long)s->send_una)
@@ -848,7 +865,7 @@ copy_in_order (_tcp_Socket *s, const BYTE *data, unsigned len)
848865
* Handle any new data that increments the 'recv_next' index.
849866
* 'ldiff >= 0'.
850867
*/
851-
static void
868+
static int
852869
data_in_order (_tcp_Socket *s, const BYTE *data, unsigned len, unsigned diff)
853870
{
854871
/* Skip data before recv_next. We must be left with some data or
@@ -893,6 +910,11 @@ data_in_order (_tcp_Socket *s, const BYTE *data, unsigned len, unsigned diff)
893910
*/
894911
copy_in_order (s, data + ms_end, len - ms_end);
895912
}
913+
914+
/* Send fast-ACK to notify peer that we caught up.
915+
*/
916+
s->dup_acks = 0;
917+
len = -1;
896918
}
897919

898920
TRACE_FILE ("data_in_order (%u): edges %lu/%lu, recv.next %lu\n",
@@ -901,6 +923,8 @@ data_in_order (_tcp_Socket *s, const BYTE *data, unsigned len, unsigned diff)
901923

902924
TRACE_FILE ("data_in_order (%u): new data now ends at %u\n",
903925
__LINE__, s->rx_datalen);
926+
927+
return (len);
904928
}
905929

906930
/*
@@ -1092,7 +1116,7 @@ static int tcp_process_data (_tcp_Socket *s, const tcp_Header *tcp,
10921116

10931117
if (ldiff >= 0)
10941118
{
1095-
data_in_order (s, data, len, ldiff);
1119+
len = data_in_order (s, data, len, ldiff);
10961120
s->unhappy = (s->tx_datalen > 0);
10971121
return (len);
10981122
}

src/wattcp.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,9 @@ typedef struct tcp_Socket {
619619
UINT rto; /**< retransmission timeout */
620620
BYTE karn_count; /**< count of packets */
621621
BYTE tos; /**< TOS from IP-header */
622-
WORD fill_5;
622+
623+
BYTE dup_acks; /**< number of dup-ACKs we sent recently */
624+
BYTE fill_5;
623625

624626
DWORD rtt_time; /**< Round Trip Time value */
625627
DWORD rtt_lasttran; /**< RTT at last transmission */

0 commit comments

Comments
 (0)