Skip to content

Commit ddb302d

Browse files
committed
tcp: avoid stall with larger MSS
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]>
1 parent efbebdf commit ddb302d

File tree

1 file changed

+6
-2
lines changed

1 file changed

+6
-2
lines changed

src/tcp/flow.ml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ open Lwt.Infix
2020
let src = Logs.Src.create "tcp.pcb" ~doc:"Mirage TCP PCB module"
2121
module Log = (val Logs.src_log src : Logs.LOG)
2222

23+
(* MSS options are 16 bites, so the max value is 64k *)
24+
let max_mss = Int32.of_int (64 * 1024)
25+
2326
module Make(Ip: Tcpip.Ip.S)(Time:Mirage_time.S)(Clock:Mirage_clock.MCLOCK)(Random:Mirage_random.S) =
2427
struct
2528

@@ -360,8 +363,9 @@ struct
360363
in
361364
(* Set up ACK module *)
362365
let ack = ACK.t ~send_ack ~last:(Sequence.succ rx_isn) in
363-
(* The user application transmit buffer *)
364-
let utx = UTX.create ~wnd ~txq ~max_size:16384l in
366+
(* The user application transmit buffer. Ensure we are always allowed to write
367+
an MSS of data into it before `available` returns 0. *)
368+
let utx = UTX.create ~wnd ~txq ~max_size:(Int32.mul 2l max_mss) in
365369
let rxq = RXS.create ~rx_data ~ack ~wnd ~state ~tx_ack in
366370
(* Set up the keepalive state if requested *)
367371
let keepalive = match keepalive with

0 commit comments

Comments
 (0)