8060170: Support SIO_LOOPBACK_FAST_PATH option on Windows
Co-authored-by: Valeriy Kopylov <v-valkop@microsoft.com> Reviewed-by: alanb
This commit is contained in:
parent
80b26e5882
commit
d03eadea27
@ -110,6 +110,8 @@ SUNWprivate_1.1 {
|
||||
NET_Bind;
|
||||
NET_MapSocketOption;
|
||||
NET_Wait;
|
||||
NET_EnableFastTcpLoopback;
|
||||
NET_ThrowNew;
|
||||
ipv6_available;
|
||||
initInetAddressIDs;
|
||||
|
||||
|
@ -50,30 +50,8 @@ public class Net {
|
||||
// set to true if exclusive binding is on for Windows
|
||||
private static final boolean exclusiveBind;
|
||||
|
||||
static {
|
||||
int availLevel = isExclusiveBindAvailable();
|
||||
if (availLevel >= 0) {
|
||||
String exclBindProp =
|
||||
java.security.AccessController.doPrivileged(
|
||||
new PrivilegedAction<String>() {
|
||||
@Override
|
||||
public String run() {
|
||||
return System.getProperty(
|
||||
"sun.net.useExclusiveBind");
|
||||
}
|
||||
});
|
||||
if (exclBindProp != null) {
|
||||
exclusiveBind = exclBindProp.length() == 0 ?
|
||||
true : Boolean.parseBoolean(exclBindProp);
|
||||
} else if (availLevel == 1) {
|
||||
exclusiveBind = true;
|
||||
} else {
|
||||
exclusiveBind = false;
|
||||
}
|
||||
} else {
|
||||
exclusiveBind = false;
|
||||
}
|
||||
}
|
||||
// set to true if the fast tcp loopback should be enabled on Windows
|
||||
private static final boolean fastLoopback;
|
||||
|
||||
// -- Miscellaneous utilities --
|
||||
|
||||
@ -391,6 +369,23 @@ public class Net {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isFastTcpLoopbackRequested() {
|
||||
String loopbackProp = java.security.AccessController.doPrivileged(
|
||||
new PrivilegedAction<String>() {
|
||||
@Override
|
||||
public String run() {
|
||||
return System.getProperty("jdk.net.useFastTcpLoopback");
|
||||
}
|
||||
});
|
||||
boolean enable;
|
||||
if ("".equals(loopbackProp)) {
|
||||
enable = true;
|
||||
} else {
|
||||
enable = Boolean.parseBoolean(loopbackProp);
|
||||
}
|
||||
return enable;
|
||||
}
|
||||
|
||||
// -- Socket operations --
|
||||
|
||||
private static native boolean isIPv6Available0();
|
||||
@ -413,15 +408,16 @@ public class Net {
|
||||
throws IOException {
|
||||
boolean preferIPv6 = isIPv6Available() &&
|
||||
(family != StandardProtocolFamily.INET);
|
||||
return IOUtil.newFD(socket0(preferIPv6, stream, false));
|
||||
return IOUtil.newFD(socket0(preferIPv6, stream, false, fastLoopback));
|
||||
}
|
||||
|
||||
static FileDescriptor serverSocket(boolean stream) {
|
||||
return IOUtil.newFD(socket0(isIPv6Available(), stream, true));
|
||||
return IOUtil.newFD(socket0(isIPv6Available(), stream, true, fastLoopback));
|
||||
}
|
||||
|
||||
// Due to oddities SO_REUSEADDR on windows reuse is ignored
|
||||
private static native int socket0(boolean preferIPv6, boolean stream, boolean reuse);
|
||||
private static native int socket0(boolean preferIPv6, boolean stream, boolean reuse,
|
||||
boolean fastLoopback);
|
||||
|
||||
public static void bind(FileDescriptor fd, InetAddress addr, int port)
|
||||
throws IOException
|
||||
@ -634,4 +630,30 @@ public class Net {
|
||||
POLLCONN = pollconnValue();
|
||||
}
|
||||
|
||||
static {
|
||||
int availLevel = isExclusiveBindAvailable();
|
||||
if (availLevel >= 0) {
|
||||
String exclBindProp =
|
||||
java.security.AccessController.doPrivileged(
|
||||
new PrivilegedAction<String>() {
|
||||
@Override
|
||||
public String run() {
|
||||
return System.getProperty(
|
||||
"sun.net.useExclusiveBind");
|
||||
}
|
||||
});
|
||||
if (exclBindProp != null) {
|
||||
exclusiveBind = exclBindProp.length() == 0 ?
|
||||
true : Boolean.parseBoolean(exclBindProp);
|
||||
} else if (availLevel == 1) {
|
||||
exclusiveBind = true;
|
||||
} else {
|
||||
exclusiveBind = false;
|
||||
}
|
||||
} else {
|
||||
exclusiveBind = false;
|
||||
}
|
||||
|
||||
fastLoopback = isFastTcpLoopbackRequested();
|
||||
}
|
||||
}
|
||||
|
@ -184,9 +184,13 @@ NET_MapSocketOption(jint cmd, int *level, int *optname);
|
||||
JNIEXPORT int JNICALL
|
||||
NET_MapSocketOptionV6(jint cmd, int *level, int *optname);
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
NET_EnableFastTcpLoopback(int fd);
|
||||
|
||||
int getScopeID (struct sockaddr *);
|
||||
|
||||
int cmpScopeID (unsigned int, struct sockaddr *);
|
||||
|
||||
unsigned short in_cksum(unsigned short *addr, int len);
|
||||
|
||||
#endif /* NET_UTILS_H */
|
||||
|
@ -790,6 +790,11 @@ void parseExclusiveBindProperty(JNIEnv *env) {
|
||||
#endif
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
NET_EnableFastTcpLoopback(int fd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* In the case of an IPv4 Inetaddress this method will return an
|
||||
* IPv4 mapped address where IPv6 is available and v4MappedAddress is TRUE.
|
||||
* Otherwise it will return a sockaddr_in structure for an IPv4 InetAddress.
|
||||
|
@ -188,7 +188,7 @@ Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl)
|
||||
|
||||
JNIEXPORT int JNICALL
|
||||
Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
|
||||
jboolean stream, jboolean reuse)
|
||||
jboolean stream, jboolean reuse, jboolean ignored)
|
||||
{
|
||||
int fd;
|
||||
int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
|
||||
|
@ -29,6 +29,9 @@
|
||||
#include "net_util.h"
|
||||
#include "jni.h"
|
||||
|
||||
// Taken from mstcpip.h in Windows SDK 8.0 or newer.
|
||||
#define SIO_LOOPBACK_FAST_PATH _WSAIOW(IOC_VENDOR,16)
|
||||
|
||||
#ifndef IPTOS_TOS_MASK
|
||||
#define IPTOS_TOS_MASK 0x1e
|
||||
#endif
|
||||
@ -844,6 +847,25 @@ jint getDefaultIPv6Interface(JNIEnv *env, struct SOCKADDR_IN6 *target_addr)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables SIO_LOOPBACK_FAST_PATH
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
NET_EnableFastTcpLoopback(int fd) {
|
||||
int enabled = 1;
|
||||
DWORD result_byte_count = -1;
|
||||
int result = WSAIoctl(fd,
|
||||
SIO_LOOPBACK_FAST_PATH,
|
||||
&enabled,
|
||||
sizeof(enabled),
|
||||
NULL,
|
||||
0,
|
||||
&result_byte_count,
|
||||
NULL,
|
||||
NULL);
|
||||
return result == SOCKET_ERROR ? WSAGetLastError() : 0;
|
||||
}
|
||||
|
||||
/* If address types is IPv6, then IPv6 must be available. Otherwise
|
||||
* no address can be generated. In the case of an IPv4 Inetaddress this
|
||||
* method will return an IPv4 mapped address where IPv6 is available and
|
||||
|
@ -127,7 +127,7 @@ Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl)
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
|
||||
jboolean stream, jboolean reuse)
|
||||
jboolean stream, jboolean reuse, jboolean fastLoopback)
|
||||
{
|
||||
SOCKET s;
|
||||
int domain = (preferIPv6) ? AF_INET6 : AF_INET;
|
||||
@ -152,6 +152,20 @@ Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
|
||||
NET_ThrowNew(env, WSAGetLastError(), "socket");
|
||||
}
|
||||
|
||||
if (stream && fastLoopback) {
|
||||
static int loopback_available = 1;
|
||||
if (loopback_available) {
|
||||
int rv = NET_EnableFastTcpLoopback((jint)s);
|
||||
if (rv) {
|
||||
if (rv == WSAEOPNOTSUPP) {
|
||||
loopback_available = 0;
|
||||
} else {
|
||||
NET_ThrowNew(env, rv, "fastLoopback");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (jint)s;
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,8 @@
|
||||
/* @test
|
||||
* @bug 6834246 6842687
|
||||
* @summary Stress test connections through the loopback interface
|
||||
* @run main StressLoopback
|
||||
* @run main/othervm -Djdk.net.useFastTcpLoopback StressLoopback
|
||||
*/
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
Loading…
x
Reference in New Issue
Block a user