Subject: Re: TCP MSS not adhered to properly when options present
To: None <tech-net@netbsd.org>
From: Scott Barron <sb125499@oak.cats.ohiou.edu>
List: tech-net
Date: 11/30/2001 10:10:52
On Fri, Nov 30, 2001 at 09:30:15AM -0500, Rick Byers wrote:
> On Fri, 30 Nov 2001, Scott Barron wrote:
> 
> > > NetBSD doesn't appear to be handling the TCP MSS option properly.
> > > According to RFC 1122, the MSS sent by a host is the maximum IP packet
> > > size its willing to receive minus 40.  This correlates to the maximum
> > > tcp payload when no tcp or ip options are present.  However, NetBSD
> > > appears to use it as the maximum tcp payload even when options are
> > > present.
> >
> > I am pretty much a novice when it comes to the networking code but the
> > way I understand it is the MSS options are exchanged when a connection
> > is created.  However the option length may not be constant during the
> > lifetime of the connection (a host that sends SACK blocks, something I'm
> > currently working on, is a good example of this).  So I see only two
> > things, set it to the size that is sent, which is what I think it
> > currently does (looking at tcp_input.c in 1.5.2) or set it to the size
> > advertised minus MAX_TCPOPTLEN and take and go for the "worst case" so
> > to speak.  Personally, I'm not sure which is a better idea and I don't
> > know how other systems handle it (I suspect the same way).  Maybe
> > somebody more experienced can chime in here (also please chime in if
> > I've gotten anything incorrect).
> 
> Right.  That is exactly why the RFCs define the MSS to be the maximum IP
> packet size minus 40.  That way, the extra IP or TCP options count against
> the segment size to keep the total packet size bounded at a constant
> (MSS+40).
> 
> > > I haven't had a chance to look into the source for either of theese
> > > problems, but I hope to have time this weekend if someone doesn't beat me
> > > to it.
> >
> > The sent MSS is recorded in tcp_dooptions() in tcp_input.c (grep for
> > TCPOPT_MAXSEG, my file is too hacked up to give you a valid line
> > number), to give you a starting point.
> 
> Cool, thanks.  I'll take a look this weekend and see if I can come up with
> a fix.  All that should be required is to subtract the length of any TCP
> or IP options when desciding how much payload to include in a TCP
> packet...
> 
> Thanks,
> 	Rick

Alright I broke out TCP/IP Illustrated v2 and noticed the following
snippet of code that is missing from the NetBSD code:

/*
 * Adjust data length if insertion of options will
 * bump the packet length beyond the t_maxseg length.
 */
if (len > tp->t_maxseg - optlen) {
    len = tp->t_maxseg - optlen;
    sendalot = 1;
}

This seems to do what you're talking about but I'm not sure why it was
removed (haven't been around that long).  Would this do the trick?
(Against a -current checked out very early this morning (Nov 30)).  This
built but I haven't tested it.

Index: tcp_output.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/tcp_output.c,v
retrieving revision 1.75
diff -r1.75 tcp_output.c
745a746,750
> 
>       if (len > txsegsize - optlen) {
>               len = txsegsize - optlen;
>               sendalot = 1;
>       }

-Scott