From 148991bcd567cfd0515cdae873f0004ebe6c7376 Mon Sep 17 00:00:00 2001 From: Fredy Wijaya Date: Mon, 15 Jul 2024 15:07:10 +0000 Subject: [PATCH] Add an option to set the UDP socket send buffer size Signed-off-by: Fredy Wijaya --- mobile/library/cc/engine_builder.cc | 14 +++++++++++ mobile/library/cc/engine_builder.h | 5 ++++ mobile/test/cc/unit/envoy_config_test.cc | 31 ++++++++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/mobile/library/cc/engine_builder.cc b/mobile/library/cc/engine_builder.cc index a59e6c3c7b8bb..c639761173fb7 100644 --- a/mobile/library/cc/engine_builder.cc +++ b/mobile/library/cc/engine_builder.cc @@ -245,6 +245,11 @@ EngineBuilder& EngineBuilder::setSocketReceiveBufferSize(int32_t size) { return *this; } +EngineBuilder& EngineBuilder::setUdpSocketSendBufferSize(int32_t size) { + udp_socket_send_buffer_size_ = size; + return *this; +} + EngineBuilder& EngineBuilder::enableDrainPostDnsRefresh(bool drain_post_dns_refresh_on) { enable_drain_post_dns_refresh_ = drain_post_dns_refresh_on; return *this; @@ -734,6 +739,15 @@ std::unique_ptr EngineBuilder::generate rcv_buf_sock_opt->set_int_value(socket_receive_buffer_size_); rcv_buf_sock_opt->set_description( absl::StrCat("SO_RCVBUF = ", socket_receive_buffer_size_, " bytes")); + + envoy::config::core::v3::SocketOption* udp_snd_buf_sock_opt = + base_cluster->mutable_upstream_bind_config()->add_socket_options(); + udp_snd_buf_sock_opt->set_name(SO_SNDBUF); + udp_snd_buf_sock_opt->set_level(SOL_SOCKET); + udp_snd_buf_sock_opt->set_int_value(udp_socket_send_buffer_size_); + udp_snd_buf_sock_opt->mutable_type()->mutable_datagram(); + udp_snd_buf_sock_opt->set_description( + absl::StrCat("SO_SNDBUF = ", udp_socket_send_buffer_size_, " bytes")); // Set the network service type on iOS, if supplied. #if defined(__APPLE__) if (ios_network_service_type_ > 0) { diff --git a/mobile/library/cc/engine_builder.h b/mobile/library/cc/engine_builder.h index 5d94d71aee6ce..e0ed01d2b2029 100644 --- a/mobile/library/cc/engine_builder.h +++ b/mobile/library/cc/engine_builder.h @@ -69,6 +69,7 @@ class EngineBuilder { // Sets whether to use GRO for upstream UDP sockets (QUIC/HTTP3). EngineBuilder& setUseGroIfAvailable(bool use_gro_if_available); EngineBuilder& setSocketReceiveBufferSize(int32_t size); + EngineBuilder& setUdpSocketSendBufferSize(int32_t size); EngineBuilder& enforceTrustChainVerification(bool trust_chain_verification_on); EngineBuilder& setUpstreamTlsSni(std::string sni); EngineBuilder& enablePlatformCertificatesValidation(bool platform_certificates_validation_on); @@ -183,6 +184,10 @@ class EngineBuilder { // This is the same value Cronet uses for QUIC: // https://source.chromium.org/chromium/chromium/src/+/main:net/quic/quic_context.h;drc=ccfe61524368c94b138ddf96ae8121d7eb7096cf;l=87 int32_t socket_receive_buffer_size_ = 1024 * 1024; // 1MB + // This is the same value Cronet uses for QUIC: + // https://source.chromium.org/chromium/chromium/src/+/main:net/quic/quic_session_pool.cc;l=790-793;drc=7f04a8e033c23dede6beae129cd212e6d4473d72 + // https://source.chromium.org/chromium/chromium/src/+/main:net/third_party/quiche/src/quiche/quic/core/quic_constants.h;l=43-47;drc=34ad7f3844f882baf3d31a6bc6e300acaa0e3fc8 + int32_t udp_socket_send_buffer_size_ = 1452 * 20; }; using EngineBuilderSharedPtr = std::shared_ptr; diff --git a/mobile/test/cc/unit/envoy_config_test.cc b/mobile/test/cc/unit/envoy_config_test.cc index 9fabb192676a4..bf5add3cc4ede 100644 --- a/mobile/test/cc/unit/envoy_config_test.cc +++ b/mobile/test/cc/unit/envoy_config_test.cc @@ -360,6 +360,37 @@ TEST(TestConfig, SocketReceiveBufferSize) { EXPECT_EQ(rcv_buf_option->level(), SOL_SOCKET); EXPECT_EQ(rcv_buf_option->int_value(), 1024 * 1024 /* 1 MB */); } + +TEST(TestConfig, UdpSocketSendBufferSize) { + EngineBuilder engine_builder; + engine_builder.enableHttp3(true); + + std::unique_ptr bootstrap = engine_builder.generateBootstrap(); + Cluster const* base_cluster = nullptr; + for (const Cluster& cluster : bootstrap->static_resources().clusters()) { + if (cluster.name() == "base") { + base_cluster = &cluster; + break; + } + } + + // The base H3 cluster should always be found. + ASSERT_THAT(base_cluster, NotNull()); + + SocketOption const* snd_buf_option = nullptr; + for (const SocketOption& sock_opt : base_cluster->upstream_bind_config().socket_options()) { + if (sock_opt.name() == SO_SNDBUF) { + snd_buf_option = &sock_opt; + break; + } + } + + // When using an H3 cluster, the UDP send buffer size option should always be set. + ASSERT_THAT(snd_buf_option, NotNull()); + EXPECT_EQ(snd_buf_option->level(), SOL_SOCKET); + EXPECT_TRUE(snd_buf_option->type().has_datagram()); + EXPECT_EQ(snd_buf_option->int_value(), 1452 * 20); +} #endif TEST(TestConfig, EnablePlatformCertificatesValidation) {