Skip to content

Commit

Permalink
add knob for h3 keepalive
Browse files Browse the repository at this point in the history
Signed-off-by: Dan Zhang <danzh@google.com>
  • Loading branch information
danzh1989 committed Oct 16, 2024
1 parent 6d6e613 commit cec91a8
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 22 deletions.
2 changes: 1 addition & 1 deletion api/envoy/config/core/v3/protocol.proto
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ message QuicKeepAliveSettings {
// If absent or zero, disable keepalive probing for a server connection. For a client connection, if :ref:`max_interval <envoy_v3_api_field_config.core.v3.QuicKeepAliveSettings.max_interval>` is also zero, do not keepalive, otherwise use max_interval or QUICHE default to probe all the time.
google.protobuf.Duration initial_interval = 2 [(validate.rules).duration = {
lte {}
gte {seconds: 1}
gte {nanos: 1000000}
}];
}

Expand Down
12 changes: 12 additions & 0 deletions mobile/library/cc/engine_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,12 @@ EngineBuilder::setQuicConnectionIdleTimeoutSeconds(int quic_connection_idle_time
return *this;
}

EngineBuilder&
EngineBuilder::setKeepAliveInitialIntervalMilliseconds(int keepalive_initial_interval_ms) {
keepalive_initial_interval_ms_ = keepalive_initial_interval_ms;
return *this;
}

EngineBuilder&
EngineBuilder::enablePlatformCertificatesValidation(bool platform_certificates_validation_on) {
platform_certificates_validation_on_ = platform_certificates_validation_on;
Expand Down Expand Up @@ -747,6 +753,12 @@ std::unique_ptr<envoy::config::bootstrap::v3::Bootstrap> EngineBuilder::generate
->mutable_idle_network_timeout()
->set_seconds(quic_connection_idle_timeout_seconds_);

auto* quic_protocol_options = alpn_options.mutable_auto_config()
->mutable_http3_protocol_options()
->mutable_quic_protocol_options();
quic_protocol_options->mutable_connection_keepalive()->mutable_initial_interval()->set_nanos(
keepalive_initial_interval_ms_ * 1000 * 1000);

base_cluster->mutable_transport_socket()->mutable_typed_config()->PackFrom(h3_proxy_socket);
(*base_cluster->mutable_typed_extension_protocol_options())
["envoy.extensions.upstreams.http.v3.HttpProtocolOptions"]
Expand Down
5 changes: 5 additions & 0 deletions mobile/library/cc/engine_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ class EngineBuilder {
// Sets the QUIC connection idle timeout in seconds.
EngineBuilder& setQuicConnectionIdleTimeoutSeconds(int quic_connection_idle_timeout_seconds);

// Sets the QUIC connection keepalive initial interval in nanoseconds
EngineBuilder& setKeepAliveInitialIntervalMilliseconds(int keepalive_initial_interval_ms);

#if defined(__APPLE__)
// Right now, this API is only used by Apple (iOS) to register the Apple proxy resolver API for
// use in reading and using the system proxy settings.
Expand Down Expand Up @@ -207,6 +210,8 @@ class EngineBuilder {
int32_t udp_socket_send_buffer_size_ = 1452 * 20;

int quic_connection_idle_timeout_seconds_ = 30;

int keepalive_initial_interval_ms_ = 0;
};

using EngineBuilderSharedPtr = std::shared_ptr<EngineBuilder>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public enum TrustChainVerification {
public final Map<String, String> runtimeGuards;
public final boolean enablePlatformCertificatesValidation;
public final String upstreamTlsSni;
public final int h3ConnectionKeepaliveInitialIntervalMilliseconds;

/**
* Create a new instance of the configuration.
Expand Down Expand Up @@ -131,6 +132,8 @@ public enum TrustChainVerification {
* @param upstreamTlsSni the upstream TLS socket SNI override.
* @param caresFallbackResolvers A list of host port pair that's used as
* c-ares's fallback resolvers.
* @param h3ConnectionKeepaliveInitialIntervalMilliseconds the initial keepalive ping timeout for
* HTTP/3.
*/
public EnvoyConfiguration(
int connectTimeoutSeconds, int dnsRefreshSeconds, int dnsFailureRefreshSecondsBase,
Expand All @@ -150,7 +153,8 @@ public EnvoyConfiguration(
Map<String, EnvoyStringAccessor> stringAccessors,
Map<String, EnvoyKeyValueStore> keyValueStores, Map<String, Boolean> runtimeGuards,
boolean enablePlatformCertificatesValidation, String upstreamTlsSni,
List<Pair<String, Integer>> caresFallbackResolvers) {
List<Pair<String, Integer>> caresFallbackResolvers,
int h3ConnectionKeepaliveInitialIntervalMilliseconds) {
JniLibrary.load();
this.connectTimeoutSeconds = connectTimeoutSeconds;
this.dnsRefreshSeconds = dnsRefreshSeconds;
Expand Down Expand Up @@ -213,6 +217,8 @@ public EnvoyConfiguration(
}
this.enablePlatformCertificatesValidation = enablePlatformCertificatesValidation;
this.upstreamTlsSni = upstreamTlsSni;
this.h3ConnectionKeepaliveInitialIntervalMilliseconds =
h3ConnectionKeepaliveInitialIntervalMilliseconds;
}

public long createBootstrap() {
Expand All @@ -239,7 +245,7 @@ public long createBootstrap() {
enableInterfaceBinding, h2ConnectionKeepaliveIdleIntervalMilliseconds,
h2ConnectionKeepaliveTimeoutSeconds, maxConnectionsPerHost, streamIdleTimeoutSeconds,
perTryIdleTimeoutSeconds, appVersion, appId, enforceTrustChainVerification, filterChain,
enablePlatformCertificatesValidation, upstreamTlsSni, runtimeGuards,
caresFallbackResolvers);
enablePlatformCertificatesValidation, upstreamTlsSni, runtimeGuards, caresFallbackResolvers,
h3ConnectionKeepaliveInitialIntervalMilliseconds);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ public static native long createBootstrap(
long streamIdleTimeoutSeconds, long perTryIdleTimeoutSeconds, String appVersion, String appId,
boolean trustChainVerification, byte[][] filterChain,
boolean enablePlatformCertificatesValidation, String upstreamTlsSni, byte[][] runtimeGuards,
byte[][] cares_fallback_resolvers);
byte[][] cares_fallback_resolvers, long h3ConnectionKeepaliveInitialIntervalMilliseconds);

/**
* Initializes c-ares.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public class NativeCronvoyEngineBuilderImpl extends CronvoyEngineBuilderImpl {
private TrustChainVerification mTrustChainVerification = VERIFY_TRUST_CHAIN;
private final boolean mEnablePlatformCertificatesValidation = true;
private String mUpstreamTlsSni = "";
private final int mH3ConnectionKeepaliveInitialIntervalMilliseconds = 0;

private final Map<String, Boolean> mRuntimeGuards = new HashMap<>();

Expand Down Expand Up @@ -234,6 +235,12 @@ public NativeCronvoyEngineBuilderImpl setUpstreamTlsSni(String sni) {
return this;
}

public NativeCronvoyEngineBuilderImpl
setH3ConnectionKeepaliveInitialIntervalMilliseconds(int interval) {
mH3ConnectionKeepaliveInitialIntervalMilliseconds = interval;
return this;
}

/**
* Indicates to skip the TLS certificate verification.
*
Expand Down Expand Up @@ -297,6 +304,6 @@ mUseGro, quicConnectionOptions(), quicClientConnectionOptions(), quicHints(),
mMaxConnectionsPerHost, mStreamIdleTimeoutSeconds, mPerTryIdleTimeoutSeconds, mAppVersion,
mAppId, mTrustChainVerification, nativeFilterChain, platformFilterChain, stringAccessors,
keyValueStores, mRuntimeGuards, mEnablePlatformCertificatesValidation, mUpstreamTlsSni,
mCaresFallbackResolvers);
mCaresFallbackResolvers, mH3ConnectionKeepaliveInitialIntervalMilliseconds);
}
}
32 changes: 18 additions & 14 deletions mobile/library/jni/jni_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1232,6 +1232,7 @@ void configureBuilder(Envoy::JNI::JniHelper& jni_helper, jlong connect_timeout_s
jobjectArray filter_chain, jboolean enable_platform_certificates_validation,
jstring upstream_tls_sni, jobjectArray runtime_guards,
jobjectArray cares_fallback_resolvers,
jlong h3_connection_keepalive_initial_interval_milliseconds,
Envoy::Platform::EngineBuilder& builder) {
builder.addConnectTimeoutSeconds((connect_timeout_seconds));
builder.addDnsRefreshSeconds((dns_refresh_seconds));
Expand Down Expand Up @@ -1286,6 +1287,8 @@ void configureBuilder(Envoy::JNI::JniHelper& jni_helper, jlong connect_timeout_s
builder.enablePlatformCertificatesValidation(enable_platform_certificates_validation == JNI_TRUE);
builder.setUpstreamTlsSni(Envoy::JNI::javaStringToCppString(jni_helper, upstream_tls_sni));
builder.setForceAlwaysUsev6(force_v6 == JNI_TRUE);
builder.setKeepAliveInitialIntervalMilliseconds(
(h3_connection_keepalive_initial_interval_milliseconds));

auto guards = javaObjectArrayToStringPairVector(jni_helper, runtime_guards);
for (std::pair<std::string, std::string>& entry : guards) {
Expand Down Expand Up @@ -1334,23 +1337,24 @@ extern "C" JNIEXPORT jlong JNICALL Java_io_envoyproxy_envoymobile_engine_JniLibr
jlong stream_idle_timeout_seconds, jlong per_try_idle_timeout_seconds, jstring app_version,
jstring app_id, jboolean trust_chain_verification, jobjectArray filter_chain,
jboolean enable_platform_certificates_validation, jstring upstream_tls_sni,
jobjectArray runtime_guards, jobjectArray cares_fallback_resolvers) {
jobjectArray runtime_guards, jobjectArray cares_fallback_resolvers,
jlong h3_connection_keepalive_initial_interval_milliseconds) {
Envoy::JNI::JniHelper jni_helper(env);
Envoy::Platform::EngineBuilder builder;

configureBuilder(jni_helper, connect_timeout_seconds, dns_refresh_seconds,
dns_failure_refresh_seconds_base, dns_failure_refresh_seconds_max,
dns_query_timeout_seconds, dns_min_refresh_seconds, dns_preresolve_hostnames,
enable_dns_cache, dns_cache_save_interval_seconds, dns_num_retries,
enable_drain_post_dns_refresh, enable_http3, use_cares, force_v6, use_gro,
http3_connection_options, http3_client_connection_options, quic_hints,
quic_canonical_suffixes, enable_gzip_decompression, enable_brotli_decompression,
num_timeouts_to_trigger_port_migration, enable_socket_tagging,
enable_interface_binding, h2_connection_keepalive_idle_interval_milliseconds,
h2_connection_keepalive_timeout_seconds, max_connections_per_host,
stream_idle_timeout_seconds, per_try_idle_timeout_seconds, app_version, app_id,
trust_chain_verification, filter_chain, enable_platform_certificates_validation,
upstream_tls_sni, runtime_guards, cares_fallback_resolvers, builder);
configureBuilder(
jni_helper, connect_timeout_seconds, dns_refresh_seconds, dns_failure_refresh_seconds_base,
dns_failure_refresh_seconds_max, dns_query_timeout_seconds, dns_min_refresh_seconds,
dns_preresolve_hostnames, enable_dns_cache, dns_cache_save_interval_seconds, dns_num_retries,
enable_drain_post_dns_refresh, enable_http3, use_cares, force_v6, use_gro,
http3_connection_options, http3_client_connection_options, quic_hints,
quic_canonical_suffixes, enable_gzip_decompression, enable_brotli_decompression,
num_timeouts_to_trigger_port_migration, enable_socket_tagging, enable_interface_binding,
h2_connection_keepalive_idle_interval_milliseconds, h2_connection_keepalive_timeout_seconds,
max_connections_per_host, stream_idle_timeout_seconds, per_try_idle_timeout_seconds,
app_version, app_id, trust_chain_verification, filter_chain,
enable_platform_certificates_validation, upstream_tls_sni, runtime_guards,
cares_fallback_resolvers, h3_connection_keepalive_initial_interval_milliseconds, builder);

return reinterpret_cast<intptr_t>(builder.generateBootstrap().release());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ open class EngineBuilder() {
private var keyValueStores = mutableMapOf<String, EnvoyKeyValueStore>()
private var enablePlatformCertificatesValidation = false
private var upstreamTlsSni: String = ""
private var h3ConnectionKeepaliveInitialIntervalMilliseconds = 0

/**
* Sets a log level to use with Envoy.
Expand Down Expand Up @@ -549,6 +550,11 @@ open class EngineBuilder() {
return this
}

fun addH3ConnectionKeepaliveInitialIntervalMilliseconds(interval: Int): EngineBuilder {
this.h3ConnectionKeepaliveInitialIntervalMilliseconds = interval
return this
}

/**
* Builds and runs a new Engine instance with the provided configuration.
*
Expand Down Expand Up @@ -598,6 +604,7 @@ open class EngineBuilder() {
enablePlatformCertificatesValidation,
upstreamTlsSni,
caresFallbackResolvers,
h3ConnectionKeepaliveInitialIntervalMilliseconds,
)

return EngineImpl(engineType(), engineConfiguration, logLevel)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class EnvoyConfigurationTest {
runtimeGuards: Map<String,Boolean> = emptyMap(),
enablePlatformCertificatesValidation: Boolean = false,
upstreamTlsSni: String = "",

h3ConnectionKeepaliveInitialIntervalMilliseconds: Int = 0,
): EnvoyConfiguration {
return EnvoyConfiguration(
connectTimeoutSeconds,
Expand Down Expand Up @@ -159,6 +159,7 @@ class EnvoyConfigurationTest {
enablePlatformCertificatesValidation,
upstreamTlsSni,
caresFallbackResolvers,
h3ConnectionKeepaliveInitialIntervalMilliseconds,
)
}

Expand Down Expand Up @@ -201,6 +202,8 @@ class EnvoyConfigurationTest {
assertThat(resolvedTemplate).contains(".xyz.com");
assertThat(resolvedTemplate).contains("connection_options: \"5RTO\"");
assertThat(resolvedTemplate).contains("client_connection_options: \"MPQC\"");
assertThat(resolvedTemplate).contains("connection_keepalive { initial_interval { }")


// Per Host Limits
assertThat(resolvedTemplate).contains("max_connections { value: 543 }")
Expand Down Expand Up @@ -251,7 +254,8 @@ class EnvoyConfigurationTest {
dnsPreresolveHostnames = mutableListOf(),
filterChain = mutableListOf(),
runtimeGuards = mapOf("test_feature_false" to true),
trustChainVerification = TrustChainVerification.ACCEPT_UNTRUSTED
trustChainVerification = TrustChainVerification.ACCEPT_UNTRUSTED,
h3ConnectionKeepaliveInitialIntervalMilliseconds = 200
)

val resolvedTemplate = TestJni.createProtoString(envoyConfiguration)
Expand Down Expand Up @@ -289,6 +293,17 @@ class EnvoyConfigurationTest {

// enablePlatformCertificatesValidation = true
assertThat(resolvedTemplate).doesNotContain("trusted_ca")

assertThat(resolvedTemplate).doesNotContain("quic_protocol_options")

val envoyConfiguration1 = buildTestEnvoyConfiguration(
enableHttp3 = true,
h3ConnectionKeepaliveInitialIntervalMilliseconds = 200
)

val resolvedTemplate1 = TestJni.createProtoString(envoyConfiguration1)
// h3ConnectionKeepaliveInitialIntervalMilliseconds = 200
assertThat(resolvedTemplate1).contains("connection_keepalive { initial_interval { nanos: 200000000 }")
}

@Test
Expand Down

0 comments on commit cec91a8

Please sign in to comment.