Congestion Control

2 posts

cloudflare3 min readCurated summary

When "idle" isn't idle: how a Linux kernel optimization became a QUIC bug

CUBIC, the default congestion controller in Linux and quiche, can become permanently stuck at its minimum congestion window after an early congestion collapse. Cloudflare found the bug in a QUIC test where packet loss stopped completely, yet CUBIC continued oscillating between recovery and congestion avoidance instead of increasing its sending rate. The problem was traced to a Linux TCP optimization for idle or app-limited connections, and ultimately fixed with an elegant near-one-line change. ## How CUBIC manages traffic - CUBIC controls the sender’s congestion window (`cwnd`), limiting how many bytes can be in flight. - It increases `cwnd` when acknowledgments arrive without loss and reduces it when loss suggests the network is overloaded. - As quiche’s default congestion controller, CUBIC affects a substantial amount of QUIC traffic. - Recovery from the minimum congestion window is an important but relatively under-tested part of congestion control. ## The failing test - The test downloaded a 10 MB file over HTTP/3 between local quiche client and server. - Network conditions included: - 10 ms RTT - 30% random packet loss during the first two seconds - No packet loss after two seconds - A 10-second timeout - The expected result was for CUBIC to reduce its window during loss, then steadily recover once the network became reliable. - Instead, approximately 60% of repeated 100-run test batches failed to finish in time. ## CUBIC becomes stuck at its minimum - After packet loss stopped at two seconds, bytes in flight remained flat rather than increasing. - CUBIC’s congestion window stayed at its minimum of 2,700 bytes—roughly two full-sized packets. - The controller repeatedly switched between recovery and congestion avoidance: - 999 transitions over about 6.7 seconds - One transition approximately every 14 ms - The oscillation closely matched the connection’s RTT, indicating that each ACK round was triggering the behavior. - Because the test was a download, client ACKs caused the server’s bytes in flight to fall to zero; the server then sent another two-packet burst, repeatedly provoking the faulty state transition. - Reno passed the same test 100% of the time, confirming that the issue was specific to CUBIC rather than the test setup. ## The connection to Linux TCP - The investigation focused on behavior when `bytes_in_flight == 0`, effectively an idle or app-limited condition. - A 2017 Linux kernel change addressed a TCP CUBIC issue after application idle periods. - Before the change, CUBIC’s epoch could remain unchanged for a long time while the application was idle. - When sending resumed, the elapsed time used by CUBIC could be extremely large, producing an excessively aggressive growth slope and dangerous congestion-window inflation. - The kernel optimization was intended to align CUBIC with the app-limited exclusion described in RFC 9438 §4.2-12. - Porting this logic to QUIC exposed an unintended interaction: repeated short periods with no bytes in flight could be interpreted incorrectly, causing CUBIC to cycle between states and remain at its minimum window. The practical lesson is that congestion-control implementations must test not only steady-state throughput and ordinary loss recovery, but also recovery from the minimum window and repeated app-limited or idle periods. In this case, a small adjustment to the idle-state handling broke the cycle and allowed CUBIC to recover normally.

Read original(opens in new tab)
lineOriginal article

Case Study: Improving Video (opens in new tab)

Engineers at LINE identified a recurring monthly degradation in video call quality, specifically in Japan, where packet loss increased and frames per second (FPS) dropped toward the end of each month. Investigation revealed that this pattern was caused by mobile ISP bitrate throttling once users exhausted their monthly data caps, which the existing congestion control mechanisms were failing to handle efficiently. To resolve this, the team improved their proprietary CCFS (Congestion Control based on Forward path Status) algorithm to more accurately detect these specific network constraints and maintain stable playback. ### Analysis of Monthly Quality Degradation * Data analysis showed a "monthly cycle" where video decoding FPS was highest at the start of the month and progressively declined toward the end. * This quality drop was specifically tied to an increase in video packet loss, which prevents normal decoding and results in stuttering or frozen frames. * Statistical segmentation revealed the issue occurred almost exclusively on 4G mobile networks rather than Wi-Fi, and was more pronounced in high-bitrate video calls than in voice calls. * The root cause was identified as mobile data plan policies; as users hit their monthly data limits, ISPs impose speed restrictions that create network congestion if the application continues to send high-bitrate data. ### Limitations of Standard Congestion Control * While the IETF RMCAT working group has standardized algorithms like NADA (RFC8698) and SCReAM (RFC8298), real-time two-way communication requires more sensitive response times than one-way streaming. * In two-way calls, even a one-second delay makes natural conversation difficult, meaning the system cannot rely on large buffers to smooth out network instability. * Existing mechanisms were not reacting fast enough to the rigid throughput limits imposed by carrier throttling, leading to packet accumulation in network queues and subsequent loss. ### The CCFS Proprietary Algorithm * LINE utilizes a custom-developed, sender-based algorithm called CCFS (Congestion Control based on Forward path Status). * Unlike older algorithms that rely on Round Trip Time (RTT), CCFS focuses on the "forward path"—the actual path packets take to the receiver—by analyzing feedback on packet arrival times and loss. * CCFS categorizes network status into four distinct states: Default, Probing, Throttled, and Competing. * The system monitors "delay variation"; when it detects a continuous increase in delay exceeding a specific threshold, it transitions to the "Throttled" state to proactively reduce bitrate before the queue overflows. ### Strategies for Quality Improvement * The team focused on refining how CCFS handles the transition into the Throttled state to better align with the artificial bandwidth ceilings created by ISPs. * By improving the sensitivity of forward path status monitoring, the application can more rapidly adjust its transmission rate to stay within the user's current data plan limits. * This technical adaptation ensures that even when a user's mobile speed is restricted, the video remains smooth, albeit at a lower resolution, rather than breaking up due to packet loss. To provide a high-quality communication experience, developers must account for external factors like regional ISP policies. Refining proprietary congestion control algorithms to detect specific patterns, such as monthly data-cap throttling, allows for a more resilient service that maintains stability across diverse mobile environments.