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.
This commit is contained in:
Kai Lüke 2017-10-28 17:32:08 +09:00 committed by whitequark
parent 959e4829a9
commit 3db035bbac
1 changed files with 40 additions and 2 deletions

View File

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