Skip to content

Keep segments within the MSS announced by the peer - #107

Open
FrenchToblerone54 wants to merge 1 commit into
narrowlink:mainfrom
FrenchToblerone54:tcp-peer-mss
Open

FrenchToblerone54 wants to merge 1 commit into
narrowlink:mainfrom
FrenchToblerone54:tcp-peer-mss

Conversation

@FrenchToblerone54

@FrenchToblerone54 FrenchToblerone54 commented Oct 17, 2026 •

Copy link
Copy Markdown

Problem

Outgoing segments are cut to the stack's MTU and the peer's window only. The MSS option in the peer's SYN is ignored, so a peer behind a smaller link gets segments larger than it said it can take, which can be dropped or fragmented on the way (RFC 9293 section 3.7.1 says a sender must not send a segment larger than the MSS the peer announced).

Reproduce

Open a connection with a SYN carrying MaximumSegmentSize(600) and write 1460 bytes. The stack sends 1460 bytes in one segment. The new test does this.

Fix

  • Tcb keeps peer_mss, unbounded by default so connections without the option behave as before.
  • The option is read from the SYN only, like the window scale option.
  • calculate_payload_max_len bounds the payload by the MSS minus the TCP options of the segment (the MSS counts options but not the 20-byte base header).
  • A value below 88 is read as 88 (Linux's TCP_MIN_MSS), so a peer cannot force a few bytes per packet. RFC 9293 section 3.7.1 only fixes the default of 536 for a SYN without the option, it sets no floor for an announced value.

Test

segments_stay_within_the_peers_mss in src/stream/tcp.rs covers an announced MSS of 600 (segments of 600), of 100 (segments of 100) and of 40 (segments of 88). It fails without the change (left: 1460, right: 600) and passes with it. cargo test and cargo clippy --all-targets are clean.

Segments were cut to the stack's MTU alone, so a peer on a smaller link
received segments larger than the MSS it had announced in its SYN. Read the
option from the SYN and bound the payload by it (RFC 9293 3.7.1), counting the
TCP options of the segment against it. An announced value below 536 is read as
536.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant