Sfoglia il codice sorgente

Restart retransmit timer on new data ACK

Simon Börjesson 5 mesi fa
parent
commit
13774ff28d
1 ha cambiato i file con 51 aggiunte e 15 eliminazioni
  1. 51 15
      src/socket/tcp.rs

+ 51 - 15
src/socket/tcp.rs

@@ -337,19 +337,12 @@ impl Timer {
 
     fn set_for_retransmit(&mut self, timestamp: Instant, delay: Duration) {
         match *self {
-            Timer::Idle { .. } | Timer::FastRetransmit { .. } => {
+            Timer::Idle { .. } | Timer::FastRetransmit { .. } | Timer::Retransmit { .. } => {
                 *self = Timer::Retransmit {
                     expires_at: timestamp + delay,
                     delay,
                 }
             }
-            Timer::Retransmit { expires_at, delay } if timestamp >= expires_at => {
-                *self = Timer::Retransmit {
-                    expires_at: timestamp + delay,
-                    delay: delay * 2,
-                }
-            }
-            Timer::Retransmit { .. } => (),
             Timer::Close { .. } => (),
         }
     }
@@ -1842,11 +1835,14 @@ impl<'a> Socket<'a> {
                 self.timer.set_for_idle(cx.now(), self.keep_alive);
             }
 
-            // ACK packets in ESTABLISHED state reset the retransmit timer,
-            // except for duplicate ACK packets which preserve it.
+            // RFC 6298: (5.2) ACK of all outstanding data turn off the retransmit timer.
+            // (5.3) ACK of new data in ESTABLISHED state restart the retransmit timer.
             (State::Established, TcpControl::None) => {
-                if !self.timer.is_retransmit() || ack_all {
+                if ack_all {
                     self.timer.set_for_idle(cx.now(), self.keep_alive);
+                } else if ack_len > 0 {
+                    self.timer
+                        .set_for_retransmit(cx.now(), self.rtte.retransmission_timeout());
                 }
             }
 
@@ -2528,9 +2524,10 @@ impl<'a> Socket<'a> {
                 .post_transmit(cx.now(), repr.segment_len());
         }
 
-        if !self.seq_to_transmit(cx) && repr.segment_len() > 0 {
-            // If we've transmitted all data we could (and there was something at all,
-            // data or flag, to transmit, not just an ACK), wind up the retransmit timer.
+        if !self.seq_to_transmit(cx) && repr.segment_len() > 0 && !self.timer.is_retransmit() {
+            // RFC 6298: (5.1) If we've transmitted all data we could (and there was
+            // something at all, data or flag, to transmit, not just an ACK), start the
+            // retransmit timer if it is not already running.
             self.timer
                 .set_for_retransmit(cx.now(), self.rtte.retransmission_timeout());
         }
@@ -5678,6 +5675,45 @@ mod test {
         recv_nothing!(s, time 1550);
     }
 
+    #[test]
+    fn test_retransmit_timer_restart_on_partial_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 600, TcpRepr {
+            seq_number: REMOTE_SEQ + 1,
+            ack_number: Some(LOCAL_SEQ + 1 + 6),
+            window_len: 6,
+            ..SEND_TEMPL
+        });
+        // The ACK of the first packet should restart the retransmit timer and delay a retransmission.
+        recv_nothing!(s, time 1500);
+        // The second packet should be re-sent.
+        recv!(s, time 1600, Ok(TcpRepr {
+            control:    TcpControl::Psh,
+            seq_number: LOCAL_SEQ + 1 + 6,
+            ack_number: Some(REMOTE_SEQ + 1),
+            payload:    &b"012345"[..],
+            ..RECV_TEMPL
+        }), exact);
+    }
+
     #[test]
     fn test_data_retransmit_bursts_half_ack_close() {
         let mut s = socket_established();
@@ -7794,7 +7830,7 @@ mod test {
         assert_eq!(r.should_retransmit(Instant::from_millis(1200)), None);
         assert_eq!(
             r.should_retransmit(Instant::from_millis(1301)),
-            Some(Duration::from_millis(300))
+            Some(Duration::from_millis(200))
         );
         r.set_for_idle(Instant::from_millis(1301), None);
         assert_eq!(r.should_retransmit(Instant::from_millis(1350)), None);