Clean up and document TCP MSS calculations.
This commit is contained in:
parent
ba2d7f483a
commit
f23bfe2014
|
@ -1172,6 +1172,17 @@ impl<'a> TcpSocket<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Construct the lowered IP representation.
|
||||||
|
// We might need this to calculate the MSS, so do it early.
|
||||||
|
let mut ip_repr = IpRepr::Unspecified {
|
||||||
|
src_addr: self.local_endpoint.addr,
|
||||||
|
dst_addr: self.remote_endpoint.addr,
|
||||||
|
protocol: IpProtocol::Tcp,
|
||||||
|
payload_len: 0
|
||||||
|
}.lower(&[])?;
|
||||||
|
|
||||||
|
// Construct the basic TCP representation, an empty ACK packet.
|
||||||
|
// We'll adjust this to be more specific as needed.
|
||||||
let mut repr = TcpRepr {
|
let mut repr = TcpRepr {
|
||||||
src_port: self.local_endpoint.port,
|
src_port: self.local_endpoint.port,
|
||||||
dst_port: self.remote_endpoint.port,
|
dst_port: self.remote_endpoint.port,
|
||||||
|
@ -1290,33 +1301,21 @@ impl<'a> TcpSocket<'a> {
|
||||||
is_keep_alive = false;
|
is_keep_alive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remember the header length before enabling the MSS option, since that option
|
|
||||||
// only affects SYN packets.
|
|
||||||
let header_len = repr.header_len();
|
|
||||||
|
|
||||||
if repr.control == TcpControl::Syn {
|
if repr.control == TcpControl::Syn {
|
||||||
// First enable the option, without assigning any value, to get a correct
|
// Compute the maximum segment size, deriving it from from the underlying
|
||||||
// result for the payload_len field of ip_repr below.
|
// maximum transmission unit and the IP and TCP header sizes.
|
||||||
repr.max_seg_size = Some(0);
|
//
|
||||||
}
|
// Note that what we actually *want* is for the other party to limit
|
||||||
|
// the total length of the TCP segment, but what we *get* is limiting
|
||||||
// Then, construct the IP representation, since we know the final length
|
// the amount of data in the TCP segment. As a result, if they interpret
|
||||||
// of the TCP header.
|
// the requirement naively and send us a TCP packet with both some options
|
||||||
let ip_repr = IpRepr::Unspecified {
|
// and an MSS-sized payload, that packet's last few bytes will get split
|
||||||
src_addr: self.local_endpoint.addr,
|
// into a tiny fragment.
|
||||||
dst_addr: self.remote_endpoint.addr,
|
//
|
||||||
protocol: IpProtocol::Tcp,
|
// TCP is not a well-designed protocol.
|
||||||
payload_len: repr.buffer_len()
|
|
||||||
}.lower(&[])?;
|
|
||||||
|
|
||||||
// Finally, compute the maximum segment size, deriving it from from the underlying
|
|
||||||
// maximum transmission unit and the header sizes we just determined.
|
|
||||||
let mut max_segment_size = limits.max_transmission_unit;
|
let mut max_segment_size = limits.max_transmission_unit;
|
||||||
max_segment_size -= header_len;
|
|
||||||
max_segment_size -= ip_repr.buffer_len();
|
max_segment_size -= ip_repr.buffer_len();
|
||||||
|
max_segment_size -= repr.header_len();
|
||||||
if repr.control == TcpControl::Syn {
|
|
||||||
// And fill in the actual option, if it's a SYN packet.
|
|
||||||
repr.max_seg_size = Some(max_segment_size as u16);
|
repr.max_seg_size = Some(max_segment_size as u16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue