From 95ce26b67aa6827b97a7fd0a9580a5d7be5dff37 Mon Sep 17 00:00:00 2001 From: eunhhu Date: Tue, 29 Sep 2026 12:04:45 +0100 Subject: Never let a zero RTT make a link's pace infinite A sample of 0 (a path within one clock tick, or a test's) made the pacing rate the window over 0, and its bytes infinity times 0: NaN, after which the sender never sent again. CUBIC's time-based estimate divided by it too. The RTT they take is at least a microsecond. --- link/link-protocol.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'link') diff --git a/link/link-protocol.c b/link/link-protocol.c index 3512f58..55062f3 100644 --- a/link/link-protocol.c +++ b/link/link-protocol.c @@ -513,6 +513,10 @@ static void sample_rtt(PureLinkSender *l, uint64_t latest, uint64_t ack_delay) { l->smoothed_rtt = (7 * l->smoothed_rtt + adjusted) / 8; } +/* The RTT as the window's pace takes it: never under a microsecond (a + * sample of 0, as on a path within one clock tick, would make it infinite). */ +static uint64_t rtt_now(const PureLinkSender *l) { return most(l->sampled ? l->smoothed_rtt : FIRST_RTT, 1000); } + /* The window after bytes acknowledged: slow start below the threshold, * then CUBIC. The cubic's target is where it will be an RTT on, and the * window closes on it by the share of the window acknowledged. */ @@ -527,7 +531,7 @@ static void grow(PureLinkSender *l, uint64_t bytes, uint64_t now) { l->cubic_max = l->cubic_reno = w; l->cubic_k = 0; } - double t = (double)(now - l->cubic_epoch) / 1e9, rtt = (double)(l->sampled ? l->smoothed_rtt : FIRST_RTT) / 1e9; + double t = (double)(now - l->cubic_epoch) / 1e9, rtt = (double)rtt_now(l) / 1e9; /* Reno's pace, 0.53 datagrams an RTT as the CUBIC deployed (Linux's, * quinn's) keeps it, not RFC 9438's whole datagram once past the window * before the event: as the acknowledgments come, or as time goes (RFC @@ -758,7 +762,7 @@ static size_t transmit(PureLinkSender *l, Flight *f, const unsigned char *body, /* Whether pacing lets a packet go now (else when it will, in pace_due). */ static bool paced(PureLinkSender *l, uint64_t now) { - double rtt = (double)(l->sampled ? l->smoothed_rtt : FIRST_RTT); + double rtt = (double)rtt_now(l); double rate = (double)l->window * (l->window < l->threshold ? 2.0 : 1.25) / rtt; /* bytes a ns */ double most = rate * 2e6, least = 10.0 * l->datagram, top = 256.0 * l->datagram; most = most < least ? least : most > top ? top : most; -- cgit v1.2.3