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 <sashas@lightbitslabs.com>
This commit is contained in:
Solganik Alexander 2019-01-06 16:43:00 +01:00 committed by Simon Goldschmidt
parent 5666f305ce
commit b1d3dcb8d7

View File

@ -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;