BUG/MINOR: quic: Lack of precision when computing K (cubic only cc)

K cubic variable is stored in ms. But it was a formula with the second as unit
for the window difference parameter which was used to compute K without
considering the loss of information. Then the result was converted in ms (K *= 1000).
This leaded to a lack of precision and multiples of 1000 as values.

To fix this, use the same formula but with the window difference in ms as parameter
passed to the cubic function and remove the conversion.

Must be backported as far as 2.6.
This commit is contained in:
Frederic Lecaille 2024-07-24 16:16:26 +02:00
parent 7eca16921b
commit a6d40e09f7

View File

@ -243,13 +243,24 @@ static inline void quic_cubic_update(struct quic_cc *cc, uint32_t acked)
c->W_target = path->cwnd; c->W_target = path->cwnd;
} }
else { else {
uint64_t wnd_diff;
/* K value computing (in seconds): /* K value computing (in seconds):
* K = cubic_root((W_max - cwnd_epoch)/C) (Figure 2) * K = cubic_root((W_max - cwnd_epoch)/C) (Figure 2)
* Note that K is stored in milliseconds. * Note that K is stored in milliseconds and that
* 8000 * 125000 = 1000^3.
*
* Supporting 2^40 windows, shifted by 10, leaves ~13 bits of unused
* precision. We exploit this precision for our NS conversion by
* multiplying by 8000 without overflowing, then later by 125000
* after the divide so that we limit the precision loss to the minimum
* before the cubic_root() call."
*/ */
c->K = cubic_root(((c->last_w_max - path->cwnd) << CUBIC_SCALE_FACTOR_SHIFT) / (CUBIC_C_SCALED * path->mtu)); wnd_diff = (c->last_w_max - path->cwnd) << CUBIC_SCALE_FACTOR_SHIFT;
/* Convert to milliseconds. */ wnd_diff *= 8000ULL;
c->K *= 1000; wnd_diff /= CUBIC_C_SCALED * path->mtu;
wnd_diff *= 125000ULL;
c->K = cubic_root(wnd_diff);
c->W_target = c->last_w_max; c->W_target = c->last_w_max;
} }