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:
parent
1d46ccf432
commit
555825e49e
|
@ -1080,13 +1080,21 @@ impl<'a> TcpSocket<'a> {
|
||||||
};
|
};
|
||||||
let ip_repr = try!(ip_repr.lower(&[]));
|
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 {
|
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);
|
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)
|
emit(&ip_repr, &repr)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::Exhausted)
|
Err(Error::Exhausted)
|
||||||
|
@ -2489,4 +2497,37 @@ mod test {
|
||||||
..RECV_TEMPL
|
..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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue