Skip to content

Commit

Permalink
Only clear retransmit timer when all packets are acked
Browse files Browse the repository at this point in the history
  • Loading branch information
SquidDev committed Aug 11, 2022
1 parent bd68588 commit a25c9f2
Showing 1 changed file with 86 additions and 2 deletions.
88 changes: 86 additions & 2 deletions src/socket/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1460,6 +1460,7 @@ impl<'a> Socket<'a> {
// from the sequence space.
let mut ack_len = 0;
let mut ack_of_fin = false;
let mut ack_all = false;
if repr.control != TcpControl::Rst {
if let Some(ack_number) = repr.ack_number {
// Sequence number corresponding to the first byte in `tx_buffer`.
Expand All @@ -1477,6 +1478,8 @@ impl<'a> Socket<'a> {
tcp_trace!("received ACK of FIN");
ack_of_fin = true;
}

ack_all = self.remote_last_seq == ack_number
}

self.rtte.on_ack(cx.now(), ack_number);
Expand Down Expand Up @@ -1585,7 +1588,7 @@ impl<'a> Socket<'a> {
// ACK packets in ESTABLISHED state reset the retransmit timer,
// except for duplicate ACK packets which preserve it.
(State::Established, TcpControl::None) => {
if !self.timer.is_retransmit() || ack_len != 0 {
if !self.timer.is_retransmit() || ack_all {
self.timer.set_for_idle(cx.now(), self.keep_alive);
}
}
Expand All @@ -1604,7 +1607,9 @@ impl<'a> Socket<'a> {
if ack_of_fin {
self.set_state(State::FinWait2);
}
self.timer.set_for_idle(cx.now(), self.keep_alive);
if ack_all {
self.timer.set_for_idle(cx.now(), self.keep_alive);
}
}

// FIN packets in FIN-WAIT-1 state change it to CLOSING, or to TIME-WAIT
Expand Down Expand Up @@ -4979,6 +4984,85 @@ mod test {
recv_nothing!(s, time 1550);
}

#[test]
fn test_data_retransmit_bursts_half_ack() {
let mut s = socket_established();
s.remote_mss = 6;
s.send_slice(b"abcdef012345").unwrap();

recv!(s, time 0, Ok(TcpRepr {
control: TcpControl::None,
seq_number: LOCAL_SEQ + 1,
ack_number: Some(REMOTE_SEQ + 1),
payload: &b"abcdef"[..],
..RECV_TEMPL
}), exact);
recv!(s, time 0, Ok(TcpRepr {
control: TcpControl::Psh,
seq_number: LOCAL_SEQ + 1 + 6,
ack_number: Some(REMOTE_SEQ + 1),
payload: &b"012345"[..],
..RECV_TEMPL
}), exact);
// Acknowledge the first packet
send!(s, time 5, TcpRepr {
seq_number: REMOTE_SEQ + 1,
ack_number: Some(LOCAL_SEQ + 1 + 6),
window_len: 6,
..SEND_TEMPL
});
// The second packet should be re-sent.
recv!(s, time 1500, Ok(TcpRepr {
control: TcpControl::Psh,
seq_number: LOCAL_SEQ + 1 + 6,
ack_number: Some(REMOTE_SEQ + 1),
payload: &b"012345"[..],
..RECV_TEMPL
}), exact);

recv_nothing!(s, time 1550);
}

#[test]
fn test_data_retransmit_bursts_half_ack_close() {
let mut s = socket_established();
s.remote_mss = 6;
s.send_slice(b"abcdef012345").unwrap();
s.close();

recv!(s, time 0, Ok(TcpRepr {
control: TcpControl::None,
seq_number: LOCAL_SEQ + 1,
ack_number: Some(REMOTE_SEQ + 1),
payload: &b"abcdef"[..],
..RECV_TEMPL
}), exact);
recv!(s, time 0, Ok(TcpRepr {
control: TcpControl::Fin,
seq_number: LOCAL_SEQ + 1 + 6,
ack_number: Some(REMOTE_SEQ + 1),
payload: &b"012345"[..],
..RECV_TEMPL
}), exact);
// Acknowledge the first packet
send!(s, time 5, TcpRepr {
seq_number: REMOTE_SEQ + 1,
ack_number: Some(LOCAL_SEQ + 1 + 6),
window_len: 6,
..SEND_TEMPL
});
// The second packet should be re-sent.
recv!(s, time 1500, Ok(TcpRepr {
control: TcpControl::Fin,
seq_number: LOCAL_SEQ + 1 + 6,
ack_number: Some(REMOTE_SEQ + 1),
payload: &b"012345"[..],
..RECV_TEMPL
}), exact);

recv_nothing!(s, time 1550);
}

#[test]
fn test_send_data_after_syn_ack_retransmit() {
let mut s = socket_syn_received();
Expand Down

0 comments on commit a25c9f2

Please sign in to comment.