--- old/make/lib/Lib-jdk.net.gmk 2017-10-12 14:12:50.885288220 +0530 +++ new/make/lib/Lib-jdk.net.gmk 2017-10-12 14:12:50.757262977 +0530 @@ -35,13 +35,34 @@ SRC := $(TOPDIR)/src/jdk.net/solaris/native/libextnet, \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/jdk.net, \ - MAPFILE := $(TOPDIR)/make/mapfiles/libextnet/mapfile-vers, \ + MAPFILE := $(TOPDIR)/make/mapfiles/libextnet/mapfile-solaris, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS := -lsocket -lc -ljava, \ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libextnet, \ )) + $(BUILD_LIBEXTNET): $(call FindLib, java.base, java) + + TARGETS += $(BUILD_LIBEXTNET) +endif + + +ifeq ($(OPENJDK_TARGET_OS), linux) + + $(eval $(call SetupNativeCompilation, BUILD_LIBEXTNET, \ + LIBRARY := extnet, \ + OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ + SRC := $(TOPDIR)/src/jdk.net/linux/native/libextnet, \ + OPTIMIZATION := LOW, \ + CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/jdk.net, \ + MAPFILE := $(TOPDIR)/make/mapfiles/libextnet/mapfile-linux, \ + LDFLAGS := $(LDFLAGS_JDKLIB) \ + $(call SET_SHARED_LIBRARY_ORIGIN), \ + LIBS := -ljvm -ljava -lc, \ + OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libextnet, \ + )) + $(BUILD_LIBEXTNET): $(call FindLib, java.base, java) TARGETS += $(BUILD_LIBEXTNET) --- old/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java 2017-10-12 14:12:51.177345803 +0530 +++ new/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java 2017-10-12 14:12:51.057322139 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,10 +85,18 @@ protected Set> supportedOptions() { HashSet> options = new HashSet<>(super.supportedOptions()); - options.addAll(extendedOptions.options()); + addExtSocketOptions(extendedOptions.options(), options); return options; } + private void addExtSocketOptions(Set> extOptions, + Set> options) { + extOptions.stream().filter((option) -> (!option.name(). + equals("TCP_QUICKACK"))).forEachOrdered((option) -> { + options.add(option); + }); // TCP_QUICKACK is applicable for TCP Sockets only. + } + protected void socketSetOption(int opt, Object val) throws SocketException { if (opt == SocketOptions.SO_REUSEPORT && !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { --- old/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java 2017-10-12 14:12:51.465402598 +0530 +++ new/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java 2017-10-12 14:12:51.337377356 +0530 @@ -68,19 +68,54 @@ ExtSocketOption("SO_FLOW_SLA", SocketFlow.class); + /** + * TCP_QUICKACK. + * + * This socket option usually enable TCP_QUICKACK mode if set or disable + * TCP_QUICKACK mode if cleared. + * + * The value of this socket option is a {@code Boolean} that represents + * whether the option is enabled or disabled. The socket option is specific + * to stream-oriented sockets using the TCP/IP protocol. + * + * The exact semantics of this socket option are socket type and system + * dependent. + * + * When TCP_QUICKACK is enabled, acks are sent immediately, rather than + * delayed if needed in accordance to normal TCP operation.This flag is not + * permanent, it only enables a switch to or from TCP_QUICKACK mode. + * + * Subsequent operation of the TCP protocol will once again enter/leave + * TCP_QUICKACK mode depending on internal protocol processing and factors + * such as delayed ack timeouts occurring and data transfer. + * + * @since 18.3 + */ + public static final SocketOption TCP_QUICKACK + = new ExtSocketOption("TCP_QUICKACK", Boolean.class); + private static final PlatformSocketOptions platformSocketOptions = PlatformSocketOptions.get(); private static final boolean flowSupported = platformSocketOptions.flowSupported(); + private static final boolean quickAckSupported = + platformSocketOptions.quickAckSupported(); private static final Set> extendedOptions = options(); static Set> options() { - if (flowSupported) - return Set.of(SO_FLOW_SLA); - else + if (flowSupported) { + if (quickAckSupported) { + return Set.of(SO_FLOW_SLA, TCP_QUICKACK); + } else { + return Set.of(SO_FLOW_SLA); + } + } else if (quickAckSupported) { + return Set.of(TCP_QUICKACK); + } else { return Collections.>emptySet(); + } } static { @@ -105,6 +140,8 @@ assert flowSupported; SocketFlow flow = checkValueType(value, option.type()); setFlowOption(fd, flow); + } else if (option == TCP_QUICKACK) { + setQuickAckOption(fd, (boolean) value); } else { throw new InternalError("Unexpected option " + option); } @@ -127,6 +164,8 @@ SocketFlow flow = SocketFlow.create(); getFlowOption(fd, flow); return flow; + } else if (option == TCP_QUICKACK) { + return getQuickAckOption(fd); } else { throw new InternalError("Unexpected option " + option); } @@ -156,12 +195,21 @@ } private static void getFlowOption(FileDescriptor fd, SocketFlow f) - throws SocketException - { + throws SocketException { int status = platformSocketOptions.getFlowOption(fdAccess.get(fd), f); f.status(status); // augment the given flow with the status } + private static void setQuickAckOption(FileDescriptor fd, boolean enable) + throws SocketException { + platformSocketOptions.setQuickAck(fdAccess.get(fd), enable == true ? 1 : 0); + } + + private static Object getQuickAckOption(FileDescriptor fd) + throws SocketException { + return platformSocketOptions.getQuickAck(fdAccess.get(fd)); + } + static class PlatformSocketOptions { protected PlatformSocketOptions() {} @@ -184,9 +232,13 @@ return System.getProperty("os.name"); } }); - if ("SunOS".equals(osname)) + if ("SunOS".equals(osname)) { return newInstance("jdk.net.SolarisSocketOptions"); - return new PlatformSocketOptions(); + } else if ("Linux".equals(osname)) { + return newInstance("jdk.net.LinuxSocketOptions"); + } else { + return new PlatformSocketOptions(); + } } private static final PlatformSocketOptions instance = create(); @@ -208,5 +260,17 @@ boolean flowSupported() { return false; } + + void setQuickAck(int fd, int on) throws SocketException { + throw new UnsupportedOperationException("unsupported TCP_QUICKACK option"); + } + + boolean getQuickAck(int fd) throws SocketException { + throw new UnsupportedOperationException("unsupported TCP_QUICKACK option"); + } + + boolean quickAckSupported() { + return false; + } } } --- old/src/jdk.net/share/classes/jdk/net/Sockets.java 2017-10-12 14:12:51.761460970 +0530 +++ new/src/jdk.net/share/classes/jdk/net/Sockets.java 2017-10-12 14:12:51.637436517 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -246,7 +246,7 @@ private static volatile boolean checkedReusePort; private static volatile boolean isReusePortAvailable; - + /** * Tells whether SO_REUSEPORT is supported. */ @@ -279,6 +279,9 @@ if (flowsupported) { set.add(ExtendedSocketOptions.SO_FLOW_SLA); } + if (QuickAck.available) { + set.add(ExtendedSocketOptions.TCP_QUICKACK); + } set = Collections.unmodifiableSet(set); options.put(Socket.class, set); @@ -290,6 +293,9 @@ if (reuseportsupported) { set.add(StandardSocketOptions.SO_REUSEPORT); } + if (QuickAck.available) { + set.add(ExtendedSocketOptions.TCP_QUICKACK); + } set.add(StandardSocketOptions.IP_TOS); set = Collections.unmodifiableSet(set); options.put(ServerSocket.class, set); @@ -331,4 +337,17 @@ return Collections.unmodifiableMap(options); } + + /** + * Tells whether TCP_QUICKACK is supported. + */ + static class QuickAck { + + static final boolean available; + + static { + Set> s = new Socket().supportedOptions(); + available = s.contains(ExtendedSocketOptions.TCP_QUICKACK); + } + } } --- /dev/null 2017-10-12 07:30:16.967999979 +0530 +++ new/make/mapfiles/libextnet/mapfile-linux 2017-10-12 14:12:51.929494101 +0530 @@ -0,0 +1,33 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +SUNWprivate_1.1 { + global: + Java_jdk_net_LinuxSocketOptions_setQuickAck0; + Java_jdk_net_LinuxSocketOptions_getQuickAck0; + Java_jdk_net_LinuxSocketOptions_quickAckSupported0; + local: + *; +}; --- /dev/null 2017-10-12 07:30:16.967999979 +0530 +++ new/make/mapfiles/libextnet/mapfile-solaris 2017-10-12 14:12:52.237554839 +0530 @@ -0,0 +1,34 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +SUNWprivate_1.1 { + global: + Java_jdk_net_SolarisSocketOptions_init; + Java_jdk_net_SolarisSocketOptions_setFlowOption; + Java_jdk_net_SolarisSocketOptions_getFlowOption; + Java_jdk_net_SolarisSocketOptions_flowSupported; + local: + *; +}; --- /dev/null 2017-10-12 07:30:16.967999979 +0530 +++ new/src/jdk.net/linux/classes/jdk/net/LinuxSocketOptions.java 2017-10-12 14:12:52.569620311 +0530 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.net; + +import java.net.SocketException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import jdk.net.ExtendedSocketOptions.PlatformSocketOptions; + +class LinuxSocketOptions extends PlatformSocketOptions { + + public LinuxSocketOptions() { + } + + @Override + void setQuickAck(int fd, int on) throws SocketException { + setQuickAck0(fd, on); + } + + @Override + boolean getQuickAck(int fd) throws SocketException { + return getQuickAck0(fd); + } + + @Override + public boolean quickAckSupported() { + return quickAckSupported0(); + } + + native static private void setQuickAck0(int fd, int on) throws SocketException; + + native static private boolean getQuickAck0(int fd) throws SocketException; + + native static private boolean quickAckSupported0(); + + static { + AccessController.doPrivileged((PrivilegedAction) () -> { + System.loadLibrary("extnet"); + return null; + }); + } +} --- /dev/null 2017-10-12 07:30:16.967999979 +0530 +++ new/src/jdk.net/linux/native/libextnet/LinuxSocketOptions.c 2017-10-12 14:12:52.921689727 +0530 @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +#include +#include +#include +#include + +#include +#include +#include "jni_util.h" + +/* + * Class: jdk_net_LinuxSocketOptions + * Method: setQuickAck + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_jdk_net_LinuxSocketOptions_setQuickAck0 +(JNIEnv *env, jobject unused, jint fd, jboolean on) { + int optval; + int rv; + optval = (on ? 1 : 0); + rv = setsockopt(fd, SOL_SOCKET, TCP_QUICKACK, &optval, sizeof (optval)); + if (rv < 0) { + if (errno == ENOPROTOOPT) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); + } else { + JNU_ThrowByNameWithLastError(env, "java/net/SocketException", + "set option TCP_QUICKACK failed"); + } + } +} + +/* + * Class: jdk_net_LinuxSocketOptions + * Method: getQuickAck + * Signature: (I)Z; + */ +JNIEXPORT jboolean JNICALL Java_jdk_net_LinuxSocketOptions_getQuickAck0 +(JNIEnv *env, jobject unused, jint fd) { + int on; + socklen_t sz = sizeof (on); + int rv = getsockopt(fd, SOL_SOCKET, TCP_QUICKACK, &on, &sz); + if (rv < 0) { + if (errno == ENOPROTOOPT) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); + } else { + JNU_ThrowByNameWithLastError(env, "java/net/SocketException", + "get option TCP_QUICKACK failed"); + } + } + return on != 0; +} + +/* + * Class: jdk_net_LinuxSocketOptions + * Method: quickAckSupported + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_jdk_net_LinuxSocketOptions_quickAckSupported0 +(JNIEnv *env, jobject unused) { + int one = 1; + int rv, s; + s = socket(PF_INET, SOCK_STREAM, 0); + if (s < 0) { + return JNI_FALSE; + } + rv = setsockopt(s, SOL_SOCKET, TCP_QUICKACK, (void *) &one, sizeof (one)); + if (rv != 0 && errno == ENOPROTOOPT) { + rv = JNI_FALSE; + } else { + rv = JNI_TRUE; + } + close(s); + return rv; +} --- /dev/null 2017-10-12 07:30:16.967999979 +0530 +++ new/test/jdk/jdk/net/Sockets/QuickAckTest.java 2017-10-12 14:12:53.253755199 +0530 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + * @test + * @bug 8145635 + * @summary Add TCP_QUICKACK socket option + * @modules jdk.net + * @run main QuickAckTest + */ +import java.io.IOException; +import java.net.DatagramSocket; +import java.net.MulticastSocket; +import java.net.ServerSocket; +import java.net.Socket; +import jdk.net.ExtendedSocketOptions; +import jdk.net.Sockets; + +public class QuickAckTest { + + private static final String LOCAL_HOST = "127.0.0.1"; + + public static void main(String args[]) throws IOException { + + try (ServerSocket ss = new ServerSocket(0); + Socket s = new Socket(LOCAL_HOST, ss.getLocalPort()); + DatagramSocket ds = new DatagramSocket(0); + MulticastSocket mc = new MulticastSocket(0)) { + + if (ss.supportedOptions().contains(ExtendedSocketOptions.TCP_QUICKACK)) { + Sockets.setOption(ss, ExtendedSocketOptions.TCP_QUICKACK, true); + if (!ss.getOption(ExtendedSocketOptions.TCP_QUICKACK)) { + throw new RuntimeException("Test failed, TCP_QUICKACK should" + + " have been set"); + } + } + if (s.supportedOptions().contains(ExtendedSocketOptions.TCP_QUICKACK)) { + Sockets.setOption(s, ExtendedSocketOptions.TCP_QUICKACK, true); + if (!s.getOption(ExtendedSocketOptions.TCP_QUICKACK)) { + throw new RuntimeException("Test failed, TCP_QUICKACK should" + + " have been set"); + } + } + if (ds.supportedOptions().contains(ExtendedSocketOptions.TCP_QUICKACK)) { + throw new RuntimeException("Test failed, TCP_QUICKACK is applicable" + + " for TCP Sockets only."); + } + if (mc.supportedOptions().contains(ExtendedSocketOptions.TCP_QUICKACK)) { + throw new RuntimeException("Test failed, TCP_QUICKACK is applicable" + + " for TCP Sockets only"); + } + } + } +} --- old/make/mapfiles/libextnet/mapfile-vers 2017-10-12 14:12:53.705844335 +0530 +++ /dev/null 2017-10-12 07:30:16.967999979 +0530 @@ -1,34 +0,0 @@ -# -# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -SUNWprivate_1.1 { - global: - Java_jdk_net_SolarisSocketOptions_init; - Java_jdk_net_SolarisSocketOptions_setFlowOption; - Java_jdk_net_SolarisSocketOptions_getFlowOption; - Java_jdk_net_SolarisSocketOptions_flowSupported; - local: - *; -};