Update remote_last_win for all ACKs
Only ACKs generated by `dispatch` were updating `remote_last_win` but not the ACKs generated by `process`, failing to keep track of the last announced receive window. This left `window_to_update` to return false in `dispatch` after the RX buffer was emptied, thus not announcing that the receive window is not zero anymore. The change updates `remote_last_win` for immediate ACKs generated by `process`. Closes: #200 Approved by: whitequark
This commit is contained in:
parent
879e3ea3cd
commit
fada9d4e27
|
@ -782,7 +782,7 @@ impl<'a> TcpSocket<'a> {
|
|||
(ip_reply_repr, reply_repr)
|
||||
}
|
||||
|
||||
fn ack_reply(&self, ip_repr: &IpRepr, repr: &TcpRepr) -> (IpRepr, TcpRepr<'static>) {
|
||||
fn ack_reply(&mut self, ip_repr: &IpRepr, repr: &TcpRepr) -> (IpRepr, TcpRepr<'static>) {
|
||||
let (ip_reply_repr, mut reply_repr) = Self::reply(ip_repr, repr);
|
||||
|
||||
// From RFC 793:
|
||||
|
@ -792,6 +792,7 @@ impl<'a> TcpSocket<'a> {
|
|||
reply_repr.seq_number = self.remote_last_seq;
|
||||
reply_repr.ack_number = self.remote_last_ack;
|
||||
reply_repr.window_len = self.rx_buffer.window() as u16;
|
||||
self.remote_last_win = reply_repr.window_len;
|
||||
|
||||
(ip_reply_repr, reply_repr)
|
||||
}
|
||||
|
@ -3340,6 +3341,66 @@ mod test {
|
|||
}]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_announce_window_after_read() {
|
||||
let mut s = socket_established();
|
||||
s.rx_buffer = SocketBuffer::new(vec![0; 6]);
|
||||
s.assembler = Assembler::new(s.rx_buffer.capacity());
|
||||
send!(s, TcpRepr {
|
||||
seq_number: REMOTE_SEQ + 1,
|
||||
ack_number: Some(LOCAL_SEQ + 1),
|
||||
payload: &b"abc"[..],
|
||||
..SEND_TEMPL
|
||||
});
|
||||
recv!(s, [TcpRepr {
|
||||
seq_number: LOCAL_SEQ + 1,
|
||||
ack_number: Some(REMOTE_SEQ + 1 + 3),
|
||||
window_len: 3,
|
||||
..RECV_TEMPL
|
||||
}]);
|
||||
// Test that `dispatch` updates `remote_last_win`
|
||||
assert_eq!(s.remote_last_win, s.rx_buffer.window() as u16);
|
||||
s.recv(|buffer| {
|
||||
(buffer.len(), ())
|
||||
}).unwrap();
|
||||
assert!(s.window_to_update());
|
||||
recv!(s, [TcpRepr {
|
||||
seq_number: LOCAL_SEQ + 1,
|
||||
ack_number: Some(REMOTE_SEQ + 1 + 3),
|
||||
window_len: 6,
|
||||
..RECV_TEMPL
|
||||
}]);
|
||||
assert_eq!(s.remote_last_win, s.rx_buffer.window() as u16);
|
||||
// Provoke immediate ACK to test that `process` updates `remote_last_win`
|
||||
send!(s, TcpRepr {
|
||||
seq_number: REMOTE_SEQ + 1 + 6,
|
||||
ack_number: Some(LOCAL_SEQ + 1),
|
||||
payload: &b"def"[..],
|
||||
..SEND_TEMPL
|
||||
}, Ok(Some(TcpRepr {
|
||||
seq_number: LOCAL_SEQ + 1,
|
||||
ack_number: Some(REMOTE_SEQ + 1 + 3),
|
||||
window_len: 6,
|
||||
..RECV_TEMPL
|
||||
})));
|
||||
send!(s, TcpRepr {
|
||||
seq_number: REMOTE_SEQ + 1 + 3,
|
||||
ack_number: Some(LOCAL_SEQ + 1),
|
||||
payload: &b"abc"[..],
|
||||
..SEND_TEMPL
|
||||
}, Ok(Some(TcpRepr {
|
||||
seq_number: LOCAL_SEQ + 1,
|
||||
ack_number: Some(REMOTE_SEQ + 1 + 9),
|
||||
window_len: 0,
|
||||
..RECV_TEMPL
|
||||
})));
|
||||
assert_eq!(s.remote_last_win, s.rx_buffer.window() as u16);
|
||||
s.recv(|buffer| {
|
||||
(buffer.len(), ())
|
||||
}).unwrap();
|
||||
assert!(s.window_to_update());
|
||||
}
|
||||
|
||||
// =========================================================================================//
|
||||
// Tests for timeouts.
|
||||
// =========================================================================================//
|
||||
|
|
Loading…
Reference in New Issue