CUBACK: CUBIC Driven by the ACK Clock
draft-kazuho-ccwg-cuback-00
This document is an Internet-Draft (I-D).
Anyone may submit an I-D to the IETF.
This I-D is not endorsed by the IETF and has no formal standing in the
IETF standards process.
| Document | Type | Active Internet-Draft (individual) | |
|---|---|---|---|
| Author | Kazuho Oku | ||
| Last updated | 2026-09-25 | ||
| RFC stream | (None) | ||
| Intended RFC status | (None) | ||
| Formats | |||
| Stream | Stream state | (No stream defined) | |
| Consensus boilerplate | Unknown | ||
| RFC Editor Note | (None) | ||
| IESG | IESG state | I-D Exists | |
| Telechat date | (None) | ||
| Responsible AD | (None) | ||
| Send notices to | (None) |
draft-kazuho-ccwg-cuback-00
Congestion Control Working Group 奥 一穂 (K. Oku)
Internet-Draft Fastly
Intended status: Standards Track 25 September 2026
Expires: 29 March 2027
CUBACK: CUBIC Driven by the ACK Clock
draft-kazuho-ccwg-cuback-00
Abstract
This document specifies Cuback, an ACK-driven reformulation of CUBIC
congestion control. It simplifies implementation by replacing
CUBIC's mutable time- and ACK-driven state with pure functions over
immutable per-epoch parameters, for which test vectors are provided.
Congestion-window growth uses the same ACK-driven mechanism as Reno,
removing several sources of implementation error. When entering a
high-capacity path, a newcomer converges on its share sooner than
under CUBIC, so short flows complete earlier.
Discussion Venues
This note is to be removed before publishing as an RFC.
Discussion of this document takes place on the Congestion Control
Working Group Working Group mailing list (ccwg@ietf.org), which is
archived at https://mailarchive.ietf.org/arch/browse/ccwg/.
Source for this draft and an issue tracker can be found at
https://github.com/kazuho/draft-kazuho-ccwg-cuback.
Status of This Memo
This Internet-Draft is submitted in full conformance with the
provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet-
Drafts is at https://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress."
This Internet-Draft will expire on 29 March 2027.
Oku Expires 29 March 2027 [Page 1]
Internet-Draft cuback September 2026
Copyright Notice
Copyright (c) 2026 IETF Trust and the persons identified as the
document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents (https://trustee.ietf.org/
license-info) in effect on the date of publication of this document.
Please review these documents carefully, as they describe your rights
and restrictions with respect to this document. Code Components
extracted from this document must include Revised BSD License text as
described in Section 4.e of the Trust Legal Provisions and are
provided without warranty as described in the Revised BSD License.
Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2
2. Conventions and Definitions . . . . . . . . . . . . . . . . . 4
3. Cuback Congestion Avoidance . . . . . . . . . . . . . . . . . 4
3.1. Fast Convergence . . . . . . . . . . . . . . . . . . . . 6
3.2. Spurious Congestion Events . . . . . . . . . . . . . . . 6
3.3. Application-Limited Senders . . . . . . . . . . . . . . . 6
4. Relationship to RFC 9438 . . . . . . . . . . . . . . . . . . 6
4.1. Sensitivity to the Bandwidth Estimate . . . . . . . . . . 7
4.2. Convergence under the ACK Clock . . . . . . . . . . . . . 7
4.3. Sensitivity to the Timing of Clock Transitions . . . . . 8
4.4. The Reno-Friendly Estimate . . . . . . . . . . . . . . . 8
4.5. Smoothing the Cubic Growth . . . . . . . . . . . . . . . 9
4.6. Calculation Overhead . . . . . . . . . . . . . . . . . . 9
5. Security Considerations . . . . . . . . . . . . . . . . . . . 10
6. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 10
7. References . . . . . . . . . . . . . . . . . . . . . . . . . 10
7.1. Normative References . . . . . . . . . . . . . . . . . . 10
7.2. Informative References . . . . . . . . . . . . . . . . . 10
Appendix A. Derivation of the Increase Function . . . . . . . . 11
Appendix B. Test Vectors . . . . . . . . . . . . . . . . . . . . 12
Appendix C. An Approximation of the Cube Root . . . . . . . . . 13
Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 14
Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 14
1. Introduction
CUBIC [CUBIC] is a widely deployed congestion-control algorithm that
improves scalability over Reno [RENO] by defining congestion-window
growth as a cubic function of elapsed time. Its implementation,
however, is more complex than the growth function itself might
suggest.
Oku Expires 29 March 2027 [Page 2]
Internet-Draft cuback September 2026
During congestion avoidance, a CUBIC sender maintains two
independently evolving window estimates: the time-driven cubic window
and the ACK-driven Reno-friendly window. The sender must update both
estimates and select the larger of the two. In addition, because the
cubic window advances with wall-clock time, the sender needs mutable
epoch state and a state machine that pauses the cubic clock when the
sender ceases to be congestion-control limited and resumes it when
transmission becomes limited by the congestion window again.
Correctly maintaining these states complicates implementations and
their interaction with application-limited periods and other
congestion-control transitions.
This document specifies Cuback, an ACK-driven reformulation of CUBIC.
Cuback expresses both the cubic and Reno-friendly growth functions in
terms of the amount of data that must be acknowledged for the
congestion window to reach a given value. The parameters defining
those functions are established at the beginning of a congestion-
avoidance epoch and remain immutable for the duration of that epoch.
Congestion-window growth can therefore be calculated from a pure
function of the current congestion window and the per-epoch
parameters, without maintaining separately evolving cubic and Reno-
friendly window estimates.
This formulation also eliminates the need to pause and resume a wall-
clock-driven CUBIC epoch. When acknowledgments stop arriving,
advancement along the Cuback curves stops naturally. The remaining
runtime state is essentially the same as in Reno: the sender tracks
how many additional bytes need to be acknowledged before increasing
the congestion window by one MSS.
Cuback therefore retains the characteristic growth behavior of CUBIC
while reducing congestion avoidance to the same ACK-driven window-
increase mechanism used by Reno. In both Reno and Cuback,
acknowledged bytes are accumulated until enough have been received to
increase the congestion window by one MSS. The difference lies only
in how the required number of acknowledged bytes is calculated: Reno
derives it directly from the current congestion window, whereas
Cuback obtains it by evaluating the pure functions defined in this
document.
What remains of CUBIC's complexity is confined to a pure function of
the congestion window and the per-epoch immutables, which can be
validated directly from its inputs and outputs without exercising a
sequence of state-machine transitions. An implementation can
therefore be checked against known values, and is correspondingly
less prone to error. This document includes test vectors for that
purpose.
Oku Expires 29 March 2027 [Page 3]
Internet-Draft cuback September 2026
The use of the ACK clock has a performance benefit as well. When a
new flow joins a high-capacity path already carrying an established
flow, it acquires its share more rapidly than it would under CUBIC.
Cuback derives its growth rate from the congestion window and round-
trip time recorded at the previous congestion event. Because the
cubic function gives a flow with a smaller window a larger
proportional increase, a newcomer gains share; its ACK rate, and
hence its ACK clock, runs faster than originally anticipated. This
gain compounds over successive round trips, and reduces the time to
completion of short flows, such as the delivery of HTTP objects. The
advantage diminishes as the flow's rate converges on the value it
recorded.
Cuback alters only the congestion avoidance stage of CUBIC. All
other behavior specified in [CUBIC] applies unchanged.
2. Conventions and Definitions
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in
BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all
capitals, as shown here.
This document uses the notation of [CUBIC], in which window sizes are
expressed in segments. An implementation that counts bytes instead
scales each window value by SMSS, divides the sums appearing in
Section 3 by SMSS, and expresses the lower bound on D(w) as 2 * SMSS.
3. Cuback Congestion Avoidance
During congestion avoidance, a Reno sender accumulates the data
acknowledged and increases cwnd by one segment each time a threshold
D(cwnd) is reached:
on entering congestion avoidance:
pending = 0
on receiving an acknowledgement, while cwnd >= ssthresh:
pending = pending + segments_acked
while pending >= D(cwnd):
pending = pending - D(cwnd)
cwnd = cwnd + 1
In Reno, that threshold is the congestion window itself:
D_reno(cwnd) = cwnd
Oku Expires 29 March 2027 [Page 4]
Internet-Draft cuback September 2026
Cuback retains the mechanism above unchanged and replaces only the
threshold, where A(w) is the amount of data, counted from the
beginning of the current congestion avoidance stage, that has to be
acknowledged for the congestion window to reach w:
D(w) = max(2, A(w + 1) - A(w))
A(w) = min(A_cubic(w), A_reno(w))
A_cubic(w) = bandwidth * (K(W_max, cwnd_epoch) + cbrt((w - W_max) / C))
A_reno(w) = (w - cwnd_epoch) * (w + cwnd_epoch - 1)
/ (2 * alpha_cubic) w <= W_max
= (W_max - cwnd_epoch) * (W_max + cwnd_epoch - 1)
/ (2 * alpha_cubic)
+ (w - W_max) * (w + W_max - 1) / 2 w > W_max
K(W_max, cwnd_epoch) = cbrt((W_max - cwnd_epoch) / C)
W_max, bandwidth, and cwnd_epoch are fixed when the congestion
avoidance stage begins and do not change until the next congestion
event:
* W_max is as defined in Section 4.1.2 of [CUBIC]. It is set to
cwnd_prior, the congestion window before the reduction at the
congestion event that began the stage.
* bandwidth is an estimate of the rate at which the bottleneck
delivers data, in segments per second. It is set at the
congestion event to cwnd_prior divided by the smoothed round-trip
time.
* cwnd_epoch is the congestion window at the beginning of the
congestion avoidance stage, as defined in Section 4.1.2 of
[CUBIC].
alpha_cubic, beta_cubic, and C are the constants defined in [CUBIC],
with recommended values:
beta_cubic = 0.7
alpha_cubic = 0.529 # 3 * (1 - beta_cubic) / (1 + beta_cubic)
C = 0.4
A sender that derives ssthresh from flight_size rather than from cwnd
(Section 4.6 of [CUBIC]) MUST use flight_size in place of cwnd_prior
throughout this section. W_max, cwnd_epoch, and bandwidth MUST be
derived from the same quantity.
Oku Expires 29 March 2027 [Page 5]
Internet-Draft cuback September 2026
When congestion avoidance is entered without a congestion event, such
as on exiting slow start, the parameters are established at that
point instead. cwnd is not reduced, so W_max equals cwnd_epoch and K
is zero, and A(w) describes growth along the convex region alone.
The expressions above are derived in Appendix A.
3.1. Fast Convergence
Fast convergence is applied as described in Section 4.7 of [CUBIC]:
on a congestion event, if cwnd is below W_max, W_max is reduced
before cwnd is:
W_max = cwnd * (1 + beta_cubic) / 2
Section 4.3 of [CUBIC] keys the switch to alpha_cubic = 1 to
cwnd_prior rather than to W_max, so A_reno in Section 3 uses
cwnd_prior in its place; a sender that does not retain it can recover
it as cwnd_epoch / beta_cubic.
3.2. Spurious Congestion Events
When a congestion event is determined to have been spurious
(Section 4.9 of [CUBIC]), a sender that reverts cwnd and ssthresh
MUST also restore W_max, bandwidth, and cwnd_epoch to the values they
held before the event.
3.3. Application-Limited Senders
The application-limited clock handling required by Section 4.2 of
[CUBIC] has no counterpart in Cuback, there being no clock to pause
and resume.
The rules of [I-D.ietf-ccwg-ratelimited-increase], which update
[CUBIC], bound the increase of a rate-limited sender without any
determination of its state. Even without them, growth is governed by
acknowledged data rather than by elapsed time: an idle sender accrues
no growth, while a sender that continues to deliver data below cwnd
grows only in proportion to that delivered data; see Section 4.3.
4. Relationship to RFC 9438
Oku Expires 29 March 2027 [Page 6]
Internet-Draft cuback September 2026
4.1. Sensitivity to the Bandwidth Estimate
bandwidth scales A_cubic linearly, so an error in it is an error in
the rate at which the cubic curve is traversed: an underestimate
traverses the curve more quickly than elapsed time would, and an
overestimate more slowly. The round-trip time it is derived from has
to describe the path as it was while cwnd was at its peak, with the
bottleneck queue at its deepest.
The error is bounded in either direction by mechanisms already
present. An overstated bandwidth makes A_cubic large, and A_reno
carries no bandwidth term at all, so A(w) becomes A_reno(w): the flow
then grows at the Reno-friendly rate, and no error in bandwidth can
slow it below that. An understated bandwidth makes A_cubic small,
and the lower bound of two segments on D(w) caps growth at half the
congestion window per round trip, which [CUBIC] adopts to keep the
increase below that of slow start.
Between those bounds the estimate matters only at windows large
enough for the cubic curve to govern. Windows that large deliver
many acknowledgements per round trip, and a QUIC sender takes a
round-trip sample from every acknowledgement that advances the
largest acknowledged packet number [RFC9002], so the smoothed round-
trip time follows the path closely by the time the estimate matters.
4.2. Convergence under the ACK Clock
Deriving the clock from acknowledgements reinforces the convergence
that AIMD provides, because bandwidth records the rate the flow was
achieving before it reduced. A flow holding a large share gives up
the most at a congestion event, so the rate it goes on to achieve
falls below the value it recorded and its clock runs slow. A flow
arriving with a small share records a correspondingly small rate and
then achieves more than it recorded, so its clock runs fast. The
congestion window advances fastest for the flow gaining share and
slowest for the one giving it up.
The curve advances at the ratio of the rate the flow is currently
achieving to the rate recorded at the last congestion event. A flow
that has since doubled its share traverses the curve twice as fast as
elapsed time would carry it; one that has halved its share, half as
fast. The advantage therefore decays as the achieved rate converges
on the recorded one.
Oku Expires 29 March 2027 [Page 7]
Internet-Draft cuback September 2026
4.3. Sensitivity to the Timing of Clock Transitions
Section 4.2 of [CUBIC] requires that elapsed time exclude periods
during which cwnd was not updated because the sender was application
limited. A CUBIC sender therefore has to pause its clock as the flow
becomes application limited and resume it as the flow ceases to be,
and an error at either edge is an error in the elapsed time the curve
is read against.
Treating an application-limited sender as congestion-window limited
leaves the clock running. W_cubic(t) advances while the flow is not
filling cwnd, and cwnd grows on evidence the path never supplied;
Section 5.8 of [CUBIC] names the consequence, that W_cubic(t) "might
be very high after restarting from these periods". Treating a
congestion-window-limited sender as application limited stops the
clock instead, so the elapsed time that should have advanced the
curve is never accrued and the flow grows too slowly.
Neither edge is easy to observe. A sender might emit as many
datagrams as it can in one pass and so appear limited by the
congestion controller, even though its bytes in flight are below
cwnd. Conversely, an in-stack pacer might withhold emission after a
train of acknowledgements, leaving bytes in flight below cwnd
although the connection is still limited by the congestion window.
[I-D.ietf-ccwg-ratelimited-increase] updates [CUBIC], mitigating the
impact of such overgrowth by capping cwnd at a value derived from the
largest FlightSize observed, but a CUBIC sender is still required to
pause and resume its clock at the correct moments.
Cuback has no clock to stop or start. When the sender stops, the
advance of A(w) stops with it: no acknowledgements arrive, and
nothing accrues to be caught up when transmission resumes. The case
in which a mistimed CUBIC clock does the most damage therefore does
not arise.
A sender that keeps sending but holds less than cwnd in flight is not
protected altogether, only bounded. Growth is governed by the amount
of data acknowledged, as in Reno, so cwnd advances in proportion to
what the path delivered rather than in proportion to elapsed time.
Applying [I-D.ietf-ccwg-ratelimited-increase] caps what remains,
holding cwnd to what one window of the largest FlightSize observed
would yield.
4.4. The Reno-Friendly Estimate
Section 4.3 of [CUBIC] advances W_est on each acknowledgement:
W_est = W_est + alpha_cubic * segments_acked / cwnd
Oku Expires 29 March 2027 [Page 8]
Internet-Draft cuback September 2026
where cwnd is the congestion window in effect. While the cubic curve
governs, that window is larger than W_est, so the growth of W_est
depends on the trajectory of the other curve. This coupling cannot
be expressed as a function of W_est alone, and A_reno instead inverts
the standalone recurrence, in which the divisor is the Reno-friendly
window itself.
Where A_reno is the smaller of the two curves, cwnd is the Reno-
friendly window and the two formulations coincide exactly: both
increase the window by one segment for every cwnd / alpha_cubic
segments acknowledged. They differ only in where that region is
entered. Because the standalone recurrence uses the smaller divisor,
it advances faster while the cubic curve governs, and a Cuback sender
enters the Reno-friendly region somewhat earlier than a sender
following [CUBIC].
4.5. Smoothing the Cubic Growth
Section 4.4 of [CUBIC] and Section 4.5 of [CUBIC] advance cwnd toward
a target one round trip ahead, W_cubic(t + RTT), rather than
assigning W_cubic(t) to cwnd directly. Because the CUBIC curve is
driven by elapsed time, the growth owed at an acknowledgement depends
on how long has passed since the previous one, and assigning the
curve directly would turn a gap in acknowledgements into a step in
cwnd, which is a burst. The one-round-trip target, together with the
per-acknowledgement increase of (target - cwnd) / cwnd, spreads one
round trip of the curve across one round trip of acknowledgements,
making the increase proportional to the data acknowledged however the
acknowledgements are distributed in time.
Cuback needs no such smoothing. D(w) is a function of acknowledged
data alone, so a gap in acknowledgements accrues no growth to be
caught up, and the increase is proportional to the ack stream by
construction.
4.6. Calculation Overhead
A_reno is arithmetic, but A_cubic requires a cube root. [CUBIC]
evaluates one when the epoch begins, to obtain K, and thereafter only
cubes; Cuback evaluates one whenever it computes D(w).
Storing the data still needed to increase the window by one segment,
rather than recomputing D(w) on every acknowledgement, moves the
evaluation from once per acknowledgement to once per increase. Each
increase then evaluates three roots: K, A_cubic(w), and A_cubic(w +
1).
Oku Expires 29 March 2027 [Page 9]
Internet-Draft cuback September 2026
Calculating a cube root to the accuracy required here is cheap. The
approximation must be continuous in slope, adjacent evaluations being
differenced, and one meeting that condition is given in Appendix C.
It runs in about nine cycles on contemporary hardware, against
roughly nine hundred to encrypt a 1460-byte segment through an AES-
GCM-128 pipeline at 1.6 bytes per cycle. In the worst case, the
window growing by one segment for every segment acknowledged, the
overhead is therefore around three percent of the cost of encrypting
the data that drove it; during congestion avoidance the window
typically grows far more slowly than that.
Furthermore, K is fixed for the duration of the epoch and could be
retained rather than recomputed, and A(w + 1) for one increase is
A(w) for the next and could be carried forward. Together these leave
a single cube root per increase.
5. Security Considerations
TODO Security
6. IANA Considerations
This document has no IANA actions.
7. References
7.1. Normative References
[CUBIC] Xu, L., Ha, S., Rhee, I., Goel, V., and L. Eggert, Ed.,
"CUBIC for Fast and Long-Distance Networks", RFC 9438,
DOI 10.17487/RFC9438, August 2023,
<https://www.rfc-editor.org/rfc/rfc9438>.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997,
<https://www.rfc-editor.org/rfc/rfc2119>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/rfc/rfc8174>.
7.2. Informative References
[I-D.ietf-ccwg-ratelimited-increase]
Welzl, M., Henderson, T., Fairhurst, G., and M. P.
Tahiliani, "Increase of the Congestion Window when the
Sender Is Rate-Limited", Work in Progress, Internet-Draft,
Oku Expires 29 March 2027 [Page 10]
Internet-Draft cuback September 2026
draft-ietf-ccwg-ratelimited-increase-11, 6 September 2026,
<https://datatracker.ietf.org/doc/html/draft-ietf-ccwg-
ratelimited-increase-11>.
[RENO] Allman, M., Paxson, V., and E. Blanton, "TCP Congestion
Control", RFC 5681, DOI 10.17487/RFC5681, September 2009,
<https://www.rfc-editor.org/rfc/rfc5681>.
[RFC9002] Iyengar, J., Ed. and I. Swett, Ed., "QUIC Loss Detection
and Congestion Control", RFC 9002, DOI 10.17487/RFC9002,
May 2021, <https://www.rfc-editor.org/rfc/rfc9002>.
Appendix A. Derivation of the Increase Function
The lower bound of two segments in D(w) limits the increase to one
half of the congestion window per round trip: cwnd segments are
acknowledged per round trip, and each one-segment increase consumes
at least two of them. It is the counterpart of the constraint target
<= 1.5 * cwnd in Section 4.4 of [CUBIC] and Section 4.5 of [CUBIC].
No lower bound on the increase is needed, as A(w) is monotonically
increasing and D(w) is therefore always positive.
CUBIC sets its congestion window to the larger of two window growth
functions. Both are monotonically increasing, so their maximum is
monotonically increasing as well, and the inverse of that maximum is
the minimum of the two inverses. A(w) is therefore obtained by
inverting each function separately and taking the smaller of the two
results.
A_cubic is the inverse of W_cubic(t) of Section 4.2 of [CUBIC],
multiplied by bandwidth to express elapsed time as acknowledged data.
That the curve is zero at w = cwnd_epoch follows from the definition
of K.
Sampling bandwidth as cwnd_prior / RTT is the rate at which the flow
was delivering data over the round trip preceding the congestion
event. It carries an identity:
bandwidth * RTT = cwnd_prior
While the congestion window is at cwnd_prior, one round trip of
acknowledgements advances A(w) by exactly one round trip along the
underlying cubic curve.
Oku Expires 29 March 2027 [Page 11]
Internet-Draft cuback September 2026
A_reno is the inverse of the Reno-friendly increase of Section 4.3 of
[CUBIC]: one segment for every cwnd / alpha_cubic segments
acknowledged, with alpha_cubic replaced by one once the window
reaches W_max. Summing those thresholds over the segment-spaced
windows from cwnd_epoch to w yields the expression in Section 3.
Differencing A_reno recovers exactly the threshold from which it was
built:
A_reno(w + 1) - A_reno(w) = w / alpha_cubic
The Reno-friendly region is therefore not a separate mechanism in
Cuback. It is the value that D(w) takes wherever A_reno is the
smaller of the two curves. The closed form exists only so that the
two curves can be compared.
Differencing A_cubic eliminates K, so an implementation need not
evaluate it when the cubic curve is the smaller of the two:
A_cubic(w + 1) - A_cubic(w)
= bandwidth * (cbrt((w + 1 - W_max) / C) - cbrt((w - W_max) / C))
Appendix B. Test Vectors
A(w) and D(w) are pure functions of the congestion window and the
parameters of Section 3, so they can be checked directly. Both
vectors below use the recommended constants, with alpha_cubic taken
as 3 * (1 - beta_cubic) / (1 + beta_cubic) rather than the rounded
0.529.
The first exercises the Reno-friendly curve. bandwidth is large
enough here that A_cubic exceeds A_reno at every window shown, so
A(w) is A_reno(w) throughout. The window reaches cwnd_prior at 10
segments, where alpha_cubic is replaced by one and each further
segment costs exactly its own window in acknowledged data.
Oku Expires 29 March 2027 [Page 12]
Internet-Draft cuback September 2026
cwnd_epoch = 7 segments
cwnd_prior = 10 segments
W_max = 10 segments
RTT = 0.1 s
bandwidth = 100 segments/s
w A(w) D(w)
7 0.0000 13.2222
8 13.2222 15.1111
9 28.3333 17.0000
10 45.3333 10.0000
11 55.3333 11.0000
12 66.3333
The second exercises the cubic curve, the parameters being chosen so
that K is exactly 10 seconds. A_reno exceeds A_cubic at every window
shown, so A(w) is A_cubic(w) throughout. A(W_max) divided by
bandwidth recovers K, and the data needed to climb the 50 segments
below W_max equals that needed for the 50 above, the curve being
point-symmetric about W_max.
cwnd_epoch = 600 segments
cwnd_prior = 1000 segments
W_max = 1000 segments
RTT = 0.1 s
bandwidth = 10000 segments/s
K = 10 s
w A(w)
600 0
950 50 000
1000 100 000
1050 150 000
1400 200 000
D(w) on the cubic curve is the difference of two cube roots taken at
adjacent windows, so an implementation using an approximation should
compare accumulated values, as above, rather than individual
increases; see Section 4.6.
Appendix C. An Approximation of the Cube Root
The cube root function below is provided for reference and is placed
in the public domain. It assumes IEEE 754 binary64. Its maximum
relative error is about 3.5e-5 and the relative error of its slope is
below 8.5e-4, holding each per-segment increase to roughly 0.1
percent, and it runs in about nine cycles on a Zen 3 core.
Oku Expires 29 March 2027 [Page 13]
Internet-Draft cuback September 2026
#define DBL2BITS(x) (((union { double f; uint64_t u; }){x}).u)
#define BITS2DBL(x) (((union { uint64_t u; double f; }){x}).f)
double approx_cbrt(double x)
{
uint64_t u = DBL2BITS(x);
uint64_t abs_u = u & 0x7fffffffffffffff;
uint64_t exp = abs_u >> 52;
if (abs_u == 0)
return x;
if (exp == 0 || exp == 0x7ff)
return cbrt(x);
int e = (int)exp - 1023;
int q = e / 3;
int r = e - 3 * q;
if (r < 0) {
r += 3;
--q;
}
uint64_t mant = abs_u & 0xfffffffffffff;
double m = BITS2DBL(mant | ((uint64_t)1023 << 52));
double y = -0.010279630422175424;
y = 0.08469719299100167 + m * y;
y = -0.2988437245358902 + m * y;
y = 0.7177663288981584 + m * y;
y = 0.5066598330689034 + m * y;
static const double cbrt2_to_r[3] = {1.0, 1.2599210498948731648,
1.5874010519681994748};
double two_to_q = BITS2DBL((uint64_t)(q + 1023) << 52);
y *= cbrt2_to_r[r] * two_to_q;
return (u >> 63) ? -y : y;
}
Acknowledgments
TODO acknowledge.
Author's Address
Kazuho Oku
Fastly
Email: kazuhooku@gmail.com
Oku Expires 29 March 2027 [Page 14]
Internet-Draft cuback September 2026
Additional contact information:
奥 一穂
Fastly
Oku Expires 29 March 2027 [Page 15]