Send the TCP MSS option.

v0.7.x
whitequark 2017-01-27 02:49:06 +00:00
parent 077513fda6
commit bc1d65ea89
5 changed files with 34 additions and 21 deletions

View File

@ -353,10 +353,11 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
let src_protocol_addrs = self.protocol_addrs.as_ref();
let arp_cache = &mut self.arp_cache;
let device = &mut self.device;
let mtu = device.mtu() - EthernetFrame::<&[u8]>::header_len();
let mut nothing_to_transmit = true;
for socket in sockets.iter_mut() {
let result = socket.dispatch(timestamp, &mut |repr, payload| {
let result = socket.dispatch(timestamp, mtu, &mut |repr, payload| {
let repr = try!(repr.lower(src_protocol_addrs));
let dst_hardware_addr =

View File

@ -92,9 +92,10 @@ impl<'a, 'b> Socket<'a, 'b> {
/// is returned.
///
/// This function is used internally by the networking stack.
pub fn dispatch<F, R>(&mut self, timestamp: u64, emit: &mut F) -> Result<R, Error>
pub fn dispatch<F, R>(&mut self, timestamp: u64, mtu: usize,
emit: &mut F) -> Result<R, Error>
where F: FnMut(&IpRepr, &IpPayload) -> Result<R, Error> {
dispatch_socket!(self, |socket [mut]| socket.dispatch(timestamp, emit))
dispatch_socket!(self, |socket [mut]| socket.dispatch(timestamp, mtu, emit))
}
}

View File

@ -816,7 +816,8 @@ impl<'a> TcpSocket<'a> {
}
/// See [Socket::dispatch](enum.Socket.html#method.dispatch).
pub fn dispatch<F, R>(&mut self, timestamp: u64, emit: &mut F) -> Result<R, Error>
pub fn dispatch<F, R>(&mut self, timestamp: u64, mtu: usize,
emit: &mut F) -> Result<R, Error>
where F: FnMut(&IpRepr, &IpPayload) -> Result<R, Error> {
if self.remote_endpoint.is_unspecified() { return Err(Error::Exhausted) }
@ -875,19 +876,12 @@ impl<'a> TcpSocket<'a> {
}
// We transmit a SYN|ACK in the SYN-RECEIVED state.
State::SynReceived => {
repr.control = TcpControl::Syn;
net_trace!("[{}]{}:{}: sending SYN|ACK",
self.debug_id, self.local_endpoint, self.remote_endpoint);
should_send = true;
}
// We transmit a SYN in the SYN-SENT state.
State::SynSent => {
State::SynReceived | State::SynSent => {
repr.control = TcpControl::Syn;
repr.ack_number = None;
net_trace!("[{}]{}:{}: sending SYN",
self.debug_id, self.local_endpoint, self.remote_endpoint);
net_trace!("[{}]{}:{}: sending SYN{}",
self.debug_id, self.local_endpoint, self.remote_endpoint,
if repr.ack_number.is_some() { "|ACK" } else { "" });
should_send = true;
}
@ -965,11 +959,18 @@ impl<'a> TcpSocket<'a> {
self.remote_last_ack = ack_number;
let ip_repr = IpRepr::Unspecified {
src_addr: self.local_endpoint.addr,
dst_addr: self.remote_endpoint.addr,
protocol: IpProtocol::Tcp,
payload_len: repr.buffer_len()
src_addr: self.local_endpoint.addr,
dst_addr: self.remote_endpoint.addr,
protocol: IpProtocol::Tcp,
payload_len: repr.buffer_len()
};
let ip_repr = try!(ip_repr.lower(&[]));
if repr.control == TcpControl::Syn {
let mtu = mtu - repr.header_len() - ip_repr.buffer_len();
repr.max_seg_size = Some(mtu as u16);
}
emit(&ip_repr, &repr)
} else {
Err(Error::Exhausted)
@ -1082,7 +1083,7 @@ mod test {
fn recv<F>(socket: &mut TcpSocket, timestamp: u64, mut f: F)
where F: FnMut(Result<TcpRepr, Error>) {
let mut buffer = vec![];
let result = socket.dispatch(timestamp, &mut |ip_repr, payload| {
let result = socket.dispatch(timestamp, 1520, &mut |ip_repr, payload| {
assert_eq!(ip_repr.protocol(), IpProtocol::Tcp);
assert_eq!(ip_repr.src_addr(), LOCAL_IP);
assert_eq!(ip_repr.dst_addr(), REMOTE_IP);
@ -1295,6 +1296,7 @@ mod test {
control: TcpControl::Syn,
seq_number: LOCAL_SEQ,
ack_number: Some(REMOTE_SEQ + 1),
max_seg_size: Some(1480),
..RECV_TEMPL
}]);
send!(s, TcpRepr {
@ -1871,6 +1873,7 @@ mod test {
control: TcpControl::Syn,
seq_number: LOCAL_SEQ,
ack_number: Some(REMOTE_SEQ + 1),
max_seg_size: Some(1480),
..RECV_TEMPL
}]);
send!(s, TcpRepr {
@ -2102,12 +2105,14 @@ mod test {
control: TcpControl::Syn,
seq_number: LOCAL_SEQ,
ack_number: Some(REMOTE_SEQ + 1),
max_seg_size: Some(1480),
..RECV_TEMPL
}));
recv!(s, time 150, Ok(TcpRepr { // retransmit
control: TcpControl::Syn,
seq_number: LOCAL_SEQ,
ack_number: Some(REMOTE_SEQ + 1),
max_seg_size: Some(1480),
..RECV_TEMPL
}));
send!(s, TcpRepr {

View File

@ -232,7 +232,8 @@ impl<'a, 'b> UdpSocket<'a, 'b> {
}
/// See [Socket::dispatch](enum.Socket.html#method.dispatch).
pub fn dispatch<F, R>(&mut self, _timestamp: u64, emit: &mut F) -> Result<R, Error>
pub fn dispatch<F, R>(&mut self, _timestamp: u64, _mtu: usize,
emit: &mut F) -> Result<R, Error>
where F: FnMut(&IpRepr, &IpPayload) -> Result<R, Error> {
let packet_buf = try!(self.tx_buffer.dequeue().map_err(|()| Error::Exhausted));
net_trace!("[{}]{}:{}: sending {} octets",

View File

@ -96,6 +96,11 @@ impl<T: AsRef<[u8]>> Frame<T> {
self.buffer
}
/// Return the length of a frame header.
pub fn header_len() -> usize {
field::PAYLOAD.start
}
/// Return the length of a buffer required to hold a packet with the payload
/// of a given length.
pub fn buffer_len(payload_len: usize) -> usize {