-
Notifications
You must be signed in to change notification settings - Fork 204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CID Lifetime Management #1496
Closed
Closed
CID Lifetime Management #1496
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1014,28 +1014,30 @@ For all other frames, the Frame Type field simply identifies the frame. These | |
frames are explained in more detail as they are referenced later in the | ||
document. | ||
|
||
| Type Value | Frame Type Name | Definition | | ||
|:------------|:------------------|:----------------------------| | ||
| 0x00 | PADDING | {{frame-padding}} | | ||
| 0x01 | RST_STREAM | {{frame-rst-stream}} | | ||
| 0x02 | CONNECTION_CLOSE | {{frame-connection-close}} | | ||
| 0x03 | APPLICATION_CLOSE | {{frame-application-close}} | | ||
| 0x04 | MAX_DATA | {{frame-max-data}} | | ||
| 0x05 | MAX_STREAM_DATA | {{frame-max-stream-data}} | | ||
| 0x06 | MAX_STREAM_ID | {{frame-max-stream-id}} | | ||
| 0x07 | PING | {{frame-ping}} | | ||
| 0x08 | BLOCKED | {{frame-blocked}} | | ||
| 0x09 | STREAM_BLOCKED | {{frame-stream-blocked}} | | ||
| 0x0a | STREAM_ID_BLOCKED | {{frame-stream-id-blocked}} | | ||
| 0x0b | NEW_CONNECTION_ID | {{frame-new-connection-id}} | | ||
| 0x0c | STOP_SENDING | {{frame-stop-sending}} | | ||
| 0x0d | ACK | {{frame-ack}} | | ||
| 0x0e | PATH_CHALLENGE | {{frame-path-challenge}} | | ||
| 0x0f | PATH_RESPONSE | {{frame-path-response}} | | ||
| 0x10 - 0x17 | STREAM | {{frame-stream}} | | ||
| 0x18 | CRYPTO | {{frame-crypto}} | | ||
| 0x19 | NEW_TOKEN | {{frame-new-token}} | | ||
| 0x20 | ACK_ECN | {{frame-ack-ecn}} | | ||
| Type Value | Frame Type Name | Definition | | ||
| :---------- | :-------------------- | :-------------------------- | | ||
| 0x00 | PADDING | {{frame-padding}} | | ||
| 0x01 | RST_STREAM | {{frame-rst-stream}} | | ||
| 0x02 | CONNECTION_CLOSE | {{frame-connection-close}} | | ||
| 0x03 | APPLICATION_CLOSE | {{frame-application-close}} | | ||
| 0x04 | MAX_DATA | {{frame-max-data}} | | ||
| 0x05 | MAX_STREAM_DATA | {{frame-max-stream-data}} | | ||
| 0x06 | MAX_STREAM_ID | {{frame-max-stream-id}} | | ||
| 0x07 | PING | {{frame-ping}} | | ||
| 0x08 | BLOCKED | {{frame-blocked}} | | ||
| 0x09 | STREAM_BLOCKED | {{frame-stream-blocked}} | | ||
| 0x0a | STREAM_ID_BLOCKED | {{frame-stream-id-blocked}} | | ||
| 0x0b | NEW_CONNECTION_ID | {{frame-new-connection-id}} | | ||
| 0x0c | STOP_SENDING | {{frame-stop-sending}} | | ||
| 0x0d | ACK | {{frame-ack}} | | ||
| 0x0e | PATH_CHALLENGE | {{frame-path-challenge}} | | ||
| 0x0f | PATH_RESPONSE | {{frame-path-response}} | | ||
| 0x10 - 0x17 | STREAM | {{frame-stream}} | | ||
| 0x18 | CRYPTO | {{frame-crypto}} | | ||
| 0x19 | NEW_TOKEN | {{frame-new-token}} | | ||
| 0x20 | ACK_ECN | {{frame-ack-ecn}} | | ||
| 0x21 | RETIRE_CONNECTION_ID | {{frame-retire-cid}} | | ||
| 0x22 | REQUEST_CONNECTION_ID | {{frame-request-cid}} | | ||
{: #frame-types title="Frame Types"} | ||
|
||
All QUIC frames are idempotent. That is, a valid frame does not cause | ||
|
@@ -3399,6 +3401,77 @@ blocks all those streams from making progress. An implementation is therefore | |
advised to bundle as few streams as necessary in outgoing packets without losing | ||
transmission efficiency to underfilled packets. | ||
|
||
## RETIRE_CONNECTION_ID Frame {#frame-retire-cid} | ||
|
||
The RETIRE_CONNECTION_ID frame (type=0x21) informs the peer that older | ||
connection IDs are being discarded by the peer and will no longer be recognized. | ||
|
||
The frame is as follows: | ||
|
||
~~~ | ||
0 1 2 3 | ||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | ||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
| Sequence (i) ... | ||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
~~~ | ||
|
||
The fields in the RETIRE_CONNECTION_ID frame are as follows: | ||
|
||
Sequence: | ||
: Sequence number of the oldest connection ID issued by the sender which the | ||
sender will still recognize as associated with the current connection. The | ||
sequence number is formatted as a variable-length integer. | ||
|
||
Upon receipt of a RETIRE_CONNECTION_ID frame, an endpoint MUST consider | ||
connection IDs older than the specified sequence number as unusable and MUST NOT | ||
consider the associated stateless reset tokens to be valid. If an older | ||
connection ID is currently being used on any local address, the endpoint MUST | ||
advance to a more recent connection ID. If a more recent connection ID is not | ||
available, no packets can be sent until a NEW_CONNECTION_ID frame is received. | ||
|
||
Endpoints sending a RETIRE_CONNECTION_ID frame MUST continue to accept packets | ||
with older connection IDs until the packet containing the frame is acknowledged. | ||
|
||
## REQUEST_CONNECTION_ID Frame {#frame-request-cid} | ||
|
||
The REQUEST_CONNECTION_ID frame (type=0x22) informs the peer that the sender | ||
has fewer available connection IDs than it wishes to maintain available. | ||
|
||
The frame is as follows: | ||
|
||
~~~ | ||
0 1 2 3 | ||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | ||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
| Received (i) ... | ||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
| Requested (8) | | ||
+-+-+-+-+-+-+-+-+ | ||
~~~ | ||
|
||
The fields in the REQUEST_CONNECTION_ID frame are as follows: | ||
|
||
Received: | ||
: The greatest connection ID sequence number received by the sender | ||
from the receiver in a NEW_CONNECTION_ID frame, formatted as a | ||
variable-length integer. | ||
|
||
Requested: | ||
: A one-byte integer specifying the number of additional connection | ||
IDs the sender would like to be issued. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not a single integer that says "fill to here" ? |
||
|
||
Upon receipt of a REQUEST_CONNECTION_ID frame, an endpoint SHOULD | ||
ensure that it has issued at least the requested number of connection | ||
IDs beyond the specified sequence number. An endpoint MAY impose | ||
implementation-specific limitations on the number of outstanding | ||
connection IDs, but packet loss and failed path migrations can result | ||
in some connection IDs being considered used by one peer and unused | ||
by another. | ||
|
||
The number of older connection IDs still outstanding MAY be constrained | ||
using the RETIRE_CONNECTION_ID frames. | ||
|
||
|
||
## CRYPTO Frame {#frame-crypto} | ||
|
||
|
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think older CIDs should be considered unusable. I can imagine a use for this to retire a CID that you used to try to probe a path that didn't work. In that case, you might still be using the older CID for your main path, and you just want to throw away the new one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps, but then you'd need to individually retire old CIDs one at a time. I'm envisioning this as more of a sliding window -- an implementation is moving the end of the window. Is there a reason you wouldn't just roll forward to another CID when you send this frame, in that situation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be dealing is so few numbers of simultaneous CIDs that it should be just fine to be explicit. I think a sliding window puts to much of a restriction that you are constantly moving the primary path to these new CIDs. I must prefer being explicit, per CID.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm inclined to think that if you're dealing in small numbers of CIDs, it's fine to just remember all of them. If you reach the point where you need to abandon old CIDs because you have too many outstanding, then we're already in a scenario where you're using a lot of them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While, we haven't implemented migration yet in WinQuic, the following is the design we'd have been considering:
But bottom line, with this design, we don't expect to age out more than one at a time. And additionally, the peer could indicate they have to throw a CID away because they tried and failed to use it for a new path validation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm surprised at throwing the path away. I'd think there are separate criteria to throw away a path, independent of needing new CIDs. Still, I can see where a reasonable implementation might get into a state where it's always discarding a single CID at a time and perhaps wanting to discard CIDs non-contiguously.
Perhaps this is a question to discuss on-list, rather than in a PR comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that we can follow up on the migration logic separate from this discussion. For this PR though, I don't think we should use a window style for CIDs. I think it restricts implementations from doing other things.