Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ private static Process createProcess(
command.addAll(jvmOptions);
command.add("--module-path");
command.add(esHome.resolve("lib").toString());
command.add("--add-modules=jdk.net");
command.add("-m");
command.add("org.elasticsearch.server/org.elasticsearch.bootstrap.Elasticsearch");

Expand Down
6 changes: 6 additions & 0 deletions docs/changelog/88935.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pr: 88935
summary: Ensure that the extended socket options TCP_KEEPXXX are available
area: Network
type: bug
issues:
- 88897
1 change: 1 addition & 0 deletions modules/transport-netty4/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

module org.elasticsearch.transport.netty4 {
requires jdk.net;
requires org.elasticsearch.base;
requires org.elasticsearch.server;
requires org.elasticsearch.xcontent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@
import org.elasticsearch.xcontent.NamedXContentRegistry;

import java.net.InetSocketAddress;
import java.net.SocketOption;
import java.util.concurrent.TimeUnit;

import static org.elasticsearch.http.HttpTransportSettings.SETTING_HTTP_MAX_CHUNK_SIZE;
Expand Down Expand Up @@ -215,25 +214,22 @@ protected void doStart() {
// Netty logs a warning if it can't set the option, so try this only on supported platforms
if (IOUtils.LINUX || IOUtils.MAC_OS_X) {
if (SETTING_HTTP_TCP_KEEP_IDLE.get(settings) >= 0) {
final SocketOption<Integer> keepIdleOption = NetUtils.getTcpKeepIdleSocketOptionOrNull();
if (keepIdleOption != null) {
serverBootstrap.childOption(NioChannelOption.of(keepIdleOption), SETTING_HTTP_TCP_KEEP_IDLE.get(settings));
}
serverBootstrap.childOption(
NioChannelOption.of(NetUtils.getTcpKeepIdleSocketOption()),
SETTING_HTTP_TCP_KEEP_IDLE.get(settings)
);
}
if (SETTING_HTTP_TCP_KEEP_INTERVAL.get(settings) >= 0) {
final SocketOption<Integer> keepIntervalOption = NetUtils.getTcpKeepIntervalSocketOptionOrNull();
if (keepIntervalOption != null) {
serverBootstrap.childOption(
NioChannelOption.of(keepIntervalOption),
SETTING_HTTP_TCP_KEEP_INTERVAL.get(settings)
);
}
serverBootstrap.childOption(
NioChannelOption.of(NetUtils.getTcpKeepIntervalSocketOption()),
SETTING_HTTP_TCP_KEEP_INTERVAL.get(settings)
);
}
if (SETTING_HTTP_TCP_KEEP_COUNT.get(settings) >= 0) {
final SocketOption<Integer> keepCountOption = NetUtils.getTcpKeepCountSocketOptionOrNull();
if (keepCountOption != null) {
serverBootstrap.childOption(NioChannelOption.of(keepCountOption), SETTING_HTTP_TCP_KEEP_COUNT.get(settings));
}
serverBootstrap.childOption(
NioChannelOption.of(NetUtils.getTcpKeepCountSocketOption()),
SETTING_HTTP_TCP_KEEP_COUNT.get(settings)
);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@

package org.elasticsearch.transport.netty4;

import jdk.net.ExtendedSocketOptions;

import org.elasticsearch.core.SuppressForbidden;

import java.io.IOException;
import java.lang.reflect.Field;
import java.net.SocketOption;
import java.net.StandardSocketOptions;
import java.nio.channels.NetworkChannel;
import java.util.Arrays;
import java.util.Objects;

/**
* Utilities for network-related methods.
Expand All @@ -22,37 +25,31 @@ public class NetUtils {

private NetUtils() {}

// Accessors to the extended socket options reduce the proliferation of the non-portable
// ExtendedSocketOptions type.

/**
* Returns the extended TCP_KEEPIDLE socket option, if available on this JDK
* Returns the extended TCP_KEEPIDLE socket option.
*/
public static SocketOption<Integer> getTcpKeepIdleSocketOptionOrNull() {
return getExtendedSocketOptionOrNull("TCP_KEEPIDLE");
@SuppressForbidden(reason = "access to non-portable socket option requied")
public static SocketOption<Integer> getTcpKeepIdleSocketOption() {
return ExtendedSocketOptions.TCP_KEEPIDLE;
}

/**
* Returns the extended TCP_KEEPINTERVAL socket option, if available on this JDK
* Returns the extended TCP_KEEPINTERVAL socket option.
*/
public static SocketOption<Integer> getTcpKeepIntervalSocketOptionOrNull() {
return getExtendedSocketOptionOrNull("TCP_KEEPINTERVAL");
@SuppressForbidden(reason = "access to non-portable socket option requied")
public static SocketOption<Integer> getTcpKeepIntervalSocketOption() {
return ExtendedSocketOptions.TCP_KEEPINTERVAL;
}

/**
* Returns the extended TCP_KEEPCOUNT socket option, if available on this JDK
* Returns the extended TCP_KEEPCOUNT socket option.
*/
public static SocketOption<Integer> getTcpKeepCountSocketOptionOrNull() {
return getExtendedSocketOptionOrNull("TCP_KEEPCOUNT");
}

@SuppressWarnings("unchecked")
private static <T> SocketOption<T> getExtendedSocketOptionOrNull(String fieldName) {
try {
final Class<?> extendedSocketOptionsClass = Class.forName("jdk.net.ExtendedSocketOptions");
final Field field = extendedSocketOptionsClass.getField(fieldName);
return (SocketOption<T>) field.get(null);
} catch (Exception t) {
// ignore
return null;
}
@SuppressForbidden(reason = "access to non-portable socket option requied")
public static SocketOption<Integer> getTcpKeepCountSocketOption() {
return ExtendedSocketOptions.TCP_KEEPCOUNT;
}

/**
Expand All @@ -67,13 +64,9 @@ public static void tryEnsureReasonableKeepAliveConfig(NetworkChannel socketChann
if (socketChannel.supportedOptions().contains(StandardSocketOptions.SO_KEEPALIVE)) {
final Boolean keepalive = socketChannel.getOption(StandardSocketOptions.SO_KEEPALIVE);
assert keepalive != null;
if (keepalive.booleanValue()) {
for (SocketOption<Integer> option : Arrays.asList(
NetUtils.getTcpKeepIdleSocketOptionOrNull(),
NetUtils.getTcpKeepIntervalSocketOptionOrNull()
)) {
setMinValueForSocketOption(socketChannel, option, 300);
}
if (keepalive) {
setMinValueForSocketOption(socketChannel, getTcpKeepIdleSocketOption(), 300);
setMinValueForSocketOption(socketChannel, getTcpKeepIntervalSocketOption(), 300);
}
}
} catch (Exception e) {
Expand All @@ -84,7 +77,8 @@ public static void tryEnsureReasonableKeepAliveConfig(NetworkChannel socketChann
}

private static void setMinValueForSocketOption(NetworkChannel socketChannel, SocketOption<Integer> option, int minValue) {
if (option != null && socketChannel.supportedOptions().contains(option)) {
Objects.requireNonNull(option);
if (socketChannel.supportedOptions().contains(option)) {
try {
final Integer currentIdleVal = socketChannel.getOption(option);
assert currentIdleVal != null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketOption;
import java.util.Map;

import static org.elasticsearch.common.settings.Setting.byteSizeSetting;
Expand Down Expand Up @@ -165,22 +164,19 @@ private Bootstrap createClientBootstrap(SharedGroupFactory.SharedGroup sharedGro
if (TransportSettings.TCP_KEEP_ALIVE.get(settings)) {
// Note that Netty logs a warning if it can't set the option
if (TransportSettings.TCP_KEEP_IDLE.get(settings) >= 0) {
final SocketOption<Integer> keepIdleOption = NetUtils.getTcpKeepIdleSocketOptionOrNull();
if (keepIdleOption != null) {
bootstrap.option(NioChannelOption.of(keepIdleOption), TransportSettings.TCP_KEEP_IDLE.get(settings));
}
bootstrap.option(NioChannelOption.of(NetUtils.getTcpKeepIdleSocketOption()), TransportSettings.TCP_KEEP_IDLE.get(settings));
}
if (TransportSettings.TCP_KEEP_INTERVAL.get(settings) >= 0) {
final SocketOption<Integer> keepIntervalOption = NetUtils.getTcpKeepIntervalSocketOptionOrNull();
if (keepIntervalOption != null) {
bootstrap.option(NioChannelOption.of(keepIntervalOption), TransportSettings.TCP_KEEP_INTERVAL.get(settings));
}
bootstrap.option(
NioChannelOption.of(NetUtils.getTcpKeepIntervalSocketOption()),
TransportSettings.TCP_KEEP_INTERVAL.get(settings)
);
}
if (TransportSettings.TCP_KEEP_COUNT.get(settings) >= 0) {
final SocketOption<Integer> keepCountOption = NetUtils.getTcpKeepCountSocketOptionOrNull();
if (keepCountOption != null) {
bootstrap.option(NioChannelOption.of(keepCountOption), TransportSettings.TCP_KEEP_COUNT.get(settings));
}
bootstrap.option(
NioChannelOption.of(NetUtils.getTcpKeepCountSocketOption()),
TransportSettings.TCP_KEEP_COUNT.get(settings)
);
}
}

Expand Down Expand Up @@ -236,23 +232,16 @@ private void createServerBootstrap(ProfileSettings profileSettings, SharedGroupF
if (profileSettings.tcpKeepAlive) {
// Note that Netty logs a warning if it can't set the option
if (profileSettings.tcpKeepIdle >= 0) {
final SocketOption<Integer> keepIdleOption = NetUtils.getTcpKeepIdleSocketOptionOrNull();
if (keepIdleOption != null) {
serverBootstrap.childOption(NioChannelOption.of(keepIdleOption), profileSettings.tcpKeepIdle);
}
serverBootstrap.childOption(NioChannelOption.of(NetUtils.getTcpKeepIdleSocketOption()), profileSettings.tcpKeepIdle);
}
if (profileSettings.tcpKeepInterval >= 0) {
final SocketOption<Integer> keepIntervalOption = NetUtils.getTcpKeepIntervalSocketOptionOrNull();
if (keepIntervalOption != null) {
serverBootstrap.childOption(NioChannelOption.of(keepIntervalOption), profileSettings.tcpKeepInterval);
}

serverBootstrap.childOption(
NioChannelOption.of(NetUtils.getTcpKeepIntervalSocketOption()),
profileSettings.tcpKeepInterval
);
}
if (profileSettings.tcpKeepCount >= 0) {
final SocketOption<Integer> keepCountOption = NetUtils.getTcpKeepCountSocketOptionOrNull();
if (keepCountOption != null) {
serverBootstrap.childOption(NioChannelOption.of(keepCountOption), profileSettings.tcpKeepCount);
}
serverBootstrap.childOption(NioChannelOption.of(NetUtils.getTcpKeepCountSocketOption()), profileSettings.tcpKeepCount);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,18 @@
import org.elasticsearch.core.IOUtils;
import org.elasticsearch.test.ESTestCase;

import java.nio.channels.SocketChannel;

public class NetUtilsTests extends ESTestCase {

public void testExtendedSocketOptions() {
public void testExtendedSocketOptions() throws Exception {
assumeTrue("JDK possibly not supported", Constants.JVM_NAME.contains("HotSpot") || Constants.JVM_NAME.contains("OpenJDK"));
assumeTrue("Platform possibly not supported", IOUtils.LINUX || IOUtils.MAC_OS_X);
assertNotNull(NetUtils.getTcpKeepIdleSocketOptionOrNull());
assertNotNull(NetUtils.getTcpKeepIntervalSocketOptionOrNull());
assertNotNull(NetUtils.getTcpKeepCountSocketOptionOrNull());
assertNotNull(NetUtils.getTcpKeepIdleSocketOption());
assertNotNull(NetUtils.getTcpKeepIntervalSocketOption());
assertNotNull(NetUtils.getTcpKeepCountSocketOption());
SocketChannel.open().supportedOptions().contains(NetUtils.getTcpKeepIdleSocketOption());
SocketChannel.open().supportedOptions().contains(NetUtils.getTcpKeepIntervalSocketOption());
SocketChannel.open().supportedOptions().contains(NetUtils.getTcpKeepCountSocketOption());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,12 @@ private void checkDefaultKeepAliveOptions(TcpChannel channel) throws IOException
assertThat(nettyChannel.getNettyChannel(), instanceOf(Netty4NioSocketChannel.class));
Netty4NioSocketChannel netty4NioSocketChannel = (Netty4NioSocketChannel) nettyChannel.getNettyChannel();
SocketChannel socketChannel = netty4NioSocketChannel.javaChannel();
assertThat(socketChannel.supportedOptions(), hasItem(NetUtils.getTcpKeepIdleSocketOptionOrNull()));
Integer keepIdle = socketChannel.getOption(NetUtils.getTcpKeepIdleSocketOptionOrNull());
assertThat(socketChannel.supportedOptions(), hasItem(NetUtils.getTcpKeepIdleSocketOption()));
Integer keepIdle = socketChannel.getOption(NetUtils.getTcpKeepIdleSocketOption());
assertNotNull(keepIdle);
assertThat(keepIdle, lessThanOrEqualTo(500));
assertThat(socketChannel.supportedOptions(), hasItem(NetUtils.getTcpKeepIntervalSocketOptionOrNull()));
Integer keepInterval = socketChannel.getOption(NetUtils.getTcpKeepIntervalSocketOptionOrNull());
assertThat(socketChannel.supportedOptions(), hasItem(NetUtils.getTcpKeepIntervalSocketOption()));
Integer keepInterval = socketChannel.getOption(NetUtils.getTcpKeepIntervalSocketOption());
assertNotNull(keepInterval);
assertThat(keepInterval, lessThanOrEqualTo(500));
}
Expand Down