Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TCP: avoid stall with larger MSS #493

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

djs55
Copy link
Member

@djs55 djs55 commented Oct 2, 2022

(I'm not an expert on this so I might have misunderstood something!)

If the connection requests a large MSS > 16k, for example to exploit a large MTU, then writes block because available space is believed to be 0.

Consider UTX.available:

let available t =
    let a = Int32.sub t.max_size t.bufbytes in
    match a < (Int32.of_int (Window.tx_mss t.wnd)) with
    | true -> 0l
    | false -> a

Initially max_size = 16k (hardcoded in flow.ml) and bufbytes = 0, so a = 16k (meaning 16k space is free in the buffer).

If the free space (a) is less than an MSS, we return 0 and the connection stalls.

I think the assumption is that the UTX can buffer at least an MSS worth of data so that when the free space (a) is less than an MSS, the buffer already contains an MSS worth of data to transmit to make progress (does this make sense? Or does it only need to contain 1 byte, so it could be MSS + 1?)

Bump the user buffer size to 128k which is 2x a 64k MSS (where 64k is the max value of the 16-bit MSS option). (Does this need to be configurable somewhere? Linux has ip route add 192.168.1.0/24 dev eth0 advmss 65536 and socket options.)

My hope is that for https://github.com/moby/vpnkit which will use a SOCK_DGRAM interface to send and recv ethernet frames via Apple virtualization.framework and qemu, I'll be able to bump the ethernet MTU and TCP MSS to 64k to reduce the number of packets, since there's a syscall overhead per-packet.

I'm not completely sure this change is correct and I've not got a 64k MTU/MSS working end-to-end yet. I thought it was worth making the PR for discussion.

This might need rethinking if we support segmentation offload because we might see segments >> MTUs.

Signed-off-by: David Scott [email protected]

If the connection requests a large MSS > 16k, for example to exploit a
large MTU, then writes block because available space is believed to be 0.

Consider UTX.available:
```
let available t =
    let a = Int32.sub t.max_size t.bufbytes in
    match a < (Int32.of_int (Window.tx_mss t.wnd)) with
    | true -> 0l
    | false -> a
```
Initially max_size = 16k (hardcoded in flow.ml) and bufbytes = 0,
so a = 16k (meaning 16k space is free in the buffer).

If the free space (a) is less than an MSS, we return 0 and the connection stalls.

I think the assumption is that the UTX can buffer at least 2*MSS worth of
data so that when the free space (a) is less than an MSS, the buffer already
contains an MSS worth of data to transmit to make progress.

Bump the user buffer size to 128k which is 2x a 64k MSS (where 64k is the max
value of the 16-bit MSS option).

This might need rethinking if we support segmentation offload because we might
see even bigger segments.

Signed-off-by: David Scott <[email protected]>
src/tcp/flow.ml Outdated Show resolved Hide resolved
@avsm
Copy link
Member

avsm commented Oct 4, 2022

I'll revisit thinking about this one when:

I've not got a 64k MTU/MSS working end-to-end yet

... just to be able to look at a whole feature patchset. Mainly the interactions with TSO, as you note.

djs55 added a commit to djs55/vpnkit that referenced this pull request Oct 13, 2022
- mirage/mirage-tcpip#492 : remove 4000 byte maximum
- mirage/mirage-tcpip#493 : avoid stall with large MSS

Signed-off-by: David Scott <[email protected]>
djs55 added a commit to djs55/vpnkit that referenced this pull request Oct 13, 2022
- mirage/mirage-tcpip#492 : remove 4000 byte maximum
- mirage/mirage-tcpip#493 : avoid stall with large MSS

Signed-off-by: David Scott <[email protected]>
djs55 added a commit to djs55/vpnkit that referenced this pull request Oct 13, 2022
- mirage/mirage-tcpip#492 : remove 4000 byte maximum
- mirage/mirage-tcpip#493 : avoid stall with large MSS

Signed-off-by: David Scott <[email protected]>
djs55 added a commit to djs55/vpnkit that referenced this pull request Oct 26, 2022
- mirage/mirage-tcpip#492 : remove 4000 byte maximum
- mirage/mirage-tcpip#493 : avoid stall with large MSS

Signed-off-by: David Scott <[email protected]>
@dinosaure
Copy link
Member

I would like a double check from someone else about this PR. Therefore, I would like to merge (or not) and cut a release 👍 .

@dinosaure dinosaure force-pushed the avoid-stall-larger-mss branch from 97793f2 to 657b7c8 Compare February 10, 2023 10:21
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.

3 participants