You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
write_frame in tracking.rs caps ACK frames at MAX_ACKS_PER_FRAME (32) ranges to "keep plenty of space for other stuff." This cap is overly conservative in two situations:
ACK-only packets (cwnd < 256): These are limited to 255 bytes by ACK_ONLY_SIZE_LIMIT, which fits only ~13 ranges. The cap of 32 never fires — the space constraint is always binding. These packets could use the full MTU instead, since ACK-only packets are exempt from congestion control per RFC 9002 Section 6.1.
Non-ACK-only packets with nothing else to send: When cwnd >= 256 but no data or control frames are queued, the packet is effectively ACK-only, yet the 32-range cap still applies. At a 1200-byte MTU, up to ~72 ranges could fit, but 40 of those slots go unused.
Impact
After #3639 increased MAX_TRACKED_RANGES to 128, we can now track many more ranges — but we can only communicate 32 per frame. Under reordering, this means it takes more round trips to acknowledge all received packets, prolonging the window where the sender might falsely declare packets lost.
Possible approaches
Remove MAX_ACKS_PER_FRAME entirely. The space-based formula 1 + (avail / 16) already uses a pessimistic 16-bytes-per-range estimate. In practice, most ranges encode much smaller, so even at the calculated maximum, the ACK frame leaves substantial room for other frames. The cap is belt-and-suspenders on top of an already conservative estimate.
Lift ACK_ONLY_SIZE_LIMIT to the full MTU. Since ACK-only packets don't count against the congestion window (RFC 9002 Section 6.1), there's no reason to artificially constrain them to 255 bytes. This was an implementation choice from Pacing #618 (2020), not an RFC requirement.
Write other frames first, ACK last. This would let the ACK frame fill whatever space remains, but is a more invasive change.
Context
ACK_ONLY_SIZE_LIMIT (256) was introduced in #618 and MAX_ACKS_PER_FRAME (32) in #998, both without recorded discussion about the specific values.
Problem
write_frameintracking.rscaps ACK frames atMAX_ACKS_PER_FRAME(32) ranges to "keep plenty of space for other stuff." This cap is overly conservative in two situations:ACK-only packets (cwnd < 256): These are limited to 255 bytes by
ACK_ONLY_SIZE_LIMIT, which fits only ~13 ranges. The cap of 32 never fires — the space constraint is always binding. These packets could use the full MTU instead, since ACK-only packets are exempt from congestion control per RFC 9002 Section 6.1.Non-ACK-only packets with nothing else to send: When cwnd >= 256 but no data or control frames are queued, the packet is effectively ACK-only, yet the 32-range cap still applies. At a 1200-byte MTU, up to ~72 ranges could fit, but 40 of those slots go unused.
Impact
After #3639 increased
MAX_TRACKED_RANGESto 128, we can now track many more ranges — but we can only communicate 32 per frame. Under reordering, this means it takes more round trips to acknowledge all received packets, prolonging the window where the sender might falsely declare packets lost.Possible approaches
Remove
MAX_ACKS_PER_FRAMEentirely. The space-based formula1 + (avail / 16)already uses a pessimistic 16-bytes-per-range estimate. In practice, most ranges encode much smaller, so even at the calculated maximum, the ACK frame leaves substantial room for other frames. The cap is belt-and-suspenders on top of an already conservative estimate.Lift
ACK_ONLY_SIZE_LIMITto the full MTU. Since ACK-only packets don't count against the congestion window (RFC 9002 Section 6.1), there's no reason to artificially constrain them to 255 bytes. This was an implementation choice from Pacing #618 (2020), not an RFC requirement.Write other frames first, ACK last. This would let the ACK frame fill whatever space remains, but is a more invasive change.
Context
ACK_ONLY_SIZE_LIMIT(256) was introduced in #618 andMAX_ACKS_PER_FRAME(32) in #998, both without recorded discussion about the specific values.