Skip to content
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

quic: fixing the disconnect between quiche stream count and Envoy #18694

Merged
merged 14 commits into from
Oct 26, 2021
Prev Previous commit
Next Next commit
comments
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
  • Loading branch information
alyssawilk committed Oct 21, 2021
commit 4fca90ca0bde52be9bc4463fe6c559a2b129a2b6
6 changes: 6 additions & 0 deletions source/common/http/http3/conn_pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ class ActiveClient : public MultiplexedActiveClientBase {
// We track the QUIC capacity here, and overload currentUnusedCapacity so the
// connection pool can accurately keep track of when it is safe to create new
// streams.
//
// Though HTTP/3 should arguably start out with 0 stream capacity until the
// initial handshake is complete and MAX_STREAMS frame has been received,
// assume optimistically it will get ~100 streams, so that the connection pool
// won't fetch a connection for each incoming stream but will assume that the
// first connection will likely be able to serve 100.
uint64_t quiche_capacity_ = 100;
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure that this initialization to 100 is quite right. At the QUIC protocol layer, this starts at 0 until the initial_max_streams_bidi transport parameter is received to specify the initial value. After that, it's set to the value from MAX_STREAMS. So I guess this makes me think 2 things.

  1. Should this be initialized to 0?
  2. Should we hook into QuicSession::OnConfigNegotiated() to grab the initial outgoing max streams value?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we need to be at 100 or we'll prefetch a connection for each incoming stream: commented
I would assume that we get a stream update on the initial frame as well, else we should fix upstream.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hm. I definitely appreciate the point about the connection prefetch issue. That makes sense to me. We have to be careful that we don't actually send streams on the wire that are above the peers MAX_STREAMS limit or we will commit a protocol violation and the connection will be closed. In quiche, we do this via ShouldCreateOutgoingBidirectionalStream() returning false until we have stream capacity, but with #18614 that will return true. With 0-RTT in particular, we could send a bunch of requests in the first flight and trigger this.

But maybe we already have logic which is queueing requests somewhere to avoid this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a test to future-proof that we update this before we raise the connected event.

Copy link
Contributor

Choose a reason for hiding this comment

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

Added a test to future-proof that we update this before we raise the connected event.

But do we send 0-RTT request before updating this? initial_max_streams_bidi in transport parameters will update this initially. And it seems reasonable to me that 0-RTT can be sent before receiving transport param.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we don't support 0-rtt right now. When we do, we'll want to set this based on the cached params.

};

Expand Down
11 changes: 6 additions & 5 deletions source/common/quic/envoy_quic_client_session.cc
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,13 @@ void EnvoyQuicClientSession::SetDefaultEncryptionLevel(quic::EncryptionLevel lev
}

void EnvoyQuicClientSession::OnCanCreateNewOutgoingStream(bool unidirectional) {
if (http_connection_callbacks_ && !unidirectional) {
quic::QuicStreamIdManager& manager = quic::test::QuicSessionPeer::getStreamIdManager(this);
ASSERT(manager.outgoing_max_streams() >= manager.outgoing_stream_count());
uint32_t streams_available = manager.outgoing_max_streams() - manager.outgoing_stream_count();
http_connection_callbacks_->onMaxStreamsChanged(streams_available);
if (!http_connection_callbacks_ || unidirectional) {
return;
}
quic::QuicStreamIdManager& manager = quic::test::QuicSessionPeer::getStreamIdManager(this);
ASSERT(manager.outgoing_max_streams() >= manager.outgoing_stream_count());
uint32_t streams_available = manager.outgoing_max_streams() - manager.outgoing_stream_count();
http_connection_callbacks_->onMaxStreamsChanged(streams_available);
}

std::unique_ptr<quic::QuicSpdyClientStream> EnvoyQuicClientSession::CreateClientStream() {
Expand Down