Skip to content

Derive the GSO segment size from the batch - #200

Open
benoitc wants to merge 1 commit into
mainfrom
fix/gso-segment-size
Open

Derive the GSO segment size from the batch#200
benoitc wants to merge 1 commit into
mainfrom
fix/gso-segment-size

Conversation

@benoitc

@benoitc benoitc commented Aug 15, 2026

Copy link
Copy Markdown
Owner

Fixes #196.

The GSO path never ran: the uniformity check compared every packet against a gso_size that no caller sets, so it stayed at the 1200 default while 1-RTT packets follow the current max datagram size. Deriving the size from the batch is the only value that can be right.

That alone is not enough to turn it on. flush_gso/1 also read the segment size from the record rather than from the batch, so making the check pass still told the kernel to cut at 1200 in the middle of 1398-byte packets, which is the idle_timeout reported in the issue. The listener path also set a socket-level UDP_SEGMENT, which segments every datagram including handshake packets; GSO is now requested per message only, as build_socket_state already documented.

CI could not catch any of this because batch_flushes and packets_coalesced advance on the individual path too, so the download test's ratio measured batching rather than offload. gso_flushes counts only the batches the kernel segmented, and the Linux job now asserts it advanced.

@jbevemyr this is your report; if you can retest on your setup that would be welcome, since the maintainer's machine cannot exercise the path.

The uniformity check compared every packet against a configured
gso_size that nothing sets, so it stayed at 1200 while 1-RTT packets
follow the max datagram size and the GSO path never ran.

- derive the segment size from the batch and pass it to the cmsg, so
  the kernel segments on the boundaries the packets actually have
- require the last packet to be no larger than the segment size
- split writes over 64 segments or 64 KB across several sendmsg calls
- send the chunks a partial write never reached instead of losing them
- request GSO per message only; a socket-level UDP_SEGMENT on the
  listener path segmented every datagram, handshake packets included
- count segmented batches separately in gso_flushes: batch_flushes and
  packets_coalesced advance on both flush paths, so the download test's
  ratio over them stayed green while the GSO path was dead
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.

GSO never engages on the 1-RTT path (gso_size fixed at 1200, packets are 1398), and enabling it breaks the connection

1 participant