From 3db035bbacdbcbe1c35cc43304009a4b7a972e65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20L=C3=BCke?= Date: Sat, 28 Oct 2017 17:32:08 +0900 Subject: [PATCH] Preserve retransmission timer for Dup-ACKs Duplicate ACKs should not replace the retransmission timer, but if not in retransmission, still set the keep-alive timer as normal ACKs do. --- src/socket/tcp.rs | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/socket/tcp.rs b/src/socket/tcp.rs index 6f1d63b..534576b 100644 --- a/src/socket/tcp.rs +++ b/src/socket/tcp.rs @@ -159,6 +159,13 @@ impl Timer { expires_at: timestamp + CLOSE_DELAY } } + + fn is_retransmit(&self) -> bool { + match *self { + Timer::Retransmit {..} => true, + _ => false, + } + } } /// A Transmission Control Protocol socket. @@ -1025,9 +1032,12 @@ impl<'a> TcpSocket<'a> { self.timer.set_for_idle(timestamp, self.keep_alive); } - // ACK packets in ESTABLISHED state reset the retransmit timer. + // ACK packets in ESTABLISHED state reset the retransmit timer, + // except for duplicate ACK packets which preserve it. (State::Established, TcpControl::None) => { - self.timer.set_for_idle(timestamp, self.keep_alive); + if !self.timer.is_retransmit() || ack_len != 0 { + self.timer.set_for_idle(timestamp, self.keep_alive); + } }, // FIN packets in ESTABLISHED state indicate the remote side has closed. @@ -2889,6 +2899,34 @@ mod test { }]) } + #[test] + fn test_established_retransmit_for_dup_ack() { + let mut s = socket_established(); + // Duplicate ACKs do not replace the retransmission timer + s.send_slice(b"abc").unwrap(); + recv!(s, time 1000, Ok(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"abc"[..], + ..RECV_TEMPL + })); + // Retransmit timer is on because all data was sent + assert_eq!(s.tx_buffer.len(), 3); + // ACK nothing new + send!(s, TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + }); + // Retransmit + recv!(s, time 4000, Ok(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"abc"[..], + ..RECV_TEMPL + })); + } + #[test] fn test_established_retransmit_reset_after_ack() { let mut s = socket_established();