Page MenuHomeFreeBSD

tcp: report MSS correctly that subtracts TCP option length
Needs RevisionPublic

Authored by cc on Mon, Jan 26, 5:10 PM.
Tags
None
Referenced Files
F143210917: D54896.id170472.diff
Tue, Jan 27, 12:40 PM
F143198363: D54896.id170472.diff
Tue, Jan 27, 7:47 AM
F143188679: D54896.diff
Tue, Jan 27, 4:13 AM
Unknown Object (File)
Tue, Jan 27, 2:55 AM
Unknown Object (File)
Tue, Jan 27, 1:58 AM
Unknown Object (File)
Mon, Jan 26, 10:29 PM
Unknown Object (File)
Mon, Jan 26, 10:29 PM
Unknown Object (File)
Mon, Jan 26, 6:18 PM

Details

Reviewers
rscheff
tuexen
glebius
Group Reviewers
transport
Test Plan

On a mtu=1500 interface, such as "ifconfig lo0 mtu 1500":

before change:
command iperf3 -c 127.0.0.1 -n1 -V over IPv4 reports: TCP MSS: 1460 (default)
command iperf3 -c ::1 -n1 -V over IPv6 reports: TCP MSS: 1440 (default)

after change:
command iperf3 -c 127.0.0.1 -n1 -V over IPv4 reports: TCP MSS: 1448 (default)
command iperf3 -c ::1 -n1 -V over IPv6 reports: TCP MSS: 1428 (default)

Therefore, the result after the change matches it in MacOS.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 70147
Build 67030: arc lint + arc unit

Event Timeline

cc requested review of this revision.Mon, Jan 26, 5:10 PM
cc retitled this revision from report MSS correctly that subtracts TCP option length to tcp: report MSS correctly that subtracts TCP option length.Mon, Jan 26, 7:53 PM
cc edited the test plan for this revision. (Show Details)

My understanding is that the TCP MSS is the maximum number of payload bytes without any IP level or TCP level options. Are we going to change that? Then it should also apply to setsockopt(). But I don't see a reason why we should change that semantic.

This is not correct. First, the TCP_MAXSEG set with setsockopt(2) should match TCP_MAXSEG later retrieved with getsockopt(2). It refers to configured MSS. Second, tcp_maxseg() determines current possible MSS to be used with cwnd calculations. The result of tcp_maxseg() maybe different depending on current state of SACK. Randall later added tcp_fixed_maxseg() that ignores SACK. I'd leave other congestions experts to judge which one is correct for cwnd calculations. But neither tcp_fixed_maxseg() will work correctly here, as would break setsockopt/getsockopt result.

If you want the socket option to properly account for TCP options in the packet, a more sophisticated patch is required. The calculations shall be different for an ESTABLISHED connection and newborn.

This socket option is not standard. It first appeared in Linux, so probably Linux should be used as a reference behavior. Linux documents that setsockopt is possible only on the newborn.

This revision now requires changes to proceed.Mon, Jan 26, 10:58 PM

The latest FreeBSD MAN page for TCP(4) shows the TCP_MAXSEG allows to determine the result of negotiation between sender and receiver.

RFC 9293 Section 3.7.1. Maximum Segment Size Option shows The MSS value to be sent in an MSS Option should be equal to the effective MTU minus the fixed IP and TCP headers. and refers RFC 6691 for greater detail.

RFC 6691 Section 2. The Short Statement shows When calculating the value to put in the TCP MSS option, the MTU value SHOULD be decreased by only the size of the fixed IP and TCP headers and SHOULD NOT be decreased to account for any possible IP or TCP options; conversely, the sender MUST reduce the TCP data length to account for any IP or TCP ptions that it is including in the packets that it sends.

I see both FreeBSD and MacOS send "mss 1460" in SYN and SYN/ACK for IPv4 and "mss 1440" for IPv6, which are correct under MTU=1500.

Then why TCP_MAXSEG from MacOS returns 1448 in IPv4 and 1428 in IPv6 is a puzzle to me.

Anyway, I will abandon this change if no further discussion is needed.