RFC 879

The TCP Maximum Segment Size and Related Topics

๐Ÿ“… published November 1983, from ietf

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