-
Notifications
You must be signed in to change notification settings - Fork 86
Description
Current Status
libp2p started deploying QUIC a few years ago, when RFC 9000 was not deployed yet. Back then, we deployed QUIC draft-29. Since node operators are slow to update their go-ipfs nodes, draft-29 is now the most deployed version.
| QUIC draft-29 | QUIC draft-29 + v1 | QUIC v1 | |
|---|---|---|---|
| QUIC draft-29 | ✔️ | ✔️ | ❌ |
| QUIC draft-29 + v1 | ✔️* | ✔️ | ✔️* |
| QUIC v1 | ❌ | ✔️ | ✔️ |
*: There's a 1 RTT penalty if the version offered on the initial connection attempt doesn't match the nodes version, as Version Negotiation is performed.
Currently, go-libp2p has support for QUIC draft-29 and QUIC v1. Since draft-29 is the most commonly deployed version (and supported by all nodes on the network), we use that version for dialing new connections.
What happens when rust-libp2p gains QUIC support
rust-libp2p is adding QUIC support, and quinn only supports RFC 9000. If we don't do anything, this means:
- Legacy nodes (those supporting only draft-29) won't be able to connect to rust-libp2p nodes. This is only fair. If you run seriously outdated software, you'll have a bad time. You asked for it.
- rust-libp2p nodes won't be able to tell which QUIC versions a node supports. It will try to connect to legacy nodes, and the QUIC connection will fail after 1 RTT.
- go-libp2p nodes now have two options:
- continue preferring draft-29. This will incur a 1 RTT penalty when connecting to rust-libp2p nodes, as we'll need to perform version negotiation.
- prefer QUIC v1. This will remove the 1 RTT penalty, but will incur a 1 RTT penalty when connecting to legacy nodes. Given the large number of nodes, this might affect our TTFB metrics.
Proposal: add a new QUIC v1 code point
We could add a new code point for QUIC v1 (string representation: quicv1). The existing code point would be reinterpreted to mean QUIC draft-29.
Nodes that support multiple versions can (and should!) offer them on the same port. There's no need to worry about demultiplexing, since QUIC packets contain the version number and any QUIC stack will be able to handle packets from different QUIC versions (if it's a multi-version stack).
But what about QUIC v2
Does this mean that we need to add a new code point for every new QUIC versions? Wouldn't that be wasteful. Yes and no.
The IETF is currently working on specifying QUIC v2, and quic-go already has support for that QUIC version. We don't need a new code point though, because QUIC v2 is a compatible version (to QUIC v1). The exact definition of what constitutes compatibility between QUIC versions is subtle, but as a rule of thumb, if there's a transformation of the ClientHello from one version to a ClientHello of the other version, chances are that the versions are compatible. QUIC versions that use TLS 1.3 (or successors) are likely to be compatible.
Using Compatible Version Negotiation (shipping as an RFC very soon), it is possible to do a version upgrade between two compatible versions without incurring any round trip penalty. Thus, it's fine to continue advertising QUIC v1, as the connection can seamlessly be upgraded to v2 during the handshake.
Only when / if QUIC v2 becomes a dominant version on the internet, AND there are good reasons to not use QUIC v1 any more, would it make sense to introduce a v2 code point, so that compatible version negotiation can be skipped.
Hypothetical: an incompatible QUIC version is defined
A QUIC that uses a different handshake protocol than TLS 1.3 would almost certainly not be be compatible with QUIC v1. Assuming that libp2p would want to support both versions, it would make sense to introduce a new codepoint for that QUIC version, as we'd incur an additional roundtrip for version negotiation when nodes offer an unsupported version.