Procházet zdrojové kódy

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
Kai Lüke před 6 roky
rodič
revize
7699265a09
1 změnil soubory, kde provedl 34 přidání a 3 odebrání
  1. 34 3
      src/socket/tcp.rs

+ 34 - 3
src/socket/tcp.rs

@@ -1157,9 +1157,10 @@ impl<'a> TcpSocket<'a> {
                 // Duplicate ACK if payload empty and ACK doesn't move send window ->
                 // Increment duplicate ACK count and set for retransmit if we just recived
                 // the third duplicate ACK
-                Some(ref mut last_rx_ack) if
+                Some(ref last_rx_ack) if
                     repr.payload.len() == 0 &&
-                    *last_rx_ack == ack_number => {
+                    *last_rx_ack == ack_number &&
+                    ack_number < self.remote_last_seq => {
                     // Increment duplicate ACK count
                     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() {
         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
         send!(s, TcpRepr {
             seq_number: REMOTE_SEQ + 1,
@@ -3345,6 +3354,9 @@ mod test {
             ..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
         // as a duplicate ACK and should reset the duplicate ACK count
         send!(s, TcpRepr {
@@ -3355,7 +3367,7 @@ mod test {
         });
 
         recv!(s, [TcpRepr {
-            seq_number: LOCAL_SEQ + 1,
+            seq_number: LOCAL_SEQ + 1 + 3,
             ack_number: Some(REMOTE_SEQ + 1 + 6),
             window_len: 58,
             ..RECV_TEMPL
@@ -3377,6 +3389,17 @@ mod test {
             ..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
         // because of previously recieved "window_len"
         s.send_slice(b"xxxxxxyyyyyywwwwwwzzzzzz").unwrap();
@@ -3444,6 +3467,14 @@ mod test {
     fn test_fast_retransmit_dup_acks_counter() {
         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 {
             seq_number: REMOTE_SEQ + 1,
             ack_number: Some(LOCAL_SEQ + 1),