Este incidente en la implementación de CUBIC en quiche de Cloudflare revela una falla sutil pero crítica en el manejo de la congestión, específicamente en condiciones de recuperación tras una pérdida severa de paquetes. La causa raíz se encuentra en una adaptación incorrecta de una optimización del kernel de Linux a un entorno de userspace (QUIC). La optimización original buscaba corregir un comportamiento anómalo de CUBIC tras periodos de inactividad de la aplicación, donde el cwnd se inflaba excesivamente. La solución en Linux fue desplazar el 'epoch_start' de CUBIC para preservar la forma de la curva de crecimiento.
El problema surgió cuando esta lógica se portó a quiche. En el entorno de QUIC, la función on_packet_sent() detectaba un estado de 'idle' si bytes_in_flight era cero. Sin embargo, en un escenario de cwnd mínimo (dos paquetes) y alta congestión, bytes_in_flight caía a cero en cada ciclo de ACK, no por inactividad real de la aplicación, sino por limitación de la ventana de congestión. Al calcular el 'delta' de inactividad como now - last_sent_time, se inflaba este valor a un RTT completo, empujando el congestion_recovery_start_time al futuro. Esto hacía que el controlador de congestión percibiera la conexión como constantemente en 'recovery', impidiendo el crecimiento del cwnd y creando un 'death spiral' donde la ventana se mantenía en su mínimo.
Las salvaguardas fallaron porque el bug se manifestaba en un 'corner case' muy específico: cwnd mínimo después de una pérdida severa, que no era cubierto por los tests de rendimiento habituales. Los tests de 'steady-state' o fases de crecimiento no lo detectaban. Solo un test diseñado para estresar la recuperación del controlador de congestión en condiciones extremas pudo sacarlo a la luz. La oscilación entre estados de recuperación y evitación de congestión, sincronizada con el RTT, fue la pista clave para diagnosticar la causa raíz. La solución, aunque conceptualmente simple (medir el 'idle' desde el último ACK en lugar del último envío), requirió una profunda comprensión de las dinámicas de CUBIC y las diferencias entre TCP en kernel y QUIC en userspace.