From 121ab41d96736cf324351f4f9b597986525fc029 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Mon, 29 Jul 2019 17:32:56 -0400 Subject: [PATCH] Introduce TCP_FASTOPEN support For best results, use Linux 4.11+ and a server modified to set the TCP_FASTOPEN flag. This should in particular benefit users of legacy forwarding. --- .../proxy/config/VelocityConfiguration.java | 14 ++++++++++++++ .../proxy/network/ConnectionManager.java | 12 +++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java b/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java index 48449e079..812d66154 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java @@ -372,6 +372,10 @@ public class VelocityConfiguration extends AnnotatedConfig implements ProxyConfi return advanced.isProxyProtocol(); } + public boolean useTcpFastOpen() { + return advanced.tcpFastOpen; + } + public Metrics getMetrics() { return metrics; } @@ -608,6 +612,10 @@ public class VelocityConfiguration extends AnnotatedConfig implements ProxyConfi @ConfigKey("proxy-protocol") private boolean proxyProtocol = false; + @Comment("Enables TCP fast open support on the proxy. Requires the proxy to run on Linux.") + @ConfigKey("tcp-fast-open") + private boolean tcpFastOpen = false; + private Advanced() { } @@ -619,6 +627,7 @@ public class VelocityConfiguration extends AnnotatedConfig implements ProxyConfi this.connectionTimeout = toml.getLong("connection-timeout", 5000L).intValue(); this.readTimeout = toml.getLong("read-timeout", 30000L).intValue(); this.proxyProtocol = toml.getBoolean("proxy-protocol", false); + this.tcpFastOpen = toml.getBoolean("tcp-fast-open", false); } } @@ -646,6 +655,10 @@ public class VelocityConfiguration extends AnnotatedConfig implements ProxyConfi return proxyProtocol; } + public boolean isTcpFastOpen() { + return tcpFastOpen; + } + @Override public String toString() { return "Advanced{" @@ -655,6 +668,7 @@ public class VelocityConfiguration extends AnnotatedConfig implements ProxyConfi + ", connectionTimeout=" + connectionTimeout + ", readTimeout=" + readTimeout + ", proxyProtocol=" + proxyProtocol + + ", tcpFastOpen=" + tcpFastOpen + '}'; } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java b/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java index d1c3dba9b..208ce766e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java @@ -15,6 +15,7 @@ import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.WriteBufferWaterMark; +import io.netty.channel.epoll.EpollChannelOption; import io.netty.resolver.dns.DnsAddressResolverGroup; import io.netty.resolver.dns.DnsNameResolverBuilder; import io.netty.util.concurrent.EventExecutor; @@ -102,6 +103,11 @@ public final class ConnectionManager { .childOption(ChannelOption.TCP_NODELAY, true) .childOption(ChannelOption.IP_TOS, 0x18) .localAddress(address); + + if (server.getConfiguration().useTcpFastOpen()) { + bootstrap.option(EpollChannelOption.TCP_FASTOPEN, 3); + } + bootstrap.bind() .addListener((ChannelFutureListener) future -> { final Channel channel = future.channel(); @@ -151,13 +157,17 @@ public final class ConnectionManager { * @return a new {@link Bootstrap} */ public Bootstrap createWorker(@Nullable EventLoopGroup group) { - return new Bootstrap() + Bootstrap bootstrap = new Bootstrap() .channel(this.transportType.socketChannelClass) .option(ChannelOption.TCP_NODELAY, true) .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, this.server.getConfiguration().getConnectTimeout()) .group(group == null ? this.workerGroup : group) .resolver(this.resolverGroup); + if (server.getConfiguration().useTcpFastOpen()) { + bootstrap.option(EpollChannelOption.TCP_FASTOPEN_CONNECT, true); + } + return bootstrap; } /**