Repository navigation
Conversation
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.
Background:
Routers and firewalls pick a path or a queue by hashing each flow's source and destination addresses and ports
(ECMP, per-flow load balancing, per-flow policing). If a flow lands on a congested, lossy or throttled path, it stays there.
So resending lost packets won't succeed and you have to wait for the timeout.
Changing the source port gives the flow a new hash and very likely a different path.
Google's PLB (Protective Load Balancing) does the same for TCP by changing the IPv6 flow label.
So this isn't a hack; it's what clients do on bad long-haul links.
And here's the point:
QUIC can move a connection to a new local port without disturbing its streams
(RFC 9000 §9), which is exactly what we need.
This patch allows applications using KWIK to migrate the client's source port:
QuicClientConnection.migrate(Duration timeout)(public API): opens a socket on a new ephemeral port,validates the path with PATH_CHALLENGE from that socket (padded to 1200 bytes, up to 3 attempts), and
only on PATH_RESPONSE switches to it, retires the old path's connection ID (§9.5) and closes the old
socket. It refuses (returns false) when the handshake isn't confirmed, the server sent
disable_active_migration, or no unused peer CID is available. Built on yourClientSocketManager.addLocalAddress/changeLocalAddress,sendAlternateAddressand the per-addresspeer CID registry.
Statistics.consecutivePtoCount(): exposesRecoveryManager.ptoCount, so an application can detect astalled path (N probe timeouts without any ack) and decide to migrate.
(
ConnectionIdManager.handshakeFinished()is no longer server-only), as the server needs an unused clientCID to validate a new path.
PacketMetaDatanow carries the local address adatagram was received on). Otherwise, when the peer probes a new path because the current one is dead, the
response is lost. On the server this only applies to paths the
PathValidatorknows about (i.e. that havea client CID assigned); before, an unconditional response to an unknown address threw "new connection ID's
are exhausted" and aborted the connection.
disable_active_migration.