# HG changeset patch # User alanb # Date 1413715973 -3600 # Node ID 885f4428b50158048b2abb7a31063d7386c0a6d5 # Parent 3717db2c3bfecfe285b8e917287d3ba4f5b58181 8060170: Support SIO_LOOPBACK_FAST_PATH option on Windows Reviewed-by: alanb Contributed-by: kirk.shoop@microsoft.com, v-valkop@microsoft.com diff -r 3717db2c3bfe -r 885f4428b501 jdk/make/mapfiles/libnet/mapfile-vers --- 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; diff -r 3717db2c3bfe -r 885f4428b501 jdk/src/java.base/share/classes/sun/nio/ch/Net.java --- 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() { - @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() { + @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() { + @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(); + } } diff -r 3717db2c3bfe -r 885f4428b501 jdk/src/java.base/share/native/libnet/net_util.h --- 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 */ diff -r 3717db2c3bfe -r 885f4428b501 jdk/src/java.base/unix/native/libnet/net_util_md.c --- 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. diff -r 3717db2c3bfe -r 885f4428b501 jdk/src/java.base/unix/native/libnio/ch/Net.c --- 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); diff -r 3717db2c3bfe -r 885f4428b501 jdk/src/java.base/windows/native/libnet/net_util_md.c --- 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 diff -r 3717db2c3bfe -r 885f4428b501 jdk/src/java.base/windows/native/libnio/ch/Net.c --- 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; } diff -r 3717db2c3bfe -r 885f4428b501 jdk/test/java/nio/channels/AsynchronousSocketChannel/StressLoopback.java --- 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;