Repository navigation
Stop requested max ACK delay from growing on each ACK_FREQUENCY exchange - #6340
Open
Joel Kiptoo (Kiptoo-Deus) wants to merge 1 commit into
Open
Joel Kiptoo (Kiptoo-Deus) wants to merge 1 commit into
Joel Kiptoo (Kiptoo-Deus) wants to merge 1 commit into
Conversation
The Requested Max Ack Delay in ACK_FREQUENCY frames was QuicConnGetAckDelay(), the configured MaxAckDelayMs plus this endpoint's timer resolution. The receiver adopts the requested value as its own MaxAckDelayMs and adds its timer resolution again when it sends the frame back, so the value grew by one timer tick per exchange (25, 41, 57, 73 ms on Windows). Request the configured MaxAckDelayMs instead, and never less than the peer's min_ack_delay. Add a test that checks MaxAckDelayMs is unchanged on both endpoints after a transfer that makes the sender emit ACK_FREQUENCY frames.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixes the first part of #6334: the max ACK delay requested in ACK_FREQUENCY frames grows by one timer tick on every exchange.
The frame's Requested Max Ack Delay was
QuicConnGetAckDelay(Connection), which is the configuredMaxAckDelayMsplus this endpoint'sTimerResolutionMs. The receiver stores the requested value as its ownSettings.MaxAckDelayMs(connection.c), and when it later sends ACK_FREQUENCY itself it adds its own timer resolution again. So each exchange adds a tick: 25 → 41 → 57 → 73 ms on Windows, as reported, and 25 → 26 → 27 ms on macOS, where the resolution is 1 ms.This change requests the configured
MaxAckDelayMsinstead, raised to the peer'smin_ack_delayif it is lower. The receiver rejects requests below its timer resolution, which is what it advertises asmin_ack_delay, so the value is still always accepted. ACK_FREQUENCY is only sent when the peer advertisedmin_ack_delay(QuicConnUpdatePeerPacketTolerance), soPeerTransportParams.MinAckDelayis valid there. The advertisedmax_ack_delaytransport parameter still includes the timer resolution, as before.A side effect: with delayed ACKs disabled (
MaxAckDelayMs == 0), the old code requested 0, which is below any peer'smin_ack_delayand which MsQuic itself treats as a protocol violation; it now requests the peer'smin_ack_delay.The second part of the issue (PTO still uses the handshake
max_ack_delayrather than the requested value, per draft section 7) is not addressed here. It needs tracking of in-flight and acknowledged ACK_FREQUENCY frames, and after this change the requested value is usually below the handshake value, so PTO stays conservative. I'm happy to follow up on it separately.Testing
Added
QuicTestAckFrequencyMaxAckDelay(Basic/WithFamilyArgs.AckFrequencyMaxAckDelay): a ~52 MB one-way transfer makes the client scheduling-limited so that it sends ACK_FREQUENCY, and the test then checks thatMaxAckDelayMsread throughQUIC_PARAM_CONN_SETTINGSis still the configured 25 ms on both the client and the server. It fails onmain(the server reads 26 on macOS) and passes with this change, for IPv4 and IPv6.A separate bidirectional loopback repro on macOS (both endpoints configured with the default 25 ms):
MaxAckDelayMsafter the transferRan on macOS (arm64, quictls):
msquiccoretest(all except the slowSpinFrame.*fuzz tests) passes apart fromSettingsTest.GlobalExecutionConfigSetAndGet, which fails the same way onmainon this machine, and the*Ack*:*Datagram*:*Send*:*Receive*:*Stream*:*Basic*:*Handshake*slice ofmsquictestpassed 1757 of 1758 tests. The one failure was a single 2 s timeout inAppData/WithSend0RttArgs1.Send0Rtt/136; that case then passed 10 of 10 repeats, and the fullSend0Rttgroup passed in three further runs, so it looks like an intermittent timing failure rather than a regression.Documentation
None.