Skip to content

Commit df9f63c

Browse files
authored
quic: Populate counter downstream_cx_tx_bytes_total for HTTP/3. (envoyproxy#39005)
Commit Message: Populate counter downstream_cx_tx_bytes_total for HTTP/3. Additional Description: Risk Level: Low Testing: Added DownstreamProtocolIntegrationTest.DownstreamCxStats Docs Changes: Release Notes: Platform Specific Features: [Optional Runtime guard:] [Optional Fixes #Issue] [Optional Fixes commit #PR or SHA] [Optional Deprecated:] [Optional [API Considerations](https://github.com/envoyproxy/envoy/blob/main/api/review_checklist.md):] --------- Signed-off-by: Bin Wu <[email protected]>
1 parent 8004f05 commit df9f63c

File tree

7 files changed

+72
-7
lines changed

7 files changed

+72
-7
lines changed

source/common/quic/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ envoy_cc_library(
383383
"//source/common/network:listen_socket_lib",
384384
"//source/common/quic:envoy_quic_utils_lib",
385385
"@com_github_google_quiche//:quic_core_connection_lib",
386+
"@com_github_google_quiche//:quic_core_packet_writer_lib",
386387
"@com_github_google_quiche//:quic_core_packets_lib",
387388
],
388389
)

source/common/quic/envoy_quic_server_connection.cc

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,32 @@
11
#include "source/common/quic/envoy_quic_server_connection.h"
22

3+
#include <memory>
4+
35
#include "source/common/network/listen_socket_impl.h"
46
#include "source/common/quic/envoy_quic_utils.h"
57
#include "source/common/quic/quic_io_handle_wrapper.h"
68

9+
#include "quiche/quic/core/quic_packet_writer_wrapper.h"
710
#include "quiche/quic/core/quic_packets.h"
811

912
namespace Envoy {
1013
namespace Quic {
1114

15+
namespace {
16+
std::unique_ptr<quic::QuicPacketWriterWrapper>
17+
wrapWriter(quic::QuicPacketWriter* writer, bool owns_writer,
18+
quic::QuicPacketWriterWrapper::OnWriteDoneCallback on_write_done) {
19+
auto wrapper = std::make_unique<quic::QuicPacketWriterWrapper>();
20+
if (owns_writer) {
21+
wrapper->set_writer(writer);
22+
} else {
23+
wrapper->set_non_owning_writer(writer);
24+
}
25+
wrapper->set_on_write_done(std::move(on_write_done));
26+
return wrapper;
27+
}
28+
} // namespace
29+
1230
EnvoyQuicServerConnection::EnvoyQuicServerConnection(
1331
const quic::QuicConnectionId& server_connection_id,
1432
quic::QuicSocketAddress initial_self_address, quic::QuicSocketAddress initial_peer_address,
@@ -17,9 +35,15 @@ EnvoyQuicServerConnection::EnvoyQuicServerConnection(
1735
const quic::ParsedQuicVersionVector& supported_versions,
1836
Network::ConnectionSocketPtr connection_socket, quic::ConnectionIdGeneratorInterface& generator,
1937
std::unique_ptr<QuicListenerFilterManagerImpl> listener_filter_manager)
20-
: quic::QuicConnection(server_connection_id, initial_self_address, initial_peer_address,
21-
&helper, &alarm_factory, writer, owns_writer,
22-
quic::Perspective::IS_SERVER, supported_versions, generator),
38+
: quic::QuicConnection(
39+
server_connection_id, initial_self_address, initial_peer_address, &helper, &alarm_factory,
40+
// Wrap the packet writer to get notified when a packet is written.
41+
wrapWriter(writer, owns_writer,
42+
[this](size_t packet_size, const quic::WriteResult& result) {
43+
OnWritePacketDone(packet_size, result);
44+
})
45+
.release(),
46+
/*owns_writer=*/true, quic::Perspective::IS_SERVER, supported_versions, generator),
2347
QuicNetworkConnection(std::move(connection_socket)),
2448
listener_filter_manager_(std::move(listener_filter_manager)) {
2549
#ifndef WIN32
@@ -47,6 +71,13 @@ bool EnvoyQuicServerConnection::OnPacketHeader(const quic::QuicPacketHeader& hea
4771
return true;
4872
}
4973

74+
void EnvoyQuicServerConnection::OnWritePacketDone(size_t packet_size,
75+
const quic::WriteResult& /*result*/) {
76+
if (hasConnectionStats()) {
77+
connectionStats().write_total_.add(packet_size);
78+
}
79+
}
80+
5081
void EnvoyQuicServerConnection::OnCanWrite() {
5182
quic::QuicConnection::OnCanWrite();
5283
onWriteEventDone();

source/common/quic/envoy_quic_server_connection.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ class EnvoyQuicServerConnection : public quic::QuicConnection, public QuicNetwor
157157
void OnEffectivePeerMigrationValidated(bool is_migration_linkable) override;
158158

159159
private:
160+
// Called when a packet is written to the packet writer.
161+
void OnWritePacketDone(size_t packet_size, const quic::WriteResult& result);
160162
std::unique_ptr<QuicListenerFilterManagerImpl> listener_filter_manager_;
161163
bool first_packet_received_ = false;
162164
};

source/common/quic/quic_network_connection.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,11 @@ class QuicNetworkConnection : protected Logger::Loggable<Logger::Id::connection>
4343
uint64_t id() const;
4444

4545
protected:
46+
// REQUIRES: hasConnectionStats() == true.
4647
Network::Connection::ConnectionStats& connectionStats() const { return *connection_stats_; }
4748

49+
bool hasConnectionStats() const { return connection_stats_ != nullptr; }
50+
4851
void setConnectionSocket(Network::ConnectionSocketPtr&& connection_socket) {
4952
connection_sockets_.push_back(std::move(connection_socket));
5053
}

test/common/quic/envoy_quic_dispatcher_test.cc

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "quiche/quic/test_tools/quic_dispatcher_peer.h"
3434
#include "quiche/quic/test_tools/quic_test_utils.h"
3535

36+
using testing::AnyNumber;
3637
using testing::Invoke;
3738
using testing::Return;
3839
using testing::ReturnRef;
@@ -211,6 +212,7 @@ class EnvoyQuicDispatcherTest : public testing::TestWithParam<Network::Address::
211212
// Stop iteration to avoid calling getRead/WriteBuffer().
212213
.WillOnce(Return(Network::FilterStatus::StopIteration));
213214
EXPECT_CALL(network_connection_callbacks_, onEvent(Network::ConnectionEvent::LocalClose));
215+
EXPECT_CALL(write_total_, add(_)).Times(AnyNumber());
214216
}
215217

216218
private:
@@ -219,7 +221,8 @@ class EnvoyQuicDispatcherTest : public testing::TestWithParam<Network::Address::
219221
Network::MockConnectionCallbacks network_connection_callbacks_;
220222
testing::StrictMock<Stats::MockCounter> read_total_;
221223
testing::StrictMock<Stats::MockGauge> read_current_;
222-
testing::StrictMock<Stats::MockCounter> write_total_;
224+
// Currently QUIC only populates write_total_.
225+
testing::NiceMock<Stats::MockCounter> write_total_;
223226
testing::StrictMock<Stats::MockGauge> write_current_;
224227

225228
Filter::NetworkFilterFactoriesList filter_factory_;
@@ -271,7 +274,8 @@ TEST_P(EnvoyQuicDispatcherTest, CloseConnectionDuringNetworkFilterInstallation)
271274
Network::MockConnectionCallbacks network_connection_callbacks;
272275
testing::StrictMock<Stats::MockCounter> read_total;
273276
testing::StrictMock<Stats::MockGauge> read_current;
274-
testing::StrictMock<Stats::MockCounter> write_total;
277+
testing::NiceMock<Stats::MockCounter> write_total;
278+
EXPECT_CALL(write_total, add(_)).Times(AnyNumber());
275279
testing::StrictMock<Stats::MockGauge> write_current;
276280

277281
Filter::NetworkFilterFactoriesList filter_factory;
@@ -433,7 +437,8 @@ TEST_P(EnvoyQuicDispatcherTest, CloseWithGivenFilterChain) {
433437
Network::MockConnectionCallbacks network_connection_callbacks;
434438
testing::StrictMock<Stats::MockCounter> read_total;
435439
testing::StrictMock<Stats::MockGauge> read_current;
436-
testing::StrictMock<Stats::MockCounter> write_total;
440+
testing::NiceMock<Stats::MockCounter> write_total;
441+
EXPECT_CALL(write_total, add(_)).Times(AnyNumber());
437442
testing::StrictMock<Stats::MockGauge> write_current;
438443

439444
Filter::NetworkFilterFactoriesList filter_factory;

test/common/quic/envoy_quic_server_session_test.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ class EnvoyQuicServerSessionTest : public testing::Test {
185185
return quic::WriteResult{quic::WRITE_STATUS_OK, static_cast<int>(buf_len)};
186186
}));
187187
ON_CALL(crypto_stream_helper_, CanAcceptClientHello(_, _, _, _, _)).WillByDefault(Return(true));
188+
EXPECT_CALL(write_total_, add(_)).Times(AnyNumber());
188189
EXPECT_CALL(*debug_visitor_factory_.mock_debug_visitor_, OnConnectionClosed(_, _));
189190
}
190191

@@ -273,7 +274,8 @@ class EnvoyQuicServerSessionTest : public testing::Test {
273274
Http::MockServerConnectionCallbacks http_connection_callbacks_;
274275
testing::StrictMock<Stats::MockCounter> read_total_;
275276
testing::StrictMock<Stats::MockGauge> read_current_;
276-
testing::StrictMock<Stats::MockCounter> write_total_;
277+
// Currently QUIC only populates write_total_.
278+
testing::NiceMock<Stats::MockCounter> write_total_;
277279
testing::StrictMock<Stats::MockGauge> write_current_;
278280
Http::ServerConnectionPtr http_connection_;
279281
Http::Http3::CodecStats stats_;

test/integration/protocol_integration_test.cc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5720,4 +5720,25 @@ TEST_P(DownstreamProtocolIntegrationTest, EmptyCookieHeader) {
57205720
codec_client_->close();
57215721
}
57225722

5723+
TEST_P(DownstreamProtocolIntegrationTest, DownstreamCxStats) {
5724+
initialize();
5725+
5726+
codec_client_ = makeHttpConnection(lookupPort("http"));
5727+
5728+
auto response = codec_client_->makeRequestWithBody(default_request_headers_, 1024);
5729+
waitForNextUpstreamRequest();
5730+
5731+
upstream_request_->encodeHeaders(default_response_headers_, false);
5732+
upstream_request_->encodeData(512, true);
5733+
ASSERT_TRUE(response->waitForEndStream());
5734+
5735+
EXPECT_TRUE(upstream_request_->complete());
5736+
EXPECT_EQ(1024U, upstream_request_->bodyLength());
5737+
EXPECT_TRUE(response->complete());
5738+
EXPECT_EQ("200", response->headers().getStatusValue());
5739+
EXPECT_EQ(512U, response->body().size());
5740+
5741+
test_server_->waitForCounterGe("http.config_test.downstream_cx_tx_bytes_total", 512);
5742+
}
5743+
57235744
} // namespace Envoy

0 commit comments

Comments
 (0)