Linux – minimal TCP MSS in Linux

linuxlinux-kernelnetworkingtcp

The TCP MSS in Linux must be at least 88 (include/net/tcp.h):

/* Minimal accepted MSS. It is (60+60+8) - (20+20). */
#define TCP_MIN_MSS             88U

My question is: where did they come up with "60 + 60 + 8" and why? I get that 20 + 20 comes from the IP header + TCP header.

EDIT: After taking a closer look at the headers, the formula looks for me like this:

(MAX_IP_HDR + MAX_TCP_HDR + MIN_IP_FRAG) - (MIN_IP_HDR + MIN_TCP_HDR)

The question still stands: why? Why does the Linux kernel use this formula, thereby prohibiting (a forced flow of) TCP segments of, say, 20 bytes? Think iperf here.

EDIT2: Here's my use case. By forcing a low MSS on socket/connection, all the packets sent by the stack will have a small size. I want to set a low MSS when working with iperf for packets/second testing. I can't get IP packets smaller than 128 bytes (Ethernet frames of 142 bytes) on the wire because of this lower limit for the MSS! I would like to get as close to an Ethernet frame size of 64 bytes as per RFC 2544. Theoretically this should be possible: 18 + 20 + 20 < 64.

Best Answer

An implementation is required to support the maximum-sized TCP and IP headers, which are 60 bytes each.

An implementation must support 576-byte datagrams, which even with maximum-headers means more than 8 bytes of data in the datagram. To send datagrams with more than 8 bytes of data, IP fragmentation must put at least 8 bytes of data in at least one of the packets that represent the fragments of the datagram. Thus an implementation must support at least 8 bytes of data in a packet.

Putting this together, an implementation must support 60+60+8 byte packets.

When we send packets that are part of a TCP stream, they have a 20-byte IP header (plus options) and a 20-byte TCP header (plus options). That leaves a minimum of (60+60+8)-(20+20) bytes remaining for data and options. Hence this is the maximum we can safely assume an implementation's TCP MSS.

Related Question