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:
parent
959e4829a9
commit
3db035bbac
|
@ -159,6 +159,13 @@ impl Timer {
|
||||||
expires_at: timestamp + CLOSE_DELAY
|
expires_at: timestamp + CLOSE_DELAY
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_retransmit(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Timer::Retransmit {..} => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A Transmission Control Protocol socket.
|
/// A Transmission Control Protocol socket.
|
||||||
|
@ -1025,9 +1032,12 @@ impl<'a> TcpSocket<'a> {
|
||||||
self.timer.set_for_idle(timestamp, self.keep_alive);
|
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) => {
|
(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.
|
// 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]
|
#[test]
|
||||||
fn test_established_retransmit_reset_after_ack() {
|
fn test_established_retransmit_reset_after_ack() {
|
||||||
let mut s = socket_established();
|
let mut s = socket_established();
|
||||||
|
|
Loading…
Reference in New Issue