浏览代码

TCP: retransmit ACK when receiving duplicate SEQ.

whitequark 8 年之前
父节点
当前提交
5b4db5fe10
共有 3 个文件被更改,包括 53 次插入1 次删除
  1. 1 1
      src/phy/fault_injector.rs
  2. 41 0
      src/socket/tcp.rs
  3. 11 0
      src/wire/tcp.rs

+ 1 - 1
src/phy/fault_injector.rs

@@ -122,7 +122,7 @@ impl<T: Device> Device for FaultInjector<T>
     fn transmit(&mut self, length: usize) -> Result<Self::TxBuffer, Error> {
         let buffer;
         if check_rng(&mut self.state, self.config.drop_pct) {
-            net_trace!("rx: dropping a packet");
+            net_trace!("tx: dropping a packet");
             buffer = None;
         } else {
             buffer = Some(try!(self.lower.transmit(length)));

+ 41 - 0
src/socket/tcp.rs

@@ -542,6 +542,9 @@ impl<'a> TcpSocket<'a> {
                     net_trace!("tcp:{}:{}: duplicate SEQ ({} in ..{})",
                                self.local_endpoint, self.remote_endpoint,
                                seq_number, next_remote_seq);
+                    // If we've seen this sequence number already but the remote end is not aware
+                    // of that, make sure we send the acknowledgement again.
+                    self.remote_last_ack = next_remote_seq - 1;
                     return Ok(())
                 }
             }
@@ -1656,4 +1659,42 @@ mod test {
         assert_eq!(s.state, State::TimeWait);
         recv!(s, []);
     }
+
+    // =========================================================================================//
+    // Tests for retransmission on packet loss.
+    // =========================================================================================//
+    fn socket_recved() -> TcpSocket<'static> {
+        let mut s = socket_established();
+        send!(s, [TcpRepr {
+            seq_number: REMOTE_SEQ + 1,
+            ack_number: Some(LOCAL_SEQ + 1),
+            payload:    &b"abcdef"[..],
+            ..SEND_TEMPL
+        }]);
+        recv!(s, [TcpRepr {
+            seq_number: LOCAL_SEQ + 1,
+            ack_number: Some(REMOTE_SEQ + 1 + 6),
+            window_len: 58,
+            ..RECV_TEMPL
+        }]);
+        s
+    }
+
+    #[test]
+    fn test_duplicate_seq_ack() {
+        let mut s = socket_recved();
+        // remote retransmission
+        send!(s, [TcpRepr {
+            seq_number: REMOTE_SEQ + 1,
+            ack_number: Some(LOCAL_SEQ + 1),
+            payload:    &b"abcdef"[..],
+            ..SEND_TEMPL
+        }]);
+        recv!(s, [TcpRepr {
+            seq_number: LOCAL_SEQ + 1,
+            ack_number: Some(REMOTE_SEQ + 1 + 6),
+            window_len: 58,
+            ..RECV_TEMPL
+        }]);
+    }
 }

+ 11 - 0
src/wire/tcp.rs

@@ -29,6 +29,17 @@ impl ops::Add<usize> for SeqNumber {
     }
 }
 
+impl ops::Sub<usize> for SeqNumber {
+    type Output = SeqNumber;
+
+    fn sub(self, rhs: usize) -> SeqNumber {
+        if rhs > i32::MAX as usize {
+            panic!("attempt to subtract to sequence number with unsigned overflow")
+        }
+        SeqNumber(self.0.wrapping_sub(rhs as i32))
+    }
+}
+
 impl ops::AddAssign<usize> for SeqNumber {
     fn add_assign(&mut self, rhs: usize) {
         *self = *self + rhs;