diff --git a/make/mapfiles/libnet/mapfile-vers b/make/mapfiles/libnet/mapfile-vers index 9e07f44b14aaeaf98f1273fde0deb6c9b892a233..3eb5e6d994a9c22a6d8658fbf81539d16ba1c480 100644 --- a/make/mapfiles/libnet/mapfile-vers +++ b/make/mapfiles/libnet/mapfile-vers @@ -110,6 +110,8 @@ SUNWprivate_1.1 { NET_Bind; NET_MapSocketOption; NET_Wait; + NET_EnableFastTcpLoopback; + NET_ThrowNew; ipv6_available; local: diff --git a/src/share/classes/sun/nio/ch/Net.java b/src/share/classes/sun/nio/ch/Net.java index 37823e98c550f6e8ae5a382708d508c634d5eb1f..598b4849e5bef82358ea143f4ca653f980261a84 100644 --- a/src/share/classes/sun/nio/ch/Net.java +++ b/src/share/classes/sun/nio/ch/Net.java @@ -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() { - @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() { + @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() { + @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 --git a/src/share/native/java/net/net_util.h b/src/share/native/java/net/net_util.h index 246c0549e7f0768f1c7c7606320e2094b64c0621..60d63fcb6b70694bd622b6e4520d4917fea54111 100644 --- a/src/share/native/java/net/net_util.h +++ b/src/share/native/java/net/net_util.h @@ -182,9 +182,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 */ diff --git a/src/solaris/native/java/net/net_util_md.c b/src/solaris/native/java/net/net_util_md.c index 769e5405024914d5f48e4395aff932949341bc48..67da52316a98918416769a974e3e453e2bf31a9c 100644 --- a/src/solaris/native/java/net/net_util_md.c +++ b/src/solaris/native/java/net/net_util_md.c @@ -777,6 +777,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. diff --git a/src/solaris/native/sun/nio/ch/Net.c b/src/solaris/native/sun/nio/ch/Net.c index ae7f5794316527d1c77c5b7ec08bd06c93625ced..73560ad6c62dc6c1c33c7dc54651b9426207cf99 100644 --- a/src/solaris/native/sun/nio/ch/Net.c +++ b/src/solaris/native/sun/nio/ch/Net.c @@ -231,7 +231,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); diff --git a/src/windows/native/java/net/net_util_md.c b/src/windows/native/java/net/net_util_md.c index 274d90995bac49d7c673ec906a749afdbf2c6ecc..9acffcaab39ffb6953114e523db2dbaa9f56dee1 100644 --- a/src/windows/native/java/net/net_util_md.c +++ b/src/windows/native/java/net/net_util_md.c @@ -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 diff --git a/src/windows/native/sun/nio/ch/Net.c b/src/windows/native/sun/nio/ch/Net.c index fb0faa87b84fa90a34826eb0aa01cc9b182e6c63..e68951b839061522d28903f7dfa41a43edf69411 100644 --- a/src/windows/native/sun/nio/ch/Net.c +++ b/src/windows/native/sun/nio/ch/Net.c @@ -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; } diff --git a/test/java/nio/channels/AsynchronousSocketChannel/StressLoopback.java b/test/java/nio/channels/AsynchronousSocketChannel/StressLoopback.java index 46b326bde06a8af702d8c8224f565134c8bf09de..4627aaa2a5a5401a05224dd39e2226c636ef8cff 100644 --- a/test/java/nio/channels/AsynchronousSocketChannel/StressLoopback.java +++ b/test/java/nio/channels/AsynchronousSocketChannel/StressLoopback.java @@ -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;