Only trigger fast retransmit for data to send
This fixes entering a loop when both endpoints are stuck in retransmission. https://github.com/m-labs/smoltcp/issues/224 Closes: #233 Approved by: whitequark
This commit is contained in:
parent
272baab3ef
commit
b23df24a2a
|
@ -1157,9 +1157,10 @@ impl<'a> TcpSocket<'a> {
|
||||||
// Duplicate ACK if payload empty and ACK doesn't move send window ->
|
// Duplicate ACK if payload empty and ACK doesn't move send window ->
|
||||||
// Increment duplicate ACK count and set for retransmit if we just recived
|
// Increment duplicate ACK count and set for retransmit if we just recived
|
||||||
// the third duplicate ACK
|
// the third duplicate ACK
|
||||||
Some(ref mut last_rx_ack) if
|
Some(ref last_rx_ack) if
|
||||||
repr.payload.len() == 0 &&
|
repr.payload.len() == 0 &&
|
||||||
*last_rx_ack == ack_number => {
|
*last_rx_ack == ack_number &&
|
||||||
|
ack_number < self.remote_last_seq => {
|
||||||
// Increment duplicate ACK count
|
// Increment duplicate ACK count
|
||||||
self.local_rx_dup_acks = self.local_rx_dup_acks.saturating_add(1);
|
self.local_rx_dup_acks = self.local_rx_dup_acks.saturating_add(1);
|
||||||
|
|
||||||
|
@ -3326,6 +3327,14 @@ mod test {
|
||||||
fn test_fast_retransmit_duplicate_detection_with_data() {
|
fn test_fast_retransmit_duplicate_detection_with_data() {
|
||||||
let mut s = socket_established();
|
let mut s = socket_established();
|
||||||
|
|
||||||
|
s.send_slice(b"abc").unwrap(); // This is lost
|
||||||
|
recv!(s, time 1000, Ok(TcpRepr {
|
||||||
|
seq_number: LOCAL_SEQ + 1,
|
||||||
|
ack_number: Some(REMOTE_SEQ + 1),
|
||||||
|
payload: &b"abc"[..],
|
||||||
|
..RECV_TEMPL
|
||||||
|
}));
|
||||||
|
|
||||||
// Normal ACK of previously recieved segment
|
// Normal ACK of previously recieved segment
|
||||||
send!(s, TcpRepr {
|
send!(s, TcpRepr {
|
||||||
seq_number: REMOTE_SEQ + 1,
|
seq_number: REMOTE_SEQ + 1,
|
||||||
|
@ -3345,6 +3354,9 @@ mod test {
|
||||||
..SEND_TEMPL
|
..SEND_TEMPL
|
||||||
});
|
});
|
||||||
|
|
||||||
|
assert_eq!(s.local_rx_dup_acks, 2,
|
||||||
|
"duplicate ACK counter is not set");
|
||||||
|
|
||||||
// This packet has content, hence should not be detected
|
// This packet has content, hence should not be detected
|
||||||
// as a duplicate ACK and should reset the duplicate ACK count
|
// as a duplicate ACK and should reset the duplicate ACK count
|
||||||
send!(s, TcpRepr {
|
send!(s, TcpRepr {
|
||||||
|
@ -3355,7 +3367,7 @@ mod test {
|
||||||
});
|
});
|
||||||
|
|
||||||
recv!(s, [TcpRepr {
|
recv!(s, [TcpRepr {
|
||||||
seq_number: LOCAL_SEQ + 1,
|
seq_number: LOCAL_SEQ + 1 + 3,
|
||||||
ack_number: Some(REMOTE_SEQ + 1 + 6),
|
ack_number: Some(REMOTE_SEQ + 1 + 6),
|
||||||
window_len: 58,
|
window_len: 58,
|
||||||
..RECV_TEMPL
|
..RECV_TEMPL
|
||||||
|
@ -3377,6 +3389,17 @@ mod test {
|
||||||
..SEND_TEMPL
|
..SEND_TEMPL
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// First duplicate, should not be counted as there is nothing to resend
|
||||||
|
send!(s, time 0, TcpRepr {
|
||||||
|
seq_number: REMOTE_SEQ + 1,
|
||||||
|
ack_number: Some(LOCAL_SEQ + 1),
|
||||||
|
window_len: 6,
|
||||||
|
..SEND_TEMPL
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(s.local_rx_dup_acks, 0,
|
||||||
|
"duplicate ACK counter is set but wound not transmit data");
|
||||||
|
|
||||||
// Send a long string of text divided into several packets
|
// Send a long string of text divided into several packets
|
||||||
// because of previously recieved "window_len"
|
// because of previously recieved "window_len"
|
||||||
s.send_slice(b"xxxxxxyyyyyywwwwwwzzzzzz").unwrap();
|
s.send_slice(b"xxxxxxyyyyyywwwwwwzzzzzz").unwrap();
|
||||||
|
@ -3444,6 +3467,14 @@ mod test {
|
||||||
fn test_fast_retransmit_dup_acks_counter() {
|
fn test_fast_retransmit_dup_acks_counter() {
|
||||||
let mut s = socket_established();
|
let mut s = socket_established();
|
||||||
|
|
||||||
|
s.send_slice(b"abc").unwrap(); // This is lost
|
||||||
|
recv!(s, time 0, Ok(TcpRepr {
|
||||||
|
seq_number: LOCAL_SEQ + 1,
|
||||||
|
ack_number: Some(REMOTE_SEQ + 1),
|
||||||
|
payload: &b"abc"[..],
|
||||||
|
..RECV_TEMPL
|
||||||
|
}));
|
||||||
|
|
||||||
send!(s, time 0, TcpRepr {
|
send!(s, time 0, TcpRepr {
|
||||||
seq_number: REMOTE_SEQ + 1,
|
seq_number: REMOTE_SEQ + 1,
|
||||||
ack_number: Some(LOCAL_SEQ + 1),
|
ack_number: Some(LOCAL_SEQ + 1),
|
||||||
|
|
Loading…
Reference in New Issue