Clamp TCP receive window to MSS multiplied by maximum burst size.

This is a conservative bound; if we don't have enough buffers
to receive more than four segments, clearly we shouldn't advertise
our ability to.

It however will only work reliably with exactly one TCP connection
continuously receiving; for two, another window adjustment mechanism
will be needed for reliable reception.
This commit is contained in:
whitequark 2017-03-07 11:21:49 +00:00
parent 1d46ccf432
commit 555825e49e
1 changed files with 44 additions and 3 deletions

View File

@ -1080,13 +1080,21 @@ impl<'a> TcpSocket<'a> {
};
let ip_repr = try!(ip_repr.lower(&[]));
let mut max_segment_size = limits.max_transmission_unit;
max_segment_size -= header_len;
max_segment_size -= ip_repr.buffer_len();
if repr.control == TcpControl::Syn {
let mut max_segment_size = limits.max_transmission_unit;
max_segment_size -= header_len;
max_segment_size -= ip_repr.buffer_len();
repr.max_seg_size = Some(max_segment_size as u16);
}
if let Some(max_burst_size) = limits.max_burst_size {
let max_window_size = max_burst_size * max_segment_size;
if repr.window_len as usize > max_window_size {
repr.window_len = max_window_size as u16;
}
}
emit(&ip_repr, &repr)
} else {
Err(Error::Exhausted)
@ -2489,4 +2497,37 @@ mod test {
..RECV_TEMPL
}])
}
// =========================================================================================//
// Tests for window management.
// =========================================================================================//
#[test]
fn test_window_size_clamp() {
let mut s = socket_established();
s.rx_buffer = SocketBuffer::new(vec![0; 32767]);
let mut limits = DeviceLimits::default();
limits.max_transmission_unit = 1520;
limits.max_burst_size = None;
s.send_slice(b"abcdef").unwrap();
s.dispatch(0, &limits, &mut |ip_repr, payload| {
let mut buffer = vec![0; payload.buffer_len()];
payload.emit(&ip_repr, &mut buffer[..]);
let packet = TcpPacket::new(&buffer[..]).unwrap();
assert_eq!(packet.window_len(), 32767);
Ok(())
}).unwrap();
limits.max_burst_size = Some(4);
s.send_slice(b"abcdef").unwrap();
s.dispatch(0, &limits, &mut |ip_repr, payload| {
let mut buffer = vec![0; payload.buffer_len()];
payload.emit(&ip_repr, &mut buffer[..]);
let packet = TcpPacket::new(&buffer[..]).unwrap();
assert_eq!(packet.window_len(), 5920);
Ok(())
}).unwrap();
}
}