From b1d3dcb8d7f7bd93d91e4f070571bb7afbfab279 Mon Sep 17 00:00:00 2001 From: Solganik Alexander Date: Sun, 6 Jan 2019 16:43:00 +0100 Subject: [PATCH] tcp: don't reset dupack count upon non-empty packet receive According to rfc5681: https://tools.ietf.org/html/rfc5681 Paragraph 3.2. Fast Retransmit/Fast Recovery The TCP sender SHOULD use the "fast retransmit" algorithm to detect and repair loss, based on incoming duplicate ACKs. The fast retransmit algorithm uses the arrival of 3 duplicate ACKs (as defined in section 2, without any intervening ACKs which move SND.UNA) as an indication that a segment has been lost. After receiving 3 duplicate ACKs, TCP performs a retransmission of what appears to be the missing segment, without waiting for the retransmission timer to expire. Now consider the following scenario: Server sends packets to client P0, P1, P2 .. PK. Client sends packets to server P`0 P`1 ... P`k. I.e. it is a pipelined conversation. Now lets assume that P1 is lost, Client will send an empty "duplicate" ack upon receive of P2, P3... In addition client will also send a new packet with "Client Data", P`0 P`1 .. e.t.c. according to sever receive window and client congestion window. Current implementation resets "duplicate" ack count upon receive of packets from client that holds new data. This in turn prevents server from fast recovery upon 3-duplicate acks receive. This is not required as in this case "sender unacknowledged window" is not moving. Signed-off-by: Solganik Alexander --- src/core/tcp_in.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index b5e85a4d..b6a4e4af 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -1146,7 +1146,6 @@ tcp_receive(struct tcp_pcb *pcb) { s16_t m; u32_t right_wnd_edge; - int found_dupack = 0; LWIP_ASSERT("tcp_receive: invalid pcb", pcb != NULL); LWIP_ASSERT("tcp_receive: wrong state", pcb->state >= ESTABLISHED); @@ -1208,7 +1207,6 @@ tcp_receive(struct tcp_pcb *pcb) if (pcb->rtime >= 0) { /* Clause 5 */ if (pcb->lastack == ackno) { - found_dupack = 1; if ((u8_t)(pcb->dupacks + 1) > pcb->dupacks) { ++pcb->dupacks; } @@ -1224,11 +1222,6 @@ tcp_receive(struct tcp_pcb *pcb) } } } - /* If Clause (1) or more is true, but not a duplicate ack, reset - * count of consecutive duplicate acks */ - if (!found_dupack) { - pcb->dupacks = 0; - } } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack + 1, pcb->snd_nxt)) { /* We come here when the ACK acknowledges new data. */ tcpwnd_size_t acked;