TCP: retransmit ACK when receiving duplicate SEQ.

This commit is contained in:
whitequark 2016-12-31 01:24:55 +00:00
parent 64a8c36118
commit 818e98f47a
3 changed files with 53 additions and 1 deletions

View File

@ -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)));

View File

@ -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
}]);
}
}

View File

@ -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;