Skip to content

QUIC: fix DCID reassignment on connection ID rotation - #180

Merged
josephnoir merged 3 commits into
apple:mainfrom
josephnoir:use-cid-in-frame
Oct 1, 2026
Merged

josephnoir merged 3 commits into
apple:mainfrom
josephnoir:use-cid-in-frame

Conversation

@josephnoir

Copy link
Copy Markdown
Contributor

I've observed connections closing with "unable to allocate a new DCID" in lossy scenarios and I think this is the issue:

The peer issues new CIDs but the packets carrying them are lost. Then a frame arrives that retires the currently held CIDs. processNewConnectionIDFrame tries to pick the replacement DCID before inserting the CID carried in the same frame. That triggers the failure path.

Since the CID in the frame should be sufficient to continue we can insert the new CID first and then do the reassignment.

@josephnoir josephnoir added the 🔨 semver/patch No public API change. label Sep 28, 2026
- When the NEW_CONNECTION_ID frames for seq 1-3 are lost, only the
  in-use seq 0 is left when a frame with seq 4 and Retire Prior To 1
  arrives. Retiring seq 0 leaves only the CID carried by that frame, so
  the current path must move to it instead of the connection closing
- Fails until the following fix
- processNewConnectionIDFrame picked a replacement DCID while retiring
  CIDs below Retire Prior To, before the frame's own CID was added.
  With earlier NEW_CONNECTION_ID frames lost, the pool could be empty
  at that point, so assignNewDCID failed and the connection closed with
  INTERNAL_ERROR although the replacement was in the frame
- Re-point after the insert. RFC 9000 Section 5.1.2 only requires
  retiring before adding the new CID to the set of active CIDs
// Every caller builds its paths from inside `context.async`, so this runs on the context.
var path = QUICPath.makeFromExternalTest(parent: self.connection)
path.set(interface: nil, priority: 1, isInitial: true) // -> .routeEstablished
path.assignDCID(dcid) // -> .cidAssigned (open for sending)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this will break cross module, right because it is referencing internal objects.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just in tests, right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. The library change only moves existing code around.

@josephnoir
josephnoir merged commit 167046d into apple:main Oct 1, 2026
35 of 38 checks passed
@josephnoir
josephnoir deleted the use-cid-in-frame branch October 1, 2026 16:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔨 semver/patch No public API change.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants