RFC 879
The TCP Maximum Segment Size and Related Topics
RFC 879: The TCP Maximum Segment Size and Related Topics ๐
Part 1 of 2: title block and sections 1 to 5. More is coming, bestie ๐
Okay so this RFC is from November 1983 ๐ธ and it's written by J. Postel from ISI, for the Network Working Group. It's an RFC, so it's one of those official Internet documents that define how protocols work. The title block doesn't list a category, and it doesn't say it obsoletes or updates anything. What it does say is that it's a clarification to the TCP spec, and that it's full of "advice to implementers" ๐ง
This memo is about the TCP Maximum Segment Size (MSS) option and how it connects to the IP Maximum Datagram Size. The goal is to clear up some confusing bits of TCP and how it works with IP โจ
1. Introduction โจ
Okay so this is the whole vibe: the TCP Maximum Segment Size and its relationship to the IP Maximum Datagram Size. TCP is specified in reference [1], and IP is specified in references [2,3] ๐
We needed this discussion because the current spec for this TCP option is kinda ambiguous ๐
A big part of the confusion about these sizes is that the IP and TCP headers can be different lengths. Which, honestly, is a lot ๐
People have also made assumptions about using a datagram size other than the default, and those assumptions had some unfortunate results ๐ญ
HOSTS MUST NOT SEND DATAGRAMS LARGER THAN 576 OCTETS UNLESS THEY HAVE SPECIFIC KNOWLEDGE THAT THE DESTINATION HOST IS PREPARED TO ACCEPT LARGER DATAGRAMS. This is a long established rule. ๐
To fix the ambiguity in the TCP MSS option definition, this rule is now established:
THE TCP MAXIMUM SEGMENT SIZE IS THE IP MAXIMUM DATAGRAM SIZE MINUS FORTY.
The default IP Maximum Datagram Size is 576 ๐ฉท The default TCP Maximum Segment Size is 536 ๐ฉท
2. The IP Maximum Datagram Size ๐ฆ
Hosts are not REQUIRED to reassemble infinitely large IP datagrams, bestie, and that's a relief. The biggest datagram that all hosts are REQUIRED to accept or reassemble from fragments is 576 octets. The biggest reassembly buffer every host MUST have is also 576 octets ๐ซถ
Hosts are allowed to accept larger datagrams and to put fragments together into larger datagrams. Hosts MAY have buffers as large as they please, so go wild ๐
Hosts MUST NOT send datagrams larger than 576 octets unless they have specific knowledge that the destination host is prepared to accept larger datagrams. Main character energy is not sending giant packets to random hosts ๐ โโ๏ธ
3. The TCP Maximum Segment Size Option ๐
TCP has an option that can be used when a connection is set up (and only then) to say the biggest TCP segment that can be accepted on that connection. This Maximum Segment Size (MSS) announcement is sent from the data receiver to the data sender. It basically says "I can accept TCP segments up to size X." People often call it a negotiation, but it's really just an announcement ๐ The size X can be bigger or smaller than the default. The MSS can be used completely independently in each direction of data flow, so you can end up with really different maximum sizes in the two directions ๐ฅ
The MSS only counts data octets in the segment. It does not count the TCP header or the IP header ๐
A footnote, because I'm extra: the MSS value only counts data octets. That means it doesn't count the TCP SYN and FIN control bits, even though SYN and FIN still use up TCP sequence numbers ๐ง
4. The Relationship of TCP Segments and IP Datagrams ๐ธ
TCP segments get sent as the data inside IP datagrams. The correspondence between TCP segments and IP datagrams MUST be one to one. Why? TCP expects to find exactly one complete TCP segment in each block of data that IP hands over to it. And IP MUST hand over a block of data for each datagram it receives (or fully reassembles) ๐
5. Layering and Modularity ๐
TCP is an end to end reliable data stream protocol. It has error control, flow control, and more. TCP remembers a lot about the state of a connection ๐ง
IP is a one shot datagram protocol. IP has no memory of the datagrams it has sent. It is not appropriate for IP to keep any information about the maximum datagram size a particular destination host might be able to accept ๐ โโ๏ธ
TCP and IP are separate layers in the protocol architecture, and they're often implemented in separate program modules ๐งฉ
Some people seem to think there should be no communication between protocol layers or program modules at all. Nope! There MUST be communication between layers and modules, but it SHOULD be carefully specified and controlled ๐ Understanding the correct view of communication between layers or modules (especially between TCP and IP) is tricky, partly because the protocol documents aren't very clear about it. That's because those documents describe the protocol exchanges between machines, not the program architecture inside a machine. There's also a desire to allow many different program architectures, with different ways of organizing tasks into modules โจ
9. Source Fragmentation โจ
Okay bestie, so a source host normally wouldn't make datagram fragments at all ๐ Fragments basically only show up when a gateway has to shove a datagram into a network with a smaller maximum packet size. In that case the gateway has to fragment it, unless it's marked "don't fragment," in which case it gets thrown away, with the option of sending an ICMP message to the source to report the problem ๐ซ
Sometimes it might be desirable for the source host to send fragments, like if the maximum segment size (default or negotiated) that the data receiver allows is bigger than the maximum packet size of the directly attached network. But those fragments must not combine into something bigger than the destination host allows ๐ซถ
Here's an example: if the receiving TCP announced that it would accept segments up to 5000 octets (in cooperation with the receiving IP), then the sending TCP could hand such a large segment to the sending IP, as long as the sending IP sends it in datagram fragments that fit in the packets of the directly attached network.
There are also some situations where source host fragmentation is literally necessary ๐ญ
First, if the host is attached to a network with a small packet size (for example 256 octets), and it supports an application that's defined to send fixed sized messages larger than that packet size (for example TFTP [5]).
Second, if the host receives ICMP Echo messages with data, it's required to send an ICMP Echo-Reply message with the same data. If the amount of data in the Echo is larger than the packet size of the directly attached network, the steps might look like this: (1) receive the fragments, (2) reassemble the datagram, (3) interpret the Echo, (4) create an Echo-Reply, (5) fragment it, and (6) send the fragments. Main character energy, but exhausting ๐
10. Gateway Fragmentation ๐ธ
Gateways gotta be ready to do fragmentation. It's not an optional feature for a gateway, no cap ๐งฑ
Gateways have no info about the size of datagrams the destination hosts are prepared to accept. It would be inappropriate for gateways to try to keep track of that info ๐
Gateways must be prepared to accept the largest datagrams that are allowed on each of the directly attached networks, even if that's larger than 576 octets.
Gateways must be prepared to fragment datagrams to fit into the packets of the next network, even if that's smaller than 576 octets.
Now, if a source host wants to take advantage of the local network's ability to carry larger datagrams, but it has no idea whether the destination host can accept larger than default datagrams, and it expects the gateway to fragment the datagram into default size fragments... the source host is misguided, bestie ๐ค If the destination host can't accept larger than default datagrams, it probably can't reassemble them either. So whether the gateway passes the large datagram whole or fragments it into default size fragments, the destination won't accept it. This mode of behavior by source hosts must be outlawed. ๐จ
A larger than default datagram can only arrive at a gateway because the source host knows the destination host can handle such large datagrams (probably because the destination host announced it to the source host in a TCP MSS option). So the gateway should pass this large datagram on in one piece, or in the largest fragments that fit into the next network. Iconic behavior ๐
An interesting footnote: even though gateways may know about the 576 rule, it's irrelevant to them ๐คทโโ๏ธ
11. Inter-Layer Communication ๐ฆ
The Network Driver (ND) or interface should know the Maximum Transmission Unit (MTU) of the directly attached network.
The IP should ask the Network Driver for the Maximum Transmission Unit.
The TCP should ask the IP for the Maximum Datagram Data Size (MDDS). This is the MTU minus the IP header length:
MDDS = MTU - IPHdrLen
When opening a connection, TCP can send an MSS option with the value equal to MDDS - TCPHdrLen:
MSS option value = MDDS - TCPHdrLen
TCP should determine the Maximum Segment Data Size (MSDS) from either the default or the received value of the MSS option. โจ
TCP should also determine if source fragmentation is possible (by asking the IP) and desirable. ๐ง
If so, TCP may hand to IP segments (including the TCP header) up to MSDS + TCPHdrLen.
If not, TCP may hand to IP segments (including the TCP header) up to the lesser of (MSDS + TCPHdrLen) and MDDS.
IP checks the length of the data passed to it by TCP. If the length is less than or equal to MDDS, IP attaches the IP header and hands it to the ND. Otherwise, IP must do source fragmentation. It's giving teamwork ๐ซถ
12. What is the Default MSS ? ๐
Another way of asking this question is "What transmitted value for MSS has exactly the same effect of not transmitting the option at all?". Ooh, I love a good plot twist ๐
In terms of the previous section, here's the breakdown:
The default assumption is that the Maximum Transmission Unit is 576 octets.
MTU = 576
The Maximum Datagram Data Size (MDDS) is the MTU minus the IP header length.
MDDS = MTU - IPHdrLen = 576 - 20 = 556
When opening a connection, TCP can send an MSS option with the value equal to MDDS - TCPHdrLen.
MSS = MDDS - TCPHdrLen = 556 - 20 = 536
TCP should determine the Maximum Segment Data Size (MSDS) from either the default or the received value of the MSS option.
Default MSS = 536, then MSDS = 536
TCP should determine if source fragmentation is possible and desirable.
If so, TCP may hand to IP segments (including the TCP header) up to MSDS + TCPHdrLen (536 + 20 = 556).
If not, TCP may hand to IP segments (including the TCP header) up to the lesser of (MSDS + TCPHdrLen (536 + 20 = 556)) and MDDS (556).
13. The Truth ๐
The rule relating the maximum IP datagram size and the maximum TCP segment size is:
TCP Maximum Segment Size = IP Maximum Datagram Size - 40
This rule must match the default case. ๐
If the TCP Maximum Segment Size option is not transmitted, then the data sender is allowed to send IP datagrams of maximum size (576) with a minimum IP header (20) and a minimum TCP header (20), and thereby be able to stuff 536 octets of data into each TCP segment. Simple, clean, and iconic โจ
The definition of the MSS option can be stated like this:
The maximum number of data octets that may be received by the sender of this TCP option in TCP segments with no TCP header options transmitted in IP datagrams with no IP header options.
14. The Consequences ๐ฅ
When TCP is used in a situation where either the IP or TCP headers are not minimum, and yet the maximum IP datagram that can be received remains 576 octets, then the TCP Maximum Segment Size option must be used to reduce the limit on data octets allowed in a TCP segment. Headers getting chunky, so the MSS has to shrink ๐
For example, if the IP Security option (11 octets) were in use and the IP maximum datagram size remained at 576 octets, then TCP should send the MSS with a value of 525 (536-11). Math is slaying ๐งฎ
15. References ๐
- [1] Postel, J., ed., "Transmission Control Protocol - DARPA Internet Program Protocol Specification", RFC 793, USC/Information Sciences Institute, September 1981.
- [2] Postel, J., ed., "Internet Protocol - DARPA Internet Program Protocol Specification", RFC 791, USC/Information Sciences Institute, September 1981.
- [3] Postel, J., "Internet Control Message Protocol - DARPA Internet Program Protocol Specification", RFC 792, USC/Information Sciences Institute, September 1981.
- [4] Plummer, D., "An Ethernet Address Resolution Protocol or Converting Network Protocol Addresses to 48-bit Ethernet Addresses for Transmission on Ethernet Hardware", RFC 826, MIT/LCS, November 1982.
- [5] Sollins, K., "The TFTP Protocol (Revision 2)", RFC 783, MIT/LCS, June 1981.
That's the whole thing, bestie! ๐๐ฆ๐
๐ฆ where this page comes from
- ietf: rfc879 1983-11
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms