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:


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.

  • How does this prohibit TCP segments of 20 bytes? Oct 24, 2011 at 2:41
  • MSS stands for Maximum Segment Size, it's upper limit (not lower) for segment size in particular connection. TCP_MIN_MSS specifies lower bound for this limit. So, it does not prohibit in any way segments with less then 88 bytes, it just states that MSS for any connection should be >= 88 bytes.
    – gelraen
    Oct 24, 2011 at 6:52
  • Of course! Sorry for not being clear enough. Please see the latest edit. Oct 24, 2011 at 12:16
  • Why did you let the bounty expire? David's answer clears things up to my satisfaction at least. The difference between his answer and mine is that we're talking about different minima. For what it's worth, there's a third minimum, that being 41, or 20+20+1 byte of TCP data. So the minimum packet size is contingent on the reason you are asking. I expect 68 is the right answer in the cases where the kernel uses TCP_MIN_MSS. Oct 24, 2011 at 18:30
  • I'm still not satisfied with the answer. I still fail to see the reason for which the kernel does not let me impose an arbirary small MSS to an app. I would love to have (a constant stream of TCP-loaded) IP packets of 41 bytes, but I can't, because of the TCP_MIN_MSS. Why can't it be 1? What RFC would it break? What theoreticat/practical problem would it cause? Are you sure it's "outside the spec"? "Different minima"? There's only one minimum of interest here: the smallest MSS allowed by the kernel. Oct 24, 2011 at 19:54

2 Answers 2


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.

  • 1
    The MSS doesn't include the header though (it's just the payload), and the 60 shows up twice Oct 23, 2011 at 4:36
  • An implementation must be able to support a packet with a maximum-sized header, but we are not sending a maximum-sized header. The difference between the maximum and what we actually send is therefore available for data and should be added to the MSS. Oct 23, 2011 at 4:43
  • OK, so you've explained the 8 bytes. I don't know what you mean by "TCP/IP" header. I know of an IP header and a TCP one. And, as Michael pointed out 60 shows up twice. And the RFC only discusses the "effective MSS" and not a minimal one. Oct 23, 2011 at 20:49
  • 60 shows up twice, once for the IP header and once for the TCP header. Oct 23, 2011 at 21:11
  • 68 is just about fragmentation. "60 + 60 + 8" might get fragmented, so why care about fragmentation then? Even "68 + 20" might get fragmented. And why "must" the other side "accept" "60 + 60 + 8"? "Accept" as in "without fragmentation"? Bottom line: why am I not allowed to send "20 + 20" + 10 bytes of data? Oct 23, 2011 at 22:28

I don't know where that number comes from, but I can tell you it's outside the spec. The minimum MTU supported for IP networks is 576 bytes, which is 512 data bytes plus up to 64 bytes for IP + TCP headers and TCP options. That value was chosen to give decently low overhead in the typical case.

My reading of bits of kernel code suggest that the value you're showing isn't arbitrary. There was an older practice to just use the raw constant 64 in place of TCP_MIN_MSS. Therefore, I assume there is some strange IP-over-Foo network the kernel developers came across that made them decide they could raise the value to what you see how.

What that nonstandard network type is, however, I cannot say.

  • 576 is the MTU for datagrams. In this case, it's the packet limits that matter, not the datagram limits because TCP packets set the DF bit. Oct 24, 2011 at 2:32
  • Minimum MTU defined for IP datagrams, and TCP packets are also IP datagrams.
    – gelraen
    Oct 24, 2011 at 6:56
  • Right, but this TCP limitation is for packets, not datagrams, because TCP datagrams never (normally) fragment. The only sense in which the 576-byte datagram rule matters is that it means the implementation must be able to support at least 8 bytes of data in a packet (hence the 8 in the formula). Otherwise, it would be impossible to fragment a 576-byte datagram. Oct 24, 2011 at 20:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .