8060170: Support SIO_LOOPBACK_FAST_PATH option on Windows
Reviewed-by: alanb
Contributed-by: kirk.shoop@microsoft.com, v-valkop@microsoft.com
--- a/jdk/make/mapfiles/libnet/mapfile-vers Fri Oct 17 10:59:32 2014 +0100
+++ b/jdk/make/mapfiles/libnet/mapfile-vers Sun Oct 19 11:52:53 2014 +0100
@@ -110,6 +110,8 @@
NET_Bind;
NET_MapSocketOption;
NET_Wait;
+ NET_EnableFastTcpLoopback;
+ NET_ThrowNew;
ipv6_available;
initInetAddressIDs;
--- a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java Fri Oct 17 10:59:32 2014 +0100
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java Sun Oct 19 11:52:53 2014 +0100
@@ -50,30 +50,8 @@
// 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 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 @@
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 @@
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();
+ }
}
--- a/jdk/src/java.base/share/native/libnet/net_util.h Fri Oct 17 10:59:32 2014 +0100
+++ b/jdk/src/java.base/share/native/libnet/net_util.h Sun Oct 19 11:52:53 2014 +0100
@@ -184,9 +184,13 @@
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 */
--- a/jdk/src/java.base/unix/native/libnet/net_util_md.c Fri Oct 17 10:59:32 2014 +0100
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.c Sun Oct 19 11:52:53 2014 +0100
@@ -790,6 +790,11 @@
#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.
--- a/jdk/src/java.base/unix/native/libnio/ch/Net.c Fri Oct 17 10:59:32 2014 +0100
+++ b/jdk/src/java.base/unix/native/libnio/ch/Net.c Sun Oct 19 11:52:53 2014 +0100
@@ -188,7 +188,7 @@
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);
--- a/jdk/src/java.base/windows/native/libnet/net_util_md.c Fri Oct 17 10:59:32 2014 +0100
+++ b/jdk/src/java.base/windows/native/libnet/net_util_md.c Sun Oct 19 11:52:53 2014 +0100
@@ -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 @@
}
}
+/**
+ * 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
--- a/jdk/src/java.base/windows/native/libnio/ch/Net.c Fri Oct 17 10:59:32 2014 +0100
+++ b/jdk/src/java.base/windows/native/libnio/ch/Net.c Sun Oct 19 11:52:53 2014 +0100
@@ -127,7 +127,7 @@
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 @@
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;
}
--- a/jdk/test/java/nio/channels/AsynchronousSocketChannel/StressLoopback.java Fri Oct 17 10:59:32 2014 +0100
+++ b/jdk/test/java/nio/channels/AsynchronousSocketChannel/StressLoopback.java Sun Oct 19 11:52:53 2014 +0100
@@ -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;