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 f4a76919ee..d4740ab1b4 100644
--- a/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java
+++ b/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java
@@ -30,6 +30,7 @@
import com.velocitypowered.proxy.config.migration.ForwardingMigration;
import com.velocitypowered.proxy.config.migration.KeyAuthenticationMigration;
import com.velocitypowered.proxy.config.migration.MotdMigration;
+import com.velocitypowered.proxy.config.migration.TcpFastOpenMigration;
import com.velocitypowered.proxy.util.AddressUtil;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
@@ -456,7 +457,8 @@ public static VelocityConfiguration read(Path path) throws IOException {
final ConfigurationMigration[] migrations = {
new ForwardingMigration(),
new KeyAuthenticationMigration(),
- new MotdMigration()
+ new MotdMigration(),
+ new TcpFastOpenMigration()
};
for (final ConfigurationMigration migration : migrations) {
@@ -695,7 +697,7 @@ private static class Advanced {
@Expose
private boolean proxyProtocol = false;
@Expose
- private boolean tcpFastOpen = false;
+ private boolean tcpFastOpen = true;
@Expose
private boolean bungeePluginMessageChannel = true;
@Expose
@@ -724,7 +726,7 @@ private Advanced(CommentedConfig config) {
} else {
this.proxyProtocol = config.getOrElse("proxy-protocol", false);
}
- this.tcpFastOpen = config.getOrElse("tcp-fast-open", false);
+ this.tcpFastOpen = config.getOrElse("tcp-fast-open", true);
this.bungeePluginMessageChannel = config.getOrElse("bungee-plugin-message-channel", true);
this.showPingRequests = config.getOrElse("show-ping-requests", false);
this.failoverOnUnexpectedServerDisconnect = config
diff --git a/proxy/src/main/java/com/velocitypowered/proxy/config/migration/ConfigurationMigration.java b/proxy/src/main/java/com/velocitypowered/proxy/config/migration/ConfigurationMigration.java
index 2dc37cb446..0a2d6dc41f 100644
--- a/proxy/src/main/java/com/velocitypowered/proxy/config/migration/ConfigurationMigration.java
+++ b/proxy/src/main/java/com/velocitypowered/proxy/config/migration/ConfigurationMigration.java
@@ -25,7 +25,7 @@
* Configuration Migration interface.
*/
public sealed interface ConfigurationMigration
- permits ForwardingMigration, KeyAuthenticationMigration, MotdMigration {
+ permits ForwardingMigration, KeyAuthenticationMigration, MotdMigration, TcpFastOpenMigration {
boolean shouldMigrate(CommentedFileConfig config);
void migrate(CommentedFileConfig config, Logger logger) throws IOException;
diff --git a/proxy/src/main/java/com/velocitypowered/proxy/config/migration/TcpFastOpenMigration.java b/proxy/src/main/java/com/velocitypowered/proxy/config/migration/TcpFastOpenMigration.java
new file mode 100644
index 0000000000..6c48864d09
--- /dev/null
+++ b/proxy/src/main/java/com/velocitypowered/proxy/config/migration/TcpFastOpenMigration.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 Velocity Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.velocitypowered.proxy.config.migration;
+
+import com.electronwill.nightconfig.core.file.CommentedFileConfig;
+import org.apache.logging.log4j.Logger;
+
+/**
+ * Migrate TCP Fast Open to be enabled by default.
+ */
+public final class TcpFastOpenMigration implements ConfigurationMigration {
+ @Override
+ public boolean shouldMigrate(final CommentedFileConfig config) {
+ return configVersion(config) < 2.7;
+ }
+
+ @Override
+ public void migrate(final CommentedFileConfig config, final Logger logger) {
+ if (!config.getOrElse("advanced.tcp-fast-open", false)) {
+ config.set("advanced.tcp-fast-open", true);
+ }
+
+ config.setComment("advanced.tcp-fast-open", """
+ Enables TCP fast open support on the proxy.
+ Disabled automatically if not supported by the operating system.""");
+ config.set("config-version", "2.7");
+ }
+}
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 be1db5522a..5a9db4f1dc 100644
--- a/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java
+++ b/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java
@@ -100,7 +100,8 @@ public void bind(final InetSocketAddress address) {
.childOption(ChannelOption.IP_TOS, 0x18)
.localAddress(address);
- if (server.getConfiguration().useTcpFastOpen()) {
+ if (server.getConfiguration().useTcpFastOpen()
+ && transportType.supportsTcpFastOpenServer()) {
bootstrap.option(ChannelOption.TCP_FASTOPEN, 3);
}
@@ -163,7 +164,8 @@ public Bootstrap createWorker(@Nullable EventLoopGroup group) {
this.server.getConfiguration().getConnectTimeout())
.group(group == null ? this.workerGroup : group)
.resolver(this.resolver.asGroup());
- if (server.getConfiguration().useTcpFastOpen()) {
+ if (server.getConfiguration().useTcpFastOpen()
+ && transportType.supportsTcpFastOpenClient()) {
bootstrap.option(ChannelOption.TCP_FASTOPEN_CONNECT, true);
}
return bootstrap;
diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/TransportType.java b/proxy/src/main/java/com/velocitypowered/proxy/network/TransportType.java
index 6cbdfd8c54..04a27d4ec4 100644
--- a/proxy/src/main/java/com/velocitypowered/proxy/network/TransportType.java
+++ b/proxy/src/main/java/com/velocitypowered/proxy/network/TransportType.java
@@ -47,32 +47,44 @@ public enum TransportType {
NIO("NIO", NioServerSocketChannel::new,
NioSocketChannel::new,
NioDatagramChannel::new,
- (name, type) -> new NioEventLoopGroup(0, createThreadFactory(name, type))),
+ (name, type) -> new NioEventLoopGroup(0, createThreadFactory(name, type)),
+ false,
+ false),
EPOLL("epoll", EpollServerSocketChannel::new,
EpollSocketChannel::new,
EpollDatagramChannel::new,
- (name, type) -> new EpollEventLoopGroup(0, createThreadFactory(name, type))),
+ (name, type) -> new EpollEventLoopGroup(0, createThreadFactory(name, type)),
+ Epoll.isTcpFastOpenServerSideAvailable(),
+ Epoll.isTcpFastOpenClientSideAvailable()),
KQUEUE("kqueue", KQueueServerSocketChannel::new,
KQueueSocketChannel::new,
KQueueDatagramChannel::new,
- (name, type) -> new KQueueEventLoopGroup(0, createThreadFactory(name, type)));
+ (name, type) -> new KQueueEventLoopGroup(0, createThreadFactory(name, type)),
+ KQueue.isTcpFastOpenServerSideAvailable(),
+ KQueue.isTcpFastOpenClientSideAvailable());
final String name;
final ChannelFactory extends ServerSocketChannel> serverSocketChannelFactory;
final ChannelFactory extends SocketChannel> socketChannelFactory;
final ChannelFactory extends DatagramChannel> datagramChannelFactory;
final BiFunction eventLoopGroupFactory;
+ final boolean supportsTcpFastOpenServer;
+ final boolean supportsTcpFastOpenClient;
TransportType(final String name,
final ChannelFactory extends ServerSocketChannel> serverSocketChannelFactory,
final ChannelFactory extends SocketChannel> socketChannelFactory,
final ChannelFactory extends DatagramChannel> datagramChannelFactory,
- final BiFunction eventLoopGroupFactory) {
+ final BiFunction eventLoopGroupFactory,
+ final boolean supportsTcpFastOpenServer,
+ final boolean supportsTcpFastOpenClient) {
this.name = name;
this.serverSocketChannelFactory = serverSocketChannelFactory;
this.socketChannelFactory = socketChannelFactory;
this.datagramChannelFactory = datagramChannelFactory;
this.eventLoopGroupFactory = eventLoopGroupFactory;
+ this.supportsTcpFastOpenServer = supportsTcpFastOpenServer;
+ this.supportsTcpFastOpenClient = supportsTcpFastOpenClient;
}
@Override
@@ -84,6 +96,14 @@ public EventLoopGroup createEventLoopGroup(final Type type) {
return this.eventLoopGroupFactory.apply(this.name, type);
}
+ public boolean supportsTcpFastOpenServer() {
+ return supportsTcpFastOpenServer;
+ }
+
+ public boolean supportsTcpFastOpenClient() {
+ return supportsTcpFastOpenClient;
+ }
+
private static ThreadFactory createThreadFactory(final String name, final Type type) {
return new VelocityNettyThreadFactory("Netty " + name + ' ' + type.toString() + " #%d");
}
diff --git a/proxy/src/main/resources/default-velocity.toml b/proxy/src/main/resources/default-velocity.toml
index 0f18208b55..d4f972d80b 100644
--- a/proxy/src/main/resources/default-velocity.toml
+++ b/proxy/src/main/resources/default-velocity.toml
@@ -1,5 +1,5 @@
# Config version. Do not change this
-config-version = "2.6"
+config-version = "2.7"
# What port should the proxy be bound to? By default, we'll bind to all addresses on port 25577.
bind = "0.0.0.0:25577"
@@ -42,7 +42,7 @@ forwarding-secret-file = "forwarding.secret"
# Announce whether or not your server supports Forge. If you run a modded server, we
# suggest turning this on.
-#
+#
# If your network runs one modpack consistently, consider using ping-passthrough = "mods"
# instead for a nicer display in the server list.
announce-forge = false
@@ -116,8 +116,9 @@ read-timeout = 30000
# don't enable it.
haproxy-protocol = false
-# Enables TCP fast open support on the proxy. Requires the proxy to run on Linux.
-tcp-fast-open = false
+# Enables TCP fast open support on the proxy.
+# Disabled automatically if not supported by the operating system.
+tcp-fast-open = true
# Enables BungeeCord plugin messaging channel support on Velocity.
bungee-plugin-message-channel = true