diff options
| author | eunhhu <[email protected]> | 2026-09-29 12:04:45 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-09-29 12:04:45 +0100 |
| commit | 95ce26b67aa6827b97a7fd0a9580a5d7be5dff37 (patch) | |
| tree | 624b1b2aa023267da0f7568974997c1eeb7483d0 | |
| parent | 8140a59205911170e151c95ed5596db7aa0d5ba5 (diff) | |
| download | pure-95ce26b67aa6827b97a7fd0a9580a5d7be5dff37.tar.gz pure-95ce26b67aa6827b97a7fd0a9580a5d7be5dff37.zip | |
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.
| -rw-r--r-- | link/link-protocol.c | 8 |
1 files changed, 6 insertions, 2 deletions
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; |
