Skip to content

Commit 7efff0c

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 0b7d39e commit 7efff0c

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
@@ -367,9 +367,18 @@ static int tcp_estab_state (_tcp_Socket **sp, const in_Header *ip,
367367
len = tcp_process_data (s, tcp, len, &flags);
368368
if (len < 0)
369369
{
370-
TCP_SEND (s); /* An out-of-order or missing segment; do fast ACK */
370+
/* An out-of-order or missing segment; do fast ACK.
371+
* Three should be enough. If those get dropped,
372+
* retransmitter will send more eventually.
373+
*/
374+
if (s->dup_acks < 3)
375+
{
376+
TCP_SEND (s);
377+
++s->dup_acks;
378+
}
371379
return (1);
372380
}
381+
s->dup_acks = 0;
373382

374383
if (s->state != tcp_StateCLOSWT &&
375384
(flags & tcp_FlagFIN) &&
@@ -403,6 +412,14 @@ static int tcp_estab_state (_tcp_Socket **sp, const in_Header *ip,
403412
}
404413
}
405414

415+
/* Send fast-ACK after retransmission.
416+
*/
417+
if (len > 0 && s->missed_seq[0] != s->missed_seq[1])
418+
{
419+
TCP_SEND (s);
420+
return (0);
421+
}
422+
406423
/* Peer ACKed some of our data, continue sending more.
407424
*/
408425
if (ldiff > 0 && s->tx_datalen > (unsigned long)s->send_una)
@@ -847,7 +864,7 @@ copy_in_order (_tcp_Socket *s, const BYTE *data, unsigned len)
847864
* Handle any new data that increments the 'recv_next' index.
848865
* 'ldiff >= 0'.
849866
*/
850-
static void
867+
static int
851868
data_in_order (_tcp_Socket *s, const BYTE *data, unsigned len, unsigned diff)
852869
{
853870
/* Skip data before recv_next. We must be left with some data or
@@ -892,6 +909,11 @@ data_in_order (_tcp_Socket *s, const BYTE *data, unsigned len, unsigned diff)
892909
*/
893910
copy_in_order (s, data + ms_end, len - ms_end);
894911
}
912+
913+
/* Send fast-ACK to notify peer that we caught up.
914+
*/
915+
s->dup_acks = 0;
916+
len = -1;
895917
}
896918

897919
TRACE_FILE ("data_in_order (%u): edges %lu/%lu, recv.next %lu\n",
@@ -900,6 +922,8 @@ data_in_order (_tcp_Socket *s, const BYTE *data, unsigned len, unsigned diff)
900922

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

905929
/*
@@ -1091,7 +1115,7 @@ static int tcp_process_data (_tcp_Socket *s, const tcp_Header *tcp,
10911115

10921116
if (ldiff >= 0)
10931117
{
1094-
data_in_order (s, data, len, ldiff);
1118+
len = data_in_order (s, data, len, ldiff);
10951119
s->unhappy = (s->tx_datalen > 0);
10961120
return (len);
10971121
}

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)