Initial load of JEP 337 implementation rsocket-branch
authoralanb
Sat, 26 Jan 2019 14:02:35 +0000
branchrsocket-branch
changeset 57115 512e7cc6ccce
parent 53485 b743968ad646
child 57116 5e54d94c238a
Initial load of JEP 337 implementation
make/gensrc/GensrcMisc.gmk
make/lib/Lib-jdk.net.gmk
make/test/JtregNativeJdk.gmk
src/java.base/share/classes/module-info.java
src/java.base/share/classes/sun/net/ext/RdmaSocketOptions.java
src/java.base/share/classes/sun/nio/ch/IOUtil.java
src/java.base/share/classes/sun/nio/ch/Net.java
src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java
src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java
src/java.base/unix/native/libnio/ch/PollSelectorImpl.c
src/jdk.net/linux/classes/jdk/internal/net/rdma/LinuxRdmaSocketDispatcherImpl.java
src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaInetAddressContainer.java
src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaNet.java
src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaOptionKey.java
src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaPollSelectorImpl.java
src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaPollSelectorProvider.java
src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaServerSocketAdaptor.java
src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaServerSocketChannelImpl.java
src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaSocketAdaptor.java
src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaSocketChannelImpl.java
src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaSocketDispatcher.java
src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaSocketImpl.java
src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaSocketInputStream.java
src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaSocketOptionRegistry.java.template
src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaSocketOutputStream.java
src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaSocketProvider.java
src/jdk.net/linux/classes/jdk/net/LinuxRdmaSocketOptions.java
src/jdk.net/linux/native/libextnet/LinuxRdmaSocketDispatcherImpl.c
src/jdk.net/linux/native/libextnet/LinuxRdmaSocketOptions.c
src/jdk.net/linux/native/libextnet/RdmaNet.c
src/jdk.net/linux/native/libextnet/RdmaPollSelectorImpl.c
src/jdk.net/linux/native/libextnet/RdmaServerSocketChannelImpl.c
src/jdk.net/linux/native/libextnet/RdmaSocketChannelImpl.c
src/jdk.net/linux/native/libextnet/RdmaSocketImpl.c
src/jdk.net/linux/native/libextnet/RdmaSocketInputStream.c
src/jdk.net/linux/native/libextnet/RdmaSocketOutputStream.c
src/jdk.net/linux/native/libextnet/Rsocket.c
src/jdk.net/linux/native/libextnet/Rsocket.h
src/jdk.net/linux/native/libextnet/rdma_util_md.c
src/jdk.net/linux/native/libextnet/rdma_util_md.h
src/jdk.net/share/classes/jdk/internal/net/rdma/RdmaPollSelectorProvider.java
src/jdk.net/share/classes/jdk/internal/net/rdma/RdmaSocketProvider.java
src/jdk.net/share/classes/jdk/net/RdmaSocketOptions.java
src/jdk.net/share/classes/jdk/net/RdmaSockets.java
test/jdk/jdk/net/RdmaSockets/rsocket/Exceptions.java
test/jdk/jdk/net/RdmaSockets/rsocket/NullBind.java
test/jdk/jdk/net/RdmaSockets/rsocket/RsocketTest.java
test/jdk/jdk/net/RdmaSockets/rsocket/Selector/BasicAccept.java
test/jdk/jdk/net/RdmaSockets/rsocket/Selector/BasicConnect.java
test/jdk/jdk/net/RdmaSockets/rsocket/Selector/Connect.java
test/jdk/jdk/net/RdmaSockets/rsocket/Selector/SelectorTest.java
test/jdk/jdk/net/RdmaSockets/rsocket/ServerSocketChannel/Basic.java
test/jdk/jdk/net/RdmaSockets/rsocket/ServerSocketChannel/SSCConfigureBlocking.java
test/jdk/jdk/net/RdmaSockets/rsocket/ServerSocketChannel/SocketOptionTests.java
test/jdk/jdk/net/RdmaSockets/rsocket/Socket/BasicSocketTest.java
test/jdk/jdk/net/RdmaSockets/rsocket/Socket/GetLocalAddress.java
test/jdk/jdk/net/RdmaSockets/rsocket/SocketChannel/BasicSocketChannelTest.java
test/jdk/jdk/net/RdmaSockets/rsocket/SocketChannel/CloseDuringWrite.java
test/jdk/jdk/net/RdmaSockets/rsocket/SocketChannel/Connect.java
test/jdk/jdk/net/RdmaSockets/rsocket/SocketChannel/FinishConnect.java
test/jdk/jdk/net/RdmaSockets/rsocket/SocketChannel/IOExchanges.java
test/jdk/jdk/net/RdmaSockets/rsocket/SocketChannel/SCConfigureBlocking.java
test/jdk/jdk/net/RdmaSockets/rsocket/SocketChannel/SocketOptionTests.java
test/jdk/jdk/net/RdmaSockets/rsocket/SocketChannel/Stream.java
test/jdk/jdk/net/RdmaSockets/rsocket/SocketChannel/VectorIO.java
test/jdk/jdk/net/RdmaSockets/rsocket/SocketOption/OptionsTest.java
test/jdk/jdk/net/RdmaSockets/rsocket/SocketOption/UnsupportedOptionsTest.java
test/jdk/jdk/net/RdmaSockets/rsocket/TestServers.java
test/jdk/jdk/net/RdmaSockets/rsocket/libRsocketTest.c
--- a/make/gensrc/GensrcMisc.gmk	Fri Jan 25 11:15:00 2019 +0100
+++ b/make/gensrc/GensrcMisc.gmk	Sat Jan 26 14:02:35 2019 +0000
@@ -87,6 +87,17 @@
 
 GENSRC_JAVA_BASE += $(GENSRC_SOR_FILE)
 
+ifeq ($(OPENJDK_TARGET_OS), linux)
+  GENSRC_RSOR_FILE += $(SUPPORT_OUTPUTDIR)/gensrc/jdk.net/jdk/internal/net/rdma/RdmaSocketOptionRegistry.java
+
+  $(GENSRC_RSOR_FILE): \
+      $(TOPDIR)/src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaSocketOptionRegistry.java.template
+	$(generate-preproc-src)
+
+  GENSRC_JAVA_BASE += $(GENSRC_RSOR_FILE)
+
+endif
+
 ################################################################################
 
 ifneq ($(OPENJDK_TARGET_OS), windows)
--- a/make/lib/Lib-jdk.net.gmk	Fri Jan 25 11:15:00 2019 +0100
+++ b/make/lib/Lib-jdk.net.gmk	Sat Jan 26 14:02:35 2019 +0000
@@ -32,12 +32,17 @@
   $(eval $(call SetupJdkLibrary, BUILD_LIBEXTNET, \
       NAME := extnet, \
       OPTIMIZATION := LOW, \
-      CFLAGS := $(CFLAGS_JDKLIB), \
+      CFLAGS := $(CFLAGS_JDKLIB) \
+            -I$(SUPPORT_OUTPUTDIR)/headers/java.base \
+            -I$(TOPDIR)/src/java.base/share/native/libnet \
+            -I$(TOPDIR)/src/java.base/unix/native/libnet \
+            -I$(TOPDIR)/src/java.base/share/native/libnio/ch \
+            -I$(TOPDIR)/src/java.base/unix/native/libnio/ch, \
       LDFLAGS := $(LDFLAGS_JDKLIB) \
           $(call SET_SHARED_LIBRARY_ORIGIN), \
       LIBS := -ljava, \
       LIBS_solaris := -lsocket, \
-      LIBS_linux := -ljvm, \
+      LIBS_linux := -ljvm -lnet -lnio -lpthread -ldl, \
   ))
 
   $(BUILD_LIBEXTNET): $(call FindLib, java.base, java)
--- a/make/test/JtregNativeJdk.gmk	Fri Jan 25 11:15:00 2019 +0100
+++ b/make/test/JtregNativeJdk.gmk	Sat Jan 26 14:02:35 2019 +0000
@@ -66,6 +66,7 @@
   BUILD_JDK_JTREG_LIBRARIES_LIBS_libDirectIO := -ljava
   ifeq ($(OPENJDK_TARGET_OS), linux)
     BUILD_JDK_JTREG_LIBRARIES_LIBS_libInheritedChannel := -ljava
+    BUILD_JDK_JTREG_LIBRARIES_LIBS_libRsocketTest := -ljava -ldl
   else ifeq ($(OPENJDK_TARGET_OS), solaris)
     BUILD_JDK_JTREG_LIBRARIES_LIBS_libInheritedChannel := -ljava -lsocket -lnsl
   endif
--- a/src/java.base/share/classes/module-info.java	Fri Jan 25 11:15:00 2019 +0100
+++ b/src/java.base/share/classes/module-info.java	Sat Jan 26 14:02:35 2019 +0000
@@ -230,7 +230,8 @@
         jdk.jfr;
     exports sun.net to
         java.net.http,
-        jdk.naming.dns;
+        jdk.naming.dns,
+        jdk.net;
     exports sun.net.ext to
         jdk.net;
     exports sun.net.dns to
@@ -265,7 +266,8 @@
         java.sql.rowset;
     exports sun.security.action to
         java.desktop,
-        java.security.jgss;
+        java.security.jgss,
+        jdk.net;
     exports sun.security.internal.interfaces to
         jdk.crypto.cryptoki;
     exports sun.security.internal.spec to
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/net/ext/RdmaSocketOptions.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2018, 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 sun.net.ext;
+
+import java.io.FileDescriptor;
+import java.net.SocketException;
+import java.net.SocketOption;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * Defines the infrastructure to support RDMA socket options.
+ *
+ * RDMA socket options are accessed through the jdk.net API, which is in
+ * the jdk.net module.
+ */
+public abstract class RdmaSocketOptions {
+
+    private final Set<SocketOption<?>> options;
+
+    /** Tells whether or not the option is supported. */
+    public final boolean isOptionSupported(SocketOption<?> option) {
+        return options().contains(option);
+    }
+
+    /** Return the, possibly empty, set of RDMA socket options available. */
+    public final Set<SocketOption<?>> options() { return options; }
+
+    /** Sets the value of a socket option, for the given socket. */
+    public abstract void setOption(FileDescriptor fd, SocketOption<?> option,
+            Object value) throws SocketException;
+
+    /** Returns the value of a socket option, for the given socket. */
+    public abstract Object getOption(FileDescriptor fd, SocketOption<?> option)
+            throws SocketException;
+
+    protected RdmaSocketOptions(Set<SocketOption<?>> options) {
+        this.options = options;
+    }
+
+    private static volatile RdmaSocketOptions instance;
+
+    public static final RdmaSocketOptions getInstance() { return instance; }
+
+    /** Registers support for RDMA socket options. Invoked by the jdk.net module. */
+    public static final void register(RdmaSocketOptions rdmaOptions) {
+        if (instance != null)
+            throw new InternalError("Attempting to reregister RDMA options");
+
+        instance = rdmaOptions;
+    }
+
+    static {
+        try {
+            // If the class is present, it will be initialized which
+            // triggers registration of the RDMA socket options.
+            Class<?> c = Class.forName("jdk.net.RdmaSocketOptions");
+        } catch (ClassNotFoundException e) {
+            // the jdk.net module is not present => no RDMA socket options
+            instance = new NoRdmaSocketOptions();
+        }
+    }
+
+    static final class NoRdmaSocketOptions extends RdmaSocketOptions {
+
+        NoRdmaSocketOptions() {
+            super(Collections.<SocketOption<?>>emptySet());
+        }
+
+        @Override
+        public void setOption(FileDescriptor fd, SocketOption<?> option,
+                Object value) throws SocketException
+        {
+            throw new UnsupportedOperationException(
+                    "no RDMA options: " + option.name());
+        }
+
+        @Override
+        public Object getOption(FileDescriptor fd, SocketOption<?> option)
+            throws SocketException
+        {
+            throw new UnsupportedOperationException(
+                    "no RDMA options: " + option.name());
+        }
+    }
+}
--- a/src/java.base/share/classes/sun/nio/ch/IOUtil.java	Fri Jan 25 11:15:00 2019 +0100
+++ b/src/java.base/share/classes/sun/nio/ch/IOUtil.java	Sat Jan 26 14:02:35 2019 +0000
@@ -43,7 +43,7 @@
 
     private IOUtil() { }                // No instantiation
 
-    static int write(FileDescriptor fd, ByteBuffer src, long position,
+    public static int write(FileDescriptor fd, ByteBuffer src, long position,
                      NativeDispatcher nd)
         throws IOException
     {
@@ -123,8 +123,8 @@
         return write(fd, bufs, 0, bufs.length, false, -1, nd);
     }
 
-    static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
-                      NativeDispatcher nd)
+    public static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset,
+                             int length, NativeDispatcher nd)
         throws IOException
     {
         return write(fd, bufs, offset, length, false, -1, nd);
@@ -216,7 +216,7 @@
         }
     }
 
-    static int read(FileDescriptor fd, ByteBuffer dst, long position,
+    public static int read(FileDescriptor fd, ByteBuffer dst, long position,
                     NativeDispatcher nd)
         throws IOException
     {
@@ -286,8 +286,8 @@
         return read(fd, bufs, 0, bufs.length, false, -1, nd);
     }
 
-    static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
-                     NativeDispatcher nd)
+    public static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset,
+                            int length, NativeDispatcher nd)
         throws IOException
     {
         return read(fd, bufs, offset, length, false, -1, nd);
--- a/src/java.base/share/classes/sun/nio/ch/Net.java	Fri Jan 25 11:15:00 2019 +0100
+++ b/src/java.base/share/classes/sun/nio/ch/Net.java	Sat Jan 26 14:02:35 2019 +0000
@@ -79,7 +79,7 @@
     /**
      * Tells whether dual-IPv4/IPv6 sockets should be used.
      */
-    static boolean isIPv6Available() {
+    public static boolean isIPv6Available() {
         if (!checkedIPv6) {
             isIPv6Available = isIPv6Available0();
             checkedIPv6 = true;
@@ -150,7 +150,7 @@
         return (InetSocketAddress)sa;
     }
 
-    static void translateToSocketException(Exception x)
+    public static void translateToSocketException(Exception x)
         throws SocketException
     {
         if (x instanceof SocketException)
@@ -180,7 +180,7 @@
             throw new Error("Untranslated exception", nx);
     }
 
-    static void translateException(Exception x,
+    public static void translateException(Exception x,
                                    boolean unknownHostForUnresolved)
         throws IOException
     {
@@ -196,7 +196,7 @@
         translateToSocketException(x);
     }
 
-    static void translateException(Exception x)
+    public static void translateException(Exception x)
         throws IOException
     {
         translateException(x, false);
@@ -205,7 +205,7 @@
     /**
      * Returns the local address after performing a SecurityManager#checkConnect.
      */
-    static InetSocketAddress getRevealedLocalAddress(InetSocketAddress addr) {
+    public static InetSocketAddress getRevealedLocalAddress(InetSocketAddress addr) {
         SecurityManager sm = System.getSecurityManager();
         if (addr == null || sm == null)
             return addr;
@@ -220,7 +220,7 @@
         return addr;
     }
 
-    static String getRevealedLocalAddressAsString(InetSocketAddress addr) {
+    public static String getRevealedLocalAddressAsString(InetSocketAddress addr) {
         return System.getSecurityManager() == null ? addr.toString() :
                 getLoopbackAddress(addr.getPort()).toString();
     }
--- a/src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java	Fri Jan 25 11:15:00 2019 +0100
+++ b/src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java	Sat Jan 26 14:02:35 2019 +0000
@@ -42,7 +42,7 @@
  * Selector implementation based on poll
  */
 
-class PollSelectorImpl extends SelectorImpl {
+public class PollSelectorImpl extends SelectorImpl {
 
     // initial capacity of poll array
     private static final int INITIAL_CAPACITY = 16;
@@ -67,7 +67,7 @@
     private final Object interruptLock = new Object();
     private boolean interruptTriggered;
 
-    PollSelectorImpl(SelectorProvider sp) throws IOException {
+    protected PollSelectorImpl(SelectorProvider sp) throws IOException {
         super(sp);
 
         int size = pollArrayCapacity * SIZE_POLLFD;
@@ -133,6 +133,14 @@
     }
 
     /**
+     * Protected poll method allows different platform-specific
+     * native implementations
+     */
+    protected int poll(long pollAddress, int numfds, int timeout) {
+        return poll0(pollAddress, numfds, timeout);
+    }
+
+    /**
      * Process changes to the interest ops.
      */
     private void processUpdateQueue() {
@@ -377,7 +385,7 @@
         return pollArray.getShort(offset);
     }
 
-    private static native int poll(long pollAddress, int numfds, int timeout);
+    private static native int poll0(long pollAddress, int numfds, int timeout);
 
     static {
         IOUtil.load();
--- a/src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java	Fri Jan 25 11:15:00 2019 +0100
+++ b/src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java	Sat Jan 26 14:02:35 2019 +0000
@@ -33,29 +33,33 @@
  * for read and write operations.
  */
 
-class SocketDispatcher extends NativeDispatcher {
+public class SocketDispatcher extends NativeDispatcher {
 
-    int read(FileDescriptor fd, long address, int len) throws IOException {
+    protected int read(FileDescriptor fd, long address, int len)
+        throws IOException {
         return FileDispatcherImpl.read0(fd, address, len);
     }
 
-    long readv(FileDescriptor fd, long address, int len) throws IOException {
+    protected long readv(FileDescriptor fd, long address, int len)
+        throws IOException {
         return FileDispatcherImpl.readv0(fd, address, len);
     }
 
-    int write(FileDescriptor fd, long address, int len) throws IOException {
+    protected int write(FileDescriptor fd, long address, int len)
+        throws IOException {
         return FileDispatcherImpl.write0(fd, address, len);
     }
 
-    long writev(FileDescriptor fd, long address, int len) throws IOException {
+    protected long writev(FileDescriptor fd, long address, int len)
+        throws IOException {
         return FileDispatcherImpl.writev0(fd, address, len);
     }
 
-    void close(FileDescriptor fd) throws IOException {
+    protected void close(FileDescriptor fd) throws IOException {
         FileDispatcherImpl.close0(fd);
     }
 
-    void preClose(FileDescriptor fd) throws IOException {
+    public void preClose(FileDescriptor fd) throws IOException {
         FileDispatcherImpl.preClose0(fd);
     }
 }
--- a/src/java.base/unix/native/libnio/ch/PollSelectorImpl.c	Fri Jan 25 11:15:00 2019 +0100
+++ b/src/java.base/unix/native/libnio/ch/PollSelectorImpl.c	Sat Jan 26 14:02:35 2019 +0000
@@ -33,9 +33,9 @@
 #include "sun_nio_ch_PollSelectorImpl.h"
 
 JNIEXPORT jint JNICALL
-Java_sun_nio_ch_PollSelectorImpl_poll(JNIEnv *env, jclass clazz,
-                                      jlong address, jint numfds,
-                                      jint timeout)
+Java_sun_nio_ch_PollSelectorImpl_poll0(JNIEnv *env, jclass clazz,
+                                       jlong address, jint numfds,
+                                       jint timeout)
 {
     struct pollfd *a;
     int res;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/classes/jdk/internal/net/rdma/LinuxRdmaSocketDispatcherImpl.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018, 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.internal.net.rdma;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import sun.nio.ch.IOUtil;
+
+public class LinuxRdmaSocketDispatcherImpl {
+
+    static {
+        java.security.AccessController.doPrivileged(
+                new java.security.PrivilegedAction<Void>() {
+                    public Void run() {
+                        System.loadLibrary("extnet");
+                        return null;
+                    }
+                });
+        IOUtil.load();
+        init();
+    }
+
+    LinuxRdmaSocketDispatcherImpl() { }
+
+
+    // -- Native methods --
+
+    static native int read0(FileDescriptor fd, long address, int len)
+            throws IOException;
+
+    static native long readv0(FileDescriptor fd, long address, int len)
+            throws IOException;
+
+    static native int write0(FileDescriptor fd, long address, int len)
+            throws IOException;
+
+    static native long writev0(FileDescriptor fd, long address, int len)
+            throws IOException;
+
+    static native void close0(FileDescriptor fd) throws IOException;
+
+    static native void init();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaInetAddressContainer.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, 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.internal.net.rdma;
+
+import java.net.InetAddress;
+class RdmaInetAddressContainer {
+   InetAddress addr;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaNet.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2018, 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.internal.net.rdma;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ProtocolFamily;
+import java.net.SocketAddress;
+import java.net.SocketOption;
+import java.net.StandardProtocolFamily;
+import java.net.StandardSocketOptions;
+import java.nio.channels.UnsupportedAddressTypeException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Enumeration;
+import sun.net.ext.RdmaSocketOptions;
+import sun.nio.ch.IOUtil;
+import sun.nio.ch.Net;
+
+public class RdmaNet {
+    private RdmaNet() { }
+
+    static final ProtocolFamily UNSPEC = new ProtocolFamily() {
+        public String name() {
+            return "UNSPEC";
+        }
+    };
+
+    static boolean isReusePortAvailable() {
+        return false;
+    }
+
+    private static volatile boolean checkedRdma;
+    private static volatile boolean isRdmaAvailable;
+
+    static boolean isRdmaAvailable() {
+        if (!checkedRdma) {
+            isRdmaAvailable = isRdmaAvailable0();
+            checkedRdma = true;
+        }
+        return isRdmaAvailable;
+    }
+
+    private static native boolean isRdmaAvailable0();
+
+    static InetSocketAddress checkAddress(SocketAddress sa, ProtocolFamily family) {
+        InetSocketAddress isa = Net.checkAddress(sa);
+        if (family == StandardProtocolFamily.INET) {
+            InetAddress addr = isa.getAddress();
+            if (!(addr instanceof Inet4Address))
+                throw new UnsupportedAddressTypeException();
+        }
+        if (family == StandardProtocolFamily.INET6) {
+            InetAddress addr = isa.getAddress();
+            if (!(addr instanceof Inet6Address))
+                throw new UnsupportedAddressTypeException();
+        }
+        return isa;
+    }
+
+    // -- Socket options
+
+    static final RdmaSocketOptions rdmaOptions =
+            RdmaSocketOptions.getInstance();
+
+    static void setSocketOption(FileDescriptor fd, ProtocolFamily family,
+            SocketOption<?> name, Object value) throws IOException
+    {
+        if (value == null)
+            throw new IllegalArgumentException("Invalid option value");
+
+        Class<?> type = name.type();
+
+        if (rdmaOptions.isOptionSupported(name)) {
+            rdmaOptions.setOption(fd, name, value);
+            return;
+        }
+
+        if (type != Integer.class && type != Boolean.class)
+            throw new AssertionError("Should not reach here");
+
+        if (name == StandardSocketOptions.SO_RCVBUF ||
+            name == StandardSocketOptions.SO_SNDBUF)
+        {
+            int i = ((Integer)value).intValue();
+            if (i < 0)
+                throw new IllegalArgumentException(
+                    "Invalid send/receive buffer size");
+        }
+
+        RdmaOptionKey key = RdmaSocketOptionRegistry.findOption(name, family);
+        if (key == null)
+            throw new AssertionError("Option not found");
+
+        int arg;
+        int maxValue = 1024 * 1024 * 1024 - 1; 
+        if (type == Integer.class) {
+            arg = ((Integer)value).intValue();
+            if (arg > maxValue)
+                arg = maxValue;
+        } else {
+            boolean b = ((Boolean)value).booleanValue();
+            arg = (b) ? 1 : 0;
+        }
+
+        boolean mayNeedConversion = (family == UNSPEC);
+        setIntOption0(fd, mayNeedConversion, key.level(),
+                      key.name(), arg);
+    }
+
+    static Object getSocketOption(FileDescriptor fd, ProtocolFamily family,
+            SocketOption<?> name) throws IOException
+    {
+        Class<?> type = name.type();
+
+        if (rdmaOptions.isOptionSupported(name)) {
+            return rdmaOptions.getOption(fd, name);
+        }
+
+        if (type != Integer.class && type != Boolean.class)
+            throw new AssertionError("Should not reach here");
+
+        RdmaOptionKey key = RdmaSocketOptionRegistry.findOption(name, family);
+        if (key == null)
+            throw new AssertionError("Option not found");
+
+        boolean mayNeedConversion = (family == UNSPEC);
+        int value = getIntOption0(fd, mayNeedConversion, key.level(),
+                                  key.name());
+
+        if (type == Integer.class) {
+            return Integer.valueOf(value);
+        } else {
+            return (value == 0) ? Boolean.FALSE : Boolean.TRUE;
+        }
+    }
+
+    // -- Socket operations --
+    static FileDescriptor socket(ProtocolFamily family, boolean stream)
+            throws IOException {
+        boolean preferIPv6 = Net.isIPv6Available() &&
+                (family != StandardProtocolFamily.INET);
+        return IOUtil.newFD(socket0(preferIPv6, stream, false));
+    }
+
+    static FileDescriptor serverSocket(ProtocolFamily family, boolean stream)
+            throws IOException {
+        boolean preferIPv6 = Net.isIPv6Available() &&
+                (family != StandardProtocolFamily.INET);
+        return IOUtil.newFD(socket0(preferIPv6, stream, true));
+    }
+
+    private static native int socket0(boolean preferIPv6, boolean stream,
+            boolean reuse);
+    static void bind(ProtocolFamily family, FileDescriptor fd,
+            InetAddress addr, int port) throws IOException
+    {
+        boolean preferIPv6 = Net.isIPv6Available() &&
+                (family != StandardProtocolFamily.INET);
+        bind0(fd, preferIPv6, addr, port);
+    }
+
+    private static native void bind0(FileDescriptor fd, boolean preferIPv6,
+            InetAddress addr, int port) throws IOException;
+
+    static native void listen(FileDescriptor fd, int backlog)
+            throws IOException;
+
+    static int connect(FileDescriptor fd, InetAddress remote, int remotePort)
+            throws IOException
+    {
+        return connect(UNSPEC, fd, remote, remotePort);
+    }
+
+    static int connect(ProtocolFamily family, FileDescriptor fd,
+            InetAddress remote, int remotePort) throws IOException
+    {
+        boolean preferIPv6 = Net.isIPv6Available() &&
+                (family != StandardProtocolFamily.INET);
+        return connect0(preferIPv6, fd, remote, remotePort);
+    }
+
+    public static InetSocketAddress localAddress(FileDescriptor fd)
+            throws IOException
+    {
+        return new InetSocketAddress(localInetAddress(fd), localPort(fd));
+    }
+
+    private static native int connect0(boolean preferIPv6, FileDescriptor fd,
+            InetAddress remote, int remotePort) throws IOException;
+
+    static native void shutdown(FileDescriptor fd, int how) throws IOException;
+
+    private static native int localPort(FileDescriptor fd)
+            throws IOException;
+
+    private static native InetAddress localInetAddress(FileDescriptor fd)
+            throws IOException;
+
+    private static native int getIntOption0(FileDescriptor fd,
+            boolean mayNeedConversion, int level, int opt) throws IOException;
+
+    private static native void setIntOption0(FileDescriptor fd,
+            boolean mayNeedConversion, int level, int opt, int arg)
+            throws IOException;
+
+    static native int poll(FileDescriptor fd, int events, long timeout)
+            throws IOException;
+
+    public static native void configureBlocking(FileDescriptor fd,
+            boolean blocking); 
+
+    private static native void initIDs();
+
+    static {
+        java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<>() {
+                public Void run() {
+                    System.loadLibrary("extnet");
+                    return null;
+                }
+            });
+        IOUtil.load();
+        initIDs();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaOptionKey.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2018, 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.internal.net.rdma;
+
+/**
+ * Represents the level/name of a RDMA socket option
+ */
+
+class RdmaOptionKey {
+    private int level;
+    private int name;
+
+    RdmaOptionKey(int level, int name) {
+        this.level = level;
+        this.name = name;
+    }
+
+    int level() {
+        return level;
+    }
+
+    int name() {
+        return name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaPollSelectorImpl.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2018, 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.internal.net.rdma;
+
+import java.io.IOException;
+import java.nio.channels.spi.SelectorProvider;
+import sun.nio.ch.PollSelectorImpl;
+import sun.nio.ch.IOUtil;
+
+/**
+ * Selector implementation based on poll
+ */
+
+public class RdmaPollSelectorImpl extends PollSelectorImpl {
+
+    private static final UnsupportedOperationException unsupported;
+
+    private static final SelectorProvider checkSupported(SelectorProvider sp) {
+        if (unsupported != null)
+            throw new UnsupportedOperationException(unsupported.getMessage(),
+                    unsupported);
+        else
+            return sp;
+    }
+
+    protected RdmaPollSelectorImpl(SelectorProvider sp) throws IOException {
+        super(checkSupported(sp));
+    }
+
+    protected int poll(long pollAddress, int numfds, int timeout) {
+        return poll0(pollAddress, numfds, timeout);
+    }
+
+    private static native int poll0(long pollAddress, int numfds, int timeout);
+
+    static {
+        java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<>() {
+                public Void run() {
+                    System.loadLibrary("extnet");
+                    return null;
+                }
+            });
+        IOUtil.load();
+        UnsupportedOperationException uoe = null;
+        try {
+            init();
+        } catch (UnsupportedOperationException e) {
+            uoe = e;
+        }
+        unsupported = uoe;
+    }
+
+    private static native void init() throws UnsupportedOperationException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaPollSelectorProvider.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2018, 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.internal.net.rdma;
+
+import java.io.IOException;
+import java.net.ProtocolFamily;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.Pipe;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.AbstractSelector;
+import java.nio.channels.spi.SelectorProvider;
+import sun.nio.ch.SelectorProviderImpl;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+public class RdmaPollSelectorProvider
+    extends SelectorProvider
+{
+    private static final Object lock = new Object();
+    private static SelectorProvider provider = null;
+
+    public static SelectorProvider provider() {
+        synchronized (lock) {
+            if (provider != null)
+                return provider;
+            return AccessController.doPrivileged(
+                new PrivilegedAction<>() {
+                    public SelectorProvider run() {
+                            provider = new RdmaPollSelectorProvider();
+                            return provider;
+                        }
+                    });
+        }
+    }
+
+    public AbstractSelector openSelector() throws IOException {
+        return new RdmaPollSelectorImpl(this);
+    }
+
+    public SocketChannel openSocketChannel()
+            throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    public SocketChannel openSocketChannel(ProtocolFamily family)
+            throws IOException {
+        return new RdmaSocketChannelImpl(this, family);
+    }
+
+    public ServerSocketChannel openServerSocketChannel()
+            throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    public ServerSocketChannel openServerSocketChannel(ProtocolFamily family)
+            throws IOException {
+        return new RdmaServerSocketChannelImpl(this, family);
+    }
+
+    public DatagramChannel openDatagramChannel()
+            throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    public DatagramChannel openDatagramChannel(ProtocolFamily family)
+            throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    public Pipe openPipe() throws IOException {
+        throw new UnsupportedOperationException();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaServerSocketAdaptor.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2018, 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.internal.net.rdma;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
+import java.net.StandardSocketOptions;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.NotYetBoundException;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import sun.nio.ch.Net;
+
+class RdmaServerSocketAdaptor
+    extends ServerSocket
+{
+    private final RdmaServerSocketChannelImpl ssc;
+
+    private volatile int timeout;
+
+    public static ServerSocket create(RdmaServerSocketChannelImpl ssc) {
+        try {
+            return new RdmaServerSocketAdaptor(ssc);
+        } catch (IOException x) {
+            throw new Error(x);
+        }
+    }
+
+    private RdmaServerSocketAdaptor(RdmaServerSocketChannelImpl ssc)
+            throws IOException {
+        this.ssc = ssc;
+    }
+
+    public void bind(SocketAddress local) throws IOException {
+        bind(local, 50);
+    }
+
+    public void bind(SocketAddress local, int backlog) throws IOException {
+        if (local == null)
+            local = new InetSocketAddress(0);
+        try {
+            ssc.bind(local, backlog);
+        } catch (Exception x) {
+            Net.translateException(x);
+        }
+    }
+
+    public InetAddress getInetAddress() {
+        InetSocketAddress local = ssc.localAddress();
+        if (local == null) {
+            return null;
+        } else {
+            return Net.getRevealedLocalAddress(local).getAddress();
+        }
+    }
+
+    public int getLocalPort() {
+        InetSocketAddress local = ssc.localAddress();
+        if (local == null) {
+            return -1;
+        } else {
+            return local.getPort();
+        }
+    }
+
+    public Socket accept() throws IOException {
+        synchronized (ssc.blockingLock()) {
+            try {
+                if (!ssc.isBound())
+                    throw new NotYetBoundException();
+
+                long to = this.timeout;
+                if (to == 0) {
+                    // for compatibility reasons: accept connection if available
+                    // when configured non-blocking
+                    SocketChannel sc = ssc.accept();
+                    if (sc == null && !ssc.isBlocking())
+                        throw new IllegalBlockingModeException();
+                    return sc.socket();
+                }
+
+                if (!ssc.isBlocking())
+                    throw new IllegalBlockingModeException();
+                for (;;) {
+                    long st = System.currentTimeMillis();
+                    if (ssc.pollAccept(to))
+                        return ssc.accept().socket();
+                    to -= System.currentTimeMillis() - st;
+                    if (to <= 0)
+                        throw new SocketTimeoutException();
+                }
+
+            } catch (Exception x) {
+                Net.translateException(x);
+                assert false;
+                return null;            // Never happens
+            }
+        }
+    }
+
+    public void close() throws IOException {
+        ssc.close();
+    }
+
+    public ServerSocketChannel getChannel() {
+        return ssc;
+    }
+
+    public boolean isBound() {
+        return ssc.isBound();
+    }
+
+    public boolean isClosed() {
+        return !ssc.isOpen();
+    }
+
+    public void setSoTimeout(int timeout) throws SocketException {
+        this.timeout = timeout;
+    }
+
+    public int getSoTimeout() throws SocketException {
+        return timeout;
+    }
+
+    public void setReuseAddress(boolean on) throws SocketException {
+        try {
+            ssc.setOption(StandardSocketOptions.SO_REUSEADDR, on);
+        } catch (IOException x) {
+            Net.translateToSocketException(x);
+        }
+    }
+
+    public boolean getReuseAddress() throws SocketException {
+        try {
+            return ssc.getOption(StandardSocketOptions.SO_REUSEADDR)
+                      .booleanValue();
+        } catch (IOException x) {
+            Net.translateToSocketException(x);
+            return false;       // Never happens
+        }
+    }
+
+    public String toString() {
+        if (!isBound())
+            return "RdmaServerSocket[unbound]";
+        return "RdmaServerSocket[addr=" + getInetAddress() +
+               ",localport=" + getLocalPort()  + "]";
+    }
+
+    public void setReceiveBufferSize(int size) throws SocketException {
+        // size 0 valid for ServerSocketChannel, invalid for ServerSocket
+        if (size <= 0)
+            throw new IllegalArgumentException("size cannot be 0 or negative");
+        try {
+            ssc.setOption(StandardSocketOptions.SO_RCVBUF, size);
+        } catch (IOException x) {
+            Net.translateToSocketException(x);
+        }
+    }
+
+    public int getReceiveBufferSize() throws SocketException {
+        try {
+            return ssc.getOption(StandardSocketOptions.SO_RCVBUF).intValue();
+        } catch (IOException x) {
+            Net.translateToSocketException(x);
+            return -1;          // Never happens
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaServerSocketChannelImpl.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,511 @@
+/*
+ * Copyright (c) 2018, 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.internal.net.rdma;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ProtocolFamily;
+import java.net.ServerSocket;
+import java.net.SocketAddress;
+import java.net.SocketOption;
+import java.net.StandardSocketOptions;
+import java.net.StandardProtocolFamily;
+import java.nio.channels.AlreadyBoundException;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.NotYetBoundException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.UnsupportedAddressTypeException;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantLock;
+import sun.nio.ch.IOStatus;
+import sun.nio.ch.IOUtil;
+import sun.nio.ch.NativeThread;
+import sun.nio.ch.Net;
+import sun.nio.ch.SelChImpl;
+import sun.nio.ch.SelectionKeyImpl;
+import sun.net.ext.RdmaSocketOptions;
+import static java.net.StandardProtocolFamily.INET;
+import static java.net.StandardProtocolFamily.INET6;
+
+public class RdmaServerSocketChannelImpl
+    extends ServerSocketChannel
+    implements SelChImpl
+{
+    //The protocol family of the socket
+    private final ProtocolFamily family;
+
+    private static RdmaSocketDispatcher nd;
+
+    private final FileDescriptor fd;
+    private final int fdVal;
+
+    private final ReentrantLock acceptLock = new ReentrantLock();
+
+    private final Object stateLock = new Object();
+
+    private static final int ST_INUSE = 0;
+    private static final int ST_CLOSING = 1;
+    private static final int ST_KILLPENDING = 2;
+    private static final int ST_KILLED = 3;
+    private int state;
+
+    private long thread;
+
+    private InetSocketAddress localAddress;
+
+    private boolean isReuseAddress;
+
+    private ServerSocket socket;
+
+    private static final UnsupportedOperationException unsupported;
+
+    private static final SelectorProvider checkSupported(SelectorProvider sp) {
+        if (unsupported != null)
+            throw new UnsupportedOperationException(unsupported.getMessage(), unsupported);
+        else
+            return sp;
+    }
+
+    RdmaServerSocketChannelImpl(SelectorProvider sp, ProtocolFamily family)
+            throws IOException {
+        super(checkSupported(sp));
+        Objects.requireNonNull(family, "'family' is null");
+        if (!(family == INET || family == INET6)) {
+            throw new UnsupportedOperationException(
+                    "Protocol family not supported");
+        }
+        if (family == INET6) {
+            if (!Net.isIPv6Available()) {
+                throw new UnsupportedOperationException(
+                        "IPv6 not available");
+            }
+        }
+        this.family = family;
+        this.fd = RdmaNet.serverSocket(family, true);
+        this.fdVal = IOUtil.fdVal(fd);
+    }
+
+    private void ensureOpen() throws ClosedChannelException {
+        if (!isOpen())
+            throw new ClosedChannelException();
+    }
+
+    @Override
+    public ServerSocket socket() {
+        synchronized (stateLock) {
+            if (socket == null)
+                socket = RdmaServerSocketAdaptor.create(this);
+            return socket;
+        }
+    }
+
+    @Override
+    public SocketAddress getLocalAddress() throws IOException {
+        synchronized (stateLock) {
+            ensureOpen();
+            return (localAddress == null)
+                    ? null
+                    : Net.getRevealedLocalAddress(localAddress);
+        }
+    }
+
+    @Override
+    public <T> ServerSocketChannel setOption(SocketOption<T> name, T value)
+            throws IOException
+    {
+        Objects.requireNonNull(name);
+        if (!supportedOptions().contains(name))
+            throw new UnsupportedOperationException("'" + name
+                    + "' not supported");
+        synchronized (stateLock) {
+            ensureOpen();
+            if (isBound() && (name == StandardSocketOptions.SO_REUSEADDR))
+                throw new UnsupportedOperationException(
+                        "RDMA server socket channel cannot set the socket option "
+                        + name.toString() + " after bind.");
+
+            RdmaNet.setSocketOption(fd, RdmaNet.UNSPEC, name, value);
+            return this;
+        }
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T> T getOption(SocketOption<T> name)
+            throws IOException
+    {
+        Objects.requireNonNull(name);
+        if (!supportedOptions().contains(name))
+            throw new UnsupportedOperationException("'" + name
+                    + "' not supported");
+
+        synchronized (stateLock) {
+            ensureOpen();
+            return (T) RdmaNet.getSocketOption(fd, RdmaNet.UNSPEC, name);
+        }
+    }
+
+    private static class DefaultOptionsHolder {
+        static final Set<SocketOption<?>> defaultOptions = defaultOptions();
+
+        private static Set<SocketOption<?>> defaultOptions() {
+            HashSet<SocketOption<?>> set = new HashSet<>(2);
+            set.add(StandardSocketOptions.SO_RCVBUF);
+            set.add(StandardSocketOptions.SO_REUSEADDR);
+            if (RdmaNet.isRdmaAvailable()) {
+                RdmaSocketOptions rdmaOptions =
+                        RdmaSocketOptions.getInstance();
+                set.addAll(rdmaOptions.options());
+            }
+            return Collections.unmodifiableSet(set);
+        }
+    }
+
+    public final Set<SocketOption<?>> supportedOptions() {
+        return DefaultOptionsHolder.defaultOptions;
+    }
+
+    private final InetSocketAddress anyLocalAddress() throws IOException {
+        if (family == INET)
+            return new InetSocketAddress(InetAddress.getByName("0.0.0.0"), 0);
+        else if (family == INET6)
+            return new InetSocketAddress(InetAddress.getByName("::"), 0);
+        else
+            throw new UnsupportedAddressTypeException();
+    }
+
+    @Override
+    public ServerSocketChannel bind(SocketAddress local, int backlog)
+            throws IOException {
+        synchronized (stateLock) {
+            ensureOpen();
+            if (localAddress != null)
+                throw new AlreadyBoundException();
+            InetSocketAddress isa = (local == null)
+                                    ? anyLocalAddress()
+                                    : RdmaNet.checkAddress(local, family);
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null)
+                sm.checkListen(isa.getPort());
+            RdmaNet.bind(family, fd, isa.getAddress(), isa.getPort());
+            RdmaNet.listen(fd, backlog < 1 ? 50 : backlog);
+            localAddress = RdmaNet.localAddress(fd);
+        }
+        return this;
+    }
+
+    private void begin(boolean blocking) throws ClosedChannelException {
+        if (blocking)
+            begin();
+        synchronized (stateLock) {
+            ensureOpen();
+            if (localAddress == null)
+                throw new NotYetBoundException();
+            if (blocking)
+                thread = NativeThread.current();
+        }
+    }
+
+    private void end(boolean blocking, boolean completed)
+            throws AsynchronousCloseException {
+        if (blocking) {
+            synchronized (stateLock) {
+                thread = 0;
+                if (state == ST_CLOSING) {
+                    stateLock.notifyAll();
+                }
+            }
+            end(completed);
+        }
+    }
+
+    @Override
+    public SocketChannel accept() throws IOException {
+        acceptLock.lock();
+        try {
+            int n = 0;
+            FileDescriptor newfd = new FileDescriptor();
+            InetSocketAddress[] isaa = new InetSocketAddress[1];
+
+            boolean blocking = isBlocking();
+            try {
+                begin(blocking);
+                do {
+                    if (blocking) {
+                        do {
+                            n  = checkAccept(this.fd);
+                        } while ((n == 0 || n == IOStatus.INTERRUPTED)
+                                && isOpen());
+                    }
+                    n = accept(this.fd, newfd, isaa);
+                } while (n == IOStatus.INTERRUPTED && isOpen());
+            } finally {
+                end(blocking, n > 0);
+                assert IOStatus.check(n);
+            }
+
+            if (n < 1)
+                return null;
+
+            // newly accepted socket is initially in blocking mode
+            RdmaNet.configureBlocking(newfd, true);
+
+            InetSocketAddress isa = isaa[0];
+            SocketChannel sc = new RdmaSocketChannelImpl(provider(),
+                    newfd, isa);
+
+            // check permitted to accept connections from the remote address
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                try {
+                    sm.checkAccept(isa.getAddress().getHostAddress(),
+                            isa.getPort());
+                } catch (SecurityException x) {
+                    sc.close();
+                    throw x;
+                }
+            }
+            return sc;
+
+        } finally {
+            acceptLock.unlock();
+        }
+    }
+
+    @Override
+    protected void implConfigureBlocking(boolean block) throws IOException {
+        acceptLock.lock();
+        try {
+            synchronized (stateLock) {
+                ensureOpen();
+                RdmaNet.configureBlocking(fd, block);
+            }
+        } finally {
+            acceptLock.unlock();
+        }
+    }
+
+    @Override
+    protected void implCloseSelectableChannel() throws IOException {
+        assert !isOpen();
+
+        boolean interrupted = false;
+        boolean blocking;
+
+        // set state to ST_CLOSING
+        synchronized (stateLock) {
+            assert state < ST_CLOSING;
+            state = ST_CLOSING;
+            blocking = isBlocking();
+        }
+
+        // wait for any outstanding accept to complete
+        if (blocking) {
+            synchronized (stateLock) {
+                assert state == ST_CLOSING;
+                long th = thread;
+                if (th != 0) {
+                    nd.preClose(fd);
+                    NativeThread.signal(th);
+
+                    // wait for accept operation to end
+                    while (thread != 0) {
+                        try {
+                            stateLock.wait();
+                        } catch (InterruptedException e) {
+                            interrupted = true;
+                        }
+                    }
+                }
+            }
+        } else {
+            // non-blocking mode: wait for accept to complete
+            acceptLock.lock();
+            acceptLock.unlock();
+        }
+
+        // set state to ST_KILLPENDING
+        synchronized (stateLock) {
+            assert state == ST_CLOSING;
+            state = ST_KILLPENDING;
+        }
+
+        // close socket if not registered with Selector
+        if (!isRegistered())
+            kill();
+
+        // restore interrupt status
+        if (interrupted)
+            Thread.currentThread().interrupt();
+    }
+
+    @Override
+    public void kill() throws IOException {
+        synchronized (stateLock) {
+            if (state == ST_KILLPENDING) {
+                state = ST_KILLED;
+                nd.close(fd);
+            }
+        }
+    }
+
+    boolean isBound() {
+        synchronized (stateLock) {
+            return localAddress != null;
+        }
+    }
+
+    InetSocketAddress localAddress() {
+        synchronized (stateLock) {
+            return localAddress;
+        }
+    }
+
+    /**
+     * Poll this channel's socket for a new connection up to the given timeout.
+     * @return {@code true} if there is a connection to accept
+     */
+    boolean pollAccept(long timeout) throws IOException {
+        assert Thread.holdsLock(blockingLock()) && isBlocking();
+        acceptLock.lock();
+        try {
+            boolean polled = false;
+            try {
+                begin(true);
+                int events = RdmaNet.poll(fd, Net.POLLIN, timeout);
+                polled = (events != 0);
+            } finally {
+                end(true, polled);
+            }
+            return polled;
+        } finally {
+            acceptLock.unlock();
+        }
+    }
+
+    public boolean translateReadyOps(int ops, int initialOps,
+            SelectionKeyImpl ski) {
+        int intOps = ski.nioInterestOps();
+        int oldOps = ski.nioReadyOps();
+        int newOps = initialOps;
+
+        if ((ops & Net.POLLNVAL) != 0) {
+            return false;
+        }
+
+        if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
+            newOps = intOps;
+            ski.nioReadyOps(newOps);
+            return (newOps & ~oldOps) != 0;
+        }
+
+        if (((ops & Net.POLLIN) != 0) &&
+            ((intOps & SelectionKey.OP_ACCEPT) != 0))
+                newOps |= SelectionKey.OP_ACCEPT;
+
+        ski.nioReadyOps(newOps);
+        return (newOps & ~oldOps) != 0;
+    }
+
+    public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl ski) {
+        return translateReadyOps(ops, ski.nioReadyOps(), ski);
+    }
+
+    public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl ski) {
+        return translateReadyOps(ops, 0, ski);
+    }
+
+    public int translateInterestOps(int ops) {
+        int newOps = 0;
+        if ((ops & SelectionKey.OP_ACCEPT) != 0)
+            newOps |= Net.POLLIN;
+        return newOps;
+    }
+
+    public FileDescriptor getFD() {
+        return fd;
+    }
+
+    public int getFDVal() {
+        return fdVal;
+    }
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(this.getClass().getName());
+        sb.append('[');
+        if (!isOpen()) {
+            sb.append("closed");
+        } else {
+            synchronized (stateLock) {
+                InetSocketAddress addr = localAddress;
+                if (addr == null) {
+                    sb.append("unbound");
+                } else {
+                    sb.append(Net.getRevealedLocalAddressAsString(addr));
+                }
+            }
+        }
+        sb.append(']');
+        return sb.toString();
+    }
+
+    private int accept(FileDescriptor ssfd, FileDescriptor newfd,
+            InetSocketAddress[] isaa) throws IOException {
+        return accept0(ssfd, newfd, isaa);
+    }
+
+    // -- Native methods --
+    private static native int checkAccept(FileDescriptor fd)
+            throws IOException;
+
+    private native int accept0(FileDescriptor ssfd, FileDescriptor newfd,
+            InetSocketAddress[] isaa) throws IOException;
+
+    private static native void initIDs()throws UnsupportedOperationException;
+
+    static {
+        IOUtil.load();
+        System.loadLibrary("extnet");
+        UnsupportedOperationException uoe = null;
+        try {
+            initIDs();
+        } catch (UnsupportedOperationException e) {
+            uoe = e;
+        }
+        unsupported = uoe;
+        nd = new RdmaSocketDispatcher();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaSocketAdaptor.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 2018, 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.internal.net.rdma;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.net.SocketOption;
+import java.net.SocketTimeoutException;
+import java.net.StandardSocketOptions;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.SocketChannel;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+import sun.nio.ch.ChannelInputStream;
+import sun.nio.ch.Net;
+
+import static java.util.concurrent.TimeUnit.*;
+
+class RdmaSocketAdaptor
+    extends Socket
+{
+    // The channel being adapted
+    private final RdmaSocketChannelImpl sc;
+
+    // Timeout "option" value for reads
+    private volatile int timeout;
+
+    private RdmaSocketAdaptor(RdmaSocketChannelImpl sc) throws SocketException {
+        super((RdmaSocketImpl) null);
+        this.sc = sc;
+    }
+
+    public static Socket create(RdmaSocketChannelImpl sc) {
+        try {
+            return new RdmaSocketAdaptor(sc);
+        } catch (SocketException e) {
+            throw new InternalError("Should not reach here");
+        }
+    }
+
+    public SocketChannel getChannel() {
+        return sc;
+    }
+
+    // Override this method just to protect against changes in the superclass
+    //
+    public void connect(SocketAddress remote) throws IOException {
+        connect(remote, 0);
+    }
+
+    public void connect(SocketAddress remote, int timeout) throws IOException {
+        if (remote == null)
+            throw new IllegalArgumentException(
+                    "connect: The address can't be null");
+        if (timeout < 0)
+            throw new IllegalArgumentException(
+                    "connect: timeout can't be negative");
+
+        synchronized (sc.blockingLock()) {
+            if (!sc.isBlocking())
+                throw new IllegalBlockingModeException();
+
+            try {
+                if (timeout == 0) {
+                    sc.connect(remote);
+                    return;
+                }
+
+                sc.configureBlocking(false);
+                try {
+                    if (sc.connect(remote))
+                        return;
+                } finally {
+                    try {
+                        sc.configureBlocking(true);
+                    } catch (ClosedChannelException e) { }
+                }
+
+                long timeoutNanos = NANOSECONDS.convert(timeout, MILLISECONDS);
+                long to = timeout;
+                for (;;) {
+                    long startTime = System.nanoTime();
+                    if (sc.pollConnected(to)) {
+                        boolean connected = sc.finishConnect();
+                        assert connected;
+                        break;
+                    }
+                    timeoutNanos -= System.nanoTime() - startTime;
+                    if (timeoutNanos <= 0) {
+                        try {
+                            sc.close();
+                        } catch (IOException x) { }
+                        throw new SocketTimeoutException();
+                    }
+                    to = MILLISECONDS.convert(timeoutNanos, NANOSECONDS);
+                }
+
+            } catch (Exception x) {
+                Net.translateException(x, true);
+            }
+        }
+
+    }
+
+    public void bind(SocketAddress local) throws IOException {
+        try {
+            sc.bind(local);
+        } catch (Exception x) {
+            Net.translateException(x);
+        }
+    }
+
+    public InetAddress getInetAddress() {
+        InetSocketAddress remote = sc.remoteAddress();
+        if (remote == null) {
+            return null;
+        } else {
+            return remote.getAddress();
+        }
+    }
+
+    public InetAddress getLocalAddress() {
+        if (sc.isOpen()) {
+            InetSocketAddress local = sc.localAddress();
+            if (local != null) {
+                return Net.getRevealedLocalAddress(local).getAddress();
+            }
+        }
+        return new InetSocketAddress(0).getAddress();
+    }
+
+    public int getPort() {
+        InetSocketAddress remote = sc.remoteAddress();
+        if (remote == null) {
+            return 0;
+        } else {
+            return remote.getPort();
+        }
+    }
+
+    public int getLocalPort() {
+        InetSocketAddress local = sc.localAddress();
+        if (local == null) {
+            return -1;
+        } else {
+            return local.getPort();
+        }
+    }
+
+    private class SocketInputStream
+        extends ChannelInputStream
+    {
+        private SocketInputStream() {
+            super(sc);
+        }
+
+        protected int read(ByteBuffer bb)
+                throws IOException {
+            synchronized (sc.blockingLock()) {
+                if (!sc.isBlocking())
+                    throw new IllegalBlockingModeException();
+
+                // no timeout
+                long to = RdmaSocketAdaptor.this.timeout;
+                if (to == 0)
+                    return sc.read(bb);
+
+                // timed read
+                long timeoutNanos = NANOSECONDS.convert(to, MILLISECONDS);
+                for (;;) {
+                    long startTime = System.nanoTime();
+                    if (sc.pollRead(to)) {
+                        return sc.read(bb);
+                    }
+                    timeoutNanos -= System.nanoTime() - startTime;
+                    if (timeoutNanos <= 0)
+                        throw new SocketTimeoutException();
+                    to = MILLISECONDS.convert(timeoutNanos, NANOSECONDS);
+                }
+            }
+        }
+    }
+
+    private InputStream socketInputStream = null;
+
+    public InputStream getInputStream() throws IOException {
+        if (!sc.isOpen())
+            throw new SocketException("Socket is closed");
+        if (!sc.isConnected())
+            throw new SocketException("Socket is not connected");
+        if (!sc.isInputOpen())
+            throw new SocketException("Socket input is shutdown");
+        if (socketInputStream == null) {
+            try {
+                socketInputStream = AccessController.doPrivileged(
+                    new PrivilegedExceptionAction<InputStream>() {
+                        public InputStream run() throws IOException {
+                            return new SocketInputStream();
+                        }
+                    });
+            } catch (java.security.PrivilegedActionException e) {
+                throw (IOException)e.getException();
+            }
+        }
+        return socketInputStream;
+    }
+
+    public OutputStream getOutputStream() throws IOException {
+        if (!sc.isOpen())
+            throw new SocketException("Socket is closed");
+        if (!sc.isConnected())
+            throw new SocketException("Socket is not connected");
+        if (!sc.isOutputOpen())
+            throw new SocketException("Socket output is shutdown");
+        OutputStream os = null;
+        try {
+            os = AccessController.doPrivileged(
+                new PrivilegedExceptionAction<OutputStream>() {
+                    public OutputStream run() throws IOException {
+                        return Channels.newOutputStream(sc);
+                    }
+                });
+        } catch (java.security.PrivilegedActionException e) {
+            throw (IOException)e.getException();
+        }
+        return os;
+    }
+
+    private void setBooleanOption(SocketOption<Boolean> name, boolean value)
+            throws SocketException {
+        try {
+            sc.setOption(name, value);
+        } catch (IOException x) {
+            Net.translateToSocketException(x);
+        }
+    }
+
+    private void setIntOption(SocketOption<Integer> name, int value)
+            throws SocketException {
+        try {
+            sc.setOption(name, value);
+        } catch (IOException x) {
+            Net.translateToSocketException(x);
+        }
+    }
+
+    private boolean getBooleanOption(SocketOption<Boolean> name)
+            throws SocketException {
+        try {
+            return sc.getOption(name).booleanValue();
+        } catch (IOException x) {
+            Net.translateToSocketException(x);
+            return false;       // keep compiler happy
+        }
+    }
+
+    private int getIntOption(SocketOption<Integer> name)
+            throws SocketException {
+        try {
+            return sc.getOption(name).intValue();
+        } catch (IOException x) {
+            Net.translateToSocketException(x);
+            return -1;          // keep compiler happy
+        }
+    }
+
+    public void setTcpNoDelay(boolean on) throws SocketException {
+        setBooleanOption(StandardSocketOptions.TCP_NODELAY, on);
+    }
+
+    public boolean getTcpNoDelay() throws SocketException {
+        return getBooleanOption(StandardSocketOptions.TCP_NODELAY);
+    }
+
+    public void sendUrgentData(int data) throws IOException {
+        int n = sc.sendOutOfBandData((byte) data);
+        if (n == 0)
+            throw new IOException("Socket buffer full");
+    }
+
+    public void setSoTimeout(int timeout) throws SocketException {
+        if (timeout < 0)
+            throw new IllegalArgumentException("timeout can't be negative");
+        this.timeout = timeout;
+    }
+
+    public int getSoTimeout() throws SocketException {
+        return timeout;
+    }
+
+    public void setSendBufferSize(int size) throws SocketException {
+        if (size <= 0)
+            throw new IllegalArgumentException("Invalid send size");
+        setIntOption(StandardSocketOptions.SO_SNDBUF, size);
+    }
+
+    public int getSendBufferSize() throws SocketException {
+        return getIntOption(StandardSocketOptions.SO_SNDBUF);
+    }
+
+    public void setReceiveBufferSize(int size) throws SocketException {
+        if (size <= 0)
+            throw new IllegalArgumentException("Invalid receive size");
+        setIntOption(StandardSocketOptions.SO_RCVBUF, size);
+    }
+
+    public int getReceiveBufferSize() throws SocketException {
+        return getIntOption(StandardSocketOptions.SO_RCVBUF);
+    }
+
+    public void setReuseAddress(boolean on) throws SocketException {
+        setBooleanOption(StandardSocketOptions.SO_REUSEADDR, on);
+    }
+
+    public boolean getReuseAddress() throws SocketException {
+        return getBooleanOption(StandardSocketOptions.SO_REUSEADDR);
+    }
+
+    public void close() throws IOException {
+        sc.close();
+    }
+
+    public void shutdownInput() throws IOException {
+        try {
+            sc.shutdownInput();
+        } catch (Exception x) {
+            Net.translateException(x);
+        }
+    }
+
+    public void shutdownOutput() throws IOException {
+        try {
+            sc.shutdownOutput();
+        } catch (Exception x) {
+            Net.translateException(x);
+        }
+    }
+
+    public String toString() {
+        if (sc.isConnected())
+            return "RdmaSocket[addr=" + getInetAddress() +
+                ",port=" + getPort() +
+                ",localport=" + getLocalPort() + "]";
+        return "RdmaSocket[unconnected]";
+    }
+
+    public boolean isConnected() {
+        return sc.isConnected();
+    }
+
+    public boolean isBound() {
+        return sc.localAddress() != null;
+    }
+
+    public boolean isClosed() {
+        return !sc.isOpen();
+    }
+
+    public boolean isInputShutdown() {
+        return !sc.isInputOpen();
+    }
+
+    public boolean isOutputShutdown() {
+        return !sc.isOutputOpen();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaSocketChannelImpl.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,988 @@
+/*
+ * Copyright (c) 2018, 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.internal.net.rdma;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ProtocolFamily;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketOption;
+import java.net.StandardSocketOptions;
+import java.nio.ByteBuffer;
+import java.nio.channels.AlreadyBoundException;
+import java.nio.channels.AlreadyConnectedException;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ConnectionPendingException;
+import java.nio.channels.NoConnectionPendingException;
+import java.nio.channels.NotYetConnectedException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.UnsupportedAddressTypeException;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantLock;
+import sun.net.ext.RdmaSocketOptions;
+import sun.nio.ch.IOStatus;
+import sun.nio.ch.IOUtil;
+import sun.nio.ch.NativeThread;
+import sun.nio.ch.Net;
+import sun.nio.ch.SelChImpl;
+import sun.nio.ch.SelectionKeyImpl;
+import static java.net.StandardProtocolFamily.INET;
+import static java.net.StandardProtocolFamily.INET6;
+
+public class RdmaSocketChannelImpl
+    extends SocketChannel
+    implements SelChImpl
+{
+    // The protocol family of the socket
+    private final ProtocolFamily family;
+
+    private static RdmaSocketDispatcher nd;
+    private final FileDescriptor fd;
+    private final int fdVal;
+
+    private final ReentrantLock readLock = new ReentrantLock();
+    private final ReentrantLock writeLock = new ReentrantLock();
+
+    private final Object stateLock = new Object();
+
+    private volatile boolean isInputClosed;
+    private volatile boolean isOutputClosed;
+
+    private boolean isReuseAddress;
+
+    private static final int ST_UNCONNECTED = 0;
+    private static final int ST_CONNECTIONPENDING = 1;
+    private static final int ST_CONNECTED = 2;
+    private static final int ST_CLOSING = 3;
+    private static final int ST_KILLPENDING = 4;
+    private static final int ST_KILLED = 5;
+    private volatile int state;  // need stateLock to change
+
+    private long readerThread;
+    private long writerThread;
+
+    private InetSocketAddress localAddress;
+    private InetSocketAddress remoteAddress;
+
+    private Socket socket;
+
+    private static final UnsupportedOperationException unsupported;
+
+    private static final SelectorProvider checkSupported(SelectorProvider sp) {
+        if (unsupported != null)
+            throw new UnsupportedOperationException(unsupported.getMessage(),
+                                                    unsupported);
+        else
+            return sp;
+    }
+
+    protected RdmaSocketChannelImpl(SelectorProvider sp, ProtocolFamily family)
+            throws IOException {
+        super(checkSupported(sp));
+
+        Objects.requireNonNull(family, "null family");
+        if (!(family == INET || family == INET6)) {
+            throw new UnsupportedOperationException("Protocol family not supported");
+        }
+        if (family == INET6) {
+            if (!Net.isIPv6Available()) {
+                throw new UnsupportedOperationException("IPv6 not available");
+            }
+        }
+
+        this.family = family;
+        this.fd = RdmaNet.socket(family, true);
+        IOUtil.configureBlocking(fd, false);
+        this.fdVal = IOUtil.fdVal(fd);
+    }
+
+    RdmaSocketChannelImpl(SelectorProvider sp,
+                          FileDescriptor fd,
+                          InetSocketAddress isa) throws IOException {
+        super(checkSupported(sp));
+        this.family = Net.isIPv6Available() ? INET6 : INET;
+        this.fd = fd;
+        this.fdVal = IOUtil.fdVal(fd);
+        IOUtil.configureBlocking(fd, false);
+        synchronized (stateLock) {
+            this.localAddress = RdmaNet.localAddress(fd);
+            this.remoteAddress = isa;
+            this.state = ST_CONNECTED;
+        }
+    }
+
+    private void ensureOpen() throws ClosedChannelException {
+        if (!isOpen())
+            throw new ClosedChannelException();
+    }
+
+    private void ensureOpenAndConnected() throws ClosedChannelException {
+        int state = this.state;
+        if (state < ST_CONNECTED) {
+            throw new NotYetConnectedException();
+        } else if (state > ST_CONNECTED) {
+            throw new ClosedChannelException();
+        }
+    }
+
+    @Override
+    public Socket socket() {
+        synchronized (stateLock) {
+            if (socket == null)
+                socket = RdmaSocketAdaptor.create(this);
+            return socket;
+        }
+    }
+
+    @Override
+    public SocketAddress getLocalAddress() throws IOException {
+        synchronized (stateLock) {
+            ensureOpen();
+            return Net.getRevealedLocalAddress(localAddress);
+        }
+    }
+
+    @Override
+    public SocketAddress getRemoteAddress() throws IOException {
+        synchronized (stateLock) {
+            ensureOpen();
+            return remoteAddress;
+        }
+    }
+
+    @Override
+    public <T> SocketChannel setOption(SocketOption<T> name, T value)
+            throws IOException {
+        Objects.requireNonNull(name);
+        if (!supportedOptions().contains(name))
+            throw new UnsupportedOperationException("'" + name
+                    + "' not supported");
+
+        synchronized (stateLock) {
+            ensureOpen();
+            RdmaNet.setSocketOption(fd, RdmaNet.UNSPEC, name, value);
+            return this;
+        }
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T> T getOption(SocketOption<T> name)
+            throws IOException {
+        Objects.requireNonNull(name);
+        if (!supportedOptions().contains(name))
+            throw new UnsupportedOperationException("'" + name
+                    + "' not supported");
+
+        synchronized (stateLock) {
+            ensureOpen();
+            return (T) RdmaNet.getSocketOption(fd, RdmaNet.UNSPEC, name);
+        }
+    }
+
+    private static class DefaultOptionsHolder {
+        static final Set<SocketOption<?>> defaultOptions = defaultOptions();
+
+        private static Set<SocketOption<?>> defaultOptions() {
+            HashSet<SocketOption<?>> set = new HashSet<>();
+            set.add(StandardSocketOptions.SO_SNDBUF);
+            set.add(StandardSocketOptions.SO_RCVBUF);
+            set.add(StandardSocketOptions.SO_REUSEADDR);
+            set.add(StandardSocketOptions.TCP_NODELAY);
+            RdmaSocketOptions rdmaOptions =
+                    RdmaSocketOptions.getInstance();
+            set.addAll(rdmaOptions.options());
+            return Collections.unmodifiableSet(set);
+        }
+    }
+
+    public Set<SocketOption<?>> supportedOptions() {
+         return DefaultOptionsHolder.defaultOptions;
+    }
+
+    private void beginRead(boolean blocking) throws ClosedChannelException {
+        if (blocking) {
+            // set hook for Thread.interrupt
+            begin();
+
+            synchronized (stateLock) {
+                ensureOpenAndConnected();
+                // record thread so it can be signalled if needed
+                readerThread = NativeThread.current();
+            }
+        } else {
+            ensureOpenAndConnected();
+        }
+    }
+    private void endRead(boolean blocking, boolean completed)
+            throws AsynchronousCloseException
+    {
+        if (blocking) {
+            synchronized (stateLock) {
+                readerThread = 0;
+                // notify any thread waiting in implCloseSelectableChannel
+                if (state == ST_CLOSING) {
+                    stateLock.notifyAll();
+                }
+            }
+            // remove hook for Thread.interrupt
+            end(completed);
+        }
+    }
+
+    @Override
+    public int read(ByteBuffer buf) throws IOException {
+        Objects.requireNonNull(buf);
+
+        readLock.lock();
+        try {
+            boolean blocking = isBlocking();
+            int n = 0;
+            try {
+                beginRead(blocking);
+
+                // check if input is shutdown
+                if (isInputClosed)
+                    return IOStatus.EOF;
+
+                n = IOUtil.read(fd, buf, -1, nd);
+                if (n == IOStatus.UNAVAILABLE && blocking) {
+                    do {
+                        RdmaNet.poll(fd, Net.POLLIN, -1);
+                        n = IOUtil.read(fd, buf, -1, nd);
+                    } while (n == IOStatus.UNAVAILABLE && isOpen());
+                }
+            } finally {
+                endRead(blocking, n > 0);
+                if (n <= 0 && isInputClosed)
+                    return IOStatus.EOF;
+            }
+            return IOStatus.normalize(n);
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    @Override
+    public long read(ByteBuffer[] dsts, int offset, int length)
+            throws IOException
+    {
+        Objects.checkFromIndexSize(offset, length, dsts.length);
+
+        readLock.lock();
+        try {
+            boolean blocking = isBlocking();
+            long n = 0;
+            try {
+                beginRead(blocking);
+
+                // check if input is shutdown
+                if (isInputClosed)
+                    return IOStatus.EOF;
+
+                n = IOUtil.read(fd, dsts, offset, length, nd);
+                if (n == IOStatus.UNAVAILABLE && blocking) {
+                    do {
+                        RdmaNet.poll(fd, Net.POLLIN, -1);
+                        n = IOUtil.read(fd, dsts, offset, length, nd);
+                    } while (n == IOStatus.UNAVAILABLE && isOpen());
+                }
+            } finally {
+                endRead(blocking, n > 0);
+                if (n <= 0 && isInputClosed)
+                    return IOStatus.EOF;
+            }
+            return IOStatus.normalize(n);
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    private void beginWrite(boolean blocking) throws ClosedChannelException {
+        if (blocking) {
+            // set hook for Thread.interrupt
+            begin();
+
+            synchronized (stateLock) {
+                ensureOpenAndConnected();
+                if (isOutputClosed)
+                    throw new ClosedChannelException();
+                // record thread so it can be signalled if needed
+                writerThread = NativeThread.current();
+            }
+        } else {
+            ensureOpenAndConnected();
+        }
+    }
+
+    private void endWrite(boolean blocking, boolean completed)
+            throws AsynchronousCloseException {
+        if (blocking) {
+            synchronized (stateLock) {
+                writerThread = 0;
+                // notify any thread waiting in implCloseSelectableChannel
+                if (state == ST_CLOSING) {
+                    stateLock.notifyAll();
+                }
+            }
+            // remove hook for Thread.interrupt
+            end(completed);
+        }
+    }
+
+    @Override
+    public int write(ByteBuffer buf) throws IOException {
+        Objects.requireNonNull(buf);
+
+        writeLock.lock();
+        try {
+            boolean blocking = isBlocking();
+            int n = 0;
+            try {
+                beginWrite(blocking);
+                n = IOUtil.write(fd, buf, -1, nd);
+                if (n == IOStatus.UNAVAILABLE && blocking) {
+                    do {
+                        RdmaNet.poll(fd, Net.POLLOUT, -1);
+                        n = IOUtil.write(fd, buf, -1, nd);
+                    } while (n == IOStatus.UNAVAILABLE && isOpen());
+                }
+            } finally {
+                endWrite(blocking, n > 0);
+                if (n <= 0 && isOutputClosed)
+                    throw new AsynchronousCloseException();
+            }
+            return IOStatus.normalize(n);
+        } finally {
+            writeLock.unlock();
+        }
+    }
+
+    @Override
+    public long write(ByteBuffer[] srcs, int offset, int length)
+            throws IOException {
+        Objects.checkFromIndexSize(offset, length, srcs.length);
+
+        writeLock.lock();
+        try {
+            boolean blocking = isBlocking();
+            long n = 0;
+            try {
+                beginWrite(blocking);
+                n = IOUtil.write(fd, srcs, offset, length, nd);
+                if (n == IOStatus.UNAVAILABLE && blocking) {
+                    do {
+                        RdmaNet.poll(fd, Net.POLLOUT, -1);
+                        n = IOUtil.write(fd, srcs, offset, length, nd);
+                    } while (n == IOStatus.UNAVAILABLE && isOpen());
+                }
+            } finally {
+                endWrite(blocking, n > 0);
+                if (n <= 0 && isOutputClosed)
+                    throw new AsynchronousCloseException();
+            }
+            return IOStatus.normalize(n);
+        } finally {
+            writeLock.unlock();
+        }
+    }
+
+    int sendOutOfBandData(byte b) throws IOException {
+        writeLock.lock();
+        try {
+            boolean blocking = isBlocking();
+            int n = 0;
+            try {
+                beginWrite(blocking);
+                n = sendOutOfBandData(fd, b);
+                if (n == IOStatus.UNAVAILABLE && blocking) {
+                    do {
+                        RdmaNet.poll(fd, Net.POLLOUT, -1);
+                        n = sendOutOfBandData(fd, b);
+                    } while (n == IOStatus.INTERRUPTED && isOpen());
+                }
+            } finally {
+                endWrite(blocking, n > 0);
+                if (n <= 0 && isOutputClosed)
+                    throw new AsynchronousCloseException();
+            }
+            return IOStatus.normalize(n);
+        } finally {
+            writeLock.unlock();
+        }
+    }
+
+    @Override
+    protected void implConfigureBlocking(boolean block) throws IOException {
+        readLock.lock();
+        try {
+            writeLock.lock();
+            try {
+                synchronized (stateLock) {
+                    ensureOpen();
+                    // do nothing
+                }
+            } finally {
+                writeLock.unlock();
+            }
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    InetSocketAddress localAddress() {
+        synchronized (stateLock) {
+            return localAddress;
+        }
+    }
+
+    InetSocketAddress remoteAddress() {
+        synchronized (stateLock) {
+            return remoteAddress;
+        }
+    }
+
+    private final InetSocketAddress anyLocalAddress() throws IOException {
+        if (family == INET)
+            return new InetSocketAddress(InetAddress.getByName("0.0.0.0"), 0);
+        else if (family == INET6)
+            return new InetSocketAddress(InetAddress.getByName("::"), 0);
+        else
+            throw new UnsupportedAddressTypeException();
+    }
+
+    @Override
+    public SocketChannel bind(SocketAddress local) throws IOException {
+        readLock.lock();
+        try {
+            writeLock.lock();
+            try {
+                synchronized (stateLock) {
+                    ensureOpen();
+                    if (state == ST_CONNECTIONPENDING)
+                        throw new ConnectionPendingException();
+                    if (localAddress != null)
+                        throw new AlreadyBoundException();
+                    InetSocketAddress isa = (local == null)
+                                            ? anyLocalAddress()
+                                            : RdmaNet.checkAddress(local, family);
+                    SecurityManager sm = System.getSecurityManager();
+                    if (sm != null) {
+                        sm.checkListen(isa.getPort());
+                    }
+                    RdmaNet.bind(family, fd, isa.getAddress(), isa.getPort());
+                    localAddress = RdmaNet.localAddress(fd);
+                }
+            } finally {
+                writeLock.unlock();
+            }
+        } finally {
+            readLock.unlock();
+        }
+        return this;
+    }
+
+    @Override
+    public boolean isConnected() {
+        return (state == ST_CONNECTED);
+    }
+
+    @Override
+    public boolean isConnectionPending() {
+        return (state == ST_CONNECTIONPENDING);
+    }
+
+    private void beginConnect(boolean blocking, InetSocketAddress isa)
+            throws IOException {
+        if (blocking) {
+            // set hook for Thread.interrupt
+            begin();
+        }
+        synchronized (stateLock) {
+            ensureOpen();
+            int state = this.state;
+            if (state == ST_CONNECTED)
+                throw new AlreadyConnectedException();
+            if (state == ST_CONNECTIONPENDING)
+                throw new ConnectionPendingException();
+            assert state == ST_UNCONNECTED;
+            this.state = ST_CONNECTIONPENDING;
+
+            remoteAddress = isa;
+
+            if (blocking) {
+                // record thread so it can be signalled if needed
+                readerThread = NativeThread.current();
+            }
+        }
+    }
+
+    private void endConnect(boolean blocking, boolean completed)
+            throws IOException {
+        endRead(blocking, completed);
+
+        if (completed) {
+            synchronized (stateLock) {
+                if (state == ST_CONNECTIONPENDING) {
+                    localAddress = RdmaNet.localAddress(fd);
+                    state = ST_CONNECTED;
+                }
+            }
+        }
+    }
+
+    @Override
+    public boolean connect(SocketAddress sa) throws IOException {
+        InetSocketAddress isa = RdmaNet.checkAddress(sa, family);
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+            sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort());
+
+        InetAddress ia = isa.getAddress();
+        if (ia.isAnyLocalAddress())
+            ia = InetAddress.getLocalHost();
+
+        try {
+            readLock.lock();
+            try {
+                writeLock.lock();
+                try {
+                    boolean blocking = isBlocking();
+                    boolean connected = false;
+                    try {
+                        beginConnect(blocking, isa);
+                        int n = RdmaNet.connect(family, fd, ia, isa.getPort());
+                        if (n == IOStatus.UNAVAILABLE && blocking) {
+                            do {
+                                RdmaNet.poll(fd, Net.POLLOUT, -1);
+                                n = checkConnect(fd, false);
+                            } while (n == IOStatus.INTERRUPTED && isOpen());
+                        }
+                        connected = (n > 0) && isOpen();
+                    } finally {
+                        endConnect(blocking, connected);
+                    }
+                    return connected;
+                } finally {
+                    writeLock.unlock();
+                }
+            } finally {
+                readLock.unlock();
+            }
+        } catch (IOException ioe) {
+            // connect failed, close the channel
+            close();
+            throw ioe;
+        }
+    }
+
+    private void beginFinishConnect(boolean blocking)
+            throws ClosedChannelException {
+        if (blocking) {
+            // set hook for Thread.interrupt
+            begin();
+        }
+        synchronized (stateLock) {
+            ensureOpen();
+            if (state != ST_CONNECTIONPENDING)
+                throw new NoConnectionPendingException();
+            if (blocking) {
+                // record thread so it can be signalled if needed
+                readerThread = NativeThread.current();
+            }
+        }
+    }
+
+    private void endFinishConnect(boolean blocking, boolean completed)
+            throws IOException
+    {
+        endRead(blocking, completed);
+
+        if (completed) {
+            synchronized (stateLock) {
+                if (state == ST_CONNECTIONPENDING) {
+                    localAddress = RdmaNet.localAddress(fd);
+                    state = ST_CONNECTED;
+                }
+            }
+        }
+    }
+
+    @Override
+    public boolean finishConnect() throws IOException {
+        try {
+            readLock.lock();
+            try {
+                writeLock.lock();
+                try {
+                    // no-op if already connected
+                    if (isConnected())
+                        return true;
+
+                    boolean blocking = isBlocking();
+                    boolean connected = false;
+                    try {
+                        beginFinishConnect(blocking);
+                        int n = checkConnect(fd, false);
+                        if (n == IOStatus.UNAVAILABLE && blocking) {
+                            do {
+                                RdmaNet.poll(fd, Net.POLLOUT, -1);
+                                n = checkConnect(fd, false);
+                            } while (n == IOStatus.UNAVAILABLE && isOpen());
+                        }
+                        connected = (n > 0) && isOpen();
+                    } finally {
+                        endFinishConnect(blocking, connected);
+                    }
+                    assert (blocking && connected) ^ !blocking;
+                    return connected;
+                } finally {
+                    writeLock.unlock();
+                }
+            } finally {
+                readLock.unlock();
+            }
+        } catch (IOException ioe) {
+            // connect failed, close the channel
+            close();
+            throw ioe;
+        }
+    }
+
+    @Override
+    protected void implCloseSelectableChannel() throws IOException {
+        assert !isOpen();
+        boolean blocking;
+        boolean connected;
+        boolean interrupted = false;
+
+        // set state to ST_CLOSING
+        synchronized (stateLock) {
+            assert state < ST_CLOSING;
+            blocking = isBlocking();
+            connected = (state == ST_CONNECTED);
+            state = ST_CLOSING;
+        }
+
+        // wait for any outstanding I/O operations to complete
+        if (blocking) {
+            synchronized (stateLock) {
+                assert state == ST_CLOSING;
+                long reader = readerThread;
+                long writer = writerThread;
+                if (reader != 0 || writer != 0) {
+                    nd.preClose(fd);
+                    connected = false; // fd is no longer connected socket
+
+                    if (reader != 0)
+                        NativeThread.signal(reader);
+                    if (writer != 0)
+                        NativeThread.signal(writer);
+
+                    // wait for blocking I/O operations to end
+                    while (readerThread != 0 || writerThread != 0) {
+                        try {
+                            stateLock.wait();
+                        } catch (InterruptedException e) {
+                            interrupted = true;
+                        }
+                    }
+                }
+            }
+        } else {
+            // non-blocking mode: wait for read/write to complete
+            readLock.lock();
+            try {
+                writeLock.lock();
+                writeLock.unlock();
+            } finally {
+                readLock.unlock();
+            }
+        }
+
+        // set state to ST_KILLPENDING
+        synchronized (stateLock) {
+            assert state == ST_CLOSING;
+            // if connected and the channel is registered with a Selector then
+            // shutdown the output if possible so that the peer reads EOF.
+            if (connected && isRegistered()) {
+                try {
+                    RdmaNet.shutdown(fd, Net.SHUT_WR);
+                } catch (IOException ignore) { }
+            }
+            state = ST_KILLPENDING;
+        }
+
+        // close socket if not registered with Selector
+        if (!isRegistered())
+            kill();
+
+        // restore interrupt status
+        if (interrupted)
+            Thread.currentThread().interrupt();
+    }
+
+    @Override
+    public void kill() throws IOException {
+        synchronized (stateLock) {
+            if (state == ST_KILLPENDING) {
+                state = ST_KILLED;
+                nd.close(fd);
+            }
+        }
+    }
+
+    @Override
+    public SocketChannel shutdownInput() throws IOException {
+        synchronized (stateLock) {
+            ensureOpen();
+            if (!isConnected())
+                throw new NotYetConnectedException();
+            if (!isInputClosed) {
+                RdmaNet.shutdown(fd, Net.SHUT_RD);
+                long thread = readerThread;
+                if (thread != 0)
+                    NativeThread.signal(thread);
+                isInputClosed = true;
+            }
+            return this;
+        }
+    }
+
+    @Override
+    public SocketChannel shutdownOutput() throws IOException {
+        synchronized (stateLock) {
+            ensureOpen();
+            if (!isConnected())
+                throw new NotYetConnectedException();
+            if (!isOutputClosed) {
+                RdmaNet.shutdown(fd, Net.SHUT_WR);
+                long thread = writerThread;
+                if (thread != 0)
+                    NativeThread.signal(thread);
+                isOutputClosed = true;
+            }
+            return this;
+        }
+    }
+
+    boolean isInputOpen() {
+        return !isInputClosed;
+    }
+
+    boolean isOutputOpen() {
+        return !isOutputClosed;
+    }
+
+    /**
+     * Poll this channel's socket for reading up to the given timeout.
+     * @return {@code true} if the socket is polled
+     */
+    boolean pollRead(long timeout) throws IOException {
+        boolean blocking = isBlocking();
+        assert Thread.holdsLock(blockingLock()) && blocking;
+
+        readLock.lock();
+        try {
+            boolean polled = false;
+            try {
+                beginRead(blocking);
+                int events = RdmaNet.poll(fd, Net.POLLIN, timeout);
+                polled = (events != 0);
+            } finally {
+                endRead(blocking, polled);
+            }
+            return polled;
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    /**
+     * Poll this channel's socket for a connection, up to the given timeout.
+     * @return {@code true} if the socket is polled
+     */
+    boolean pollConnected(long timeout) throws IOException {
+        boolean blocking = isBlocking();
+        assert Thread.holdsLock(blockingLock()) && blocking;
+
+        readLock.lock();
+        try {
+            writeLock.lock();
+            try {
+                boolean polled = false;
+                try {
+                    beginFinishConnect(blocking);
+                    int events = RdmaNet.poll(fd, Net.POLLCONN, timeout);
+                    polled = (events != 0);
+                } finally {
+                    // invoke endFinishConnect with completed = false so that
+                    // the state is not changed to ST_CONNECTED. The socket
+                    // adaptor will use finishConnect to finish.
+                    endFinishConnect(blocking, /*completed*/false);
+                }
+                return polled;
+            } finally {
+                writeLock.unlock();
+            }
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    public boolean translateReadyOps(int ops, int initialOps,
+            SelectionKeyImpl ski) {
+        int intOps = ski.nioInterestOps();
+        int oldOps = ski.nioReadyOps();
+        int newOps = initialOps;
+
+        if ((ops & Net.POLLNVAL) != 0) {
+            return false;
+        }
+
+        if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
+            newOps = intOps;
+            ski.nioReadyOps(newOps);
+            return (newOps & ~oldOps) != 0;
+        }
+
+        boolean connected = isConnected();
+        if (((ops & Net.POLLIN) != 0) &&
+            ((intOps & SelectionKey.OP_READ) != 0) && connected)
+            newOps |= SelectionKey.OP_READ;
+
+        if (((ops & Net.POLLCONN) != 0) &&
+            ((intOps & SelectionKey.OP_CONNECT) != 0) && isConnectionPending())
+            newOps |= SelectionKey.OP_CONNECT;
+
+        if (((ops & Net.POLLOUT) != 0) &&
+            ((intOps & SelectionKey.OP_WRITE) != 0) && connected)
+            newOps |= SelectionKey.OP_WRITE;
+
+        ski.nioReadyOps(newOps);
+        return (newOps & ~oldOps) != 0;
+    }
+
+    public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl ski) {
+        return translateReadyOps(ops, ski.nioReadyOps(), ski);
+    }
+
+    public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl ski) {
+        return translateReadyOps(ops, 0, ski);
+    }
+
+    public int translateInterestOps(int ops) {
+        int newOps = 0;
+        if ((ops & SelectionKey.OP_READ) != 0)
+            newOps |= Net.POLLIN;
+        if ((ops & SelectionKey.OP_WRITE) != 0)
+            newOps |= Net.POLLOUT;
+        if ((ops & SelectionKey.OP_CONNECT) != 0)
+            newOps |= Net.POLLCONN;
+        return newOps;
+    }
+
+    public FileDescriptor getFD() {
+        return fd;
+    }
+
+    public int getFDVal() {
+        return fdVal;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(this.getClass().getSuperclass().getName());
+        sb.append('[');
+        if (!isOpen())
+            sb.append("closed");
+        else {
+            synchronized (stateLock) {
+                switch (state) {
+                case ST_UNCONNECTED:
+                    sb.append("unconnected");
+                    break;
+                case ST_CONNECTIONPENDING:
+                    sb.append("connection-pending");
+                    break;
+                case ST_CONNECTED:
+                    sb.append("connected");
+                    if (isInputClosed)
+                        sb.append(" ishut");
+                    if (isOutputClosed)
+                        sb.append(" oshut");
+                    break;
+                }
+                InetSocketAddress addr = localAddress();
+                if (addr != null) {
+                    sb.append(" local=");
+                    sb.append(Net.getRevealedLocalAddressAsString(addr));
+                }
+                if (remoteAddress() != null) {
+                    sb.append(" remote=");
+                    sb.append(remoteAddress().toString());
+                }
+            }
+        }
+        sb.append(']');
+        return sb.toString();
+    }
+
+    // -- Native methods --
+
+    private static native void initIDs() throws UnsupportedOperationException;
+
+    private static native int checkConnect(FileDescriptor fd, boolean block)
+            throws IOException;
+
+    private static native int sendOutOfBandData(FileDescriptor fd, byte data)
+            throws IOException;
+
+    static {
+        IOUtil.load();
+        System.loadLibrary("extnet");
+        UnsupportedOperationException uoe = null;
+        try {
+            initIDs();
+        } catch (UnsupportedOperationException e) {
+            uoe = e;
+        }
+        unsupported = uoe;
+        nd = new RdmaSocketDispatcher();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaSocketDispatcher.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2018, 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.internal.net.rdma;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import sun.nio.ch.SocketDispatcher;
+
+/**
+ * Allows different platforms to call different native methods
+ * for read and write operations.
+ */
+
+public class RdmaSocketDispatcher extends SocketDispatcher
+{
+    protected int read(FileDescriptor fd, long address, int len)
+            throws IOException {
+        return LinuxRdmaSocketDispatcherImpl.read0(fd, address, len);
+    }
+
+    protected long readv(FileDescriptor fd, long address, int len)
+            throws IOException {
+        return LinuxRdmaSocketDispatcherImpl.readv0(fd, address, len);
+    }
+
+    protected int write(FileDescriptor fd, long address, int len)
+            throws IOException {
+        return LinuxRdmaSocketDispatcherImpl.write0(fd, address, len);
+    }
+
+    protected long writev(FileDescriptor fd, long address, int len)
+            throws IOException {
+        return LinuxRdmaSocketDispatcherImpl.writev0(fd, address, len);
+    }
+
+    protected void close(FileDescriptor fd) throws IOException {
+        LinuxRdmaSocketDispatcherImpl.close0(fd);
+    }
+
+    public void preClose(FileDescriptor fd) throws IOException {
+        /* With RDMA socket channels, no need to do preClose */
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaSocketImpl.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,635 @@
+/*
+ * Copyright (c) 2018, 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.internal.net.rdma;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ProtocolFamily;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.net.SocketImpl;
+import java.net.SocketOption;
+import java.net.SocketOptions;
+import java.net.StandardSocketOptions;
+import java.net.UnknownHostException;
+import java.util.Objects;
+import java.util.Set;
+import sun.nio.ch.Net;
+import static java.net.StandardProtocolFamily.INET;
+import static java.net.StandardProtocolFamily.INET6;
+
+public abstract class RdmaSocketImpl extends SocketImpl
+{
+    private ProtocolFamily family;
+
+    Socket socket = null;
+    ServerSocket serverSocket = null;
+
+    int timeout;   // timeout in millisec
+
+    int trafficClass;
+
+    InputStream socketInputStream;
+    OutputStream socketOutputStream;
+
+    private boolean shut_rd = false;
+    private boolean shut_wr = false;
+
+    /* number of threads using the FileDescriptor */
+    protected int fdUseCount = 0;
+
+    /* lock when increment/decrementing fdUseCount */
+    protected final Object fdLock = new Object();
+
+    /* indicates a close is pending on the file descriptor */
+    protected boolean closePending = false;
+
+    /* indicates connection reset state */
+    private int CONNECTION_NOT_RESET = 0;
+    private int CONNECTION_RESET_PENDING = 1;
+    private int CONNECTION_RESET = 2;
+    private int resetState;
+    private final Object resetLock = new Object();
+
+    protected boolean stream;
+
+    private static UnsupportedOperationException unsupported;
+
+    static final sun.net.ext.RdmaSocketOptions rdmaOptions =
+            sun.net.ext.RdmaSocketOptions.getInstance();
+
+    static {
+        java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<>() {
+                public Void run() {
+                    System.loadLibrary("net");
+                    System.loadLibrary("extnet");
+                    return null;
+                }
+            });
+        UnsupportedOperationException uoe = null;
+        try {
+            initProto();
+        } catch (UnsupportedOperationException e) {
+            uoe = e;
+        }
+        unsupported = uoe;
+    }
+
+    private static final Void checkSupported() {
+        if (unsupported != null) {
+            Exception e = unsupported;
+            throw new UnsupportedOperationException(e.getMessage(), e);
+        } else {
+            return null;
+        }
+    }
+
+    public RdmaSocketImpl(ProtocolFamily family) {
+        this(checkSupported(), family);
+    }
+
+    private RdmaSocketImpl(Void unused, ProtocolFamily family) {
+        Objects.requireNonNull(family, "null family");
+        if (!(family == INET || family == INET6)) {
+            throw new UnsupportedOperationException("Protocol family not supported");
+        }
+        if (family == INET6) {
+            if (!Net.isIPv6Available()) {
+                throw new UnsupportedOperationException(
+                        "IPv6 not available");
+            }
+        }
+        this.family = family;
+    }
+
+    private static volatile boolean checkedRdma;
+    private static volatile boolean isRdmaAvailable;
+
+    boolean isRdmaAvailable() {
+        if (!checkedRdma) {
+            isRdmaAvailable = isRdmaAvailable0();
+            checkedRdma = true;
+        }
+        return isRdmaAvailable;
+    }
+
+    void setSocket(Socket soc) {
+        this.socket = soc;
+    }
+
+    Socket getSocket() {
+        return socket;
+    }
+
+    void setServerSocket(ServerSocket soc) {
+        this.serverSocket = soc;
+    }
+
+    ServerSocket getServerSocket() {
+        return serverSocket;
+    }
+
+    @Override
+    protected abstract Set<SocketOption<?>> supportedOptions();
+
+    protected synchronized void create(boolean stream) throws IOException {
+        this.stream = stream;
+        if (stream) {
+            fd = new FileDescriptor();
+
+            boolean preferIPv6 = Net.isIPv6Available() && (family != INET);
+            rdmaSocketCreate(preferIPv6, true);
+        }
+    }
+
+    protected void connect(String host, int port)
+            throws UnknownHostException, IOException {
+        boolean connected = false;
+        try {
+            InetAddress address = InetAddress.getByName(host);
+            this.port = port;
+            this.address = address;
+
+            connectToAddress(address, port, timeout);
+            connected = true;
+        } finally {
+            if (!connected) {
+                try {
+                    close();
+                } catch (IOException ioe) {
+                }
+            }
+        }
+    }
+
+    protected void connect(InetAddress address, int port) throws IOException {
+        if (family == INET && !(address instanceof Inet4Address))
+                throw new IllegalArgumentException("address type mismatch");
+        if (family == INET6 && !(address instanceof Inet6Address))
+                throw new IllegalArgumentException("address type mismatch");
+
+        this.port = port;
+        this.address = address;
+        try {
+            connectToAddress(address, port, timeout);
+            return;
+        } catch (IOException e) {
+            close();
+            throw e;
+        }
+    }
+
+    protected void connect(SocketAddress address, int timeout)
+            throws IOException {
+        boolean connected = false;
+        try {
+            if (address == null || !(address instanceof InetSocketAddress))
+                throw new IllegalArgumentException("unsupported address type");
+            InetSocketAddress addr = (InetSocketAddress) address;
+            InetAddress ia = addr.getAddress();
+            if (family == INET && !(ia instanceof Inet4Address))
+                throw new IllegalArgumentException("address type mismatch");
+            if (family == INET6 && !(ia instanceof Inet6Address))
+                throw new IllegalArgumentException("address type mismatch");
+            if (addr.isUnresolved())
+                throw new UnknownHostException(addr.getHostName());
+            this.port = addr.getPort();
+            this.address = addr.getAddress();
+
+            connectToAddress(this.address, port, timeout);
+            connected = true;
+        } finally {
+            if (!connected) {
+                try {
+                    close();
+                } catch (IOException ioe) {
+                }
+            }
+        }
+    }
+
+    private void connectToAddress(InetAddress address, int port, int timeout)
+            throws IOException {
+        if (address.isAnyLocalAddress()) {
+            doConnect(InetAddress.getLocalHost(), port, timeout);
+        } else {
+            doConnect(address, port, timeout);
+        }
+    }
+
+    @Override
+    protected abstract <T> void setOption(SocketOption<T> name, T value)
+            throws IOException;
+
+    @SuppressWarnings("unchecked")
+    @Override
+    protected abstract <T> T getOption(SocketOption<T> name)
+            throws IOException;
+
+    public void setOption(int opt, Object val) throws SocketException {
+        if (isClosedOrPending()) {
+            throw new SocketException("Socket Closed");
+        }
+        boolean on = true;
+        switch (opt) {
+        case SO_TIMEOUT:
+            if (val == null || (!(val instanceof Integer)))
+                throw new SocketException("Bad parameter for SO_TIMEOUT");
+            int tmp = ((Integer) val).intValue();
+            if (tmp < 0)
+                throw new IllegalArgumentException("timeout < 0");
+            timeout = tmp;
+            break;
+        case SO_BINDADDR:
+            throw new SocketException("Cannot re-bind socket");
+        case TCP_NODELAY:
+            if (val == null || !(val instanceof Boolean))
+                throw new SocketException("bad parameter for TCP_NODELAY");
+            on = ((Boolean)val).booleanValue();
+            break;
+        case SO_SNDBUF:
+        case SO_RCVBUF:
+            int value = ((Integer)val).intValue();
+            int maxValue = 1024 * 1024 * 1024 - 1;   //maximum value for the buffer
+            if (val == null || !(val instanceof Integer) ||
+                !(value > 0)) {
+                throw new SocketException("bad parameter for SO_SNDBUF " +
+                                          "or SO_RCVBUF");
+            }
+            if (value >= maxValue)
+                value = maxValue;
+            break;
+        case SO_REUSEADDR:
+            if (val == null || !(val instanceof Boolean))
+                throw new SocketException("bad parameter for SO_REUSEADDR");
+            on = ((Boolean)val).booleanValue();
+            if (serverSocket != null && serverSocket.isBound())
+                    throw new UnsupportedOperationException(
+                            "RDMA server socket cannot set " +
+                            "SO_REUSEADDR after bind.");
+            if (socket != null && socket.isConnected())
+                    throw new UnsupportedOperationException(
+                            "RDMA socket cannot set " +
+                            "SO_REUSEADDR after connect.");
+            break;
+        default:
+            throw new SocketException("unrecognized TCP option: " + opt);
+        }
+        socketSetOption(opt, on, val);
+    }
+
+    public Object getOption(int opt) throws SocketException {
+        if (isClosedOrPending()) {
+            throw new SocketException("Socket Closed");
+        }
+        if (opt == SO_TIMEOUT) {
+            return timeout;
+        }
+        int ret = 0;
+
+        switch (opt) {
+        case TCP_NODELAY:
+            ret = rdmaSocketGetOption(opt, null);
+            return Boolean.valueOf(ret != -1);
+        case SO_REUSEADDR:
+            ret = rdmaSocketGetOption(opt, null);
+            return Boolean.valueOf(ret != -1);
+        case SO_BINDADDR:
+            RdmaInetAddressContainer in = new RdmaInetAddressContainer();
+            ret = rdmaSocketGetOption(opt, in);
+            return in.addr;
+        case SO_SNDBUF:
+        case SO_RCVBUF:
+            ret = rdmaSocketGetOption(opt, null);
+            return ret;
+        default:
+            return null;
+        }
+    }
+
+    protected void socketSetOption(int opt, boolean b, Object val)
+            throws SocketException {
+        if (opt == SocketOptions.SO_REUSEPORT &&
+            !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
+            throw new UnsupportedOperationException("unsupported option");
+        }
+        try {
+            rdmaSocketSetOption(opt, b, val);
+        } catch (SocketException se) {
+            if (socket == null || !socket.isConnected())
+                throw se;
+        }
+    }
+
+    synchronized void doConnect(InetAddress address, int port, int timeout)
+            throws IOException {
+        try {
+            acquireFD();
+            boolean preferIPv6 = Net.isIPv6Available() && (family != INET);
+            try {
+                rdmaSocketConnect(preferIPv6, address, port, timeout);
+                synchronized (fdLock) {
+                    if (closePending) {
+                        throw new SocketException ("Socket closed");
+                    }
+                }
+            } finally {
+                releaseFD();
+            }
+        } catch (IOException e) {
+            close();
+            throw e;
+        }
+    }
+
+    private final InetAddress anyLocalAddress() throws IOException {
+        if (family == INET)
+            return InetAddress.getByName("0.0.0.0");
+        else if (family == INET6)
+            return InetAddress.getByName("::");
+        else
+            throw new IllegalArgumentException("Unsupported address type " + family);
+    }
+
+    protected synchronized void bind(InetAddress address, int lport)
+            throws IOException {
+        if (address == null)
+            throw new IllegalArgumentException("address is null");
+
+        if (address.isAnyLocalAddress())
+            address = anyLocalAddress();
+
+        if (family == INET && !(address instanceof Inet4Address))
+            throw new IllegalArgumentException("address type mismatch");
+        if (family == INET6 && !(address instanceof Inet6Address))
+            throw new IllegalArgumentException("address type mismatch");
+        boolean preferIPv6 = Net.isIPv6Available() && (family != INET);
+        rdmaSocketBind(preferIPv6, address, lport);
+    }
+
+    protected synchronized void listen(int count) throws IOException {
+        rdmaSocketListen(count);
+    }
+
+    protected void accept(SocketImpl s) throws IOException {
+        acquireFD();
+        try {
+            rdmaSocketAccept(s);
+        } finally {
+            releaseFD();
+        }
+    }
+
+    protected synchronized InputStream getInputStream() throws IOException {
+        synchronized (fdLock) {
+            if (isClosedOrPending())
+                throw new IOException("Socket Closed");
+            if (shut_rd)
+                throw new IOException("Socket input is shutdown");
+            if (socketInputStream == null)
+                socketInputStream = new RdmaSocketInputStream(this);
+        }
+        return socketInputStream;
+    }
+
+    protected synchronized OutputStream getOutputStream() throws IOException {
+        synchronized (fdLock) {
+            if (isClosedOrPending())
+                throw new IOException("Socket Closed");
+            if (shut_wr)
+                throw new IOException("Socket output is shutdown");
+            if (socketOutputStream == null)
+                socketOutputStream = new RdmaSocketOutputStream(this);
+        }
+        return socketOutputStream;
+    }
+
+    protected FileDescriptor getFileDescriptor() {
+        return fd;
+    }
+
+    protected void setFileDescriptor(FileDescriptor fd) {
+        this.fd = fd;
+    }
+
+    protected void setAddress(InetAddress address) {
+        this.address = address;
+    }
+
+    void setPort(int port) {
+        this.port = port;
+    }
+
+    void setLocalPort(int localport) {
+        this.localport = localport;
+    }
+
+    protected synchronized int available() throws IOException {
+        throw new UnsupportedOperationException(
+                "unsupported socket operation");
+    }
+
+    protected void close() throws IOException {
+        synchronized(fdLock) {
+            if (fd != null) {
+                if (fdUseCount == 0) {
+                    if (closePending) {
+                        return;
+                    }
+                    closePending = true;
+                    rdmaSocketClose();
+                    fd = null;
+                    return;
+                } else {
+                    if (!closePending) {
+                        closePending = true;
+                        fdUseCount--;
+                        rdmaSocketClose();
+                    }
+                }
+            }
+        }
+    }
+
+    void reset() throws IOException {
+        if (fd != null) {
+            rdmaSocketClose();
+        }
+        fd = null;
+        postReset();
+    }
+
+    void postReset() throws IOException {
+        address = null;
+        port = 0;
+        localport = 0;
+    }
+
+    protected void shutdownInput() throws IOException {
+        if (fd != null) {
+            rdmaSocketShutdown(SHUT_RD);
+            if (socketInputStream != null) {
+                ((RdmaSocketInputStream)socketInputStream).setEOF(true);
+            }
+            shut_rd = true;
+        }
+    }
+
+    protected void shutdownOutput() throws IOException {
+        if (fd != null) {
+            rdmaSocketShutdown(SHUT_WR);
+            shut_wr = true;
+        }
+    }
+
+    protected boolean supportsUrgentData () {
+        return true;
+    }
+
+    protected void sendUrgentData (int data) throws IOException {
+        if (fd == null) {
+            throw new IOException("Socket Closed");
+        }
+        rdmaSocketSendUrgentData(data);
+    }
+
+    FileDescriptor acquireFD() {
+        synchronized (fdLock) {
+            fdUseCount++;
+            return fd;
+        }
+    }
+
+    void releaseFD() {
+        synchronized (fdLock) {
+            fdUseCount--;
+            if (fdUseCount == -1) {
+                if (fd != null) {
+                    try {
+                        rdmaSocketClose();
+                    } catch (IOException e) {
+                    } finally {
+                        fd = null;
+                    }
+                }
+            }
+        }
+    }
+
+    public boolean isConnectionReset() {
+        synchronized (resetLock) {
+            return (resetState == CONNECTION_RESET);
+        }
+    }
+
+    public boolean isConnectionResetPending() {
+        synchronized (resetLock) {
+            return (resetState == CONNECTION_RESET_PENDING);
+        }
+    }
+
+    public void setConnectionReset() {
+        synchronized (resetLock) {
+            resetState = CONNECTION_RESET;
+        }
+    }
+
+    public void setConnectionResetPending() {
+        synchronized (resetLock) {
+            if (resetState == CONNECTION_NOT_RESET) {
+                resetState = CONNECTION_RESET_PENDING;
+            }
+        }
+
+    }
+
+    public boolean isClosedOrPending() {
+        synchronized (fdLock) {
+            if (closePending || (fd == null)) {
+                return true;
+            } else {
+                return false;
+            }
+        }
+    }
+
+    public int getTimeout() {
+        return timeout;
+    }
+
+    protected InetAddress getInetAddress() {
+        return address;
+    }
+
+    protected int getPort() {
+        return port;
+    }
+
+    protected int getLocalPort() {
+        return localport;
+    }
+
+    public static final int SHUT_RD = 0;
+    public static final int SHUT_WR = 1;
+
+    static native void initProto() throws UnsupportedOperationException;
+
+    private static native boolean isRdmaAvailable0();
+
+    native void rdmaSocketCreate(boolean preferIPv6, boolean isServer)
+            throws IOException;
+
+    native void rdmaSocketConnect(boolean preferIPv6, InetAddress address,
+            int port, int timeout) throws IOException;
+
+    native void rdmaSocketBind(boolean preferIPv6, InetAddress address,
+            int port) throws IOException;
+
+    native void rdmaSocketListen(int count) throws IOException;
+
+    native void rdmaSocketAccept(SocketImpl s) throws IOException;
+
+    native void rdmaSocketClose() throws IOException;
+
+    native void rdmaSocketShutdown(int howto) throws IOException;
+
+    native void rdmaSocketSetOption(int cmd, boolean on, Object value)
+            throws SocketException;
+
+    native int rdmaSocketGetOption(int opt, Object iaContainerObj)
+            throws SocketException;
+
+    native void rdmaSocketSendUrgentData(int data) throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaSocketInputStream.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2018, 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.internal.net.rdma;
+
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.channels.FileChannel;
+import java.net.Socket;
+import java.net.SocketException;
+
+import sun.net.ConnectionResetException;
+
+class RdmaSocketInputStream extends FileInputStream
+{
+    static {
+        init();
+    }
+
+    private boolean eof;
+    private RdmaSocketImpl impl = null;
+    private byte temp[];
+    private Socket socket = null;
+
+    RdmaSocketInputStream(RdmaSocketImpl impl) throws IOException {
+        super(impl.getFileDescriptor());
+        this.impl = impl;
+        socket = impl.getSocket();
+    }
+
+    public final FileChannel getChannel() {
+        return null;
+    }
+
+    private native int rdmaSocketRead0(FileDescriptor fd, byte b[],
+            int off, int len, int timeout) throws IOException;
+
+    private int rdmaSocketRead(FileDescriptor fd, byte b[], 
+            int off, int len, int timeout) throws IOException {
+        return rdmaSocketRead0(fd, b, off, len, timeout);
+    }
+
+    public int read(byte b[]) throws IOException {
+        return read(b, 0, b.length);
+    }
+
+    public int read(byte b[], int off, int length) throws IOException {
+        return read(b, off, length, impl.getTimeout());
+    }
+
+    int read(byte b[], int off, int length, int timeout) throws IOException {
+        int n;
+
+        if (eof) {
+            return -1;
+        }
+
+        if (impl.isConnectionReset()) {
+            throw new SocketException("Connection reset");
+        }
+
+        if (length <= 0 || off < 0 || length > b.length - off) {
+            if (length == 0) {
+                return 0;
+            }
+            throw new ArrayIndexOutOfBoundsException("length == " + length
+                    + " off == " + off + " buffer length == " + b.length);
+        }
+
+        boolean gotReset = false;
+
+        FileDescriptor fd = impl.acquireFD();
+        try {
+            n = rdmaSocketRead(fd, b, off, length, timeout);
+            if (n > 0) {
+                return n;
+            }
+        } catch (ConnectionResetException rstExc) {
+            gotReset = true;
+        } finally {
+            impl.releaseFD();
+        }
+
+        if (gotReset) {
+            impl.setConnectionResetPending();
+            impl.acquireFD();
+            try {
+                n = rdmaSocketRead(fd, b, off, length, timeout);
+                if (n > 0) {
+                    return n;
+                }
+            } catch (ConnectionResetException rstExc) {
+            } finally {
+                impl.releaseFD();
+            }
+        }
+
+        if (impl.isClosedOrPending()) {
+            throw new SocketException("Socket closed");
+        }
+        if (impl.isConnectionResetPending()) {
+            impl.setConnectionReset();
+        }
+        if (impl.isConnectionReset()) {
+            throw new SocketException("Connection reset");
+        }
+        eof = true;
+        return -1;
+    }
+
+    /**
+     * Reads a single byte from the socket.
+     */
+    public int read() throws IOException {
+        if (eof) {
+            return -1;
+        }
+        temp = new byte[1];
+        int n = read(temp, 0, 1);
+        if (n <= 0) {
+            return -1;
+        }
+        return temp[0] & 0xff;
+    }
+
+    /**
+     * Skips n bytes of input.
+     * @param numbytes the number of bytes to skip
+     * @return  the actual number of bytes skipped.
+     * @exception IOException If an I/O error has occurred.
+     */
+    public long skip(long numbytes) throws IOException {
+        if (numbytes <= 0) {
+            return 0;
+        }
+        long n = numbytes;
+        int buflen = (int) Math.min(1024, n);
+        byte data[] = new byte[buflen];
+        while (n > 0) {
+            int r = read(data, 0, (int) Math.min((long) buflen, n));
+            if (r < 0) {
+                break;
+            }
+            n -= r;
+        }
+        return numbytes - n;
+    }
+
+    public int available() throws IOException {
+        throw new UnsupportedOperationException(
+                "unsupported socket operation");
+    }
+
+    /**
+     * Closes the stream.
+     */
+    private boolean closing = false;
+    public void close() throws IOException {
+        if (closing)
+            return;
+        closing = true;
+        if (socket != null) {
+            if (!socket.isClosed())
+                socket.close();
+        } else
+            impl.close();
+        closing = false;
+    }
+
+    void setEOF(boolean eof) {
+        this.eof = eof;
+    }
+
+    /**
+     * Perform class load-time initializations.
+     */
+    private static native void init();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaSocketOptionRegistry.java.template	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2018, 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.
+ *
+ */
+@@END_COPYRIGHT@@
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+/* To be able to name the Java constants the same as the C constants without
+   having the preprocessor rewrite those identifiers, add PREFIX_ to all
+   identifiers matching a C constant. The PREFIX_ is filtered out in the
+   makefile. */
+
+@@START_HERE@@
+
+package jdk.internal.net.rdma;
+import java.net.SocketOption;
+import java.net.StandardSocketOptions;
+import java.net.ProtocolFamily;
+import java.util.Map;
+import java.util.HashMap;
+
+class RdmaSocketOptionRegistry {
+
+    private RdmaSocketOptionRegistry() { }
+
+    private static class RegistryKey {
+        private final SocketOption<?> name;
+        private final ProtocolFamily family;
+        RegistryKey(SocketOption<?> name, ProtocolFamily family) {
+            this.name = name;
+            this.family = family;
+        }
+        public int hashCode() {
+            return name.hashCode() + family.hashCode();
+        }
+        public boolean equals(Object ob) {
+            if (ob == null) return false;
+            if (!(ob instanceof RegistryKey)) return false;
+            RegistryKey other = (RegistryKey)ob;
+            if (this.name != other.name) return false;
+            if (this.family != other.family) return false;
+            return true;
+        }
+    }
+
+    private static class LazyInitialization {
+
+        static final Map<RegistryKey,RdmaOptionKey> options = options();
+
+        private static Map<RegistryKey,RdmaOptionKey> options() {
+            Map<RegistryKey,RdmaOptionKey> map =
+                new HashMap<RegistryKey,RdmaOptionKey>();
+            map.put(new RegistryKey(StandardSocketOptions.PREFIX_SO_SNDBUF,
+                RdmaNet.UNSPEC), new RdmaOptionKey(SOL_SOCKET, SO_SNDBUF));
+            map.put(new RegistryKey(StandardSocketOptions.PREFIX_SO_RCVBUF,
+                RdmaNet.UNSPEC), new RdmaOptionKey(SOL_SOCKET, SO_RCVBUF));
+            map.put(new RegistryKey(StandardSocketOptions.PREFIX_SO_REUSEADDR,
+                RdmaNet.UNSPEC), new RdmaOptionKey(SOL_SOCKET, SO_REUSEADDR));
+            // IPPROTO_TCP is 6
+            map.put(new RegistryKey(StandardSocketOptions.PREFIX_TCP_NODELAY,
+                RdmaNet.UNSPEC), new RdmaOptionKey(6, TCP_NODELAY));
+            return map;
+        }
+    }
+
+    public static RdmaOptionKey findOption(SocketOption<?> name,
+                                           ProtocolFamily family) {
+        RegistryKey key = new RegistryKey(name, family);
+        return LazyInitialization.options.get(key);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaSocketOutputStream.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2018, 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.internal.net.rdma;
+
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.channels.FileChannel;
+import java.net.Socket;
+import java.net.SocketException;
+
+class RdmaSocketOutputStream extends FileOutputStream
+{
+    static {
+        init();
+    }
+
+    private RdmaSocketImpl impl = null;
+    private byte temp[] = new byte[1];
+    private Socket socket = null;
+
+    RdmaSocketOutputStream(RdmaSocketImpl impl) throws IOException {
+        super(impl.getFileDescriptor());
+        this.impl = impl;
+        socket = impl.getSocket();
+    }
+
+    public final FileChannel getChannel() {
+        return null;
+    }
+
+    /**
+     * Writes to the socket.
+     * @param fd the FileDescriptor
+     * @param b the data to be written
+     * @param off the start offset in the data
+     * @param len the number of bytes that are written
+     * @exception IOException If an I/O error has occurred.
+     */
+    private native void rdmaSocketWrite0(FileDescriptor fd, byte[] b,
+            int off, int len) throws IOException;
+
+    /**
+     * Writes to the socket with appropriate locking of the
+     * FileDescriptor.
+     * @param b the data to be written
+     * @param off the start offset in the data
+     * @param len the number of bytes that are written
+     * @exception IOException If an I/O error has occurred.
+     */
+    private void rdmaSocketWrite(byte b[], int off, int len)
+            throws IOException {
+        if (len <= 0 || off < 0 || len > b.length - off) {
+            if (len == 0) {
+                return;
+            }
+            throw new ArrayIndexOutOfBoundsException("len == " + len
+                    + " off == " + off + " buffer length == " + b.length);
+        }
+
+        FileDescriptor fd = impl.acquireFD();
+        try {
+            rdmaSocketWrite0(fd, b, off, len);
+        } catch (SocketException se) {
+            if (se instanceof sun.net.ConnectionResetException) {
+                impl.setConnectionResetPending();
+                se = new SocketException("Connection reset");
+            }
+            if (impl.isClosedOrPending()) {
+                throw new SocketException("Socket closed");
+            } else {
+                throw se;
+            }
+        } finally {
+            impl.releaseFD();
+        }
+    }
+
+    /**
+     * Writes a byte to the socket.
+     * @param b the data to be written
+     * @exception IOException If an I/O error has occurred.
+     */
+    public void write(int b) throws IOException {
+        temp[0] = (byte)b;
+        rdmaSocketWrite(temp, 0, 1);
+    }
+
+    /**
+     * Writes the contents of the buffer <i>b</i> to the socket.
+     * @param b the data to be written
+     * @exception SocketException If an I/O error has occurred.
+     */
+    public void write(byte b[]) throws IOException {
+        rdmaSocketWrite(b, 0, b.length);
+    }
+
+    /**
+     * Writes <i>length</i> bytes from buffer <i>b</i> starting at
+     * offset <i>len</i>.
+     * @param b the data to be written
+     * @param off the start offset in the data
+     * @param len the number of bytes that are written
+     * @exception SocketException If an I/O error has occurred.
+     */
+    public void write(byte b[], int off, int len) throws IOException {
+        rdmaSocketWrite(b, off, len);
+    }
+
+    /**
+     * Closes the stream.
+     */
+    private boolean closing = false;
+    public void close() throws IOException {
+        if (closing)
+            return;
+        closing = true;
+        if (socket != null) {
+            if (!socket.isClosed())
+                socket.close();
+        } else
+            impl.close();
+        closing = false;
+    }
+
+    /**
+     * Perform class load-time initializations.
+     */
+    private static native void init();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/classes/jdk/internal/net/rdma/RdmaSocketProvider.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2018, 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.internal.net.rdma;
+
+import java.io.IOException;
+import java.net.ProtocolFamily;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.SocketImpl;
+import java.net.SocketOption;
+import java.net.SocketOptions;
+import java.net.StandardSocketOptions;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import jdk.net.RdmaSocketOptions;
+
+public class RdmaSocketProvider {
+
+    static class RdmaClientSocketImpl extends RdmaSocketImpl {
+
+        private final Set<SocketOption<?>> options =
+                Set.of(StandardSocketOptions.SO_SNDBUF,
+                       StandardSocketOptions.SO_RCVBUF,
+                       StandardSocketOptions.SO_REUSEADDR,
+                       StandardSocketOptions.TCP_NODELAY,
+                       RdmaSocketOptions.RDMA_SQSIZE,
+                       RdmaSocketOptions.RDMA_RQSIZE,
+                       RdmaSocketOptions.RDMA_INLINE);
+
+        RdmaClientSocketImpl(ProtocolFamily family) {
+            super(family);
+        }
+
+        @Override
+        public Set<SocketOption<?>> supportedOptions() {
+            return options;
+        }
+
+        @Override
+        protected <T> void setOption(SocketOption<T> name, T value)
+                throws IOException {
+            if (!rdmaOptions.isOptionSupported(name)) {
+                int opt;
+                if (name == StandardSocketOptions.SO_SNDBUF) {
+                    opt = SocketOptions.SO_SNDBUF;
+                } else if (name == StandardSocketOptions.SO_RCVBUF) {
+                    opt = SocketOptions.SO_RCVBUF;
+                } else if (name == StandardSocketOptions.SO_REUSEADDR) {
+                    opt = SocketOptions.SO_REUSEADDR;
+                } else if (name == StandardSocketOptions.TCP_NODELAY) {
+                    opt = SocketOptions.TCP_NODELAY;
+                } else {
+                    throw new UnsupportedOperationException(
+                            "unsupported option: " + name);
+                }
+                setOption(opt, value);
+            } else {
+                rdmaOptions.setOption(fd, name, value);
+            }
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        protected <T> T getOption(SocketOption<T> name) throws IOException {
+            Object value;
+            if (!rdmaOptions.isOptionSupported(name)) {
+                int opt;
+                if (name == StandardSocketOptions.SO_SNDBUF) {
+                    opt = SocketOptions.SO_SNDBUF;
+                } else if (name == StandardSocketOptions.SO_RCVBUF) {
+                    opt = SocketOptions.SO_RCVBUF;
+                } else if (name == StandardSocketOptions.SO_REUSEADDR) {
+                    opt = SocketOptions.SO_REUSEADDR;
+                } else if (name == StandardSocketOptions.TCP_NODELAY) {
+                    opt = SocketOptions.TCP_NODELAY;
+                } else {
+                    throw new UnsupportedOperationException(
+                            "unsupported option: " + name);
+                }
+                value = getOption(opt);
+            } else {
+                value = rdmaOptions.getOption(fd, name);
+            }
+            return (T) value;
+        }
+    }
+
+    static class RdmaServerSocketImpl extends RdmaSocketImpl {
+        private final Set<SocketOption<?>> options =
+                Set.of(StandardSocketOptions.SO_RCVBUF,
+                       StandardSocketOptions.SO_REUSEADDR,
+                       RdmaSocketOptions.RDMA_SQSIZE,
+                       RdmaSocketOptions.RDMA_RQSIZE,
+                       RdmaSocketOptions.RDMA_INLINE);
+
+        RdmaServerSocketImpl(ProtocolFamily family) {
+            super(family);
+        }
+
+        @Override
+        public Set<SocketOption<?>> supportedOptions() {
+            return options;
+        }
+
+        @Override
+        protected <T> void setOption(SocketOption<T> name, T value)
+                throws IOException {
+            if (!rdmaOptions.isOptionSupported(name)) {
+                int opt;
+                if (name == StandardSocketOptions.SO_RCVBUF) {
+                    opt = SocketOptions.SO_RCVBUF;
+                } else if (name == StandardSocketOptions.SO_REUSEADDR) {
+                    opt = SocketOptions.SO_REUSEADDR;
+                } else {
+                    throw new UnsupportedOperationException(
+                            "unsupported option: " + name);
+                }
+                setOption(opt, value);
+            } else {
+                rdmaOptions.setOption(fd, name, value);
+            }
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        protected <T> T getOption(SocketOption<T> name) throws IOException {
+            Object value;
+            if (!rdmaOptions.isOptionSupported(name)) {
+                int opt;
+                if (name == StandardSocketOptions.SO_RCVBUF) {
+                    opt = SocketOptions.SO_RCVBUF;
+                } else if (name == StandardSocketOptions.SO_REUSEADDR) {
+                    opt = SocketOptions.SO_REUSEADDR;
+                } else {
+                    throw new UnsupportedOperationException(
+                            "unsupported option: " + name);
+                }
+                value = getOption(opt);
+            } else {
+                value = rdmaOptions.getOption(fd, name);
+            }
+            return (T) value;
+         }
+    }
+
+    public static Socket openSocket(ProtocolFamily family) throws IOException {
+        return new Socket(new RdmaClientSocketImpl(family)) {  };
+    }
+
+    public static ServerSocket openServerSocket(ProtocolFamily family)
+            throws IOException {
+        return new ServerSocket(new RdmaServerSocketImpl(family)) {
+            public Socket accept() throws IOException {
+                if (isClosed())
+                    throw new SocketException("Socket is closed");
+                if (!isBound())
+                    throw new SocketException("Socket is not bound yet");
+
+                Socket s = openSocket(family);
+                implAccept(s);
+                return s;
+            }
+        };
+    }
+
+    private RdmaSocketProvider() {}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/classes/jdk/net/LinuxRdmaSocketOptions.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2018, 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 jdk.net.RdmaSocketOptions.PlatformRdmaSocketOptions;
+
+class LinuxRdmaSocketOptions extends PlatformRdmaSocketOptions {
+
+    private static final UnsupportedOperationException unsupported;
+
+    private static final Void checkSupported() {
+        if (unsupported != null)
+            throw new UnsupportedOperationException(unsupported.getMessage(), unsupported);
+        else
+            return null;
+    }
+
+    public LinuxRdmaSocketOptions() {
+        this(checkSupported());
+    }
+
+    private LinuxRdmaSocketOptions(Void unused) { }
+
+    @Override native void setSockOpt(int fd, int opt, int value)
+            throws SocketException;
+
+    @Override native int getSockOpt(int fd, int opt)
+            throws SocketException;
+
+    @Override native boolean rdmaSocketSupported();
+
+    static {
+        java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<>() {
+                public Void run() {
+                    System.loadLibrary("extnet");
+                    return null;
+                }
+            });
+        UnsupportedOperationException uoe = null;
+        try {
+            init();
+        } catch (UnsupportedOperationException e) {
+            uoe = e;
+        }
+        unsupported = uoe;
+    }
+
+    private static native void init() throws UnsupportedOperationException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/native/libextnet/LinuxRdmaSocketDispatcherImpl.c	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2018, 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 "jdk_internal_net_rdma_LinuxRdmaSocketDispatcherImpl.h"
+#include "nio.h"
+#include "nio_util.h"
+#include <Rsocket.h>
+
+static jfieldID fd_fdID;
+
+jint
+convertReturnVal(JNIEnv *env, jint n, jboolean reading) {
+    if (n > 0)
+        return n;
+    else if (n == 0) {
+        if (reading) {
+            return IOS_EOF;
+        } else {
+            return 0;
+        }
+    }
+    else if (errno == EAGAIN)
+        return IOS_UNAVAILABLE;
+    else if (errno == EINTR)
+        return IOS_INTERRUPTED;
+    else {
+        const char *msg = reading ? "Read failed" : "Write failed";
+        JNU_ThrowIOExceptionWithLastError(env, msg);
+        return IOS_THROWN;
+    }
+}
+
+jlong
+convertLongReturnVal(JNIEnv *env, jlong n, jboolean reading) {
+    if (n > 0)
+        return n;
+    else if (n == 0) {
+        if (reading) {
+            return IOS_EOF;
+        } else {
+            return 0;
+        }
+    }
+    else if (errno == EAGAIN)
+        return IOS_UNAVAILABLE;
+    else if (errno == EINTR)
+        return IOS_INTERRUPTED;
+    else {
+        const char *msg = reading ? "Read failed" : "Write failed";
+        JNU_ThrowIOExceptionWithLastError(env, msg);
+        return IOS_THROWN;
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_LinuxRdmaSocketDispatcherImpl_init(JNIEnv *env,
+        jclass cl) {
+    loadRdmaFuncs(env);
+    CHECK_NULL(cl = (*env)->FindClass(env, "java/io/FileDescriptor"));
+    CHECK_NULL(fd_fdID = (*env)->GetFieldID(env, cl, "fd", "I"));
+}
+
+JNIEXPORT jint JNICALL
+Java_jdk_internal_net_rdma_LinuxRdmaSocketDispatcherImpl_read0(JNIEnv *env,
+        jclass clazz, jobject fdo, jlong address, jint len) {
+    jint fd = (*env)->GetIntField(env, fdo, fd_fdID);
+    void *buf = (void *)jlong_to_ptr(address);
+    jint result = convertReturnVal(env, rs_read(fd, buf, len), JNI_TRUE);
+/*
+    if (result == IOS_UNAVAILABLE
+            && (rs_fcntl(fd, F_GETFL, 0) & O_NONBLOCK) == 0) {  // blocking
+        struct pollfd pfd[1];
+        pfd[0].fd = fd;
+        pfd[0].events = POLLIN;
+        rs_poll(pfd, 1, -1);
+        if (pfd[0].revents & POLLIN)
+            result = convertReturnVal(env, rs_read(fd, buf, len), JNI_TRUE);
+        else {
+            JNU_ThrowIOExceptionWithLastError(env, "Read failed");
+            return IOS_THROWN;
+        }
+    }
+*/
+    return result;
+}
+
+JNIEXPORT jlong JNICALL
+Java_jdk_internal_net_rdma_LinuxRdmaSocketDispatcherImpl_readv0(JNIEnv *env,
+        jclass clazz, jobject fdo, jlong address, jint len) {
+    jint fd = (*env)->GetIntField(env, fdo, fd_fdID);
+    struct iovec *iov = (struct iovec *)jlong_to_ptr(address);
+    jlong result = convertLongReturnVal(env, rs_readv(fd, iov, len), JNI_TRUE);
+/*
+    if (result == IOS_UNAVAILABLE
+            && (rs_fcntl(fd, F_GETFL, 0) & O_NONBLOCK) == 0) {  // blocking
+        struct pollfd pfd[1];
+        pfd[0].fd = fd;
+        pfd[0].events = POLLIN;
+        rs_poll(pfd, 1, -1);
+        if (pfd[0].revents & POLLIN)
+            result = convertLongReturnVal(env, rs_readv(fd, iov, len), JNI_TRUE);
+        else {
+            JNU_ThrowIOExceptionWithLastError(env, "Read failed");
+            return IOS_THROWN;
+        }
+    }
+*/
+    return result;
+}
+
+JNIEXPORT jint JNICALL
+Java_jdk_internal_net_rdma_LinuxRdmaSocketDispatcherImpl_write0(JNIEnv *env,
+        jclass clazz, jobject fdo, jlong address, jint len) {
+    jint fd = (*env)->GetIntField(env, fdo, fd_fdID);
+    void *buf = (void *)jlong_to_ptr(address);
+    jint result = convertReturnVal(env, rs_write(fd, buf, len), JNI_FALSE);
+/*
+    if (result == IOS_UNAVAILABLE
+            && (rs_fcntl(fd, F_GETFL, 0) & O_NONBLOCK) == 0) {  // blocking
+        struct pollfd pfd[1];
+        pfd[0].fd = fd;
+        pfd[0].events = POLLOUT;
+        rs_poll(pfd, 1, -1);
+        if (pfd[0].revents & POLLOUT)
+            result = convertReturnVal(env, rs_write(fd, buf, len), JNI_FALSE);
+        else {
+            JNU_ThrowIOExceptionWithLastError(env, "Write failed");
+            return IOS_THROWN;
+        }
+    }
+*/
+    return result;
+}
+
+JNIEXPORT jlong JNICALL
+Java_jdk_internal_net_rdma_LinuxRdmaSocketDispatcherImpl_writev0(JNIEnv *env,
+        jclass clazz, jobject fdo, jlong address, jint len) {
+    jint fd = (*env)->GetIntField(env, fdo, fd_fdID);
+    struct iovec *iov = (struct iovec *)jlong_to_ptr(address);
+    jlong result = convertLongReturnVal(env, rs_writev(fd, iov, len),
+            JNI_FALSE);
+/*
+    if (result == IOS_UNAVAILABLE
+            && (rs_fcntl(fd, F_GETFL, 0) & O_NONBLOCK) == 0) {  // blocking
+        struct pollfd pfd[1];
+        pfd[0].fd = fd;
+        pfd[0].events = POLLOUT;
+        rs_poll(pfd, 1, -1);
+        if (pfd[0].revents & POLLOUT)
+            result = convertLongReturnVal(env, rs_writev(fd, iov, len), JNI_FALSE);
+        else {
+            JNU_ThrowIOExceptionWithLastError(env, "Write failed");
+            return IOS_THROWN;
+        }
+    }
+*/
+    return result;
+}
+
+static void closeFileDescriptor(JNIEnv *env, int fd) {
+    if (fd != -1) {
+        int result = rs_close(fd);
+        if (result < 0)
+            JNU_ThrowIOExceptionWithLastError(env, "Close failed");
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_LinuxRdmaSocketDispatcherImpl_close0(JNIEnv *env,
+        jclass clazz, jobject fdo) {
+    jint fd = (*env)->GetIntField(env, fdo, fd_fdID);
+    closeFileDescriptor(env, fd);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/native/libextnet/LinuxRdmaSocketOptions.c	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2018, 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 "jdk_net_LinuxRdmaSocketOptions.h"
+#include "rdma_util_md.h"
+#include "Rsocket.h"
+#include "jni_util.h"
+
+void throwByNameWithLastError(JNIEnv *env, const char *name,
+        const char *defaultDetail) {
+  char defaultMsg[255];
+  sprintf(defaultMsg, "errno: %d, %s", errno, defaultDetail);
+  JNU_ThrowByNameWithLastError(env, name, defaultMsg);
+}
+
+JNIEXPORT void JNICALL
+Java_jdk_net_LinuxRdmaSocketOptions_init(JNIEnv *env, jclass c) {
+   loadRdmaFuncs(env);
+}
+ 
+JNIEXPORT void JNICALL
+Java_jdk_net_LinuxRdmaSocketOptions_setSockOpt(JNIEnv *env,
+        jobject unused, jint fd, jint opt, jint value) {
+    int optname;
+    int level = SOL_RDMA;
+    RDMA_MapSocketOption(opt, &level, &optname);
+    int len = sizeof(value);
+    int rv = RDMA_SetSockOpt(fd, level, optname, (char*)&value, len);    
+    if (rv < 0) {
+        if (errno == ENOPROTOOPT) {
+            JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+                            "unsupported RDMA socket option");
+        } else if (errno == EACCES || errno == EPERM) {
+            JNU_ThrowByName(env, "java/net/SocketException", "Permission denied");
+        } else {
+            throwByNameWithLastError(env, "java/net/SocketException",
+                                     "set RDMA option failed");
+        }
+    }
+}
+
+JNIEXPORT jint JNICALL
+Java_jdk_net_LinuxRdmaSocketOptions_getSockOpt(JNIEnv *env,
+        jobject unused, jint fd, jint opt) {
+    int optname;
+    int level = SOL_RDMA;
+    RDMA_MapSocketOption(opt, &level, &optname);
+    int value;
+    int len = sizeof(value);
+    int rv = RDMA_GetSockOpt(fd, level, optname, (char*)&value, &len);
+
+    if (rv < 0) {
+        if (errno == ENOPROTOOPT) {
+            JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+                            "unsupported RDMA socket option");
+        } else if (errno == EACCES || errno == EPERM) {
+            JNU_ThrowByName(env, "java/net/SocketException", "Permission denied");
+        } else {
+            throwByNameWithLastError(env, "java/net/SocketException",
+                                     "get RDMA option failed");
+        }
+        return -1;
+    }
+    return value;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_jdk_net_LinuxRdmaSocketOptions_rdmaSocketSupported(JNIEnv *env,
+        jobject unused) {
+    int rv, s;
+
+    s = rs_socket(PF_INET, SOCK_STREAM, 0);
+    if (s < 0) {
+        return JNI_FALSE;
+    }
+    rs_close(s);
+    return JNI_TRUE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/native/libextnet/RdmaNet.c	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2018, 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 "net_util.h"
+#include "nio.h"
+#include "nio_util.h"
+#include "rdma_util_md.h"
+#include "Rsocket.h"
+#include "sun_nio_ch_Net.h"
+
+static jfieldID fd_fdID;
+
+JNIEXPORT jboolean JNICALL
+Java_jdk_internal_net_rdma_RdmaNet_isRdmaAvailable0(JNIEnv *env,
+        jclass clazz) {
+    return rdma_supported();
+}
+
+static int
+configureBlocking(int fd, jboolean blocking) {
+    int flags = rs_fcntl(fd, F_GETFL);
+    int newflags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
+
+    return (flags == newflags) ? 0 : rs_fcntl(fd, F_SETFL, newflags);
+}
+
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaNet_configureBlocking(JNIEnv *env, jclass clazz,
+        jobject fdo, jboolean blocking) {
+    int fd = (*env)->GetIntField(env, fdo, fd_fdID);
+    if (configureBlocking(fd, blocking) < 0)
+        JNU_ThrowIOExceptionWithLastError(env, "Configure blocking failed");
+}
+
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaNet_initIDs(JNIEnv *env, jclass clazz) {
+    loadRdmaFuncs(env);
+    CHECK_NULL(clazz = (*env)->FindClass(env, "java/io/FileDescriptor"));
+    CHECK_NULL(fd_fdID = (*env)->GetFieldID(env, clazz, "fd", "I"));
+    initInetAddressIDs(env);
+}
+
+JNIEXPORT jint JNICALL
+Java_jdk_internal_net_rdma_RdmaNet_socket0(JNIEnv *env, jclass clazz,
+        jboolean preferIPv6, jboolean stream, jboolean reuse) {
+    int fd;
+    int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
+    int domain = (ipv6_available() && preferIPv6) ? AF_INET6 : AF_INET;
+
+    fd = rs_socket(domain, type, 0);
+
+    rs_fcntl(fd, F_SETFL, rs_fcntl(fd, F_GETFL) | O_NONBLOCK);
+
+    if (fd < 0) {
+        return handleSocketError(env, errno);
+    }
+
+    if (reuse) {
+        int arg = 1;
+        if (rs_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
+                       sizeof(arg)) < 0) {
+            JNU_ThrowByNameWithLastError(env,
+                    JNU_JAVANETPKG "SocketException",
+                    "Unable to set SO_REUSEADDR");
+            rs_close(fd);
+            return -1;
+        }
+    }
+    return fd;
+}
+
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaNet_bind0(JNIEnv *env, jclass clazz,
+        jobject fdo, jboolean preferIPv6, jobject iao, int port) {
+    SOCKETADDRESS sa;
+    int sa_len = 0;
+    int rv = 0;
+
+    if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len,
+            preferIPv6) != 0) {
+        return;
+    }
+
+    int fd = (*env)->GetIntField(env, fdo, fd_fdID);
+    rv = RDMA_Bind(fd, &sa, sa_len);
+    if (rv != 0) {
+        handleSocketError(env, errno);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaNet_listen(JNIEnv *env, jclass clazz,
+        jobject fdo, jint backlog) {
+    int fd = (*env)->GetIntField(env, fdo, fd_fdID);
+    if (rs_listen(fd, backlog) < 0)
+       handleSocketError(env, errno);
+}
+
+JNIEXPORT jint JNICALL
+Java_jdk_internal_net_rdma_RdmaNet_connect0(JNIEnv *env, jclass clazz,
+        jboolean preferIPv6, jobject fdo, jobject iao, jint port) {
+    SOCKETADDRESS sa;
+    int sa_len = 0;
+    int rv;
+
+    if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len,
+            preferIPv6) != 0) {
+        return IOS_THROWN;
+    }
+
+    int fd = (*env)->GetIntField(env, fdo, fd_fdID);
+
+    rv = rs_connect(fd, &sa.sa, sa_len);
+
+    if (rv != 0) {
+        if (errno == EINPROGRESS) {
+            return IOS_UNAVAILABLE;
+        } else if (errno == EINTR) {
+            return IOS_INTERRUPTED;
+        }
+        return handleSocketError(env, errno);
+    }
+    return 1;
+}
+
+JNIEXPORT jint JNICALL
+Java_jdk_internal_net_rdma_RdmaNet_localPort(JNIEnv *env, jclass clazz,
+        jobject fdo) {
+    SOCKETADDRESS sa;
+    socklen_t sa_len = sizeof(SOCKETADDRESS);
+    int fd = (*env)->GetIntField(env, fdo, fd_fdID);
+    if (rs_getsockname(fd, &sa.sa, &sa_len) < 0) {
+        handleSocketError(env, errno);
+        return -1;
+    }
+    return NET_GetPortFromSockaddr(&sa);
+}
+
+JNIEXPORT jobject JNICALL
+Java_jdk_internal_net_rdma_RdmaNet_localInetAddress(JNIEnv *env, jclass clazz,
+        jobject fdo) {
+    SOCKETADDRESS sa;
+    socklen_t sa_len = sizeof(SOCKETADDRESS);
+    int port;
+    int fd = (*env)->GetIntField(env, fdo, fd_fdID);
+    if (rs_getsockname(fd, &sa.sa, &sa_len) < 0) {
+        handleSocketError(env, errno);
+        return NULL;
+    }
+    return NET_SockaddrToInetAddress(env, &sa, &port);
+}
+
+JNIEXPORT jint JNICALL
+Java_jdk_internal_net_rdma_RdmaNet_getIntOption0(JNIEnv *env, jclass clazz,
+        jobject fdo, jboolean mayNeedConversion, jint level, jint opt) {
+    int result;
+    void *arg;
+    socklen_t arglen;
+    int n;
+
+    arg = (void *)&result;
+    arglen = sizeof(result);
+
+    int fd = (*env)->GetIntField(env, fdo, fd_fdID);
+
+    if (mayNeedConversion) {
+        n = RDMA_GetSockOpt(fd, level, opt, arg, (int*)&arglen);
+    } else {
+        n = rs_getsockopt(fd, level, opt, arg, &arglen);
+    }
+
+    if (n < 0) {
+        JNU_ThrowByNameWithLastError(env,
+                JNU_JAVANETPKG "SocketException",
+                "jdk.internal.net.rdma.RdmaNet.getIntOption");
+        return -1;
+    }
+
+    return (jint)result;
+}
+
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaNet_setIntOption0(JNIEnv *env, jclass clazz,
+        jobject fdo, jboolean mayNeedConversion, jint level, jint opt,
+        jint arg) {
+    int result;
+    void *parg;
+    socklen_t arglen;
+    int n;
+
+    parg = (void*)&arg;
+    arglen = sizeof(arg);
+
+    int fd = (*env)->GetIntField(env, fdo, fd_fdID);
+
+    if (mayNeedConversion) {
+        n = RDMA_SetSockOpt(fd, level, opt, parg, arglen);
+    } else {
+        n = rs_setsockopt(fd, level, opt, parg, arglen);
+    }
+    if (n < 0) {
+        JNU_ThrowByNameWithLastError(env,
+                JNU_JAVANETPKG "SocketException",
+                "jdk.internal.net.rdma.RdmaNet.setIntOption");
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaNet_shutdown(JNIEnv *env, jclass clazz,
+        jobject fdo, jint jhow) {
+    int how = (jhow == sun_nio_ch_Net_SHUT_RD) ? SHUT_RD :
+        (jhow == sun_nio_ch_Net_SHUT_WR) ? SHUT_WR : SHUT_RDWR;
+    int fd = (*env)->GetIntField(env, fdo, fd_fdID);
+    if ((rs_shutdown(fd, how) < 0) && (errno != ENOTCONN))
+        handleSocketError(env, errno);
+}
+
+JNIEXPORT jint JNICALL
+Java_jdk_internal_net_rdma_RdmaNet_poll(JNIEnv* env, jclass clazz,
+        jobject fdo, jint events, jlong timeout) {
+    struct pollfd pfd;
+    int rv;
+    pfd.fd = (*env)->GetIntField(env, fdo, fd_fdID);
+    pfd.events = events;
+    if (timeout < -1) {
+        timeout = -1;
+    } else if (timeout > INT_MAX) {
+        timeout = INT_MAX;
+    }
+    rv = rs_poll(&pfd, 1, (int)timeout);
+
+    if (rv >= 0) {
+        return pfd.revents;
+    } else if (errno == EINTR) {
+        // interrupted, no events to return
+        return 0;
+    } else {
+        handleSocketError(env, errno);
+        return IOS_THROWN;
+    }
+}
+
+jint handleSocketError(JNIEnv *env, jint errorValue) {
+    char *xn;
+    switch (errorValue) {
+        case EINPROGRESS:       /* Non-blocking connect */
+            return 0;
+#ifdef EPROTO
+        case EPROTO:
+            xn = JNU_JAVANETPKG "ProtocolException";
+            break;
+#endif
+        case ECONNREFUSED:
+        case ETIMEDOUT:
+        case ENOTCONN:
+            xn = JNU_JAVANETPKG "ConnectException";
+            break;
+
+        case EHOSTUNREACH:
+            xn = JNU_JAVANETPKG "NoRouteToHostException";
+            break;
+        case EADDRINUSE:  /* Fall through */
+        case EADDRNOTAVAIL:
+            xn = JNU_JAVANETPKG "BindException";
+            break;
+        default:
+            xn = JNU_JAVANETPKG "SocketException";
+            break;
+    }
+    errno = errorValue;
+    JNU_ThrowByNameWithLastError(env, xn, "NioSocketError");
+    return IOS_THROWN;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/native/libextnet/RdmaPollSelectorImpl.c	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018, 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 <Rsocket.h>
+#include "jni_util.h"
+#include "jvm.h"
+#include "nio.h"
+#include "jdk_internal_net_rdma_RdmaPollSelectorImpl.h"
+
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaPollSelectorImpl_init(JNIEnv *env,
+        jclass clazz) {
+    loadRdmaFuncs(env);
+}
+
+JNIEXPORT jint JNICALL
+Java_jdk_internal_net_rdma_RdmaPollSelectorImpl_poll0(JNIEnv *env,
+        jclass clazz, jlong address, jint numfds, jint timeout) {
+    struct pollfd *a;
+    int res;
+
+    a = (struct pollfd *) jlong_to_ptr(address);
+    res = rs_poll(a, numfds, timeout);
+    if (res < 0) {
+        if (errno == EINTR) {
+            return IOS_INTERRUPTED;
+        } else {
+            JNU_ThrowIOExceptionWithLastError(env, "poll failed");
+            return IOS_THROWN;
+        }
+    }
+    return (jint) res;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/native/libextnet/RdmaServerSocketChannelImpl.c	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2018, 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 "jdk_internal_net_rdma_RdmaServerSocketChannelImpl.h"
+#include "net_util.h"
+#include "nio.h"
+#include <Rsocket.h>
+
+static jfieldID fd_fdID;        /* java.io.FileDescriptor.fd */
+static jclass isa_class;        /* java.net.InetSocketAddress */
+static jmethodID isa_ctorID;    /*   .InetSocketAddress(InetAddress, int) */
+
+
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaServerSocketChannelImpl_initIDs(JNIEnv *env,
+        jclass c) {
+    loadRdmaFuncs(env);
+
+    jclass cls;
+
+    cls = (*env)->FindClass(env, "java/io/FileDescriptor");
+    CHECK_NULL(cls);
+    fd_fdID = (*env)->GetFieldID(env, cls, "fd", "I");
+    CHECK_NULL(fd_fdID);
+
+    cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
+    CHECK_NULL(cls);
+    isa_class = (*env)->NewGlobalRef(env, cls);
+    if (isa_class == NULL) {
+        JNU_ThrowOutOfMemoryError(env, NULL);
+        return;
+    }
+    isa_ctorID = (*env)->GetMethodID(env, cls, "<init>",
+                                     "(Ljava/net/InetAddress;I)V");
+    CHECK_NULL(isa_ctorID);
+}
+
+JNIEXPORT jint JNICALL
+Java_jdk_internal_net_rdma_RdmaServerSocketChannelImpl_checkAccept(JNIEnv *env,
+        jobject this, jobject fdo) {
+    jint fd = (*env)->GetIntField(env, fdo, fd_fdID);
+    int result = 0;
+    struct pollfd poller;
+
+    poller.fd = fd;
+    poller.events = POLLIN;
+    poller.revents = 0;
+
+    result = rs_poll(&poller, 1, -1);
+
+    if (result < 0) {
+        if (errno == EINTR) {
+            return IOS_INTERRUPTED;
+        } else {
+            JNU_ThrowIOExceptionWithLastError(env, "rpoll failed");
+            return IOS_THROWN;
+        }
+    }
+
+    if (poller.revents & poller.events) {
+        return 1;
+    }
+    return 0;
+}
+
+JNIEXPORT jint JNICALL
+Java_jdk_internal_net_rdma_RdmaServerSocketChannelImpl_accept0(JNIEnv *env,
+        jobject this, jobject ssfdo, jobject newfdo, jobjectArray isaa) {
+    jint ssfd = (*env)->GetIntField(env, ssfdo, fd_fdID);
+    jint newfd;
+    SOCKETADDRESS sa;
+    socklen_t sa_len = sizeof(SOCKETADDRESS);
+    jobject remote_ia = 0;
+    jobject isa;
+    jint remote_port = 0;
+
+    /*
+     * accept connection but ignore ECONNABORTED indicating that
+     * a connection was eagerly accepted but was reset before
+     * accept() was called.
+     */
+    for (;;) {
+        newfd = rs_accept(ssfd, &sa.sa, &sa_len);
+        if (newfd >= 0) {
+            break;
+        }
+        if (errno != ECONNABORTED) {
+            break;
+        }
+        /* ECONNABORTED => restart accept */
+    }
+
+    if (newfd < 0) {
+        if (errno == EAGAIN)
+            return IOS_UNAVAILABLE;
+        if (errno == EINTR)
+            return IOS_INTERRUPTED;
+        JNU_ThrowIOExceptionWithLastError(env, "Accept failed");
+        return IOS_THROWN;
+    }
+
+    (*env)->SetIntField(env, newfdo, fd_fdID, newfd);
+    remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port);
+    CHECK_NULL_RETURN(remote_ia, IOS_THROWN);
+    isa = (*env)->NewObject(env, isa_class, isa_ctorID,
+        remote_ia, remote_port);
+    CHECK_NULL_RETURN(isa, IOS_THROWN);
+    (*env)->SetObjectArrayElement(env, isaa, 0, isa);
+    return 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/native/libextnet/RdmaSocketChannelImpl.c	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2018, 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 "jdk_internal_net_rdma_RdmaSocketChannelImpl.h"
+#include "nio_util.h"
+#include "nio.h"
+#include <Rsocket.h>
+
+static jfieldID fd_fdID;
+
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaSocketChannelImpl_initIDs(JNIEnv *env,
+        jclass clazz) {
+    loadRdmaFuncs(env);
+    CHECK_NULL(clazz = (*env)->FindClass(env, "java/io/FileDescriptor"));
+    CHECK_NULL(fd_fdID = (*env)->GetFieldID(env, clazz, "fd", "I"));
+}
+
+jint fdVal(JNIEnv *env, jobject fdo) {
+    return (*env)->GetIntField(env, fdo, fd_fdID);
+}
+
+JNIEXPORT jint JNICALL
+Java_jdk_internal_net_rdma_RdmaSocketChannelImpl_checkConnect(JNIEnv *env,
+        jobject this, jobject fdo, jboolean block) {
+    int error = 0;
+    socklen_t n = sizeof(int);
+    jint fd = fdVal(env, fdo);
+    int result = 0;
+    struct pollfd poller;
+
+    poller.fd = fd;
+    poller.events = POLLOUT;
+    poller.revents = 0;
+
+    result = rs_poll(&poller, 1, block ? -1 : 0);
+
+    if (result < 0) {
+        if (errno == EINTR) {
+            return IOS_INTERRUPTED;
+        } else {
+            JNU_ThrowIOExceptionWithLastError(env, "rpoll failed");
+            return IOS_THROWN;
+        }
+    }
+    if (!block && (result == 0))
+        return IOS_UNAVAILABLE;
+
+    if (result > 0) {
+        errno = 0;
+        result = rs_getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &n);
+        if (result < 0) {
+            return handleSocketError(env, errno);
+        } else if (error) {
+            return handleSocketError(env, error);
+        } else if ((poller.revents & POLLHUP) != 0) {
+            return handleSocketError(env, ENOTCONN);
+        }
+        // connected
+        return 1;
+    }
+    return 0;
+}
+
+JNIEXPORT jint JNICALL
+Java_jdk_internal_net_rdma_RdmaSocketChannelImpl_sendOutOfBandData(JNIEnv* env,
+        jclass this, jobject fdo, jbyte b) {
+    int n = rs_send(fdVal(env, fdo), (const void*)&b, 1, MSG_OOB);
+    return convertReturnVal(env, n, JNI_FALSE);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/native/libextnet/RdmaSocketImpl.c	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,711 @@
+/*
+ * Copyright (c) 2018, 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 "java_net_SocketOptions.h"
+#include "jdk_internal_net_rdma_RdmaSocketImpl.h"
+#include "jvm.h"
+#include "net_util.h"
+#include "rdma_util_md.h"
+#include "Rsocket.h"
+
+/************************************************************************
+ * RdmaSocketImpl
+ */
+
+static jfieldID IO_fd_fdID;
+
+jfieldID psi_fdID;
+jfieldID psi_addressID;
+jfieldID psi_ipaddressID;
+jfieldID psi_portID;
+jfieldID psi_localportID;
+jfieldID psi_timeoutID;
+jfieldID psi_trafficClassID;
+jfieldID psi_serverSocketID;
+jfieldID psi_fdLockID;
+jfieldID psi_closePendingID;
+
+#define SET_NONBLOCKING(fd) {           \
+        int flags = rs_fcntl(fd, F_GETFL); \
+        flags |= O_NONBLOCK;            \
+        rs_fcntl(fd, F_SETFL, flags);      \
+}
+
+#define SET_BLOCKING(fd) {              \
+        int flags = rs_fcntl(fd, F_GETFL); \
+        flags &= ~O_NONBLOCK;           \
+        rs_fcntl(fd, F_SETFL, flags);      \
+}
+
+static jclass socketExceptionCls;
+
+static int getFD(JNIEnv *env, jobject this) {
+    jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
+    CHECK_NULL_RETURN(fdObj, -1);
+    return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+}
+
+
+jfieldID
+NET_GetFileDescriptorID(JNIEnv *env) {
+    jclass cls = (*env)->FindClass(env, "java/io/FileDescriptor");
+    CHECK_NULL_RETURN(cls, NULL);
+    return (*env)->GetFieldID(env, cls, "fd", "I");
+}
+
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaSocketImpl_initProto(JNIEnv *env,
+        jclass cls) {
+    loadRdmaFuncs(env);
+
+    jclass clazz = (*env)->FindClass(env,
+            "jdk/internal/net/rdma/RdmaSocketImpl");
+    psi_fdID = (*env)->GetFieldID(env, clazz , "fd",
+            "Ljava/io/FileDescriptor;");
+    CHECK_NULL(psi_fdID);
+    psi_addressID = (*env)->GetFieldID(env, clazz, "address",
+            "Ljava/net/InetAddress;");
+    CHECK_NULL(psi_addressID);
+    psi_timeoutID = (*env)->GetFieldID(env, clazz, "timeout", "I");
+    CHECK_NULL(psi_timeoutID);
+    psi_trafficClassID = (*env)->GetFieldID(env, clazz, "trafficClass", "I");
+    CHECK_NULL(psi_trafficClassID);
+    psi_portID = (*env)->GetFieldID(env, clazz, "port", "I");
+    CHECK_NULL(psi_portID);
+    psi_localportID = (*env)->GetFieldID(env, clazz, "localport", "I");
+    CHECK_NULL(psi_localportID);
+    psi_serverSocketID = (*env)->GetFieldID(env, clazz, "serverSocket",
+                        "Ljava/net/ServerSocket;");
+    CHECK_NULL(psi_serverSocketID);
+
+    IO_fd_fdID = NET_GetFileDescriptorID(env);
+    CHECK_NULL(IO_fd_fdID);
+
+    initInetAddressIDs(env);
+    JNU_CHECK_EXCEPTION(env);
+}
+
+JNIEXPORT jboolean JNICALL
+Java_jdk_internal_net_rdma_RdmaSocketImpl_isRdmaAvailable0(JNIEnv *env,
+        jclass cls) {
+    return rdma_supported();
+}
+
+void
+NET_SetTrafficClass(SOCKETADDRESS *sa, int trafficClass) {
+    if (sa->sa.sa_family == AF_INET6) {
+        sa->sa6.sin6_flowinfo = htonl((trafficClass & 0xff) << 20);
+    }
+}
+
+/*
+ * Class:     jdk_net_RdmaSocketImpl
+ * Method:    rdmaSocketCreate
+ * Signature: (Z)V */
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaSocketImpl_rdmaSocketCreate(JNIEnv *env,
+        jclass cls, jboolean preferIPv6, jboolean stream) {
+    jobject fdObj, ssObj;
+    int fd;
+    int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
+    int domain = (ipv6_available() && preferIPv6) ? AF_INET6 : AF_INET;
+
+    if (socketExceptionCls == NULL) {
+        jclass c = (*env)->FindClass(env, "java/net/SocketException");
+        CHECK_NULL(c);
+        socketExceptionCls = (jclass)(*env)->NewGlobalRef(env, c);
+        CHECK_NULL(socketExceptionCls);
+    }
+
+    fdObj = (*env)->GetObjectField(env, cls, psi_fdID);
+
+    if (fdObj == NULL) {
+        (*env)->ThrowNew(env, socketExceptionCls, "null fd object");
+        return;
+    }
+
+    if ((fd = rs_socket(domain, type, 0)) == -1) {
+        NET_ThrowNew(env, errno, "can't create socket");
+        return;
+    }
+    if (domain == AF_INET6) {
+        int arg = 0;
+        if (rs_setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
+                       sizeof(int)) < 0) {
+            NET_ThrowNew(env, errno, "cannot set IPPROTO_IPV6");
+            rs_close(fd);
+            return;
+        }
+    }
+
+    ssObj = (*env)->GetObjectField(env, cls, psi_serverSocketID);
+    if (ssObj != NULL) {
+        int arg = 1;
+        SET_NONBLOCKING(fd);
+        if (RDMA_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
+                       sizeof(arg)) < 0) {
+            NET_ThrowNew(env, errno, "cannot set SO_REUSEADDR");
+            rs_close(fd);
+            return;
+        }
+    }
+    (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
+}
+
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaSocketImpl_rdmaSocketConnect(JNIEnv *env,
+        jclass cls, jboolean preferIPv6, jobject iaObj, jint port,
+        jint timeout) {
+    jint localport = (*env)->GetIntField(env, cls, psi_localportID);
+    int len = 0;
+    jobject fdObj = (*env)->GetObjectField(env, cls, psi_fdID);
+
+    jobject fdLock;
+
+    jint trafficClass = (*env)->GetIntField(env, cls, psi_trafficClassID);
+
+    jint fd;
+
+    SOCKETADDRESS sa;
+    int connect_rv = -1;
+
+    if (IS_NULL(fdObj)) {
+        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+        return;
+    } else {
+        fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+    }
+    if (IS_NULL(iaObj)) {
+        JNU_ThrowNullPointerException(env, "inet address argument null.");
+        return;
+    }
+
+    if (NET_InetAddressToSockaddr(env, iaObj, port, &sa, &len,
+            preferIPv6) != 0) {
+        return;
+    }
+
+    if (trafficClass != 0 && ipv6_available()) {
+        NET_SetTrafficClass(&sa, trafficClass);
+    }
+
+    if (timeout <= 0) {
+        connect_rv = RDMA_Connect(fd, &sa.sa, len);
+    } else {
+        SET_NONBLOCKING(fd);
+
+        connect_rv = rs_connect(fd, &sa.sa, len);
+
+        if (connect_rv != 0) {
+            socklen_t optlen;
+            jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
+            jlong prevNanoTime = JVM_NanoTime(env, 0);
+
+            if (errno != EINPROGRESS) {
+                JNU_ThrowByNameWithMessageAndLastError(env,
+                        JNU_JAVANETPKG "ConnectException", "connect failed");
+                SET_BLOCKING(fd);
+                return;
+            }
+
+            while (1) {
+                jlong newNanoTime;
+                struct pollfd pfd;
+                pfd.fd = fd;
+                pfd.events = POLLOUT;
+
+                errno = 0;
+
+                connect_rv = RDMA_Poll(&pfd, 1, nanoTimeout / NET_NSEC_PER_MSEC);
+
+                if (connect_rv >= 0) {
+                    break;
+                }
+                if (errno != EINTR) {
+                    break;
+                }
+
+                newNanoTime = JVM_NanoTime(env, 0);
+                nanoTimeout -= (newNanoTime - prevNanoTime);
+                if (nanoTimeout < NET_NSEC_PER_MSEC) {
+                    connect_rv = 0;
+                    break;
+                }
+                prevNanoTime = newNanoTime;
+
+            }
+
+            if (connect_rv == 0) {
+                JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
+                        "connect timed out");
+
+                SET_BLOCKING(fd);
+                rs_shutdown(fd, 2);
+                return;
+            }
+
+            optlen = sizeof(connect_rv);
+            if (rs_getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
+                            &optlen) <0) {
+                connect_rv = errno;
+            }
+        }
+
+        SET_BLOCKING(fd);
+
+        if (connect_rv != 0) {
+            errno = connect_rv;
+            connect_rv = -1;
+        }
+    }
+
+    if (connect_rv < 0) {
+        if (connect_rv == -1 && errno == EINVAL) {
+            JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+                "Invalid argument or cannot assign requested address");
+            return;
+        }
+#if defined(EPROTO)
+        if (errno == EPROTO) {
+            JNU_ThrowByNameWithMessageAndLastError(env,
+                    JNU_JAVANETPKG "ProtocolException", "Protocol error");
+            return;
+        }
+#endif
+        if (errno == ECONNREFUSED) {
+            JNU_ThrowByNameWithMessageAndLastError(env,
+                    JNU_JAVANETPKG "ConnectException", "Connection refused");
+        } else if (errno == ETIMEDOUT) {
+            JNU_ThrowByNameWithMessageAndLastError(env,
+                    JNU_JAVANETPKG "ConnectException", "Connection timed out");
+        } else if (errno == EHOSTUNREACH) {
+            JNU_ThrowByNameWithMessageAndLastError(env,
+                    JNU_JAVANETPKG "NoRouteToHostException", "Host unreachable");
+        } else if (errno == EADDRNOTAVAIL) {
+            JNU_ThrowByNameWithMessageAndLastError(env,
+                    JNU_JAVANETPKG "NoRouteToHostException",
+                    "Address not available");
+        } else if ((errno == EISCONN) || (errno == EBADF)) {
+            JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+                    "Socket closed");
+        } else {
+            JNU_ThrowByNameWithMessageAndLastError(env,
+                    JNU_JAVANETPKG "SocketException", "connect failed");
+        }
+        return;
+    }
+
+    (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
+
+    (*env)->SetObjectField(env, cls, psi_addressID, iaObj);
+    (*env)->SetIntField(env, cls, psi_portID, port);
+
+    if (localport == 0) {
+        socklen_t slen = sizeof(SOCKETADDRESS);
+        if (rs_getsockname(fd, &sa.sa, &slen) == -1) {
+            JNU_ThrowByNameWithMessageAndLastError(env,
+                    JNU_JAVANETPKG "SocketException",
+                    "Error getting socket name");
+        } else {
+            localport = NET_GetPortFromSockaddr(&sa);
+            (*env)->SetIntField(env, cls, psi_localportID, localport);
+        }
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaSocketImpl_rdmaSocketBind(JNIEnv *env,
+        jclass cls, jboolean preferIPv6, jobject iaObj, jint localport) {
+    jobject fdObj = (*env)->GetObjectField(env, cls, psi_fdID);
+    int fd;
+    int len = 0;
+    SOCKETADDRESS sa;
+
+    if (IS_NULL(fdObj)) {
+        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+                        "Socket closed");
+        return;
+    } else {
+        fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+    }
+    if (IS_NULL(iaObj)) {
+        JNU_ThrowNullPointerException(env, "iaObj is null.");
+        return;
+    }
+
+    if (NET_InetAddressToSockaddr(env, iaObj, localport, &sa,
+                                  &len, preferIPv6) != 0) {
+        return;
+    }
+
+    if (RDMA_Bind(fd, &sa, len) < 0) {
+        if (errno == EADDRINUSE || errno == EADDRNOTAVAIL ||
+            errno == EPERM || errno == EACCES) {
+            JNU_ThrowByNameWithMessageAndLastError(env,
+                    JNU_JAVANETPKG "BindException", "Bind failed");
+        } else {
+            JNU_ThrowByNameWithMessageAndLastError(env,
+                    JNU_JAVANETPKG "SocketException", "Bind failed");
+        }
+        return;
+    }
+    (*env)->SetObjectField(env, cls, psi_addressID, iaObj);
+
+    if (localport == 0) {
+        socklen_t slen = sizeof(SOCKETADDRESS);
+        if (rs_getsockname(fd, &sa.sa, &slen) == -1) {
+            JNU_ThrowByNameWithMessageAndLastError(env,
+                    JNU_JAVANETPKG "SocketException",
+                    "Error getting socket name");
+            return;
+        }
+        localport = NET_GetPortFromSockaddr(&sa);
+        (*env)->SetIntField(env, cls, psi_localportID, localport);
+    } else {
+        (*env)->SetIntField(env, cls, psi_localportID, localport);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaSocketImpl_rdmaSocketListen(JNIEnv *env,
+        jclass cls, jint count) {
+    jobject fdObj = (*env)->GetObjectField(env, cls, psi_fdID);
+    int fd;
+
+    if (IS_NULL(fdObj)) {
+        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+                "Socket closed");
+        return;
+    } else {
+        fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+    }
+
+    if (count == 0x7fffffff)
+        count -= 1;
+
+    int rv = rs_listen(fd, count);
+    if (rv == -1) {
+        JNU_ThrowByNameWithMessageAndLastError(env,
+                JNU_JAVANETPKG "SocketException", "Listen failed");
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaSocketImpl_rdmaSocketAccept(JNIEnv *env,
+        jclass cls, jobject socket) {
+    int port;
+    jint timeout = (*env)->GetIntField(env, cls, psi_timeoutID);
+    jlong prevNanoTime = 0;
+    jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
+    jobject fdObj = (*env)->GetObjectField(env, cls, psi_fdID);
+
+    jobject socketFdObj;
+    jobject socketAddressObj;
+
+    jint fd;
+
+    jint newfd;
+
+    SOCKETADDRESS sa;
+    socklen_t slen = sizeof(SOCKETADDRESS);
+
+    if (IS_NULL(fdObj)) {
+        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+                "Socket closed");
+        return;
+    } else {
+        fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+    }
+    if (IS_NULL(socket)) {
+        JNU_ThrowNullPointerException(env, "socket is null");
+        return;
+    }
+
+    for (;;) {
+        int ret;
+        jlong currNanoTime;
+
+        if (prevNanoTime == 0 && nanoTimeout > 0) {
+            prevNanoTime = JVM_NanoTime(env, 0);
+        }
+
+        if (timeout <= 0) {
+            ret = RDMA_Timeout(env, fd, -1, 0);
+        } else {
+            ret = RDMA_Timeout(env, fd, nanoTimeout / NET_NSEC_PER_MSEC,
+                    prevNanoTime);
+        }
+
+        if (ret == 0) {
+            JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
+                    "Accept timed out");
+            return;
+        } else if (ret == -1) {
+            if (errno == EBADF) {
+               JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+                       "Socket closed");
+            } else if (errno == ENOMEM) {
+               JNU_ThrowOutOfMemoryError(env,
+                       "NET_Timeout native heap allocation failed");
+            } else {
+               JNU_ThrowByNameWithMessageAndLastError(env,
+                       JNU_JAVANETPKG "SocketException", "Accept failed");
+            }
+            return;
+        }
+
+        newfd = RDMA_Accept(fd, &sa.sa, &slen);
+
+        if (newfd >= 0) {
+            SET_BLOCKING(newfd);
+            break;
+        }
+
+        if (!(errno == ECONNABORTED || errno == EWOULDBLOCK)) {
+            break;
+        }
+
+        if (nanoTimeout >= NET_NSEC_PER_MSEC) {
+            currNanoTime = JVM_NanoTime(env, 0);
+            nanoTimeout -= (currNanoTime - prevNanoTime);
+            if (nanoTimeout < NET_NSEC_PER_MSEC) {
+                JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
+                        "Accept timed out");
+                return;
+            }
+            prevNanoTime = currNanoTime;
+        }
+    }
+
+    if (newfd < 0) {
+        if (newfd == -2) {
+            JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
+                    "operation interrupted");
+        } else {
+            if (errno == EINVAL) {
+                errno = EBADF;
+            }
+            if (errno == EBADF) {
+                JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+                        "Socket closed");
+            } else {
+                JNU_ThrowByNameWithMessageAndLastError(env,
+                        JNU_JAVANETPKG "SocketException", "Accept failed");
+            }
+        }
+        return;
+    }
+
+    socketAddressObj = NET_SockaddrToInetAddress(env, &sa, &port);
+    if (socketAddressObj == NULL) {
+        rs_close(newfd);
+        return;
+    }
+
+    socketFdObj = (*env)->GetObjectField(env, socket, psi_fdID);
+    (*env)->SetIntField(env, socketFdObj, IO_fd_fdID, newfd);
+    (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj);
+    (*env)->SetIntField(env, socket, psi_portID, port);
+    port = (*env)->GetIntField(env, cls, psi_localportID);
+    (*env)->SetIntField(env, socket, psi_localportID, port);
+}
+
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaSocketImpl_rdmaSocketClose(JNIEnv *env,
+        jclass cls) {
+    jobject fdObj = (*env)->GetObjectField(env, cls, psi_fdID);
+    jint fd;
+
+    if (IS_NULL(fdObj)) {
+        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+                "socket already closed");
+        return;
+    } else {
+        fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+    }
+    if (fd != -1) {
+        (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1);
+        RDMA_SocketClose(fd);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaSocketImpl_rdmaSocketShutdown(JNIEnv *env,
+        jclass cls, jint howto) {
+    jobject fdObj = (*env)->GetObjectField(env, cls, psi_fdID);
+    jint fd;
+
+    if (IS_NULL(fdObj)) {
+        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+                "socket already closed");
+        return;
+    } else {
+        fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+    }
+    rs_shutdown(fd, howto);
+}
+
+
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaSocketImpl_rdmaSocketSetOption(JNIEnv *env,
+        jclass cls, jint cmd, jboolean on, jobject value) {
+    int fd;
+    int level, optname, optlen;
+    union {
+        int i;
+        struct linger ling;
+    } optval;
+
+    fd = getFD(env, cls);
+    if (fd < 0) {
+        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+                "Socket closed");
+        return;
+    }
+
+    if (cmd == java_net_SocketOptions_SO_TIMEOUT) {
+        return;
+    }
+
+    if (RDMA_MapSocketOption(cmd, &level, &optname)) {
+        JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
+        return;
+    }
+
+    switch (cmd) {
+        case java_net_SocketOptions_SO_SNDBUF :
+        case java_net_SocketOptions_SO_RCVBUF :
+            {
+                jclass cls;
+                jfieldID fid;
+
+                cls = (*env)->FindClass(env, "java/lang/Integer");
+                CHECK_NULL(cls);
+                fid = (*env)->GetFieldID(env, cls, "value", "I");
+                CHECK_NULL(fid);
+
+                optval.i = (*env)->GetIntField(env, value, fid);
+                optlen = sizeof(optval.i);
+                break;
+            }
+        default :
+            optval.i = (on ? 1 : 0);
+            optlen = sizeof(optval.i);
+
+    }
+    if (RDMA_SetSockOpt(fd, level, optname, (const void *)&optval, optlen) < 0) {
+        JNU_ThrowByNameWithMessageAndLastError(env,
+                JNU_JAVANETPKG "SocketException", "Error setting socket option");
+    }
+}
+
+JNIEXPORT jint JNICALL
+Java_jdk_internal_net_rdma_RdmaSocketImpl_rdmaSocketGetOption(JNIEnv *env,
+        jclass cls, jint cmd, jobject iaContainerObj) {
+    int fd;
+    int level, optname, optlen;
+    union {
+        int i;
+        struct linger ling;
+    } optval;
+
+    fd = getFD(env, cls);
+    if (fd < 0) {
+        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+                "Socket closed");
+        return -1;
+    }
+
+    if (cmd == java_net_SocketOptions_SO_BINDADDR) {
+        SOCKETADDRESS sa;
+        socklen_t len = sizeof(SOCKETADDRESS);
+        int port;
+        jobject iaObj;
+        jclass iaCntrClass;
+        jfieldID iaFieldID;
+
+        if (rs_getsockname(fd, &sa.sa, &len) < 0) {
+            JNU_ThrowByNameWithMessageAndLastError(env,
+                    JNU_JAVANETPKG "SocketException",
+                    "Error getting socket name");
+            return -1;
+        }
+        iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
+        CHECK_NULL_RETURN(iaObj, -1);
+
+        iaCntrClass = (*env)->GetObjectClass(env, iaContainerObj);
+        iaFieldID = (*env)->GetFieldID(env, iaCntrClass,
+                "addr", "Ljava/net/InetAddress;");
+        CHECK_NULL_RETURN(iaFieldID, -1);
+        (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);
+        return 0;
+    }
+
+    if (RDMA_MapSocketOption(cmd, &level, &optname)) {
+        JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
+        return -1;
+    }
+
+    optlen = sizeof(optval.i);
+
+    if (RDMA_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) {
+        JNU_ThrowByNameWithMessageAndLastError(env,
+        JNU_JAVANETPKG "SocketException", "Error getting socket option");
+        return -1;
+    }
+
+    switch (cmd) {
+        case java_net_SocketOptions_SO_SNDBUF:
+        case java_net_SocketOptions_SO_RCVBUF:
+            return optval.i;
+
+        default :
+            return (optval.i == 0) ? -1 : 1;
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaSocketImpl_rdmaSocketSendUrgentData(
+        JNIEnv *env, jclass cls, jint data) {
+    jobject fdObj = (*env)->GetObjectField(env, cls, psi_fdID);
+    int n, fd;
+    unsigned char d = data & 0xFF;
+
+    if (IS_NULL(fdObj)) {
+        JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
+        return;
+    } else {
+        fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+        if (fd == -1) {
+            JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
+            return;
+        }
+
+    }
+    n = RDMA_Send(fd, (char *)&d, 1, MSG_OOB);
+    if (n == -1) {
+        JNU_ThrowIOExceptionWithLastError(env, "Write failed");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/native/libextnet/RdmaSocketInputStream.c	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2018, 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 <stdlib.h>
+#include "jvm.h"
+#include "net_util.h"
+#include "rdma_util_md.h"
+#include "jdk_internal_net_rdma_RdmaSocketInputStream.h"
+
+static jfieldID IO_fd_fdID;
+
+/*
+ * Class:     jdk_net_RdmaSocketInputStream
+ * Method:    init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaSocketInputStream_init(JNIEnv *env, jclass cls) {
+    IO_fd_fdID = NET_GetFileDescriptorID(env);
+}
+
+static int RDMA_ReadWithTimeout(JNIEnv *env, int fd, char *bufP, int len,
+        long timeout) {
+    int result = 0;
+    jlong prevNanoTime = JVM_NanoTime(env, 0);
+    jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
+    while (nanoTimeout >= NET_NSEC_PER_MSEC) {
+        result = RDMA_Timeout(env, fd, nanoTimeout / NET_NSEC_PER_MSEC,
+                prevNanoTime);
+        if (result <= 0) {
+            if (result == 0) {
+                JNU_ThrowByName(env, "java/net/SocketTimeoutException",
+                        "Read timed out");
+            } else if (result == -1) {
+                if (errno == EBADF) {
+                    JNU_ThrowByName(env, "java/net/SocketException",
+                            "Socket closed");
+                } else if (errno == ENOMEM) {
+                    JNU_ThrowOutOfMemoryError
+                            (env, "NET_Timeout native heap allocation failed");
+                } else {
+                    JNU_ThrowByNameWithMessageAndLastError
+                            (env, "java/net/SocketException", "select/poll failed");
+                }
+            }
+            return -1;
+        }
+        result = RDMA_NonBlockingRead(fd, bufP, len);
+        if (result == -1 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) {
+            jlong newtNanoTime = JVM_NanoTime(env, 0);
+            nanoTimeout -= newtNanoTime - prevNanoTime;
+            if (nanoTimeout >= NET_NSEC_PER_MSEC) {
+                prevNanoTime = newtNanoTime;
+            }
+        } else {
+            break;
+        }
+    }
+    return result;
+}
+
+/*
+ * Class:     jdk_net_RdmaSocketInputStream
+ * Method:    rdmaSocketRead0
+ * Signature: (Ljava/io/FileDescriptor;[BIII)I
+ */
+JNIEXPORT jint JNICALL
+Java_jdk_internal_net_rdma_RdmaSocketInputStream_rdmaSocketRead0(JNIEnv *env,
+        jobject this, jobject fdObj, jbyteArray data,
+        jint off, jint len, jint timeout) {
+    char BUF[MAX_BUFFER_LEN];
+    char *bufP;
+    jint fd, nread;
+
+    if (IS_NULL(fdObj)) {
+        JNU_ThrowByName(env, "java/net/SocketException",
+                        "Socket closed");
+        return -1;
+    }
+    fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+    if (fd == -1) {
+        JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
+        return -1;
+    }
+
+    if (len > MAX_BUFFER_LEN) {
+        if (len > MAX_HEAP_BUFFER_LEN) {
+            len = MAX_HEAP_BUFFER_LEN;
+        }
+        bufP = (char *)malloc((size_t)len);
+        if (bufP == NULL) {
+            bufP = BUF;
+            len = MAX_BUFFER_LEN;
+        }
+    } else {
+        bufP = BUF;
+    }
+    if (timeout) {
+        nread = RDMA_ReadWithTimeout(env, fd, bufP, len, timeout);
+        if ((*env)->ExceptionCheck(env)) {
+            if (bufP != BUF) {
+                free(bufP);
+            }
+            return nread;
+        }
+    } else {
+        nread = RDMA_Read(fd, bufP, len);
+    }
+
+    if (nread <= 0) {
+        if (nread < 0) {
+
+            switch (errno) {
+                case ECONNRESET:
+                case EPIPE:
+                    JNU_ThrowByName(env, "sun/net/ConnectionResetException",
+                        "Connection reset");
+                    break;
+
+                case EBADF:
+                    JNU_ThrowByName(env, "java/net/SocketException",
+                        "Socket closed");
+                    break;
+
+                case EINTR:
+                     JNU_ThrowByName(env, "java/io/InterruptedIOException",
+                           "Operation interrupted");
+                     break;
+                default:
+                    JNU_ThrowByNameWithMessageAndLastError
+                        (env, "java/net/SocketException", "Read failed");
+            }
+        }
+    } else {
+        (*env)->SetByteArrayRegion(env, data, off, nread, (jbyte *)bufP);
+    }
+
+    if (bufP != BUF) {
+        free(bufP);
+    }
+    return nread;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/native/libextnet/RdmaSocketOutputStream.c	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2018, 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 <stdlib.h>
+#include "net_util.h"
+#include "rdma_util_md.h"
+#include "jdk_internal_net_rdma_RdmaSocketOutputStream.h"
+
+#define min(a, b)       ((a) < (b) ? (a) : (b))
+
+static jfieldID IO_fd_fdID;
+
+/*
+ * Class:     jdk_net_SocketOutputStream
+ * Method:    init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaSocketOutputStream_init(JNIEnv *env,
+        jclass cls) {
+    IO_fd_fdID = NET_GetFileDescriptorID(env);
+}
+
+/*
+ * Class:     jdk_net_RdmaSocketOutputStream
+ * Method:    rdmaSocketWrite0
+ * Signature: (Ljava/io/FileDescriptor;[BII)V
+ */
+JNIEXPORT void JNICALL
+Java_jdk_internal_net_rdma_RdmaSocketOutputStream_rdmaSocketWrite0(JNIEnv *env,
+        jobject this, jobject fdObj, jbyteArray data, jint off, jint len) {
+    char *bufP;
+    char BUF[MAX_BUFFER_LEN];
+    int buflen;
+    int fd;
+
+    if (IS_NULL(fdObj)) {
+        JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
+        return;
+    } else {
+        fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+        if (fd == -1) {
+            JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
+            return;
+        }
+    }
+
+    if (len <= MAX_BUFFER_LEN) {
+        bufP = BUF;
+        buflen = MAX_BUFFER_LEN;
+    } else {
+        buflen = min(MAX_HEAP_BUFFER_LEN, len);
+        bufP = (char *)malloc((size_t)buflen);
+
+        if (bufP == NULL) {
+            bufP = BUF;
+            buflen = MAX_BUFFER_LEN;
+        }
+    }
+
+    while(len > 0) {
+        int loff = 0;
+        int chunkLen = min(buflen, len);
+        int llen = chunkLen;
+        (*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP);
+
+        if ((*env)->ExceptionCheck(env)) {
+            break;
+        } else {
+            while(llen > 0) {
+                int n = RDMA_Send(fd, bufP + loff, llen, 0);
+                if (n > 0) {
+                    llen -= n;
+                    loff += n;
+                    continue;
+                }
+                if (errno == ECONNRESET) {
+                    JNU_ThrowByName(env, "sun/net/ConnectionResetException",
+                            "Connection reset");
+                } else {
+                    JNU_ThrowByNameWithMessageAndLastError
+                        (env, "java/net/SocketException", "Write failed");
+                }
+                if (bufP != BUF) {
+                    free(bufP);
+                }
+                return;
+            }
+            len -= chunkLen;
+            off += chunkLen;
+        }
+    }
+
+    if (bufP != BUF) {
+        free(bufP);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/native/libextnet/Rsocket.c	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2018, 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 <Rsocket.h>
+#include <dlfcn.h>
+#include "jni_util.h"
+
+static const char* nativeRdmaLib = "librdmacm.so.1";
+static jboolean funcs_loaded = JNI_FALSE;
+ 
+jboolean loadRdmaFuncs(JNIEnv* env) {
+    if (funcs_loaded)
+        return JNI_TRUE;
+
+    if (dlopen(nativeRdmaLib, RTLD_GLOBAL | RTLD_LAZY) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
+    if ((rs_socket = (rs_rsocket_func*)
+            dlsym(RTLD_DEFAULT, "rsocket")) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
+    if ((rs_fcntl = (rs_rfcntl_func*)
+            dlsym(RTLD_DEFAULT, "rfcntl")) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
+    if ((rs_listen = (rs_rlisten_func*)
+            dlsym(RTLD_DEFAULT, "rlisten")) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
+    if ((rs_bind = (rs_rbind_func*)
+            dlsym(RTLD_DEFAULT, "rbind")) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
+    if ((rs_connect = (rs_rconnect_func*)
+            dlsym(RTLD_DEFAULT, "rconnect")) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
+    if ((rs_getsockname = (rs_rgetsockname_func*)
+            dlsym(RTLD_DEFAULT, "rgetsockname")) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
+    if ((rs_getsockopt = (rs_rgetsockopt_func*)
+            dlsym(RTLD_DEFAULT, "rgetsockopt")) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
+    if ((rs_setsockopt = (rs_rsetsockopt_func*)
+            dlsym(RTLD_DEFAULT, "rsetsockopt")) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
+    if ((rs_shutdown = (rs_rshutdown_func*)
+            dlsym(RTLD_DEFAULT, "rshutdown")) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
+    if ((rs_poll = (rs_rpoll_func*)
+            dlsym(RTLD_DEFAULT, "rpoll")) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
+    if ((rs_send = (rs_rsend_func*)
+            dlsym(RTLD_DEFAULT, "rsend")) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
+    if ((rs_accept = (rs_raccept_func*)
+            dlsym(RTLD_DEFAULT, "raccept")) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
+    if ((rs_close = (rs_rclose_func*)
+            dlsym(RTLD_DEFAULT, "rclose")) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
+    if ((rs_read = (rs_rread_func*)
+            dlsym(RTLD_DEFAULT, "rread")) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
+    if ((rs_readv = (rs_rreadv_func*)
+            dlsym(RTLD_DEFAULT, "rreadv")) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
+    if ((rs_write = (rs_rwrite_func*)
+            dlsym(RTLD_DEFAULT, "rwrite")) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
+    if ((rs_writev = (rs_rwritev_func*)
+            dlsym(RTLD_DEFAULT, "rwritev")) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
+    if ((rs_recv = (rs_rrecv_func*)
+            dlsym(RTLD_DEFAULT, "rrecv")) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
+    if ((rs_recvfrom = (rs_rrecvfrom_func*)
+            dlsym(RTLD_DEFAULT, "rrecvfrom")) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
+    if ((rs_sendto = (rs_rsendto_func*)
+            dlsym(RTLD_DEFAULT, "rsendto")) == NULL) {
+        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+              dlerror());
+        return JNI_FALSE;
+    }
+
+    funcs_loaded = JNI_TRUE;
+    return JNI_TRUE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/native/libextnet/Rsocket.h	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2018, 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 <sys/socket.h>
+#include <poll.h>
+#include "jni.h"
+
+/* Function types to support dynamic linking of socket API extension functions
+ * for RDMA. This is so that there is no linkage depandancy during build or
+ * runtime for librdmacm.*/
+typedef int rs_rsocket_func(int domain, int type, int protocol);
+typedef int rs_rfcntl_func(int fd, int cmd, ... /* arg */ );
+typedef int rs_rlisten_func(int sockfd, int backlog);
+typedef int rs_rbind_func(int sockfd, const struct sockaddr *addr,
+        socklen_t addrlen);
+typedef int rs_rconnect_func(int sockfd, const struct sockaddr *addr,
+        socklen_t addlen);
+typedef int rs_rgetsockname_func(int sockfd, struct sockaddr *addr,
+        socklen_t *addrlen);
+typedef int rs_rgetsockopt_func(int sockfd, int level, int optname,
+        void *optval, socklen_t *optlen);
+typedef int rs_rsetsockopt_func(int sockfd, int level, int optname,
+        const void *optval, socklen_t optlen);
+typedef int rs_rshutdown_func(int sockfd, int how);
+typedef int rs_rpoll_func(struct pollfd *fds, nfds_t nfds, int timeout);
+typedef size_t rs_rsend_func(int sockfd, const void *buf, size_t len,
+        int flags);
+typedef int rs_raccept_func(int sockfd, struct sockaddr *addr,
+        socklen_t *addrlen);
+typedef int rs_rclose_func(int sockfd);
+typedef ssize_t rs_rread_func(int sockfd, void *buf, size_t count);
+typedef ssize_t rs_rreadv_func(int sockfd, const struct iovec *iov,
+        int iovcnt);
+typedef ssize_t rs_rwrite_func(int sockfd, const void *buf, size_t count);
+typedef ssize_t rs_rwritev_func(int sockfd, const struct iovec *iov,
+        int iovcnt);
+typedef ssize_t rs_rrecv_func(int sockfd, void *buf, size_t len, int flags);
+typedef ssize_t rs_rrecvfrom_func(int sockfd, void *buf, size_t len, int flags,
+        struct sockaddr *src_addr, socklen_t *addrlen);
+typedef ssize_t rs_rsendto_func(int sockfd, const void *buf, size_t len,
+        int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
+
+rs_rsocket_func* rs_socket;
+rs_rfcntl_func* rs_fcntl;
+rs_rlisten_func* rs_listen;
+rs_rbind_func* rs_bind;
+rs_rconnect_func* rs_connect;
+rs_rgetsockname_func* rs_getsockname;
+rs_rgetsockopt_func* rs_getsockopt;
+rs_rsetsockopt_func* rs_setsockopt;
+rs_rshutdown_func* rs_shutdown;
+rs_rpoll_func* rs_poll;
+rs_rsend_func* rs_send;
+rs_raccept_func* rs_accept;
+rs_rclose_func* rs_close;
+rs_rread_func* rs_read;
+rs_rreadv_func* rs_readv;
+rs_rwrite_func* rs_write;
+rs_rwritev_func* rs_writev;
+rs_rrecv_func* rs_recv;
+rs_rrecvfrom_func* rs_recvfrom;
+rs_rsendto_func* rs_sendto;
+
+jboolean loadRdmaFuncs(JNIEnv* env);
+
+/* Definitions taken from librdmacm/include/rdma/rsocket.h */
+#ifndef SOL_RDMA
+#define SOL_RDMA 0x10000
+#endif
+enum {
+        RDMA_SQSIZE,
+        RDMA_RQSIZE,
+        RDMA_INLINE,
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/native/libextnet/rdma_util_md.c	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,441 @@
+/*
+ * Copyright (c) 2018, 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 <assert.h>
+#include "java_net_SocketOptions.h"
+#include "jdk_net_RdmaSocketOptions.h"
+#include "jvm.h"
+#include <netinet/tcp.h> // defines TCP_NODELAY
+#include "net_util.h"
+#include "rdma_util_md.h"
+#include "Rsocket.h"
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/resource.h>
+#include <pthread.h>
+
+#define BLOCKING_IO_RETURN_INT(FD, FUNC) {      \
+    int ret;                                    \
+    threadEntry_t self;                         \
+    fdEntry_t *fdEntry = getFdEntry(FD);        \
+    if (fdEntry == NULL) {                      \
+        errno = EBADF;                          \
+        return -1;                              \
+    }                                           \
+    do {                                        \
+        startOp(fdEntry, &self);                \
+        ret = FUNC;                             \
+        endOp(fdEntry, &self);                  \
+    } while (ret == -1 && errno == EINTR);      \
+    return ret;                                 \
+}
+
+typedef struct threadEntry {
+    pthread_t thr;                      /* this thread */
+    struct threadEntry *next;           /* next thread */
+    int intr;                           /* interrupted */
+} threadEntry_t;
+
+typedef struct {
+    pthread_mutex_t lock;               /* fd lock */
+    threadEntry_t *threads;             /* threads blocked on fd */
+} fdEntry_t;
+
+static int sigWakeup = (__SIGRTMAX - 2);
+
+static fdEntry_t* fdTable = NULL;
+
+static const int fdTableMaxSize = 0x1000; /* 4K */
+
+static int fdTableLen = 0;
+
+static int fdLimit = 0;
+
+static fdEntry_t** fdOverflowTable = NULL;
+
+static int fdOverflowTableLen = 0;
+
+static const int fdOverflowTableSlabSize = 0x10000; /* 64k */
+
+pthread_mutex_t fdOverflowTableLock = PTHREAD_MUTEX_INITIALIZER;
+
+static void sig_wakeup(int sig) {
+}
+
+static void __attribute((constructor)) init() {
+    struct rlimit nbr_files;
+    sigset_t sigset;
+    struct sigaction sa;
+    int i = 0;
+
+    if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) {
+        fprintf(stderr, "library initialization failed - "
+                "unable to get max # of allocated fds\n");
+        abort();
+    }
+    if (nbr_files.rlim_max != RLIM_INFINITY) {
+        fdLimit = nbr_files.rlim_max;
+    } else {
+        fdLimit = INT_MAX;
+    }
+
+    fdTableLen = fdLimit < fdTableMaxSize ? fdLimit : fdTableMaxSize;
+    fdTable = (fdEntry_t*) calloc(fdTableLen, sizeof(fdEntry_t));
+    if (fdTable == NULL) {
+        fprintf(stderr, "library initialization failed - "
+                "unable to allocate file descriptor table - out of memory");
+        abort();
+    } else {
+        for (i = 0; i < fdTableLen; i ++) {
+            pthread_mutex_init(&fdTable[i].lock, NULL);
+        }
+    }
+
+    if (fdLimit > fdTableMaxSize) {
+        fdOverflowTableLen = ((fdLimit - fdTableMaxSize) / fdOverflowTableSlabSize) + 1;
+        fdOverflowTable = (fdEntry_t**) calloc(fdOverflowTableLen, sizeof(fdEntry_t*));
+        if (fdOverflowTable == NULL) {
+            fprintf(stderr, "library initialization failed - "
+                    "unable to allocate file descriptor overflow table - out of memory");
+            abort();
+        }
+    }
+
+    sa.sa_handler = sig_wakeup;
+    sa.sa_flags   = 0;
+    sigemptyset(&sa.sa_mask);
+    sigaction(sigWakeup, &sa, NULL);
+
+    sigemptyset(&sigset);
+    sigaddset(&sigset, sigWakeup);
+    sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+}
+
+static inline fdEntry_t *getFdEntry(int fd) {
+    fdEntry_t* result = NULL;
+
+    if (fd < 0) {
+        return NULL;
+    }
+
+    assert(fd < fdLimit);
+
+    if (fd < fdTableMaxSize) {
+        assert(fd < fdTableLen);
+        result = &fdTable[fd];
+    } else {
+        const int indexInOverflowTable = fd - fdTableMaxSize;
+        const int rootindex = indexInOverflowTable / fdOverflowTableSlabSize;
+        const int slabindex = indexInOverflowTable % fdOverflowTableSlabSize;
+        fdEntry_t* slab = NULL;
+        assert(rootindex < fdOverflowTableLen);
+        assert(slabindex < fdOverflowTableSlabSize);
+        pthread_mutex_lock(&fdOverflowTableLock);
+        if (fdOverflowTable[rootindex] == NULL) {
+            fdEntry_t* const newSlab =
+                (fdEntry_t*)calloc(fdOverflowTableSlabSize, sizeof(fdEntry_t));
+            if (newSlab == NULL) {
+                fprintf(stderr, "Unable to allocate file descriptor overflow"
+                        " table slab - out of memory");
+                pthread_mutex_unlock(&fdOverflowTableLock);
+                abort();
+            } else {
+                int i;
+                for (i = 0; i < fdOverflowTableSlabSize; i ++) {
+                    pthread_mutex_init(&newSlab[i].lock, NULL);
+                }
+                fdOverflowTable[rootindex] = newSlab;
+            }
+        }
+        pthread_mutex_unlock(&fdOverflowTableLock);
+        slab = fdOverflowTable[rootindex];
+        result = &slab[slabindex];
+    }
+    return result;
+}
+
+static inline void startOp(fdEntry_t *fdEntry, threadEntry_t *self) {
+    self->thr = pthread_self();
+    self->intr = 0;
+
+    pthread_mutex_lock(&(fdEntry->lock));
+    {
+        self->next = fdEntry->threads;
+        fdEntry->threads = self;
+    }
+    pthread_mutex_unlock(&(fdEntry->lock));
+}
+
+static inline void endOp (fdEntry_t *fdEntry, threadEntry_t *self) {
+    int orig_errno = errno;
+    pthread_mutex_lock(&(fdEntry->lock));
+    {
+        threadEntry_t *curr, *prev=NULL;
+        curr = fdEntry->threads;
+        while (curr != NULL) {
+            if (curr == self) {
+                if (curr->intr) {
+                    orig_errno = EBADF;
+                }
+                if (prev == NULL) {
+                    fdEntry->threads = curr->next;
+                } else {
+                    prev->next = curr->next;
+                }
+                break;
+            }
+            prev = curr;
+            curr = curr->next;
+        }
+    }
+    pthread_mutex_unlock(&(fdEntry->lock));
+    errno = orig_errno;
+}
+
+#define RESTARTABLE(_cmd, _result) do { \
+    do { \
+        _result = _cmd; \
+    } while((_result == -1) && (errno == EINTR)); \
+} while(0)
+
+int rdma_supported() {
+    int one = 1;
+    int rv, s;
+    s = rs_socket(PF_INET, SOCK_STREAM, 0);
+    if (s < 0) {
+        return JNI_FALSE;
+    }
+    return JNI_TRUE;
+}
+
+int RDMA_MapSocketOption(jint cmd, int *level, int *optname) {
+    static struct {
+        jint cmd;
+        int level;
+        int optname;
+    } const opts[] = {
+        { java_net_SocketOptions_TCP_NODELAY,           IPPROTO_TCP,    TCP_NODELAY },
+        { java_net_SocketOptions_SO_SNDBUF,             SOL_SOCKET,     SO_SNDBUF },
+        { java_net_SocketOptions_SO_RCVBUF,             SOL_SOCKET,     SO_RCVBUF },
+        { java_net_SocketOptions_SO_REUSEADDR,          SOL_SOCKET,     SO_REUSEADDR },
+        { jdk_net_RdmaSocketOptions_SQSIZE,             SOL_RDMA,       RDMA_SQSIZE },
+        { jdk_net_RdmaSocketOptions_RQSIZE,             SOL_RDMA,       RDMA_RQSIZE },
+        { jdk_net_RdmaSocketOptions_INLINE,             SOL_RDMA,       RDMA_INLINE },
+    };
+    int i;
+    for (i=0; i<(int)(sizeof(opts) / sizeof(opts[0])); i++) {
+        if (cmd == opts[i].cmd) {
+            *level = opts[i].level;
+            *optname = opts[i].optname;
+            return 0;
+        }
+    }
+    return -1;
+}
+
+int RDMA_GetSockOpt(int fd, int level, int opt, void *result, int *len) {
+    int rv;
+    socklen_t socklen = *len;
+
+    rv = rs_getsockopt(fd, level, opt, result, &socklen);
+    *len = socklen;
+
+    if (rv < 0) {
+        return rv;
+    }
+
+    if ((level == SOL_SOCKET) && ((opt == SO_SNDBUF)
+                                  || (opt == SO_RCVBUF))) {
+        int n = *((int *)result);
+        n /= 2;
+        *((int *)result) = n;
+    }
+    return rv;
+}
+
+int RDMA_SetSockOpt(int fd, int level, int  opt, const void *arg, int len) {
+    int *bufsize;
+    if (level == SOL_SOCKET && opt == SO_RCVBUF) {
+        int *bufsize = (int *)arg;
+        if (*bufsize < 1024) {
+            *bufsize = 1024;
+        }
+    }
+
+    return rs_setsockopt(fd, level, opt, arg, len);
+}
+
+int RDMA_Bind(int fd, SOCKETADDRESS *sa, int len) {
+    int rv;
+    int arg, alen;
+
+    if (sa->sa.sa_family == AF_INET) {
+        if ((ntohl(sa->sa4.sin_addr.s_addr) & 0x7f0000ff) == 0x7f0000ff) {
+            errno = EADDRNOTAVAIL;
+            return -1;
+        }
+    }
+    rv = rs_bind(fd, &sa->sa, len);
+    return rv;
+}
+
+jint RDMA_Wait(JNIEnv *env, jint fd, jint flags, jint timeout) {
+    jlong prevNanoTime = JVM_NanoTime(env, 0);
+    jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
+    jint read_rv;
+
+    while (1) {
+        jlong newNanoTime;
+        struct pollfd pfd;
+        pfd.fd = fd;
+        pfd.events = 0;
+        if (flags & NET_WAIT_READ)
+          pfd.events |= POLLIN;
+        if (flags & NET_WAIT_WRITE)
+          pfd.events |= POLLOUT;
+        if (flags & NET_WAIT_CONNECT)
+          pfd.events |= POLLOUT;
+
+        errno = 0;
+        read_rv = RDMA_Poll(&pfd, 1, nanoTimeout / NET_NSEC_PER_MSEC);
+
+        newNanoTime = JVM_NanoTime(env, 0);
+        nanoTimeout -= (newNanoTime - prevNanoTime);
+        if (nanoTimeout < NET_NSEC_PER_MSEC) {
+          return read_rv > 0 ? 0 : -1;
+        }
+        prevNanoTime = newNanoTime;
+
+        if (read_rv > 0) {
+          break;
+        }
+      } 
+    return (nanoTimeout / NET_NSEC_PER_MSEC);
+}
+
+static int rdma_closefd(int fd2) {
+    int rv, orig_errno;
+    fdEntry_t *fdEntry = getFdEntry(fd2);
+    if (fdEntry == NULL) {
+        errno = EBADF;
+        return -1;
+    }
+
+    pthread_mutex_lock(&(fdEntry->lock));
+    do {
+        rv = rs_close(fd2);
+    } while (rv == -1 && errno == EINTR);
+
+    threadEntry_t *curr = fdEntry->threads;
+    while (curr != NULL) {
+        curr->intr = 1;
+        pthread_kill( curr->thr, sigWakeup );
+        curr = curr->next;
+    }
+    orig_errno = errno;
+    pthread_mutex_unlock(&(fdEntry->lock));
+    errno = orig_errno;
+    return rv;
+}
+
+int RDMA_SocketClose(int fd) {
+    return rdma_closefd(fd);
+}
+
+int RDMA_Read(int s, void* buf, size_t len) {
+    BLOCKING_IO_RETURN_INT(s, rs_recv(s, buf, len, 0));
+}
+
+int RDMA_NonBlockingRead(int s, void* buf, size_t len) {
+    BLOCKING_IO_RETURN_INT(s, rs_recv(s, buf, len, MSG_DONTWAIT));
+}
+
+int RDMA_ReadV(int s, const struct iovec * vector, int count) {
+    BLOCKING_IO_RETURN_INT(s, rs_readv(s, vector, count) );
+}
+
+int RDMA_RecvFrom(int s, void *buf, int len, unsigned int flags,
+        struct sockaddr *from, socklen_t *fromlen) {
+    BLOCKING_IO_RETURN_INT(s, rs_recvfrom(s, buf, len, flags, from, fromlen));
+}
+
+int RDMA_Send(int s, void *msg, int len, unsigned int flags) {
+    BLOCKING_IO_RETURN_INT(s, rs_send(s, msg, len, flags));
+}
+
+int RDMA_WriteV(int s, const struct iovec * vector, int count) {
+    BLOCKING_IO_RETURN_INT(s, rs_writev(s, vector, count));
+}
+
+int NET_RSendTo(int s, const void *msg, int len,  unsigned  int
+       flags, const struct sockaddr *to, int tolen) {
+    BLOCKING_IO_RETURN_INT(s, rs_sendto(s, msg, len, flags, to, tolen));
+}
+
+int RDMA_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
+    BLOCKING_IO_RETURN_INT(s, rs_accept(s, addr, addrlen));
+}
+
+int RDMA_Connect(int s, struct sockaddr *addr, int addrlen) {
+    BLOCKING_IO_RETURN_INT(s, rs_connect(s, addr, addrlen));
+}
+
+int RDMA_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
+    BLOCKING_IO_RETURN_INT(ufds[0].fd, rs_poll(ufds, nfds, timeout));
+}
+
+int RDMA_Timeout(JNIEnv *env, int s, long timeout, jlong nanoTimeStamp) {
+    jlong prevNanoTime = nanoTimeStamp;
+    jlong nanoTimeout = (jlong)timeout * NET_NSEC_PER_MSEC;
+    fdEntry_t *fdEntry = getFdEntry(s);
+
+    if (fdEntry == NULL) {
+        errno = EBADF;
+        return -1;
+    }
+
+    for(;;) {
+        struct pollfd pfd;
+        int rv;
+        threadEntry_t self;
+
+        pfd.fd = s;
+        pfd.events = POLLIN | POLLERR;
+
+        startOp(fdEntry, &self);
+        rv = rs_poll(&pfd, 1, nanoTimeout / NET_NSEC_PER_MSEC);
+        endOp(fdEntry, &self);
+        if (rv < 0 && errno == EINTR) {
+            jlong newNanoTime = JVM_NanoTime(env, 0);
+            nanoTimeout -= newNanoTime - prevNanoTime;
+            if (nanoTimeout < NET_NSEC_PER_MSEC) {
+                return 0;
+            }
+            prevNanoTime = newNanoTime;
+        } else {
+            return rv;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/linux/native/libextnet/rdma_util_md.h	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018, 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 <poll.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <net_util_md.h>
+
+/************************************************************************
+ * Functions
+ */
+int rdma_supported();
+int RDMA_MapSocketOption(jint cmd, int *level, int *optname);
+int RDMA_Bind(int fd, SOCKETADDRESS *sa, int len);
+int RDMA_Timeout(JNIEnv *env, int s, long timeout, jlong  nanoTimeStamp);
+int RDMA_Read(int s, void* buf, size_t len);
+int RDMA_NonBlockingRead(int s, void* buf, size_t len);
+int RDMA_RecvFrom(int s, void *buf, int len, unsigned int flags,
+                 struct sockaddr *from, socklen_t *fromlen);
+int RDMA_ReadV(int s, const struct iovec * vector, int count);
+int RDMA_Send(int s, void *msg, int len, unsigned int flags);
+int RDMA_SendTo(int s, const void *msg, int len,  unsigned  int
+               flags, const struct sockaddr *to, int tolen);
+int RDMA_Writev(int s, const struct iovec * vector, int count);
+int RDMA_Connect(int s, struct sockaddr *addr, int addrlen);
+int RDMA_Accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+int RDMA_SocketClose(int s);
+int RDMA_Poll(struct pollfd *ufds, unsigned int nfds, int timeout);
+int RDMA_SetSockOpt(int fd, int level, int  opt, const void *arg, int len);
+int RDMA_GetSockOpt(int fd, int level, int opt, void *result, int *len);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/share/classes/jdk/internal/net/rdma/RdmaPollSelectorProvider.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2018, 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.internal.net.rdma;
+
+import java.io.IOException;
+import java.net.ProtocolFamily;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.Pipe;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.AbstractSelector;
+import java.nio.channels.spi.SelectorProvider;
+import sun.nio.ch.SelectorProviderImpl;
+
+public class RdmaPollSelectorProvider
+    extends SelectorProvider
+{
+    public static SelectorProvider provider() {
+        throw new UnsupportedOperationException();
+    }
+
+    public AbstractSelector openSelector() throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    public SocketChannel openSocketChannel()
+            throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    public SocketChannel openSocketChannel(ProtocolFamily family)
+            throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    public ServerSocketChannel openServerSocketChannel()
+            throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    public ServerSocketChannel openServerSocketChannel(ProtocolFamily family)
+            throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    public DatagramChannel openDatagramChannel()
+            throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    public DatagramChannel openDatagramChannel(ProtocolFamily family)
+            throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    public Pipe openPipe() throws IOException {
+        throw new UnsupportedOperationException();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/share/classes/jdk/internal/net/rdma/RdmaSocketProvider.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018, 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.internal.net.rdma;
+
+import java.io.IOException;
+import java.net.ProtocolFamily;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+public class RdmaSocketProvider {
+    public static Socket openSocket(ProtocolFamily family)
+            throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    public static ServerSocket openServerSocket(ProtocolFamily family)
+            throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    private RdmaSocketProvider() {}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/share/classes/jdk/net/RdmaSocketOptions.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2018, 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.io.FileDescriptor;
+import java.net.SocketException;
+import java.net.SocketOption;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Collections;
+import java.util.Set;
+import jdk.internal.access.JavaIOFileDescriptorAccess;
+import jdk.internal.access.SharedSecrets;
+import java.lang.annotation.Native;
+
+/**
+ * Defines socket options specific to RDMA-based TCP sockets and channels.
+ *
+ * @since 12
+ */
+public final class RdmaSocketOptions {
+
+    private static class RdmaSocketOption<T> implements SocketOption<T> {
+        private final String name;
+        private final Class<T> type;
+        RdmaSocketOption(String name, Class<T> type) {
+            this.name = name;
+            this.type = type;
+        }
+        @Override public String name() { return name; }
+        @Override public Class<T> type() { return type; }
+        @Override public String toString() { return name; }
+    }
+
+    private RdmaSocketOptions() { }
+
+    /**
+     * The integer size of the underlying RDMA send queue used by the
+     * platform for network I/O.
+     *
+     * The initial/default size of the RDMA send queue and the range of
+     * allowable values is system and device dependent although a negative
+     * size is not allowed.
+     *
+     * <p> An implementation allows this socket option to be set before the
+     * socket is bound or connected. Changing the value of this socket option
+     * after the socket is bound or connected has no effect.
+     *
+     * Valid for RDMA-based TCP sockets.
+     */
+    public static final SocketOption<Integer> RDMA_SQSIZE = new
+        RdmaSocketOption<Integer>("RDMA_SQSIZE", Integer.class);
+
+    /**
+     * The integer size of the underlying RDMA receive queue used by the
+     * platform for network I/O.
+     *
+     * The initial/default size of the RDMA receive queue and the range of
+     * allowable values is system and device dependent although a negative
+     * size is not allowed.
+     *
+     * <p> An implementation allows this socket option to be set before the
+     * socket is bound or connected. Changing the value of this socket option
+     * after the socket is bound or connected has no effect.
+     *
+     * Valid for RDMA-based TCP sockets.
+     */
+    public static final SocketOption<Integer> RDMA_RQSIZE = new
+        RdmaSocketOption<Integer>("RDMA_RQSIZE", Integer.class);
+
+    /**
+     * The integer size of the underlying RDMA inline data used by the
+     * platform for network I/O.
+     *
+     * The initial/default size of the RDMA inline data and the range of
+     * allowable values is system and device dependent although a negative
+     * size is not allowed.
+     *
+     * <p> An implementation allows this socket option to be set before the
+     * socket is bound or connected. Changing the value of this socket option
+     * after the socket is bound or connected has no effect.
+     *
+     * Valid for RDMA-based TCP sockets.
+     */
+    public static final SocketOption<Integer> RDMA_INLINE = new
+        RdmaSocketOption<Integer>("RDMA_INLINE", Integer.class);
+
+    @Native private static final int SQSIZE = 0x3001;
+
+    @Native private static final int RQSIZE = 0x3002;
+
+    @Native private static final int INLINE = 0x3003;
+
+    private static final PlatformRdmaSocketOptions platformRdmaSocketOptions =
+            PlatformRdmaSocketOptions.get();
+
+    private static final boolean rdmaSocketSupported =
+            platformRdmaSocketOptions.rdmaSocketSupported();
+
+    private static final Set<SocketOption<?>> rdmaOptions = options();
+
+    static Set<SocketOption<?>> options() {
+        if (rdmaSocketSupported)
+            return Set.of(RDMA_SQSIZE, RDMA_RQSIZE, RDMA_INLINE);
+        else
+            return Collections.<SocketOption<?>>emptySet();
+    }
+
+    static {
+        sun.net.ext.RdmaSocketOptions.register(
+                new sun.net.ext.RdmaSocketOptions(rdmaOptions) {
+
+            @Override
+            public void setOption(FileDescriptor fd,
+                    SocketOption<?> option, Object value)
+                    throws SocketException {
+                SecurityManager sm = System.getSecurityManager();
+                if (sm != null)
+                    sm.checkPermission(new NetworkPermission("setOption."
+                            + option.name()));
+
+                if (fd == null || !fd.valid())
+                    throw new SocketException("socket closed");
+
+                if ((option == RDMA_SQSIZE) || (option == RDMA_RQSIZE)
+                    || (option == RDMA_INLINE)) {
+                    assert rdmaSocketSupported;
+
+                    int val;
+                    int opt;
+                    if (option == RDMA_SQSIZE) {
+                        if (value == null || (!(value instanceof Integer)))
+                            throw new SocketException(
+                                    "Bad parameter for RDMA_SQSIZE");
+                        val = ((Integer) value).intValue();
+                        opt = SQSIZE;
+                        if (val < 0)
+                            throw new IllegalArgumentException(
+                                    "send queue size < 0");
+                    } else if (option == RDMA_RQSIZE) {
+                        if (value == null || (!(value instanceof Integer)))
+                            throw new SocketException(
+                                    "Bad parameter for RDMA_RQSIZE");
+                        val = ((Integer) value).intValue();
+                        opt = RQSIZE;
+                        if (val < 0)
+                            throw new IllegalArgumentException(
+                                    "receive queue size < 0");
+                    } else if (option == RDMA_INLINE) {
+                        if (value == null || (!(value instanceof Integer)))
+                            throw new SocketException(
+                                    "Bad parameter for RDMA_INLINE");
+                        val = ((Integer) value).intValue();
+                        opt = INLINE;
+                        if (val < 0)
+                            throw new IllegalArgumentException(
+                                    "inline size < 0");
+                    } else {
+                        throw new SocketException(
+                                "unrecognized RDMA socket option: " + option);
+                    }
+
+                    setSockOpt(fd, opt, val);
+
+                } else {
+                    throw new InternalError("Unexpected option " + option);
+                }
+            }
+
+            @Override
+            public Object getOption(FileDescriptor fd,
+                    SocketOption<?> option) throws SocketException {
+                SecurityManager sm = System.getSecurityManager();
+                if (sm != null)
+                    sm.checkPermission(new NetworkPermission("getOption."
+                            + option.name()));
+
+                if (fd == null || !fd.valid())
+                    throw new SocketException("socket closed");
+
+                if ((option == RDMA_SQSIZE) || (option == RDMA_RQSIZE)
+                    || (option == RDMA_INLINE)) {
+                    assert rdmaSocketSupported;
+                    int opt;
+                    if (option == RDMA_SQSIZE) {
+                        opt = SQSIZE;
+                    } else if (option == RDMA_RQSIZE) {
+                        opt = RQSIZE;
+                    } else {
+                        opt = INLINE;
+                    }
+                    return getSockOpt(fd, opt);
+                } else {
+                    throw new InternalError("Unexpected option " + option);
+                }
+            }
+        });
+    }
+
+    private static final JavaIOFileDescriptorAccess fdAccess =
+            SharedSecrets.getJavaIOFileDescriptorAccess();
+
+    private static void setSockOpt(FileDescriptor fd, int opt, int val)
+            throws SocketException {
+        platformRdmaSocketOptions.setSockOpt(fdAccess.get(fd), opt, val);
+    }
+
+    private static int getSockOpt(FileDescriptor fd, int opt)
+            throws SocketException {
+        return platformRdmaSocketOptions.getSockOpt(fdAccess.get(fd), opt);
+    }
+
+    static class PlatformRdmaSocketOptions {
+
+        protected PlatformRdmaSocketOptions() {}
+
+        @SuppressWarnings("unchecked")
+        private static PlatformRdmaSocketOptions newInstance(String cn) {
+            Class<PlatformRdmaSocketOptions> c;
+            try {
+                c = (Class<PlatformRdmaSocketOptions>)Class.forName(cn);
+                return c.getConstructor(new Class<?>[] { }).newInstance();
+            } catch (ReflectiveOperationException x) {
+                if (x.getCause() instanceof UnsupportedOperationException)
+                    throw (UnsupportedOperationException)x.getCause();
+                throw new AssertionError(x);
+            }
+        }
+
+        private static PlatformRdmaSocketOptions create() {
+            String osname = AccessController.doPrivileged(
+                    new PrivilegedAction<String>() {
+                        public String run() {
+                            return System.getProperty("os.name");
+                        }
+                    });
+            if ("Linux".equals(osname)) {
+                try {
+                    return newInstance("jdk.net.LinuxRdmaSocketOptions");
+                } catch (UnsupportedOperationException uoe) {
+                    return new PlatformRdmaSocketOptions();
+                }
+            }
+            return new PlatformRdmaSocketOptions();
+        }
+
+        private static final PlatformRdmaSocketOptions instance = create();
+
+        static PlatformRdmaSocketOptions get() {
+            return instance;
+        }
+
+        void setSockOpt(int fd, int opt, int value) throws SocketException {
+            throw new UnsupportedOperationException(
+                    "unsupported socket option");
+        }
+
+        int getSockOpt(int fd, int opt) throws SocketException {
+            throw new UnsupportedOperationException(
+                    "unsupported socket option");
+        }
+
+        boolean rdmaSocketSupported() {
+            return false;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/share/classes/jdk/net/RdmaSockets.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2018, 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.ProtocolFamily;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.SocketOption;
+import java.net.StandardSocketOptions;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+import java.io.IOException;
+import java.util.Objects;
+import jdk.internal.net.rdma.RdmaPollSelectorProvider;
+import jdk.internal.net.rdma.RdmaSocketProvider;
+
+/**
+ * Factory methods for creating RDMA-based TCP sockets and channels.
+ *
+ * <p>The {@link #openSocket(ProtocolFamily family) openSocket} and {@link
+ * #openServerSocket(ProtocolFamily family) openServerSocket} methods
+ * create RDMA-based TCP sockets.
+ *
+ * <p>The {@link #openSelector() openSelector}, {@link
+ * #openSocketChannel(ProtocolFamily family) openSocketChannel}, and {@link
+ * #openServerSocketChannel(ProtocolFamily family) openServerSocketChannel}
+ * methods create selectors and selectable channels for use with RDMA sockets.
+ * These objects are created by a {@link java.nio.channels.spi.SelectorProvider
+ * SelectorProvider} that is not the default {@code SelectorProvider}.
+ * Consequently, selectable channels to RDMA sockets may not be multiplexed
+ * with selectable channels created by the default selector provider. Its
+ * selector provider does not support datagram channels and pipes.
+ * The {@link java.nio.channels.spi.SelectorProvider#openDatagramChannel
+ * openDatagramChannel} and
+ * {@link java.nio.channels.spi.SelectorProvider#openPipe openPipe} methods
+ * throw {@link java.lang.UnsupportedOperationException
+ * UnsupportedOperationException}.
+ *
+ * @since 12
+ */
+public class RdmaSockets {
+
+    private RdmaSockets() {}
+
+    /**
+     * Creates an unbound and unconnected RDMA socket.
+     *
+     * <p> An RDMA socket supports the same socket options that {@link
+     * java.net.Socket java.net.Socket} defines. In addition, it supports the
+     * socket options specified by {@link RdmaSocketOptions}.
+     *
+     * <p> When binding the socket to a local address, or invoking {@code
+     * connect} to connect the socket, the socket address specified to those
+     * methods must correspond to the protocol family specified here.
+     *
+     * @param   family
+     *          The protocol family
+     *
+     * @throws IOException
+     *         If an I/O error occurs
+     * @throws NullPointerException
+     *         If name is {@code null}
+     * @throws UnsupportedOperationException
+     *         If RDMA sockets are not supported on this platform or if the
+     *         specified protocol family is not supported. For example, if
+     *         the parameter is {@link java.net.StandardProtocolFamily#INET6
+     *         StandardProtocolFamily.INET6} but IPv6 is not enabled on the
+     *         platform.
+     */
+    public static Socket openSocket(ProtocolFamily family) throws IOException {
+        Objects.requireNonNull("protocol family is null");
+        return RdmaSocketProvider.openSocket(family);
+    }
+
+    /**
+     * Creates an unbound RDMA server socket.
+     *
+     * <p> An RDMA socket supports the same socket options that {@link
+     * java.net.ServerSocket java.net.ServerSocket} defines.
+     *
+     * <p> When binding the socket to an address, the socket address specified
+     * to the {@code bind} method must correspond to the protocol family
+     * specified here.
+     *
+     * @param   family
+     *          The protocol family
+     *
+     * @throws IOException
+     *         If an I/O error occurs
+     * @throws NullPointerException
+     *         If name is {@code null}
+     * @throws UnsupportedOperationException
+     *         If RDMA sockets are not supported on this platform or if the
+     *         specified protocol family is not supported. For example, if
+     *         the parameter is {@link java.net.StandardProtocolFamily#INET6
+     *         StandardProtocolFamily.INET6} but IPv6 is not enabled on the
+     *         platform.
+     */
+    public static ServerSocket openServerSocket(ProtocolFamily family)
+            throws IOException {
+        Objects.requireNonNull("protocol family is null");
+        return RdmaSocketProvider.openServerSocket(family);
+    }
+
+    /**
+     * Opens a socket channel to an RDMA socket. A newly created socket channel
+     * is {@link SocketChannel#isOpen() open}, not yet bound to a {@link
+     * SocketChannel#getLocalAddress() local address}, and not yet
+     * {@link SocketChannel#isConnected() connected}.
+     *
+     * <p> A socket channel to an RDMA socket supports all of the socket options
+     * specified by {@code SocketChannel}. In addition, it supports the
+     * socket options specified by {@link RdmaSocketOptions}.
+     *
+     * <p> When binding the channel's socket to a local address, or invoking
+     * {@code connect} to connect channel's socket, the socket address specified
+     * to those methods must correspond to the protocol family specified here.
+     *
+     * @param   family
+     *          The protocol family
+     *
+     * @throws IOException
+     *         If an I/O error occurs
+     * @throws NullPointerException
+     *         If name is {@code null}
+     * @throws UnsupportedOperationException
+     *         If RDMA sockets are not supported on this platform or if the
+     *         specified protocol family is not supported. For example, if
+     *         the parameter is {@link java.net.StandardProtocolFamily#INET6
+     *         StandardProtocolFamily.INET6} but IPv6 is not enabled on the
+     *         platform.
+     */
+    public static SocketChannel openSocketChannel(ProtocolFamily family)
+            throws IOException {
+        Objects.requireNonNull("protocol family is null");
+        SelectorProvider provider = RdmaPollSelectorProvider.provider();
+        return ((RdmaPollSelectorProvider)provider).openSocketChannel(family);
+    }
+
+    /**
+     * Opens a server socket channel to an RDMA socket. A newly created socket
+     * channel is {@link SocketChannel#isOpen() open} but not yet bound to a
+     * {@link SocketChannel#getLocalAddress() local address}.
+     *
+     * <p> When binding the channel's socket to an address, the socket address
+     * specified to the {@code bind} method must correspond to the protocol
+     * family specified here.
+     *
+     * @param   family
+     *          The protocol family
+     *
+     * @throws IOException
+     *         If an I/O error occurs
+     * @throws NullPointerException
+     *         If name is {@code null}
+     * @throws UnsupportedOperationException
+     *         If RDMA sockets are not supported on this platform or if the
+     *         specified protocol family is not supported. For example, if
+     *         the parameter is {@link java.net.StandardProtocolFamily#INET6
+     *         StandardProtocolFamily.INET6} but IPv6 is not enabled on the
+     *         platform.
+     */
+    public static ServerSocketChannel openServerSocketChannel(
+            ProtocolFamily family) throws IOException {
+        Objects.requireNonNull("protocol family is null");
+        SelectorProvider provider = RdmaPollSelectorProvider.provider();
+        return ((RdmaPollSelectorProvider)provider)
+                .openServerSocketChannel(family);
+    }
+
+    /**
+     * Opens a selector to multiplex selectable channels to RDMA sockets.
+     *
+     * @throws IOException
+     *         If an I/O error occurs
+     * @throws UnsupportedOperationException
+     *         If RDMA sockets are not supported on this platform
+     */
+    public static Selector openSelector() throws IOException {
+        SelectorProvider provider = RdmaPollSelectorProvider.provider();
+        return provider.openSelector();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/Exceptions.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2018, 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 8195160
+ * @summary RdmaSockets API Exceptions
+ * @run testng Exceptions
+ */
+
+import java.net.ProtocolFamily;
+import org.testng.annotations.Test;
+import static jdk.net.RdmaSockets.*;
+import static org.testng.Assert.*;
+
+public class Exceptions {
+
+    static final Class<NullPointerException> NPE = NullPointerException.class;
+    static final Class<UnsupportedOperationException> UOE = UnsupportedOperationException.class;
+
+    @Test
+    public void testNull() {
+        assertThrows(NPE, () -> openSocket(null));
+        assertThrows(NPE, () -> openServerSocket(null));
+        assertThrows(NPE, () -> openSocketChannel(null));
+        assertThrows(NPE, () -> openServerSocketChannel(null));
+    }
+
+    static class UnsupportedFamily implements ProtocolFamily {
+        @Override public String name() { return null; }
+    }
+
+    @Test
+    public void testBadFamily() {
+        assertThrows(UOE, () -> openSocket(new UnsupportedFamily()));
+        assertThrows(UOE, () -> openServerSocket(new UnsupportedFamily()));
+        assertThrows(UOE, () -> openSocketChannel(new UnsupportedFamily()));
+        assertThrows(UOE, () -> openServerSocketChannel(new UnsupportedFamily()));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/NullBind.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2018, 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 8195160
+ * @summary Tests binding with null ( automatically assigned address )
+ * @requires (os.family == "linux")
+ * @library /test/lib
+ * @build RsocketTest
+ * @run testng/othervm NullBind
+ * @run testng/othervm -Djava.net.preferIPv6Addresses=true NullBind
+ */
+
+import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ProtocolFamily;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import org.testng.SkipException;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static java.lang.String.format;
+import static java.net.StandardProtocolFamily.INET;
+import static java.net.StandardProtocolFamily.INET6;
+import static jdk.net.RdmaSockets.*;
+import static org.testng.Assert.assertTrue;
+
+public class NullBind {
+
+    @BeforeTest
+    public void setup() throws Exception {
+        if (!RsocketTest.isRsocketAvailable())
+            throw new SkipException("rsocket is not available");
+    }
+
+    @DataProvider(name = "families")
+    public Object[][] families() {
+        return new Object[][] {
+            { INET,  Inet4Address.class },
+            { INET6, Inet6Address.class }
+        };
+    }
+
+    @Test(dataProvider = "families")
+    public void testSocket(ProtocolFamily family,
+                           Class<? extends InetAddress> expectedClass)
+        throws IOException
+    {
+        try (Socket s = openSocket(family)) {
+            s.bind(null);
+            InetAddress addr = s.getLocalAddress();
+            //TODO: Argh! still a family issue in Socket.getLocalAddress
+            //assertTrue(expectedClass.isAssignableFrom(addr.getClass()),
+            //           format("Excepted %s got: %s", expectedClass, addr));
+            assertTrue(addr.isAnyLocalAddress(),
+                       format("Expected any local address, got: %s", addr));
+        }
+    }
+
+    @Test(dataProvider = "families")
+    public void testServerSocket(ProtocolFamily family,
+                                 Class<? extends InetAddress> expectedClass)
+        throws IOException
+    {
+        try (ServerSocket ss = openServerSocket(family)) {
+            ss.bind(null);
+            InetAddress addr = ss.getInetAddress();
+            assertTrue(expectedClass.isAssignableFrom(addr.getClass()),
+                       format("Excepted %s got: %s", expectedClass, addr));
+            assertTrue(addr.isAnyLocalAddress(),
+                       format("Expected any local address, got: %s", addr));
+        }
+    }
+
+    @Test(dataProvider = "families")
+    public void testSocketChannel(ProtocolFamily family,
+                                  Class<? extends InetAddress> expectedClass)
+        throws IOException
+    {
+        try (SocketChannel sc = openSocketChannel(family)) {
+            sc.bind(null);
+            InetAddress addr = ((InetSocketAddress)sc.getLocalAddress()).getAddress();
+            assertTrue(expectedClass.isAssignableFrom(addr.getClass()),
+                      format("Excepted %s got: %s", expectedClass, addr));
+            assertTrue(addr.isAnyLocalAddress(),
+                       format("Expected any local address, got: %s", addr));
+        }
+    }
+
+    @Test(dataProvider = "families")
+    public void testServerSocketChannel(ProtocolFamily family,
+                                        Class<? extends InetAddress> expectedClass)
+        throws IOException
+    {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            ssc.bind(null);
+            InetAddress addr = ((InetSocketAddress)ssc.getLocalAddress()).getAddress();
+            assertTrue(expectedClass.isAssignableFrom(addr.getClass()),
+                       format("Excepted %s got: %s", expectedClass, addr));
+            assertTrue(addr.isAnyLocalAddress(),
+                       format("Expected any local address, got: %s", addr));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/RsocketTest.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/*
+ * @test
+ * @bug 8195160
+ * @summary Test to check if rsocket is available
+ * @requires (os.family == "linux")
+ * @library /test/lib
+ * @build jdk.test.lib.Platform
+ * @run main/native RsocketTest
+ */
+
+import java.io.IOException;
+import java.net.SocketException;
+import java.net.StandardProtocolFamily;
+
+public class RsocketTest {
+    private static boolean libInstalled;
+    private static boolean supported;
+    private static boolean checked;
+
+    static {
+        System.loadLibrary("RsocketTest");
+    }
+
+    public static boolean isRsocketAvailable()
+            throws IOException {
+        if (!checked) {
+            checked = true;
+            supported = isRsocketAvailable0();
+        }
+        if (!supported) {
+            checkUnsupportedWithParameter();
+            checkUnsupportedNoParameter();
+        }
+        return supported;
+    }
+
+    static void checkUnsupportedWithParameter() throws IOException {
+        checkThrowsUOEWithParameter(jdk.net.RdmaSockets::openSocket);
+        checkThrowsUOEWithParameter(jdk.net.RdmaSockets::openServerSocket);
+        checkThrowsUOEWithParameter(jdk.net.RdmaSockets::openSocketChannel);
+        checkThrowsUOEWithParameter(
+                jdk.net.RdmaSockets::openServerSocketChannel);
+    }
+
+    static void checkUnsupportedNoParameter() throws IOException {
+        checkThrowsUOENoParameter(jdk.net.RdmaSockets::openSelector);
+    }
+
+    static void checkThrowsUOEWithParameter(
+            ThrowingRunnableWithParameter runnable) throws IOException {
+        try {
+            runnable.run(StandardProtocolFamily.INET);
+            runnable.run(StandardProtocolFamily.INET6);
+            if (!libInstalled)
+                throw new RuntimeException("Unexpected creation");
+        } 
+        catch (UnsupportedOperationException | SocketException expected) { }
+    }
+
+    static void checkThrowsUOENoParameter(ThrowingRunnableNoParameter runnable)
+            throws IOException {
+        try {
+            runnable.run();
+            if (!libInstalled)
+                throw new RuntimeException("Unexpected creation");
+        }
+        catch (UnsupportedOperationException expected) { }
+    }
+
+    interface ThrowingRunnableWithParameter {
+        void run(StandardProtocolFamily family) throws IOException;
+    }
+
+    interface ThrowingRunnableNoParameter { void run() throws IOException; }
+
+    private static native boolean isRsocketAvailable0();
+
+    public static void main(String[] args) throws Exception {
+         System.out.println("testing rsocket!");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/Selector/BasicAccept.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2018, 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 8195160
+ * @summary Test RdmaSelector with RdmaServerSocketChannels
+ * @requires (os.family == "linux")
+ * @library .. /test/lib /test/jdk/java/nio/channels 
+ * @build RsocketTest
+ * @run main/othervm BasicAccept
+ */
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.StandardProtocolFamily;
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.Iterator;
+import java.util.Set;
+import jdk.net.RdmaSockets;
+
+import jtreg.SkippedException;
+
+public class BasicAccept {
+
+    static void server(ServerSocketChannel ssc) throws Exception {
+        Selector acceptSelector = RdmaSockets.openSelector();
+        try {
+            ssc.configureBlocking(false);
+            SelectionKey acceptKey
+                = ssc.register(acceptSelector, SelectionKey.OP_ACCEPT);
+            for (;;) {
+                int n = acceptSelector.select();
+                if (Thread.interrupted())
+                    break;
+                if (n == 0)
+                    continue;
+                Set<SelectionKey> readyKeys = acceptSelector.selectedKeys();
+                Iterator<SelectionKey> i = readyKeys.iterator();
+                while (i.hasNext()) {
+                    SelectionKey sk = i.next();
+                    i.remove();
+                    ServerSocketChannel nextReady
+                        = (ServerSocketChannel)sk.channel();
+                    SocketChannel sc = nextReady.accept();
+                    ByteBuffer bb = ByteBuffer.wrap(new byte[] { 42 });
+                    sc.write(bb);
+                    sc.close();
+                }
+            }
+        } finally {
+            acceptSelector.close();
+        }
+    }
+
+    private static class Server extends TestThread {
+        final ServerSocketChannel ssc;
+        Server() throws IOException {
+            super("Server", System.err);
+            this.ssc = RdmaSockets.openServerSocketChannel(
+                StandardProtocolFamily.INET)
+                .bind(new InetSocketAddress(InetAddress.getLocalHost(), 0));
+        }
+        int port() {
+            return ssc.socket().getLocalPort();
+        }
+        void go() throws Exception {
+            try {
+                server(ssc);
+            } finally {
+                ssc.close();
+            }
+        }
+    }
+
+    static void client(int port) throws Exception {
+        // Get a connection from the server
+        InetAddress lh = InetAddress.getLocalHost();
+        InetSocketAddress isa
+            = new InetSocketAddress(lh, port);
+        int connectFailures = 0;
+        boolean result = false;
+        SocketChannel sc = RdmaSockets.openSocketChannel(
+            StandardProtocolFamily.INET);
+        for (;;) {
+            try {
+                result = sc.connect(isa);
+                break;
+            } catch (java.net.ConnectException e) {
+                connectFailures++;
+                if (connectFailures > 30)
+                    throw new RuntimeException("Cannot connect");
+                Thread.currentThread().sleep(100);
+                sc = RdmaSockets.openSocketChannel(StandardProtocolFamily.INET);
+            }
+        }
+        if (result) {
+            System.err.println("Connected");
+        } else {
+            // Only happens when server and client are on separate machines
+            System.err.println("Connection pending...");
+            connectFailures = 0;
+            while (!result) {
+                try {
+                    result = sc.finishConnect();
+                    if (!result)
+                        System.err.println("Not finished");
+                    Thread.sleep(50);
+                } catch (java.net.ConnectException e) {
+                    Thread.sleep(100);
+                    connectFailures++;
+                    if (connectFailures > 30)
+                        throw new RuntimeException("Cannot finish connecting");
+                }
+            }
+            System.err.println("Finished connecting");
+        }
+
+        ByteBuffer bb = ByteBuffer.allocateDirect(1024);
+        if (sc.read(bb) < 0)
+            throw new RuntimeException("Failed to read from server");
+        if (bb.get(0) != 42)
+            throw new RuntimeException("Read wrong byte from server");
+        System.err.println("Read from server");
+        sc.close();
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (!RsocketTest.isRsocketAvailable())
+            throw new SkippedException("rsocket is not available");
+        
+        Server server = new Server();
+        server.start();
+        try {
+            client(server.port());
+        } finally {
+            server.interrupt();
+            server.finish(2000);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/Selector/BasicConnect.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2018, 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 8195160
+ * @summary Test for nonblocking connect and finishConnect
+ * @requires (os.family == "linux")
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @build RsocketTest
+ * @run main/othervm BasicConnect
+ */
+
+import java.net.InetSocketAddress;
+import java.net.StandardProtocolFamily;
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.Iterator;
+import java.util.Set;
+import jdk.net.RdmaSockets;
+
+import jtreg.SkippedException;
+
+/**
+ * Typically there would be more than one channel registered to select
+ * on, this test is just a very simple version with only one channel
+ * registered for the connectSelector.
+ */
+
+public class BasicConnect {
+
+    public static void main(String[] args) throws Exception {
+        if (!RsocketTest.isRsocketAvailable())
+            throw new SkippedException("rsocket is not available");
+
+        Selector connectSelector =
+            RdmaSockets.openSelector();
+        try {
+            TestServers.EchoServer echoServer
+                = TestServers.EchoServer.startNewServer(100);
+            InetSocketAddress isa
+                = new InetSocketAddress(echoServer.getAddress(),
+                                        echoServer.getPort());
+            SocketChannel sc = RdmaSockets.openSocketChannel(
+                StandardProtocolFamily.INET);
+            sc.configureBlocking(false);
+            boolean result = sc.connect(isa);
+            if (result) {
+                System.out.println("Socket immediately connected on "
+                        + System.getProperty("os.name")
+                        + ": " + sc);
+            }
+            while (!result) {
+                SelectionKey connectKey = sc.register(connectSelector,
+                                                      SelectionKey.OP_CONNECT);
+                int keysAdded = connectSelector.select();
+                if (keysAdded > 0) {
+                    Set readyKeys = connectSelector.selectedKeys();
+                    Iterator i = readyKeys.iterator();
+                    while (i.hasNext()) {
+                        SelectionKey sk = (SelectionKey)i.next();
+                        i.remove();
+                        SocketChannel nextReady = (SocketChannel)sk.channel();
+                        result = nextReady.finishConnect();
+                        if (result)
+                            sk.cancel();
+                    }
+                }
+            }
+
+            byte[] bs = new byte[] { (byte)0xca, (byte)0xfe,
+                                     (byte)0xba, (byte)0xbe };
+            ByteBuffer bb = ByteBuffer.wrap(bs);
+            sc.configureBlocking(true);
+            sc.write(bb);
+            bb.rewind();
+
+            ByteBuffer bb2 = ByteBuffer.allocateDirect(100);
+            int n = sc.read(bb2);
+            bb2.flip();
+
+            sc.close();
+            connectSelector.close();
+
+            if (!bb.equals(bb2))
+                throw new Exception("Echoed bytes incorrect: Sent "
+                                    + bb + ", got " + bb2);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException("Test Failed!");
+        } 
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/Selector/Connect.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2018, 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 8195160
+ * @summary Test making lots of Selectors
+ * @requires (os.family == "linux")
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @build RsocketTest
+ * @run main/othervm Connect
+ */
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
+import java.util.Iterator;
+import java.util.Set;
+import jdk.net.RdmaSockets;
+import jtreg.SkippedException;
+import static java.net.StandardProtocolFamily.INET;
+
+public class Connect {
+
+    static int success = 0;
+    static final int LIMIT = 30;
+
+    public static void main(String[] args) throws Exception {
+        if (!RsocketTest.isRsocketAvailable())
+            throw new SkippedException("rsocket is not available");
+
+        try (TestServers.DayTimeServer daytimeServer
+                = TestServers.DayTimeServer.startNewServer(50)) {
+            scaleTest(daytimeServer);
+        }
+    }
+
+    static void scaleTest(TestServers.DayTimeServer daytimeServer)
+        throws Exception
+    {
+        InetAddress myAddress = daytimeServer.getAddress();
+        InetSocketAddress isa = new InetSocketAddress(myAddress, daytimeServer.getPort());
+
+        for (int j=0; j<LIMIT; j++) {
+            SocketChannel sc = RdmaSockets.openSocketChannel(INET);
+            sc.configureBlocking(false);
+            boolean connected = sc.connect(isa);
+            System.out.println("connected = " + connected);
+
+            if (!connected) {
+                Selector selector = RdmaSockets.openSelector();
+                sc.register(selector, SelectionKey.OP_CONNECT);
+                while (!connected) {
+                    int keysAdded = selector.select(100);
+                    if (keysAdded > 0) {
+                        Set<SelectionKey> readyKeys = selector.selectedKeys();
+                        Iterator<SelectionKey> i = readyKeys.iterator();
+                        while (i.hasNext()) {
+                            SelectionKey sk = i.next();
+                            SocketChannel nextReady = (SocketChannel)sk.channel();
+                            connected = nextReady.finishConnect();
+                        }
+                        readyKeys.clear();
+                    }
+                }
+                selector.close();
+            }
+            readAndClose(sc);
+        }
+    }
+
+    static void readAndClose(SocketChannel sc) throws Exception {
+        ByteBuffer bb = ByteBuffer.allocateDirect(100);
+        int n = 0;
+        while (n == 0) // Note this is not a rigorous check for done reading
+            n = sc.read(bb);
+        sc.close();
+        success++;
+        System.out.println("success count = " + success);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/Selector/SelectorTest.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,429 @@
+/*
+ * Copyright (c) 2018, 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 8195160
+ * @summary Test RdmaSelector with RdmaServerSocketChannels
+ * @requires (os.family == "linux")
+ * @library .. /test/lib /test/jdk/java/nio/channels
+ * @build RsocketTest
+ * @run main/othervm BasicAccept
+ */
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.StandardProtocolFamily;
+import java.nio.ByteBuffer;
+import java.nio.channels.Selector;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.Iterator;
+import java.util.Set;
+import jdk.net.RdmaSockets;
+
+import jtreg.SkippedException;
+
+public class SelectorTest {
+    private static List clientList = new LinkedList();
+    private static Random rnd = new Random();
+    public static int NUM_CLIENTS = 5;
+    public static int TEST_PORT = 31452;
+    static PrintStream log = System.err;
+    private static int FINISH_TIME = 30000;
+
+    /*
+     * Usage note
+     *
+     * java SelectorTest [server] [client <host>] [<port>]
+     *
+     * No arguments runs both client and server in separate threads
+     * using the default port of 31452.
+     *
+     * client runs the client on this machine and connects to server
+     * at the given IP address.
+     *
+     * server runs the server on localhost.
+     */
+    public static void main(String[] args) throws Exception {
+        if (!RsocketTest.isRsocketAvailable())
+            throw new SkippedException("rsocket is not available");
+
+        if (args.length == 0) {
+            Server server = new Server(0);
+            server.start();
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException e) { }
+            InetSocketAddress isa
+                = new InetSocketAddress(InetAddress.getLocalHost(), server.port());
+            Client client = new Client(isa);
+            client.start();
+            if ((server.finish(FINISH_TIME) & client.finish(FINISH_TIME)) == 0)
+                throw new Exception("Failure");
+            log.println();
+
+        } else if (args[0].equals("server")) {
+
+            if (args.length > 1)
+                TEST_PORT = Integer.parseInt(args[1]);
+            Server server = new Server(TEST_PORT);
+            server.start();
+            if (server.finish(FINISH_TIME) == 0)
+                throw new Exception("Failure");
+            log.println();
+
+        } else if (args[0].equals("client")) {
+
+            if (args.length < 2) {
+                log.println("No host specified: terminating.");
+                return;
+            }
+            String ip = args[1];
+            if (args.length > 2)
+                TEST_PORT = Integer.parseInt(args[2]);
+            InetAddress ia = InetAddress.getByName(ip);
+            InetSocketAddress isa = new InetSocketAddress(ia, TEST_PORT);
+            Client client = new Client(isa);
+            client.start();
+            if (client.finish(FINISH_TIME) == 0)
+                throw new Exception("Failure");
+            log.println();
+
+        } else {
+            System.out.println("Usage note:");
+            System.out.println("java SelectorTest [server] [client <host>] [<port>]");
+            System.out.println("No arguments runs both client and server in separate threads using the default port of 31452.");
+            System.out.println("client runs the client on this machine and connects to the server specified.");
+            System.out.println("server runs the server on localhost.");
+        }
+    }
+
+    static class Client extends TestThread {
+        InetSocketAddress isa;
+        Client(InetSocketAddress isa) {
+            super("Client", SelectorTest.log);
+            this.isa = isa;
+        }
+
+        public void go() throws Exception {
+            log.println("starting client...");
+            for (int i=0; i<NUM_CLIENTS; i++)
+                clientList.add(new RemoteEntity(i, isa, log));
+
+            Collections.shuffle(clientList);
+
+            log.println("created "+NUM_CLIENTS+" clients");
+            do {
+                for (Iterator i = clientList.iterator(); i.hasNext(); ) {
+                    RemoteEntity re = (RemoteEntity) i.next();
+                    if (re.cycle()) {
+                        i.remove();
+                    }
+                }
+                Collections.shuffle(clientList);
+            } while (clientList.size() > 0);
+        }
+    }
+
+    static class Server extends TestThread {
+        private final ServerSocketChannel ssc;
+        private List socketList = new ArrayList();
+        private ServerSocket ss;
+        private int connectionsAccepted = 0;
+        private Selector pollSelector;
+        private Selector acceptSelector;
+        private Set pkeys;
+        private Set pskeys;
+
+        Server(int port) throws IOException {
+            super("Server", SelectorTest.log);
+            this.ssc = RdmaSockets.openServerSocketChannel(
+                StandardProtocolFamily.INET);
+            ssc.bind(new InetSocketAddress(InetAddress.getLocalHost(), port));
+        }
+
+        int port() {
+            return ssc.socket().getLocalPort();
+        }
+
+        public void go() throws Exception {
+            log.println("starting server...");
+            acceptSelector = RdmaSockets.openSelector();
+            pollSelector = RdmaSockets.openSelector();
+            pkeys = pollSelector.keys();
+            pskeys = pollSelector.selectedKeys();
+            Set readyKeys = acceptSelector.selectedKeys();
+            RequestHandler rh = new RequestHandler(pollSelector, log);
+            Thread requestThread = new Thread(rh);
+
+            requestThread.start();
+
+            ssc.configureBlocking(false);
+            SelectionKey acceptKey = ssc.register(acceptSelector,
+                                                  SelectionKey.OP_ACCEPT);
+            while(connectionsAccepted < SelectorTest.NUM_CLIENTS) {
+                int keysAdded = acceptSelector.select(100);
+                if (keysAdded > 0) {
+                    Iterator i = readyKeys.iterator();
+                    while(i.hasNext()) {
+                        SelectionKey sk = (SelectionKey)i.next();
+                        i.remove();
+                        ServerSocketChannel nextReady =
+                            (ServerSocketChannel)sk.channel();
+                        SocketChannel sc = nextReady.accept();
+                        connectionsAccepted++;
+                        if (sc != null) {
+                            sc.configureBlocking(false);
+                            synchronized (pkeys) {
+                               sc.register(pollSelector, SelectionKey.OP_READ);
+                            }
+                        } else {
+                            throw new RuntimeException(
+                                "Socket does not support Channels");
+                        }
+                    }
+                }
+            }
+            acceptKey.cancel();
+            requestThread.join();
+            acceptSelector.close();
+            pollSelector.close();
+        }
+    }
+}
+
+class RemoteEntity {
+    private static Random rnd = new Random();
+    int id;
+    ByteBuffer data;
+    int dataWrittenIndex;
+    int totalDataLength;
+    boolean initiated = false;
+    boolean connected = false;
+    boolean written = false;
+    boolean acked = false;
+    boolean closed = false;
+    private SocketChannel sc;
+    ByteBuffer ackBuffer;
+    PrintStream log;
+    InetSocketAddress server;
+
+    RemoteEntity(int id, InetSocketAddress server, PrintStream log)
+        throws Exception
+    {
+        int connectFailures = 0;
+        this.id = id;
+        this.log = log;
+        this.server = server;
+
+        sc = RdmaSockets.openSocketChannel(StandardProtocolFamily.INET);
+        sc.configureBlocking(false);
+
+        // Prepare the data buffer to write out from this entity
+        // Let's use both slow and fast buffers
+        if (rnd.nextBoolean())
+            data = ByteBuffer.allocateDirect(100);
+        else
+            data = ByteBuffer.allocate(100);
+        String number = Integer.toString(id);
+        if (number.length() == 1)
+            number = "0"+number;
+        String source = "Testing from " + number;
+        data.put(source.getBytes("8859_1"));
+        data.flip();
+        totalDataLength = source.length();
+
+        // Allocate an ack buffer
+        ackBuffer = ByteBuffer.allocateDirect(10);
+    }
+
+    private void reset() throws Exception {
+        sc.close();
+        sc = RdmaSockets.openSocketChannel(StandardProtocolFamily.INET);
+        sc.configureBlocking(false);
+    }
+
+    private void connect() throws Exception {
+        try {
+            connected = sc.connect(server);
+            initiated = true;
+        }  catch (ConnectException e) {
+            initiated = false;
+            reset();
+        }
+    }
+
+    private void finishConnect() throws Exception {
+        try {
+            connected = sc.finishConnect();
+        }  catch (IOException e) {
+            initiated = false;
+            reset();
+        }
+    }
+
+    int id() {
+        return id;
+    }
+
+    boolean cycle() throws Exception {
+        if (!initiated)
+            connect();
+        else if (!connected)
+            finishConnect();
+        else if (!written)
+            writeCycle();
+        else if (!acked)
+            ackCycle();
+        else if (!closed)
+            close();
+        return closed;
+    }
+
+    private void ackCycle() throws Exception {
+        //log.println("acking from "+id);
+        int bytesRead = sc.read(ackBuffer);
+        if (bytesRead > 0) {
+            acked = true;
+        }
+    }
+
+    private void close() throws Exception {
+        sc.close();
+        closed = true;
+    }
+
+    private void writeCycle() throws Exception {
+        log.println("writing from "+id);
+        int numBytesToWrite = rnd.nextInt(10)+1;
+        int newWriteTarget = dataWrittenIndex + numBytesToWrite;
+        if (newWriteTarget > totalDataLength)
+            newWriteTarget = totalDataLength;
+        data.limit(newWriteTarget);
+        int bytesWritten = sc.write(data);
+        if (bytesWritten > 0)
+            dataWrittenIndex += bytesWritten;
+        if (dataWrittenIndex == totalDataLength) {
+            written = true;
+            sc.socket().shutdownOutput();
+        }
+    }
+
+}
+
+
+class RequestHandler implements Runnable {
+    private static Random rnd = new Random();
+    private Selector selector;
+    private int connectionsHandled = 0;
+    private HashMap dataBin = new HashMap();
+    PrintStream log;
+
+    public RequestHandler(Selector selector, PrintStream log) {
+        this.selector = selector;
+        this.log = log;
+    }
+
+    public void run() {
+        log.println("starting request handler...");
+        int connectionsAccepted = 0;
+
+        Set nKeys = selector.keys();
+        Set readyKeys = selector.selectedKeys();
+
+        try {
+            while(connectionsHandled < SelectorTest.NUM_CLIENTS) {
+                int numKeys = selector.select(100);
+
+                // Process channels with data
+                synchronized (nKeys) {
+                    if (readyKeys.size() > 0) {
+                        Iterator i = readyKeys.iterator();
+                        while(i.hasNext()) {
+                            SelectionKey sk = (SelectionKey)i.next();
+                            i.remove();
+                            SocketChannel sc = (SocketChannel)sk.channel();
+                            if (sc.isOpen())
+                                read(sk, sc);
+                        }
+                    }
+                }
+
+                // Give other threads a chance to run
+                if (numKeys == 0) {
+                    try {
+                        Thread.sleep(1);
+                    } catch (Exception x) {}
+                }
+            }
+        } catch (Exception e) {
+            log.println("Unexpected error 1: "+e);
+            e.printStackTrace();
+        }
+    }
+
+    private void read(SelectionKey sk, SocketChannel sc) throws Exception {
+        ByteBuffer bin = (ByteBuffer)dataBin.get(sc);
+        if (bin == null) {
+            if (rnd.nextBoolean())
+                bin = ByteBuffer.allocateDirect(100);
+            else
+                bin = ByteBuffer.allocate(100);
+            dataBin.put(sc, bin);
+        }
+
+        int bytesRead = 0;
+        do {
+            bytesRead = sc.read(bin);
+        } while(bytesRead > 0);
+
+        if (bytesRead == -1) {
+            sk.interestOps(0);
+            bin.flip();
+            int size = bin.limit();
+            byte[] data = new byte[size];
+            for(int j=0; j<size; j++)
+                data[j] = bin.get();
+            String message = new String(data, "8859_1");
+            connectionsHandled++;
+            acknowledge(sc);
+            log.println("Received >>>"+message + "<<<");
+            log.println("Handled: "+connectionsHandled);
+        }
+    }
+
+    private void acknowledge(SocketChannel sc) throws Exception {
+            ByteBuffer ackBuffer = ByteBuffer.allocateDirect(10);
+            String s = "ack";
+            ackBuffer.put(s.getBytes("8859_1"));
+            ackBuffer.flip();
+            int bytesWritten = 0;
+            while(bytesWritten == 0) {
+                bytesWritten += sc.write(ackBuffer);
+            }
+            sc.close();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/ServerSocketChannel/Basic.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2018, 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 8195160
+ * @summary Unit test for server-socket channels
+ * @requires (os.family == "linux")
+ * @library .. /test/lib /test/jdk/java/nio/channels
+ * @build RsocketTest
+ * @run main/othervm Basic
+ */
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.StandardProtocolFamily;
+import java.nio.ByteBuffer;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.util.Random;
+import jdk.net.RdmaSockets;
+
+import jtreg.SkippedException;
+
+public class Basic {
+
+    static PrintStream log = System.err;
+
+    static class Server
+        extends TestThread
+    {
+        ServerSocketChannel ssc;
+        boolean block;
+
+        Server(ServerSocketChannel ssc, boolean block) {
+            super("Server", Basic.log);
+            this.ssc = ssc;
+            this.block = block;
+        }
+
+        void go() throws Exception {
+            log.println("Server: Listening "
+                        + (block ? "(blocking)" : "(non-blocking)"));
+            if (!block)
+                ssc.configureBlocking(false);
+            log.println("  " + ssc);
+            SocketChannel sc = null;
+            for (;;) {
+                sc = ssc.accept();
+                if (sc != null) {
+                    break;
+                }
+                log.println("Server: Sleeping...");
+                Thread.sleep(50);
+            }
+            log.println("Server: Accepted " + sc);
+            ByteBuffer bb = ByteBuffer.allocateDirect(100);
+            if (sc.read(bb) != 1)
+                throw new Exception("Read failed");
+            bb.flip();
+            byte b = bb.get();
+            log.println("Server: Read " + b + ", writing " + (b + 1));
+            bb.clear();
+            bb.put((byte)43);
+            bb.flip();
+            if (sc.write(bb) != 1)
+                throw new Exception("Write failed");
+            sc.close();
+            ssc.close();
+            log.println("Server: Finished");
+        }
+
+    }
+
+    static class Client
+        extends TestThread
+    {
+        int port;
+        boolean dally;
+
+        Client(int port, boolean block) {
+            super("Client", Basic.log);
+            this.port = port;
+            this.dally = !block;
+        }
+
+        public void go() throws Exception {
+            if (dally)
+                Thread.sleep(200);
+            InetSocketAddress isa
+                = new InetSocketAddress(InetAddress.getLocalHost(), port);
+            log.println("Client: Connecting to " + isa);
+            SocketChannel sc = RdmaSockets.openSocketChannel(
+                StandardProtocolFamily.INET);
+            sc.connect(isa);
+            log.println("Client: Connected");
+            ByteBuffer bb = ByteBuffer.allocateDirect(512);
+            bb.put((byte)42).flip();
+            log.println("Client: Writing " + bb.get(0));
+            if (sc.write(bb) != 1)
+                throw new Exception("Write failed");
+            bb.clear();
+            if (sc.read(bb) != 1)
+                throw new Exception("Read failed");
+            bb.flip();
+            if (bb.get() != 43)
+                throw new Exception("Read " + bb.get(bb.position() - 1));
+            log.println("Client: Read " + bb.get(0));
+            sc.close();
+            log.println("Client: Finished");
+        }
+
+    }
+
+    static void test(boolean block) throws Exception {
+        ServerSocketChannel ssc = RdmaSockets.openServerSocketChannel(
+            StandardProtocolFamily.INET);
+        ssc.socket().setReuseAddress(true);
+        InetAddress lh = InetAddress.getLocalHost();
+        int port;
+        Random r = new Random();
+        for (;;) {
+            port = r.nextInt((1 << 16) - 1024) + 1024;
+            InetSocketAddress isa = new InetSocketAddress(lh, port);
+            try {
+                ssc.socket().bind(isa);
+            } catch (IOException x) {
+                continue;
+            }
+            break;
+        }
+
+        Server server = new Server(ssc, block);
+        Client client = new Client(port, block);
+        server.start();
+        client.start();
+        if ((server.finish(0) & client.finish(0)) == 0)
+            throw new Exception("Failure");
+        log.println();
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (!RsocketTest.isRsocketAvailable())
+            throw new SkippedException("rsocket is not available");
+
+        log.println();
+        test(true);
+        test(false);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/ServerSocketChannel/SSCConfigureBlocking.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2018, 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 8195160
+ * @summary Tests blocking configuration of server socket channels
+ * @requires (os.family == "linux")
+ * @library ../ /test/lib
+ * @build RsocketTest
+ * @run testng/othervm SSCConfigureBlocking
+ */
+
+import java.io.IOException;
+import java.net.ProtocolFamily;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import org.testng.SkipException;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static java.net.StandardProtocolFamily.INET;
+import static java.net.StandardProtocolFamily.INET6;
+import static java.nio.channels.SelectionKey.OP_ACCEPT;
+import static jdk.net.RdmaSockets.*;
+import static org.testng.Assert.assertThrows;
+import static org.testng.Assert.assertTrue;
+
+public class SSCConfigureBlocking {
+
+    @BeforeTest
+    public void setup() throws Exception {
+        if (!RsocketTest.isRsocketAvailable())
+            throw new SkipException("rsocket is not available");
+    }
+
+    @DataProvider(name = "families")
+    public Object[][] families() {
+        return new Object[][] { { INET }, { INET6 } };
+    }
+
+     // Newly-created selectable channels are always in blocking mode.
+
+    @Test(dataProvider = "families")
+    public void testServerSocketChannel(ProtocolFamily family)
+        throws IOException
+    {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            assertTrue(ssc.isBlocking(), "Newly created channel is not blocking");
+            ssc.configureBlocking(false);
+            assertTrue(!ssc.isBlocking(), "Expected non-blocking");
+            ssc.configureBlocking(true);
+            assertTrue(ssc.isBlocking(), "Expected blocking");
+        }
+    }
+
+    static final Class<IllegalBlockingModeException> IBME = IllegalBlockingModeException.class;
+
+    @Test(dataProvider = "families")
+    public void testServerSocketChannelRegister(ProtocolFamily family)
+        throws IOException
+    {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family);
+             Selector selector = Selector.open()) {
+            assertThrows(IBME, () -> ssc.register(selector, OP_ACCEPT));
+            assertThrows(IBME, () -> ssc.register(selector, OP_ACCEPT, new Object()));
+            ssc.configureBlocking(false);
+            ssc.register(selector, OP_ACCEPT);
+            assertThrows(IBME, () -> ssc.configureBlocking(true));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/ServerSocketChannel/SocketOptionTests.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2018, 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 8195160
+ * @summary Unit test for ServerSocketChannel setOption/getOption/options
+ *          methods.
+ * @modules jdk.net
+ * @requires !vm.graal.enabled
+ * @requires (os.family == "linux")
+ * @library .. /test/lib
+ * @build RsocketTest
+ * @run main/othervm SocketOptionTests
+ */
+
+import java.io.IOException;
+import java.net.StandardProtocolFamily;
+import java.net.SocketOption;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ServerSocketChannel;
+import java.util.Set;
+import jdk.net.RdmaSockets;
+import static java.net.StandardSocketOptions.*;
+import static jdk.net.RdmaSocketOptions.*;
+
+import jtreg.SkippedException;
+
+public class SocketOptionTests {
+
+    static void checkOption(ServerSocketChannel ssc, SocketOption name, Object expectedValue)
+        throws IOException
+    {
+        Object value = ssc.getOption(name);
+        if (!value.equals(expectedValue))
+            throw new RuntimeException("value not as expected");
+    }
+
+    public static void main(String[] args) throws IOException {
+        if (!RsocketTest.isRsocketAvailable())
+            throw new SkippedException("rsocket is not available");
+
+        ServerSocketChannel ssc = RdmaSockets.openServerSocketChannel(
+            StandardProtocolFamily.INET);
+
+        // check supported options
+        Set<SocketOption<?>> options = ssc.supportedOptions();
+        if (!options.contains(SO_REUSEADDR))
+            throw new RuntimeException("SO_REUSEADDR should be supported");
+        if (!options.contains(SO_RCVBUF))
+            throw new RuntimeException("SO_RCVBUF should be supported");
+        if (!options.contains(RDMA_SQSIZE))
+            throw new RuntimeException("RDMA_SQSIZE should be supported");
+        if (!options.contains(RDMA_RQSIZE))
+            throw new RuntimeException("RDMA_RQSIZE should be supported");
+        if (!options.contains(RDMA_INLINE))
+            throw new RuntimeException("RDMA_INLINE should be supported");
+
+        // allowed to change when not bound
+        ssc.setOption(SO_RCVBUF, 256*1024);     // can't check
+        int before = ssc.getOption(SO_RCVBUF);
+        int after = ssc.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF);
+        if (after < before)
+            throw new RuntimeException("setOption caused SO_RCVBUF to decrease");
+        ssc.setOption(SO_REUSEADDR, true);
+        checkOption(ssc, SO_REUSEADDR, true);
+        ssc.setOption(SO_REUSEADDR, false);
+        checkOption(ssc, SO_REUSEADDR, false);
+
+        // NullPointerException
+        try {
+            ssc.setOption(null, "value");
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException x) {
+        }
+        try {
+            ssc.getOption(null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException x) {
+        }
+
+        // ClosedChannelException
+        ssc.close();
+        try {
+            ssc.setOption(SO_REUSEADDR, true);
+            throw new RuntimeException("ClosedChannelException not thrown");
+        } catch (ClosedChannelException x) {
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/Socket/BasicSocketTest.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2018, 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 8195160
+ * @summary Test for basic functionality for RdmaSocket and RdmaServerSocket
+ * @requires (os.family == "linux")
+ * @library .. /test/lib
+ * @build RsocketTest
+ * @run main/othervm BasicSocketTest
+ */
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.StandardProtocolFamily;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import jdk.net.RdmaSockets;
+
+import jtreg.SkippedException;
+
+public class BasicSocketTest implements Runnable {
+    static ServerSocket ss;
+    static Socket s1, s2;
+    static InetAddress iaddr;
+    static int port = 0;
+    static ServerSocketChannel ssc;
+    static SocketChannel sc1, sc2;
+    static String message = "This is a message!";
+    static int length = -1;
+
+    public static void main(String args[]) throws Exception {
+        if (!RsocketTest.isRsocketAvailable())
+            throw new SkippedException("rsocket is not available");
+
+        iaddr = InetAddress.getLocalHost();
+
+        try {
+            ss = RdmaSockets.openServerSocket(StandardProtocolFamily.INET);
+            s1 = RdmaSockets.openSocket(StandardProtocolFamily.INET);         
+            ss.bind(new InetSocketAddress(iaddr, port));
+
+            Thread t = new Thread(new BasicSocketTest());
+            t.start();
+            s2 = ss.accept();
+
+            InputStream is = s2.getInputStream();
+            length = message.length();
+
+            int num = 0;
+            byte[] buf = new byte[length];
+            while (num < length) {
+                int l = is.read(buf);
+                num += l;
+            }
+
+            String result = new String(buf);
+            if(!result.equals(message))
+                throw new RuntimeException("Test Failed!");
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException("Test Failed!");
+        } finally {
+            ss.close();
+            s1.close();
+            s2.close();
+        }
+    }
+
+    public void run() {
+        try {
+            s1.connect(new InetSocketAddress(iaddr, ss.getLocalPort()));
+
+            OutputStream os = s1.getOutputStream();
+            os.write(message.getBytes());
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException("Test Failed!");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/Socket/GetLocalAddress.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2018, 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 8195160
+ * @summary Test the java.net.socket.GetLocalAddress method
+ * @requires (os.family == "linux")
+ * @library .. /test/lib
+ * @build RsocketTest
+ * @run main/othervm GetLocalAddress
+ */
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.StandardProtocolFamily;
+import java.net.ServerSocket;
+import java.net.Socket;
+import jdk.net.RdmaSockets;
+
+import jtreg.SkippedException;
+
+public class GetLocalAddress implements Runnable {
+    static Socket s;
+    static ServerSocket ss;
+    static InetAddress addr;
+    static int port;
+
+    public static void main(String args[]) throws Exception {
+        if (!RsocketTest.isRsocketAvailable())
+            throw new SkippedException("rsocket is not available");
+
+        testBindNull();
+
+        boolean error = true;
+        int value = 0;
+        addr = InetAddress.getLocalHost();
+
+        ss = RdmaSockets.openServerSocket(StandardProtocolFamily.INET);
+        s = RdmaSockets.openSocket(StandardProtocolFamily.INET);
+        addr = InetAddress.getLocalHost();
+        ss.bind(new InetSocketAddress(addr, 0));
+
+        port = ss.getLocalPort();
+
+        Thread t = new Thread(new GetLocalAddress());
+        t.start();
+
+        Socket soc = ss.accept();
+
+        if(addr.equals(soc.getLocalAddress())) {
+            error = false;
+        }
+        if (error)
+            throw new RuntimeException("Socket.GetLocalAddress failed.");
+        soc.close();
+    }
+
+    public void run() {
+        try {
+            s.connect(new InetSocketAddress(addr, port));
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException("Socket.GetLocalAddress failed.");
+        }
+    }
+
+    static void testBindNull() throws Exception {
+        try {
+            Socket soc = RdmaSockets.openSocket(StandardProtocolFamily.INET);
+            soc.bind(null);
+            if (!soc.isBound())
+                throw new RuntimeException(
+                    "should be bound after bind(null)");
+            if (soc.getLocalPort() <= 0)
+                throw new RuntimeException(
+                   "bind(null) failed, local port: " + soc.getLocalPort());
+            if (soc.getLocalAddress() == null)
+                 throw new RuntimeException(
+                   "bind(null) failed, local address is null");
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException("Socket.GetLocalAddress failed.");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/SocketChannel/BasicSocketChannelTest.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2018, 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 8195160
+ * @summary Test for basic functionality for RdmaSocketChannel
+ *         and RdmaServerSocketChannel
+ * @requires (os.family == "linux")
+ * @library ../ /test/lib
+ * @build RsocketTest
+ * @run main/othervm BasicSocketChannelTest
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.net.*;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.ByteBuffer;
+import jdk.net.RdmaSockets;
+import jtreg.SkippedException;
+import static java.lang.String.format;
+import static java.lang.System.out;
+import static java.net.StandardProtocolFamily.INET;
+import static java.net.StandardProtocolFamily.INET6;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+public class BasicSocketChannelTest {
+
+    static final String MESSAGE = "This is a MESSAGE!";
+    static final int MESSAGE_LENGTH = MESSAGE.length();
+
+    public static void main(String args[]) throws Exception {
+        if (!RsocketTest.isRsocketAvailable())
+            throw new SkippedException("rsocket is not available");
+
+        InetAddress iaddr = InetAddress.getLocalHost();
+        ProtocolFamily family = iaddr instanceof Inet6Address ? INET6 : INET;
+        out.printf("local address: %s%n", iaddr);
+
+        testChannel(iaddr, family);
+        testSocket(iaddr, family);
+    }
+
+    // Tests SocketChannel and ServerSocketChannel
+    static void testChannel(InetAddress iaddr, ProtocolFamily family) throws Exception {
+        out.printf("--- testChannel iaddr:%s, family:%s%n", iaddr, family);
+
+        try (ServerSocketChannel ssc = RdmaSockets.openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(iaddr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            Thread t = new Thread("Channel") {
+                public void run() {
+                    try (SocketChannel sc1 = RdmaSockets.openSocketChannel(family)) {
+                        sc1.connect(new InetSocketAddress(iaddr, port));
+                        if (!sc1.isConnected())
+                            throw new RuntimeException("Unconnected channel:" + sc1);
+                        ByteBuffer input = ByteBuffer.allocate(MESSAGE_LENGTH);
+                        input.put(MESSAGE.getBytes(UTF_8));
+                        input.flip();
+                        int inputNum = 0;
+                        while (inputNum < MESSAGE_LENGTH) {
+                            inputNum += sc1.write(input);
+                        }
+                        sc1.shutdownInput();
+                        assertInputShutdown(sc1);
+                        sc1.shutdownOutput();
+                        assertOutputShutdown(sc1);
+                    } catch (IOException e) {
+                        throw new UncheckedIOException(e);
+                    }
+                }
+            };
+            t.start();
+
+            try (SocketChannel sc2 = ssc.accept()) {
+                ByteBuffer output = ByteBuffer.allocate(MESSAGE_LENGTH + 1);
+                while (sc2.read(output) != -1);
+                output.flip();
+
+                String result = UTF_8.decode(output).toString();
+                if (!result.equals(MESSAGE)) {
+                    String msg = format("Expected [%s], received [%s]", MESSAGE, result);
+                    throw new RuntimeException("Test Failed! " + msg);
+                }
+                sc2.shutdownInput();
+                assertInputShutdown(sc2);
+                sc2.shutdownOutput();
+                assertOutputShutdown(sc2);
+            }
+            t.join();
+            out.printf("passed%n");
+        }
+    }
+
+    // Tests SocketChannel.socket() and ServerSocketChannel.socket()
+    static void testSocket(InetAddress iaddr, ProtocolFamily family) throws Exception {
+        out.printf("--- testSocket iaddr:%s, family:%s%n", iaddr, family);
+
+        try (ServerSocketChannel ssc = RdmaSockets.openServerSocketChannel(family)) {
+            ssc.socket().bind(new InetSocketAddress(iaddr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            Thread t = new Thread("Socket") {
+                public void run() {
+                    try (SocketChannel sc1 = RdmaSockets.openSocketChannel(family);
+                         Socket client = sc1.socket()) {
+                        client.connect(new InetSocketAddress(iaddr, port));
+                        if (!client.isConnected())
+                            throw new RuntimeException("Test Failed!");
+                        InputStream is = client.getInputStream();
+                        OutputStream os = client.getOutputStream();
+                        os.write(MESSAGE.getBytes(UTF_8));
+
+                        client.shutdownInput();
+                        assertInputShutdown(sc1);
+                        assertInputShutdown(client, is);
+                        client.shutdownOutput();
+                        assertOutputShutdown(sc1);
+                        assertOutputShutdown(client, os);
+                    } catch (IOException e) {
+                        throw new UncheckedIOException(e);
+                    }
+                }
+            };
+            t.start();
+
+            try (Socket conn = ssc.socket().accept()) {
+                InputStream is = conn.getInputStream();
+                OutputStream os = conn.getOutputStream();
+                byte[] buf = is.readAllBytes();
+
+                String result = new String(buf, UTF_8);
+                if (!result.equals(MESSAGE)) {
+                    String msg = format("Expected [%s], received [%s]", MESSAGE, result);
+                    throw new RuntimeException("Test Failed! " + msg);
+                }
+                conn.shutdownInput();
+                assertInputShutdown(conn, is);
+                conn.shutdownOutput();
+                assertOutputShutdown(conn, os);
+            }
+            t.join();
+            out.printf("passed%n");
+        }
+    }
+
+    static void assertInputShutdown(SocketChannel sc) throws IOException {
+        ByteBuffer bb = ByteBuffer.allocate(1);
+        int r = sc.read(bb);
+        if (r != -1)
+            throw new RuntimeException(format("Unexpected read of %d bytes", r));
+
+        try {
+            sc.socket().getInputStream();
+        } catch (IOException expected) {
+            String msg = expected.getMessage();
+            if (!msg.contains("input"))
+                throw new RuntimeException("Expected to find \"input\" in " + expected);
+            if (!msg.contains("shutdown"))
+                throw new RuntimeException("Expected to find \"shutdown\" in " + expected);
+        }
+    }
+
+    static void assertOutputShutdown(SocketChannel sc) throws IOException {
+        ByteBuffer bb = ByteBuffer.allocate(1);
+        bb.put((byte)0x05);
+        bb.flip();
+        try {
+            sc.write(bb);
+            throw new RuntimeException("Unexpected write of bytes");
+        } catch (ClosedChannelException expected) { }
+
+        try {
+            sc.socket().getOutputStream();
+        } catch (IOException expected) {
+            String msg = expected.getMessage();
+            if (!msg.contains("output"))
+                throw new RuntimeException("Expected to find \"output\" in " + expected);
+            if (!msg.contains("shutdown"))
+                throw new RuntimeException("Expected to find \"shutdown\" in " + expected);
+        }
+    }
+
+    static void assertInputShutdown(Socket s, InputStream is) throws IOException {
+        if (!s.isInputShutdown()) {
+            throw new RuntimeException("Unexpected open input: " + s);
+        }
+        int r;
+        if ((r = is.read()) != -1)
+            throw new RuntimeException(format("Unexpected read of %d", r));
+
+        try {
+            s.getInputStream();
+        } catch (IOException expected) {
+            String msg = expected.getMessage();
+            if (!msg.contains("input"))
+                throw new RuntimeException("Expected to find \"input\" in " + expected);
+            if (!msg.contains("shutdown"))
+                throw new RuntimeException("Expected to find \"shutdown\" in " + expected);
+        }
+    }
+
+    static void assertOutputShutdown(Socket s, OutputStream os) throws IOException {
+        if (!s.isOutputShutdown()) {
+            throw new RuntimeException("Unexpected open output: " + s);
+        }
+        try {
+            os.write((byte)0x07);
+            throw new RuntimeException("Unexpected write of bytes");
+        } catch (ClosedChannelException expected) { }
+
+        try {
+            s.getOutputStream();
+        } catch (IOException expected) {
+            String msg = expected.getMessage();
+            if (!msg.contains("output"))
+                throw new RuntimeException("Expected to find \"output\" in " + expected);
+            if (!msg.contains("shutdown"))
+                throw new RuntimeException("Expected to find \"shutdown\" in " + expected);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/SocketChannel/CloseDuringWrite.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2018, 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 8195160
+ * @summary Test asynchronous close during a blocking write
+ * @requires (os.family == "linux")
+ * @library .. /test/lib
+ * @build RsocketTest
+ * @run main/othervm CloseDuringWrite
+ * @key randomness
+ */
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ProtocolFamily;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.Random;
+import jdk.net.RdmaSockets;
+import jtreg.SkippedException;
+import static java.net.StandardProtocolFamily.INET;
+import static java.net.StandardProtocolFamily.INET6;
+
+public class CloseDuringWrite {
+
+    static final Random rand = new Random();
+
+    /**
+     * A task that closes a Closeable
+     */
+    static class Closer implements Callable<Void> {
+        final Closeable c;
+        Closer(Closeable c) {
+            this.c = c;
+        }
+        public Void call() throws IOException {
+            c.close();
+            return null;
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (!RsocketTest.isRsocketAvailable())
+            throw new SkippedException("rsocket is not available");
+
+        InetAddress lh = InetAddress.getLocalHost();
+        ProtocolFamily family = lh instanceof Inet6Address ? INET6 : INET;
+        System.out.printf("local address: %s%n", lh);
+
+        ScheduledExecutorService pool = Executors.newSingleThreadScheduledExecutor();
+        try (ServerSocketChannel ssc = RdmaSockets.openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(lh, 0));
+            int port = ssc.socket().getLocalPort();
+            SocketAddress sa = new InetSocketAddress(lh, port);
+
+            ByteBuffer bb = ByteBuffer.allocate(2 * 1024 * 1024);
+
+            for (int i = 0; i < 20; i++) {
+                System.out.println(i);
+                try (SocketChannel source = RdmaSockets.openSocketChannel(family)) {
+                    Runnable runnable = new Runnable() {
+                        @Override
+                        public void run() {
+                            try {
+                                System.out.println("connecting ...");
+                                source.connect(sa);
+                                System.out.println("connected");
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                                throw new RuntimeException("Test Failed");
+                            }
+                        }
+                    };
+
+                    Thread t = new Thread(runnable);
+                    t.start();
+                    try (SocketChannel sink = ssc.accept()) {
+                        System.out.println("accepted new connection");
+                        // schedule channel to be closed
+                        Closer c = new Closer(source);
+                        int when = 1000 + rand.nextInt(2000);
+                        Future<Void> result = pool.schedule(c, when, TimeUnit.MILLISECONDS);
+
+                        // the write should either succeed or else throw a
+                        // ClosedChannelException (more likely an
+                        // AsynchronousCloseException)
+                        try {
+                            for (;;) {
+                                int limit = rand.nextInt(bb.capacity());
+                                bb.position(0);
+                                bb.limit(limit);
+                                int n = source.write(bb);
+                                System.out.format("wrote %d, expected %d%n", n, limit);
+                            }
+                        } catch (ClosedChannelException expected) {
+                            System.out.println(expected + " (expected)");
+                        } finally {
+                            result.get();
+                        }
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    throw new RuntimeException("Test Failed");
+                }
+            }
+        } finally {
+            pool.shutdown();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/SocketChannel/Connect.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2018, 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 8195160
+ * @summary Unit test for socket channels
+ * @requires (os.family == "linux")
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @build RsocketTest
+ * @run main/othervm Connect
+ */
+
+import java.net.ConnectException;
+import java.net.InetSocketAddress;
+import java.net.StandardProtocolFamily;
+import java.nio.ByteBuffer;
+import java.nio.channels.Selector;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.SocketChannel;
+import java.util.Set;
+import jdk.net.RdmaSockets;
+
+import jtreg.SkippedException;
+
+public class Connect {
+
+    private static final long INCREMENTAL_DELAY = 30L * 1000L;
+
+    public static void main(String args[]) throws Exception {
+        if (!RsocketTest.isRsocketAvailable())
+            throw new SkippedException("rsocket is not available");
+
+        try (TestServers.EchoServer echoServer
+                = TestServers.EchoServer.startNewServer(1000)) {
+            test1(echoServer);
+        }
+        try {
+            test1(TestServers.RefusingServer.newRefusingServer());
+            throw new Exception("Refused connection throws no exception");
+        } catch (ConnectException ce) {
+            // Correct result
+        }
+    }
+
+    static void test1(TestServers.AbstractServer server) throws Exception {
+        Selector selector;
+        SocketChannel sc;
+        SelectionKey sk;
+        InetSocketAddress isa = new InetSocketAddress(
+            server.getAddress(), server.getPort());
+        sc = RdmaSockets.openSocketChannel(StandardProtocolFamily.INET);
+        sc.configureBlocking(false);
+
+        selector = RdmaSockets.openSelector();
+        sk = sc.register(selector, SelectionKey.OP_CONNECT);
+        if (sc.connect(isa)) {
+            System.err.println("Connected immediately!");
+            sc.close();
+            selector.close();
+            return;
+        } else {
+            ByteBuffer buf = ByteBuffer.allocateDirect(100);
+            buf.asCharBuffer().put(new String(
+                "The quick brown fox jumped over the lazy dog."
+                ).toCharArray());
+            buf.flip();
+            long startTime = System.currentTimeMillis();
+            while(true) {
+                selector.select(INCREMENTAL_DELAY);
+                Set selectedKeys = selector.selectedKeys();
+
+                if(selectedKeys.isEmpty()) {
+                    System.err.println("Elapsed time without response: " +
+                                       (System.currentTimeMillis() -
+                                        startTime) / 1000L + " seconds.");
+                }
+                else if(!selectedKeys.contains(sk))
+                {
+                    System.err.println("Got wrong event about selection key.");
+                } else {
+                    System.err.println("Got event for our selection key.");
+                    if(sk.isConnectable()) {
+                        if(sc.finishConnect()) {
+                            if(sc.isConnected()) {
+                                System.err.println("Successful connect.");
+                                sk.interestOps(SelectionKey.OP_WRITE);
+                                sc.write(buf);
+                            } else {
+                                System.err.println(
+                                      "Finish connect completed incorrectly.");
+                            }
+                        } else {
+                            System.err.println(
+                     "key incorrectly indicated socket channel connectable.");
+                        }
+                    }
+                    if(sk.isWritable() && (buf.remaining() > 0)) {
+                        sc.write(buf);
+                    }
+                    if(buf.remaining() == 0) {
+                        System.err.println(
+                            "SUCCESS! buffer contents were sent.");
+                        sc.close();
+                        selector.close();
+                        return;
+                    }
+                }
+                selectedKeys.clear();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/SocketChannel/FinishConnect.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2018, 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 8195160
+ * @summary Test RDMA SocketChannel.finishConnect
+ * @requires (os.family == "linux")
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @build RsocketTest
+ * @run main/othervm FinishConnect
+ */
+
+import java.net.InetSocketAddress;
+import java.net.StandardProtocolFamily;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.Selector;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+import java.nio.charset.Charset;
+import java.util.Iterator;
+import java.util.Set;
+import jdk.net.RdmaSockets;
+
+import jtreg.SkippedException;
+
+public class FinishConnect {
+
+    public static void main(String[] args) throws Exception {
+        if (!RsocketTest.isRsocketAvailable())
+            throw new SkippedException("rsocket is not available");
+
+        try (TestServers.DayTimeServer dayTimeServer
+                = TestServers.DayTimeServer.startNewServer(100)) {
+            test1(dayTimeServer, true, true);
+            test1(dayTimeServer, true, false);
+            test1(dayTimeServer, false, true);
+            test1(dayTimeServer, false, false);
+            test2(dayTimeServer);
+        }
+    }
+
+    static void test1(TestServers.DayTimeServer daytimeServer,
+                      boolean select,
+                      boolean setBlocking)
+        throws Exception
+    {
+        InetSocketAddress isa
+            = new InetSocketAddress(daytimeServer.getAddress(),
+                                    daytimeServer.getPort());
+        SocketChannel sc = RdmaSockets.openSocketChannel(
+            StandardProtocolFamily.INET);
+        sc.configureBlocking(false);
+        boolean connected = sc.connect(isa);
+        int attempts = 0;
+
+        try {
+            sc.connect(isa);
+            throw new RuntimeException("Allowed another connect call");
+        } catch (IllegalStateException ise) {
+            // Correct behavior
+        }
+
+        if (setBlocking)
+            sc.configureBlocking(true);
+
+        if (!connected && select && !setBlocking) {
+            Selector selector = RdmaSockets.openSelector();
+            sc.register(selector, SelectionKey.OP_CONNECT);
+            while (!connected) {
+                int keysAdded = selector.select(100);
+                if (keysAdded > 0) {
+                    Set readyKeys = selector.selectedKeys();
+                    Iterator i = readyKeys.iterator();
+                    while (i.hasNext()) {
+                        SelectionKey sk = (SelectionKey)i.next();
+                        SocketChannel nextReady =
+                            (SocketChannel)sk.channel();
+                        connected = sc.finishConnect();
+                    }
+                }
+            }
+            selector.close();
+        }
+
+        while (!connected) {
+            if (attempts++ > 30)
+                throw new RuntimeException("Failed to connect");
+            Thread.sleep(100);
+            connected = sc.finishConnect();
+        }
+
+        ByteBuffer bb = ByteBuffer.allocateDirect(100);
+        int bytesRead = 0;
+        int totalRead = 0;
+        while (totalRead < 20) {
+            bytesRead = sc.read(bb);
+            if (bytesRead > 0)
+                totalRead += bytesRead;
+            if (bytesRead < 0)
+                throw new RuntimeException("Message shorter than expected");
+        }
+        bb.position(bb.position() - 2);         // Drop CRLF
+        bb.flip();
+        CharBuffer cb = Charset.forName("US-ASCII").newDecoder().decode(bb);
+        System.err.println(isa + " says: \"" + cb + "\"");
+        sc.close();
+    }
+
+    static void test2(TestServers.DayTimeServer daytimeServer) throws Exception {
+        InetSocketAddress isa
+            = new InetSocketAddress(daytimeServer.getAddress(),
+                                    daytimeServer.getPort());
+        boolean done = false;
+        int globalAttempts = 0;
+        int connectSuccess = 0;
+        while (!done) {
+            // When using a local daytime server it is not always possible
+            // to get a pending connection, as sc.connect(isa) may always
+            // return true.
+            // So we're going to throw the exception only if there was
+            // at least 1 case where we did not manage to connect.
+            if (globalAttempts++ > 50) {
+                if (globalAttempts == connectSuccess + 1) {
+                    System.out.println("Can't fully test on "
+                            + System.getProperty("os.name"));
+                    break;
+                }
+                throw new RuntimeException("Failed to connect");
+            }
+            SocketChannel sc = RdmaSockets.openSocketChannel(
+                StandardProtocolFamily.INET);
+            sc.configureBlocking(false);
+            boolean connected = sc.connect(isa);
+            int localAttempts = 0;
+            while (!connected) {
+                if (localAttempts++ > 500)
+                    throw new RuntimeException("Failed to connect");
+                connected = sc.finishConnect();
+                if (connected) {
+                    done = true;
+                    break;
+                }
+                Thread.sleep(10);
+            }
+            if (connected) {
+                connectSuccess++;
+            }
+            sc.close();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/SocketChannel/IOExchanges.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,1199 @@
+/*
+ * Copyright (c) 2018, 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 8195160
+ * @summary Tests various combinations of blocking/nonblocking connections
+ * @requires (os.family == "linux")
+ * @library ../ /test/lib
+ * @build RsocketTest
+ * @run testng/othervm IOExchanges
+ * @author chegar
+ */
+
+import java.io.IOException;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ProtocolFamily;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.ByteBuffer;
+import jdk.net.RdmaSockets;
+import org.testng.SkipException;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static java.lang.System.out;
+import static java.net.StandardProtocolFamily.INET;
+import static java.net.StandardProtocolFamily.INET6;
+import static java.nio.channels.SelectionKey.OP_ACCEPT;
+import static java.nio.channels.SelectionKey.OP_READ;
+import static java.nio.channels.SelectionKey.OP_WRITE;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+public class IOExchanges {
+
+    // Whether, or not, to use RDMA channels or regular socket channels.
+    // For test assertion purposes during development.
+    static final boolean useRDMA = true;
+
+    static InetAddress addr;
+    static ProtocolFamily family;
+
+    @BeforeTest
+    public void setup() throws Exception {
+        if (useRDMA && !RsocketTest.isRsocketAvailable())
+            throw new SkipException("rsocket is not available");
+
+        addr = InetAddress.getLocalHost();
+        family = addr instanceof Inet6Address ? INET6 : INET;
+        out.printf("local address: %s%n", addr);
+        out.printf("useRDMA: %b%n", useRDMA);
+    }
+
+    static SocketChannel openSocketChannel(ProtocolFamily family)
+        throws IOException
+    {
+        return useRDMA ? RdmaSockets.openSocketChannel(family)
+                       : SocketChannel.open();
+    }
+    static ServerSocketChannel openServerSocketChannel(ProtocolFamily family)
+        throws IOException
+    {
+        return useRDMA ? RdmaSockets.openServerSocketChannel(family)
+                       : ServerSocketChannel.open();
+    }
+    static Selector openSelector( ) throws IOException {
+        return useRDMA ? RdmaSockets.openSelector() : Selector.open();
+    }
+
+    /*
+     The following, non-exhaustive set, of tests exercise different combinations
+     of blocking and non-blocking accept/connect calls along with I/O
+     operations, that exchange a single byte. The intent it to test a reasonable
+     set of blocking and non-blocking scenarios.
+
+      The individual test method names follow their test scenario.
+       [BAccep|SELNBAccep|SPINNBAccep] - Accept either:
+                        blocking, select-non-blocking, spinning-non-blocking
+       [BConn|NBConn] - blocking connect / non-blocking connect
+       [BIO|NBIO]     - blocking / non-blocking I/O operations (read/write)
+       [WR|RW] - connecting thread write/accepting thread reads first, and vice-versa
+       [Id]    - unique test Id
+
+        BAccep_BConn_BIO_WR_1
+        BAccep_BConn_BIO_RW_2
+        SELNBAccep_BConn_BIO_WR_3
+        SELNBAccep_BConn_BIO_RW_4
+        SPINNBAccep_BConn_BIO_WR_5
+        SPINNBAccep_BConn_BIO_RW_6
+        BAccep_NBConn_BIO_WR_7
+        BAccep_NBConn_BIO_RW_8
+        SELNBAccep_NBConn_BIO_WR_9
+        SELNBAccep_NBConn_BIO_RW_10
+        SPINNBAccep_NBConn_BIO_WR_11
+        SPINNBAccep_NBConn_BIO_RW_12
+
+        BAccep_BConn_NBIO_WR_1a        << Non-Blocking I/O
+        BAccep_BConn_NBIO_RW_2a
+        SELNBAccep_BConn_NBIO_WR_3a
+        SELNBAccep_BConn_NBIO_RW_4a
+        SPINNBAccep_BConn_NBIO_WR_5a
+        SPINNBAccep_BConn_NBIO_RW_6a
+        BAccep_NBConn_NBIO_WR_7a
+        BAccep_NBConn_NBIO_RW_8a
+        SELNBAccep_NBConn_NBIO_WR_9a
+        SELNBAccep_NBConn_NBIO_RW_10a
+        SPINBAccep_NBConn_NBIO_WR_11a
+        SPINBAccep_NBConn_NBIO_RW_12a
+    */
+
+
+    @Test
+    public void BAccep_BConn_BIO_WR_1() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            TestThread t = TestThread.of("t1", () -> {
+                try (SocketChannel sc = openSocketChannel(family)) {
+                    assertTrue(sc.connect(new InetSocketAddress(addr, port)));
+                    ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0x01).flip();
+                    assertEquals(sc.write(bb), 1);
+                    out.printf("wrote: 0x%x%n", bb.get(0));
+                    assertEquals(sc.read(bb.clear()), -1);
+                }
+            });
+            t.start();
+
+            try (SocketChannel sc = ssc.accept()) {
+                ByteBuffer bb = ByteBuffer.allocate(10);
+                assertEquals(sc.read(bb), 1);
+                out.printf("read:  0x%x%n", bb.get(0));
+                assertEquals(bb.get(0), 0x01);
+            }
+            t.awaitCompletion();
+        }
+    }
+
+    @Test
+    public void BAccep_BConn_BIO_RW_2() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            TestThread t = TestThread.of("t2", () -> {
+                try (SocketChannel sc = openSocketChannel(family)) {
+                    assertTrue(sc.connect(new InetSocketAddress(addr, port)));
+                    ByteBuffer bb = ByteBuffer.allocate(10);
+                    assertEquals(sc.read(bb), 1);
+                    out.printf("read:  0x%x%n", bb.get(0));
+                    assertEquals(bb.get(0), 0x02);
+                }
+            });
+            t.start();
+
+            try (SocketChannel sc = ssc.accept()) {
+                ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0x02).flip();
+                assertEquals(sc.write(bb), 1);
+                out.printf("wrote: 0x%x%n", bb.get(0));
+                assertEquals(sc.read(bb.clear()), -1);
+            }
+            t.awaitCompletion();
+        }
+    }
+
+    @Test
+    public void SELNBAccep_BConn_BIO_WR_3() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family);
+             Selector selector = openSelector()) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            TestThread t = TestThread.of("t3", () -> {
+                try (SocketChannel sc = openSocketChannel(family)) {
+                    assertTrue(sc.connect(new InetSocketAddress(addr, port)));
+                    ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0x03).flip();
+                    assertEquals(sc.write(bb), 1);
+                    out.printf("wrote: 0x%x%n", bb.get(0));
+                    assertEquals(sc.read(bb.clear()), -1);
+                }
+            });
+            t.start();
+
+            ssc.configureBlocking(false).register(selector, OP_ACCEPT);
+            assertEquals(selector.select(), 1);
+
+            try (SocketChannel sc = ssc.accept()) {
+                ByteBuffer bb = ByteBuffer.allocate(10);
+                assertEquals(sc.read(bb), 1);
+                out.printf("read:  0x%x%n", bb.get(0));
+                assertEquals(bb.get(0), 0x03);
+            }
+            t.awaitCompletion();
+        }
+    }
+
+    @Test
+    public void SELNBAccep_BConn_BIO_RW_4() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family);
+             Selector selector = openSelector()) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            TestThread t = TestThread.of("t4", () -> {
+                try (SocketChannel sc = openSocketChannel(family)) {
+                    assertTrue(sc.connect(new InetSocketAddress(addr, port)));
+                    ByteBuffer bb = ByteBuffer.allocate(10);
+                    assertEquals(sc.read(bb), 1);
+                    out.printf("read:  0x%x%n", bb.get(0));
+                    assertEquals(bb.get(0), 0x04);
+                }
+            });
+            t.start();
+
+            ssc.configureBlocking(false).register(selector, OP_ACCEPT);
+            assertEquals(selector.select(), 1);
+
+            try (SocketChannel sc = ssc.accept()) {
+                ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0x04).flip();
+                assertEquals(sc.write(bb), 1);
+                out.printf("wrote: 0x%x%n", bb.get(0));
+                assertEquals(sc.read(bb.clear()), -1);
+
+            }
+            t.awaitCompletion();
+        }
+    }
+
+    @Test
+    public void SPINNBAccep_BConn_BIO_WR_5() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            TestThread t = TestThread.of("t5", () -> {
+                try (SocketChannel sc = openSocketChannel(family)) {
+                    assertTrue(sc.connect(new InetSocketAddress(addr, port)));
+                    ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0x05).flip();
+                    assertEquals(sc.write(bb), 1);
+                    out.printf("wrote: 0x%x%n", bb.get(0));
+                    assertEquals(sc.read(bb.clear()), -1);
+                }
+            });
+            t.start();
+
+            SocketChannel accepted;
+            for (;;) {
+                accepted = ssc.accept();
+                if (accepted != null) {
+                    out.println("accepted new connection");
+                    break;
+                }
+                Thread.onSpinWait();
+            }
+
+            try (SocketChannel sc = accepted) {
+                ByteBuffer bb = ByteBuffer.allocate(10);
+                assertEquals(sc.read(bb), 1);
+                out.printf("read:  0x%x%n", bb.get(0));
+                assertEquals(bb.get(0), 0x05);
+            }
+            t.awaitCompletion();
+        }
+    }
+
+    @Test
+    public void SPINNBAccep_BConn_BIO_RW_6() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            TestThread t = TestThread.of("t6", () -> {
+                try (SocketChannel sc = openSocketChannel(family)) {
+                    assertTrue(sc.connect(new InetSocketAddress(addr, port)));
+                    ByteBuffer bb = ByteBuffer.allocate(10);
+                    assertEquals(sc.read(bb), 1);
+                    out.printf("read:  0x%x%n", bb.get(0));
+                    assertEquals(bb.get(0), 0x06);
+                }
+            });
+            t.start();
+
+            SocketChannel accepted;
+            for (;;) {
+                accepted = ssc.accept();
+                if (accepted != null) {
+                    out.println("accepted new connection");
+                    break;
+                }
+                Thread.onSpinWait();
+            }
+
+            try (SocketChannel sc = accepted) {
+                ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0x06).flip();
+                assertEquals(sc.write(bb), 1);
+                out.printf("wrote: 0x%x%n", bb.get(0));
+                assertEquals(sc.read(bb.clear()), -1);
+
+            }
+            t.awaitCompletion();
+        }
+    }
+
+    // Similar to the previous six scenarios, but with same-thread
+    // non-blocking connect.
+/*
+    @Test
+    public void BAccep_NBConn_BIO_WR_7() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            try (SocketChannel sc = openSocketChannel(family)) {
+                sc.configureBlocking(false);
+                sc.connect(new InetSocketAddress(addr, port));
+
+                try (SocketChannel sc2 = ssc.accept()) {
+                    assertTrue(sc.finishConnect());
+                    sc.configureBlocking(true);
+                    TestThread t = TestThread.of("t7", () -> {
+                        ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0x07).flip();
+                        assertEquals(sc.write(bb), 1);
+                        out.printf("wrote: 0x%x%n", bb.get(0));
+                        assertEquals(sc.read(bb.clear()), -1);
+                    });
+                    t.start();
+
+                    ByteBuffer bb = ByteBuffer.allocate(10);
+                    assertEquals(sc2.read(bb), 1);
+                    out.printf("read:  0x%x%n", bb.get(0));
+                    assertEquals(bb.get(0), 0x07);
+                    sc2.shutdownOutput();
+                    t.awaitCompletion();
+                }
+            }
+        }
+    }
+
+    @Test
+    public void BAccep_NBConn_BIO_RW_8() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            try (SocketChannel sc = openSocketChannel(family)) {
+                sc.configureBlocking(false);
+                sc.connect(new InetSocketAddress(addr, port));
+
+                try (SocketChannel sc2 = ssc.accept()) {
+                    assertTrue(sc.finishConnect());
+                    sc.configureBlocking(true);
+                    TestThread t = TestThread.of("t8", () -> {
+                        ByteBuffer bb = ByteBuffer.allocate(10);
+                        assertEquals(sc.read(bb), 1);
+                        out.printf("read:  0x%x%n", bb.get(0));
+                        assertEquals(bb.get(0), 0x08);
+                        sc.shutdownOutput();
+                    });
+                    t.start();
+
+                    ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0x08).flip();
+                    assertEquals(sc2.write(bb), 1);
+                    out.printf("wrote: 0x%x%n", bb.get(0));
+                    assertEquals(sc2.read(bb.clear()), -1);
+                    t.awaitCompletion();
+                }
+            }
+        }
+    }
+
+    @Test
+    public void SELNBAccep_NBConn_BIO_WR_9() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            try (SocketChannel sc = openSocketChannel(family);
+                 Selector selector = openSelector()) {
+                sc.configureBlocking(false);
+                sc.connect(new InetSocketAddress(addr, port));
+
+                ssc.configureBlocking(false).register(selector, OP_ACCEPT);
+                assertEquals(selector.select(), 1);
+
+                try (SocketChannel sc2 = ssc.accept()) {
+                    assertTrue(sc.finishConnect());
+                    sc.configureBlocking(true);
+                    TestThread t = TestThread.of("t9", () -> {
+                        ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0x09).flip();
+                        assertEquals(sc.write(bb), 1);
+                        out.printf("wrote: 0x%x%n", bb.get(0));
+                        assertEquals(sc.read(bb.clear()), -1);
+                    });
+                    t.start();
+
+                    ByteBuffer bb = ByteBuffer.allocate(10);
+                    assertEquals(sc2.read(bb), 1);
+                    out.printf("read:  0x%x%n", bb.get(0));
+                    assertEquals(bb.get(0), 0x09);
+                    sc2.shutdownOutput();
+                    t.awaitCompletion();
+                }
+            }
+        }
+    }
+
+    @Test
+    public void SELNBAccep_NBConn_BIO_RW_10() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            try (SocketChannel sc = openSocketChannel(family);
+                 Selector selector = openSelector()) {
+                sc.configureBlocking(false);
+                sc.connect(new InetSocketAddress(addr, port));
+
+                ssc.configureBlocking(false).register(selector, OP_ACCEPT);
+                assertEquals(selector.select(), 1);
+
+                try (SocketChannel sc2 = ssc.accept()) {
+                    assertTrue(sc.finishConnect());
+                    sc.configureBlocking(true);
+                    TestThread t = TestThread.of("t10", () -> {
+                        ByteBuffer bb = ByteBuffer.allocate(10);
+                        assertEquals(sc.read(bb), 1);
+                        out.printf("read:  0x%x%n", bb.get(0));
+                        assertEquals(bb.get(0), 0x10);
+                        sc.shutdownOutput();
+                    });
+                    t.start();
+
+                    ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0x10).flip();
+                    assertEquals(sc2.write(bb), 1);
+                    out.printf("wrote: 0x%x%n", bb.get(0));
+                    assertEquals(sc2.read(bb.clear()), -1);
+                    t.awaitCompletion();
+                }
+            }
+        }
+    }
+
+    @Test
+    public void SPINNBAccep_NBConn_BIO_WR_11() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            try (SocketChannel sc = openSocketChannel(family)) {
+                sc.configureBlocking(false);
+                sc.connect(new InetSocketAddress(addr, port));
+
+                SocketChannel accepted;
+                for (;;) {
+                    accepted = ssc.accept();
+                    if (accepted != null) {
+                        out.println("accepted new connection");
+                        break;
+                    }
+                    Thread.onSpinWait();
+                }
+
+                try (SocketChannel sc2 = accepted) {
+                    assertTrue(sc.finishConnect());
+                    sc.configureBlocking(true);
+                    TestThread t = TestThread.of("t11", () -> {
+                        ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0x11).flip();
+                        assertEquals(sc.write(bb), 1);
+                        out.printf("wrote: 0x%x%n", bb.get(0));
+                        assertEquals(sc.read(bb.clear()), -1);
+                    });
+                    t.start();
+
+                    ByteBuffer bb = ByteBuffer.allocate(10);
+                    assertEquals(sc2.read(bb), 1);
+                    out.printf("read:  0x%x%n", bb.get(0));
+                    assertEquals(bb.get(0), 0x11);
+                    sc2.shutdownOutput();
+                    t.awaitCompletion();
+                }
+            }
+        }
+    }
+
+    @Test
+    public void SPINNBAccep_NBConn_BIO_RW_12() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            try (SocketChannel sc = openSocketChannel(family)) {
+                sc.configureBlocking(false);
+                sc.connect(new InetSocketAddress(addr, port));
+
+                SocketChannel accepted;
+                for (;;) {
+                    accepted = ssc.accept();
+                    if (accepted != null) {
+                        out.println("accepted new connection");
+                        break;
+                    }
+                    Thread.onSpinWait();
+                }
+
+                try (SocketChannel sc2 = accepted) {
+                    assertTrue(sc.finishConnect());
+                    sc.configureBlocking(true);
+                    TestThread t = TestThread.of("t12", () -> {
+                        ByteBuffer bb = ByteBuffer.allocate(10);
+                        assertEquals(sc.read(bb), 1);
+                        out.printf("read:  0x%x%n", bb.get(0));
+                        assertEquals(bb.get(0), 0x12);
+                        sc.shutdownOutput();
+                    });
+                    t.start();
+
+                    ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0x12).flip();
+                    assertEquals(sc2.write(bb), 1);
+                    out.printf("wrote: 0x%x%n", bb.get(0));
+                    assertEquals(sc2.read(bb.clear()), -1);
+                    t.awaitCompletion();
+                }
+            }
+        }
+    }
+*/
+    // ---
+    // Similar to the previous twelve scenarios but with non-blocking IO
+    // ---
+
+    @Test
+    public void BAccep_BConn_NBIO_WR_1a() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            TestThread t = TestThread.of("t1a", () -> {
+                try (SocketChannel sc = openSocketChannel(family);
+                     Selector selector = openSelector()) {
+                    assertTrue(sc.connect(new InetSocketAddress(addr, port)));
+                    ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0x1A).flip();
+                    sc.configureBlocking(false);
+                    SelectionKey k = sc.register(selector, OP_WRITE);
+                    selector.select();
+                    int c;
+                    while ((c = sc.write(bb)) < 1);
+                    assertEquals(c, 1);
+                    out.printf("wrote: 0x%x%n", bb.get(0));
+                    k.interestOps(OP_READ);
+                    selector.select();
+                    bb.clear();
+                    while ((c = sc.read(bb)) == 0);
+                    assertEquals(c, -1);
+                }
+            });
+            t.start();
+
+            try (SocketChannel sc = ssc.accept();
+                 Selector selector = openSelector()) {
+                ByteBuffer bb = ByteBuffer.allocate(10);
+                sc.configureBlocking(false);
+                sc.register(selector, OP_READ);
+                selector.select();
+                int c;
+                while ((c = sc.read(bb)) == 0) ;
+                assertEquals(c, 1);
+                out.printf("read:  0x%x%n", bb.get(0));
+                assertEquals(bb.get(0), 0x1A);
+            }
+            t.awaitCompletion();
+        }
+    }
+
+    @Test
+    public void BAccep_BConn_NBIO_RW_2a() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            TestThread t = TestThread.of("t2a", () -> {
+                try (SocketChannel sc = openSocketChannel(family);
+                     Selector selector = openSelector()) {
+                    assertTrue(sc.connect(new InetSocketAddress(addr, port)));
+                    ByteBuffer bb = ByteBuffer.allocate(10);
+                    sc.configureBlocking(false);
+                    sc.register(selector, OP_READ);
+                    selector.select();
+                    int c;
+                    while ((c = sc.read(bb)) == 0);
+                    assertEquals(c, 1);
+                    out.printf("read:  0x%x%n", bb.get(0));
+                    assertEquals(bb.get(0), 0x2A);
+                }
+            });
+            t.start();
+
+            try (SocketChannel sc = ssc.accept();
+                 Selector selector = openSelector()) {
+                ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0x2A).flip();
+                sc.configureBlocking(false);
+                SelectionKey k = sc.register(selector, OP_WRITE);
+                selector.select();
+                int c;
+                while ((c = sc.write(bb)) < 1);
+                assertEquals(c, 1);
+                out.printf("wrote: 0x%x%n", bb.get(0));
+                k.interestOps(OP_READ);
+                selector.select();
+                bb.clear();
+                while ((c = sc.read(bb)) == 0);
+                assertEquals(c, -1);
+            }
+            t.awaitCompletion();
+        }
+    }
+
+    @Test
+    public void SELNBAccep_BConn_NBIO_WR_3a() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family);
+             Selector aselector = openSelector()) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            TestThread t = TestThread.of("t3a", () -> {
+                try (SocketChannel sc = openSocketChannel(family);
+                     Selector selector = openSelector()) {
+                    assertTrue(sc.connect(new InetSocketAddress(addr, port)));
+                    ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0x3A).flip();
+                    sc.configureBlocking(false);
+                    SelectionKey k = sc.register(selector, OP_WRITE);
+                    selector.select();
+                    int c;
+                    while ((c = sc.write(bb)) < 1);
+                    assertEquals(c, 1);
+                    out.printf("wrote: 0x%x%n", bb.get(0));
+                    k.interestOps(OP_READ);
+                    selector.select();
+                    bb.clear();
+                    while ((c = sc.read(bb)) == 0);
+                    assertEquals(c, -1);
+                }
+            });
+            t.start();
+
+            ssc.configureBlocking(false).register(aselector, OP_ACCEPT);
+            assertEquals(aselector.select(), 1);
+
+            try (SocketChannel sc = ssc.accept();
+                 Selector selector = openSelector()) {
+                ByteBuffer bb = ByteBuffer.allocate(10);
+                sc.configureBlocking(false);
+                sc.register(selector, OP_READ);
+                selector.select();
+                int c;
+                while ((c = sc.read(bb)) == 0) ;
+                assertEquals(c, 1);
+                out.printf("read:  0x%x%n", bb.get(0));
+                assertEquals(bb.get(0), 0x3A);
+            }
+            t.awaitCompletion();
+        }
+    }
+
+    @Test
+    public void SELNBAccep_BConn_NBIO_RW_4a() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family);
+             Selector aselector = openSelector()) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            TestThread t = TestThread.of("t4a", () -> {
+                try (SocketChannel sc = openSocketChannel(family);
+                     Selector selector = openSelector()) {
+                    assertTrue(sc.connect(new InetSocketAddress(addr, port)));
+                    ByteBuffer bb = ByteBuffer.allocate(10);
+                    sc.configureBlocking(false);
+                    sc.register(selector, OP_READ);
+                    selector.select();
+                    int c;
+                    while ((c = sc.read(bb)) == 0);
+                    assertEquals(c, 1);
+                    out.printf("read:  0x%x%n", bb.get(0));
+                    assertEquals(bb.get(0), 0x4A);
+                }
+            });
+            t.start();
+
+            ssc.configureBlocking(false).register(aselector, OP_ACCEPT);
+            assertEquals(aselector.select(), 1);
+
+            try (SocketChannel sc = ssc.accept();
+                 Selector selector = openSelector()) {
+                ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0x4A).flip();
+                sc.configureBlocking(false);
+                SelectionKey k = sc.register(selector, OP_WRITE);
+                selector.select();
+                int c;
+                while ((c = sc.write(bb)) < 1);
+                assertEquals(c, 1);
+                out.printf("wrote: 0x%x%n", bb.get(0));
+                k.interestOps(OP_READ);
+                selector.select();
+                bb.clear();
+                while ((c = sc.read(bb)) == 0);
+                assertEquals(c, -1);
+            }
+            t.awaitCompletion();
+        }
+    }
+
+    @Test
+    public void SPINNBAccep_BConn_NBIO_WR_5a() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            TestThread t = TestThread.of("t5a", () -> {
+                try (SocketChannel sc = openSocketChannel(family);
+                     Selector selector = openSelector()) {
+                    assertTrue(sc.connect(new InetSocketAddress(addr, port)));
+                    ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0x5A).flip();
+                    sc.configureBlocking(false);
+                    SelectionKey k = sc.register(selector, OP_WRITE);
+                    selector.select();
+                    int c;
+                    while ((c = sc.write(bb)) < 1);
+                    assertEquals(c, 1);
+                    out.printf("wrote: 0x%x%n", bb.get(0));
+                    k.interestOps(OP_READ);
+                    selector.select();
+                    bb.clear();
+                    while ((c = sc.read(bb)) == 0);
+                    assertEquals(c, -1);
+                }
+            });
+            t.start();
+
+            SocketChannel accepted;
+            for (;;) {
+                accepted = ssc.accept();
+                if (accepted != null) {
+                    out.println("accepted new connection");
+                    break;
+                }
+                Thread.onSpinWait();
+            }
+
+            try (SocketChannel sc = accepted;
+                 Selector selector = openSelector()) {
+                ByteBuffer bb = ByteBuffer.allocate(10);
+                sc.configureBlocking(false);
+                sc.register(selector, OP_READ);
+                selector.select();
+                int c;
+                while ((c = sc.read(bb)) == 0) ;
+                assertEquals(c, 1);
+                out.printf("read:  0x%x%n", bb.get(0));
+                assertEquals(bb.get(0), 0x5A);
+            }
+            t.awaitCompletion();
+        }
+    }
+
+    @Test
+    public void SPINNBAccep_BConn_NBIO_RW_6a() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            TestThread t = TestThread.of("t6a", () -> {
+                try (SocketChannel sc = openSocketChannel(family);
+                     Selector selector = openSelector()) {
+                    assertTrue(sc.connect(new InetSocketAddress(addr, port)));
+                    ByteBuffer bb = ByteBuffer.allocate(10);
+                    sc.configureBlocking(false);
+                    sc.register(selector, OP_READ);
+                    selector.select();
+                    int c;
+                    while ((c = sc.read(bb)) == 0);
+                    assertEquals(c, 1);
+                    out.printf("read:  0x%x%n", bb.get(0));
+                    assertEquals(bb.get(0), 0x6A);
+                }
+            });
+            t.start();
+
+            SocketChannel accepted;
+            for (;;) {
+                accepted = ssc.accept();
+                if (accepted != null) {
+                    out.println("accepted new connection");
+                    break;
+                }
+                Thread.onSpinWait();
+            }
+
+            try (SocketChannel sc = accepted;
+                 Selector selector = openSelector()) {
+                ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0x6A).flip();
+                sc.configureBlocking(false);
+                SelectionKey k = sc.register(selector, OP_WRITE);
+                selector.select();
+                int c;
+                while ((c = sc.write(bb)) < 1);
+                assertEquals(c, 1);
+                out.printf("wrote: 0x%x%n", bb.get(0));
+                k.interestOps(OP_READ);
+                selector.select();
+                bb.clear();
+                while ((c = sc.read(bb)) == 0);
+                assertEquals(c, -1);
+
+            }
+            t.awaitCompletion();
+        }
+    }
+
+    // Similar to the previous six scenarios but with same-thread
+    // non-blocking connect.
+/*
+    @Test
+    public void BAccep_NBConn_NBIO_WR_7a() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            try (SocketChannel sc = openSocketChannel(family)) {
+                sc.configureBlocking(false);
+                sc.connect(new InetSocketAddress(addr, port));
+
+                try (SocketChannel sc2 = ssc.accept()) {
+                    assertTrue(sc.finishConnect());
+                    TestThread t = TestThread.of("t7a", () -> {
+                        try (Selector selector = openSelector()) {
+                            ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0x7A).flip();
+                            sc.configureBlocking(false);
+                            SelectionKey k = sc.register(selector, OP_WRITE);
+                            selector.select();
+                            int c;
+                            while ((c = sc.write(bb)) < 1) ;
+                            assertEquals(c, 1);
+                            out.printf("wrote: 0x%x%n", bb.get(0));
+                            k.interestOps(OP_READ);
+                            selector.select();
+                            bb.clear();
+                            while ((c = sc.read(bb)) == 0) ;
+                            assertEquals(c, -1);
+                        }
+                    });
+                    t.start();
+
+                    ByteBuffer bb = ByteBuffer.allocate(10);
+                    sc2.configureBlocking(false);
+                    try (Selector selector = openSelector()) {
+                        sc2.register(selector, OP_READ);
+                        selector.select();
+                        int c;
+                        while ((c = sc2.read(bb)) == 0) ;
+                        assertEquals(c, 1);
+                        out.printf("read:  0x%x%n", bb.get(0));
+                        assertEquals(bb.get(0), 0x7A);
+                        sc2.shutdownOutput();
+                    }
+                    t.awaitCompletion();
+                }
+            }
+        }
+    }
+
+    @Test
+    public void BAccep_NBConn_NBIO_RW_8a() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            try (SocketChannel sc = openSocketChannel(family)) {
+                sc.configureBlocking(false);
+                sc.connect(new InetSocketAddress(addr, port));
+
+                try (SocketChannel sc2 = ssc.accept()) {
+                    assertTrue(sc.finishConnect());
+                    TestThread t = TestThread.of("t8a", () -> {
+                        try (Selector selector = openSelector()) {
+                            ByteBuffer bb = ByteBuffer.allocate(10);
+                            sc.register(selector, OP_READ);
+                            selector.select();
+                            int c;
+                            while ((c = sc.read(bb)) == 0);
+                            assertEquals(c, 1);
+                            out.printf("read:  0x%x%n", bb.get(0));
+                            assertEquals(bb.get(0), (byte)0x8A);
+                            sc.shutdownOutput();
+                        }
+                    });
+                    t.start();
+
+                    ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0x8A).flip();
+                    sc2.configureBlocking(false);
+                    try (Selector selector = openSelector()) {
+                        SelectionKey k = sc2.register(selector, OP_WRITE);
+                        selector.select();
+                        int c;
+                        while ((c = sc2.write(bb)) < 1) ;
+                        assertEquals(c, 1);
+                        out.printf("wrote: 0x%x%n", bb.get(0));
+                        k.interestOps(OP_READ);
+                        selector.select();
+                        bb.clear();
+                        while ((c = sc2.read(bb)) == 0) ;
+                        assertEquals(c, -1);
+                    }
+                    t.awaitCompletion();
+                }
+            }
+        }
+    }
+
+    @Test
+    public void SELNBAccep_NBConn_NBIO_WR_9a() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            try (SocketChannel sc = openSocketChannel(family)) {
+                sc.configureBlocking(false);
+                sc.connect(new InetSocketAddress(addr, port));
+
+                Selector aselector = openSelector();
+                ssc.configureBlocking(false).register(aselector, OP_ACCEPT);
+                assertEquals(aselector.select(), 1);
+
+                try (SocketChannel sc2 = ssc.accept()) {
+                    assertTrue(sc.finishConnect());
+                    TestThread t = TestThread.of("t9a", () -> {
+                        try (Selector selector = openSelector()) {
+                            ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0x9A).flip();
+                            sc.configureBlocking(false);
+                            SelectionKey k = sc.register(selector, OP_WRITE);
+                            selector.select();
+                            int c;
+                            while ((c = sc.write(bb)) < 1) ;
+                            assertEquals(c, 1);
+                            out.printf("wrote: 0x%x%n", bb.get(0));
+                            k.interestOps(OP_READ);
+                            selector.select();
+                            bb.clear();
+                            while ((c = sc.read(bb)) == 0) ;
+                            assertEquals(c, -1);
+                        }
+                    });
+                    t.start();
+
+                    ByteBuffer bb = ByteBuffer.allocate(10);
+                    sc2.configureBlocking(false);
+                    try (Selector selector = openSelector()) {
+                        sc2.register(selector, OP_READ);
+                        selector.select();
+                        int c;
+                        while ((c = sc2.read(bb)) == 0) ;
+                        assertEquals(c, 1);
+                        out.printf("read:  0x%x%n", bb.get(0));
+                        assertEquals(bb.get(0), (byte)0x9A);
+                        sc2.shutdownOutput();
+                    }
+                    t.awaitCompletion();
+                }
+            }
+        }
+    }
+
+    @Test
+    public void SELNBAccep_NBConn_NBIO_RW_10a() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            try (SocketChannel sc = openSocketChannel(family)) {
+                sc.configureBlocking(false);
+                sc.connect(new InetSocketAddress(addr, port));
+
+                Selector aselector = openSelector();
+                ssc.configureBlocking(false).register(aselector, OP_ACCEPT);
+                assertEquals(aselector.select(), 1);
+
+                try (SocketChannel sc2 = ssc.accept()) {
+                    assertTrue(sc.finishConnect());
+                    TestThread t = TestThread.of("t10a", () -> {
+                        try (Selector selector = openSelector()) {
+                            ByteBuffer bb = ByteBuffer.allocate(10);
+                            sc.register(selector, OP_READ);
+                            selector.select();
+                            int c;
+                            while ((c = sc.read(bb)) == 0);
+                            assertEquals(c, 1);
+                            out.printf("read:  0x%x%n", bb.get(0));
+                            assertEquals(bb.get(0), (byte)0xAA);
+                            sc.shutdownOutput();
+                        }
+                    });
+                    t.start();
+
+                    ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0xAA).flip();
+                    sc2.configureBlocking(false);
+                    try (Selector selector = openSelector()) {
+                        SelectionKey k = sc2.register(selector, OP_WRITE);
+                        selector.select();
+                        int c;
+                        while ((c = sc2.write(bb)) < 1) ;
+                        assertEquals(c, 1);
+                        out.printf("wrote: 0x%x%n", bb.get(0));
+                        k.interestOps(OP_READ);
+                        selector.select();
+                        bb.clear();
+                        while ((c = sc2.read(bb)) == 0) ;
+                        assertEquals(c, -1);
+                    }
+                    t.awaitCompletion();
+                }
+            }
+        }
+    }
+
+    @Test
+    public void SPINBAccep_NBConn_NBIO_WR_11a() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            try (SocketChannel sc = openSocketChannel(family)) {
+                sc.configureBlocking(false);
+                sc.connect(new InetSocketAddress(addr, port));
+
+                SocketChannel accepted;
+                for (;;) {
+                    accepted = ssc.accept();
+                    if (accepted != null) {
+                        out.println("accepted new connection");
+                        break;
+                    }
+                    Thread.onSpinWait();
+                }
+
+                try (SocketChannel sc2 = accepted) {
+                    assertTrue(sc.finishConnect());
+                    TestThread t = TestThread.of("t11a", () -> {
+                        try (Selector selector = openSelector()) {
+                            ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0xBA).flip();
+                            sc.configureBlocking(false);
+                            SelectionKey k = sc.register(selector, OP_WRITE);
+                            selector.select();
+                            int c;
+                            while ((c = sc.write(bb)) < 1) ;
+                            assertEquals(c, 1);
+                            out.printf("wrote: 0x%x%n", bb.get(0));
+                            k.interestOps(OP_READ);
+                            selector.select();
+                            bb.clear();
+                            while ((c = sc.read(bb)) == 0) ;
+                            assertEquals(c, -1);
+                        }
+                    });
+                    t.start();
+
+                    ByteBuffer bb = ByteBuffer.allocate(10);
+                    sc2.configureBlocking(false);
+                    try (Selector selector = openSelector()) {
+                        sc2.register(selector, OP_READ);
+                        selector.select();
+                        int c;
+                        while ((c = sc2.read(bb)) == 0) ;
+                        assertEquals(c, 1);
+                        out.printf("read:  0x%x%n", bb.get(0));
+                        assertEquals(bb.get(0), (byte)0xBA);
+                        sc2.shutdownOutput();
+                    }
+                    t.awaitCompletion();
+                }
+            }
+        }
+    }
+
+    @Test
+    public void SPINBAccep_NBConn_NBIO_RW_12a() throws Throwable {
+        try (ServerSocketChannel ssc = openServerSocketChannel(family)) {
+            ssc.bind(new InetSocketAddress(addr, 0));
+            final int port = ssc.socket().getLocalPort();
+
+            try (SocketChannel sc = openSocketChannel(family)) {
+                sc.configureBlocking(false);
+                sc.connect(new InetSocketAddress(addr, port));
+
+                SocketChannel accepted;
+                for (;;) {
+                    accepted = ssc.accept();
+                    if (accepted != null) {
+                        out.println("accepted new connection");
+                        break;
+                    }
+                    Thread.onSpinWait();
+                }
+
+                try (SocketChannel sc2 = accepted) {
+                    assertTrue(sc.finishConnect());
+                    TestThread t = TestThread.of("t10a", () -> {
+                        try (Selector selector = openSelector()) {
+                            ByteBuffer bb = ByteBuffer.allocate(10);
+                            sc.register(selector, OP_READ);
+                            selector.select();
+                            int c;
+                            while ((c = sc.read(bb)) == 0);
+                            assertEquals(c, 1);
+                            out.printf("read:  0x%x%n", bb.get(0));
+                            assertEquals(bb.get(0), (byte)0xCA);
+                            sc.shutdownOutput();
+                        }
+                    });
+                    t.start();
+
+                    ByteBuffer bb = ByteBuffer.allocate(10).put((byte)0xCA).flip();
+                    sc2.configureBlocking(false);
+                    try (Selector selector = openSelector()) {
+                        SelectionKey k = sc2.register(selector, OP_WRITE);
+                        selector.select();
+                        int c;
+                        while ((c = sc2.write(bb)) < 1) ;
+                        assertEquals(c, 1);
+                        out.printf("wrote: 0x%x%n", bb.get(0));
+                        k.interestOps(OP_READ);
+                        selector.select();
+                        bb.clear();
+                        while ((c = sc2.read(bb)) == 0) ;
+                        assertEquals(c, -1);
+                    }
+                    t.awaitCompletion();
+                }
+            }
+        }
+    }
+*/
+    // --
+
+    static class TestThread extends Thread {
+        private final UncheckedRunnable runnable;
+        private volatile Throwable throwable;
+
+        TestThread(UncheckedRunnable runnable, String name) {
+            super(name);
+            this.runnable = runnable;
+        }
+
+        @Override
+        public void run() {
+            try {
+                runnable.run();
+            } catch (Throwable t) {
+                out.printf("[%s] caught unexpected: %s%n", getName(), t);
+                throwable = t;
+            }
+        }
+
+        interface UncheckedRunnable {
+            void run() throws Throwable;
+        }
+
+        static TestThread of(String name, UncheckedRunnable runnable) {
+            return new TestThread(runnable, name);
+        }
+
+        void awaitCompletion() throws Throwable {
+            this.join();
+            if (throwable != null)
+                throw throwable;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/SocketChannel/SCConfigureBlocking.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2018, 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 8195160
+ * @summary Tests blocking configuration of socket channels
+ * @requires (os.family == "linux")
+ * @library ../ /test/lib
+ * @build RsocketTest
+ * @run testng/othervm SCConfigureBlocking
+ */
+
+import java.io.IOException;
+import java.net.ProtocolFamily;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
+import org.testng.SkipException;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static java.net.StandardProtocolFamily.INET;
+import static java.net.StandardProtocolFamily.INET6;
+import static java.nio.channels.SelectionKey.OP_READ;
+import static java.nio.channels.SelectionKey.OP_WRITE;
+import static jdk.net.RdmaSockets.*;
+import static org.testng.Assert.assertThrows;
+import static org.testng.Assert.assertTrue;
+
+public class SCConfigureBlocking {
+
+    @BeforeTest
+    public void setup() throws Exception {
+        if (!RsocketTest.isRsocketAvailable())
+            throw new SkipException("rsocket is not available");
+    }
+
+    @DataProvider(name = "families")
+    public Object[][] families() {
+        return new Object[][] { { INET }, { INET6 } };
+    }
+
+     // Newly-created selectable channels are always in blocking mode.
+
+    @Test(dataProvider = "families")
+    public void testSocketChannel(ProtocolFamily family)
+        throws IOException
+    {
+        try (SocketChannel sc = openSocketChannel(family)) {
+            assertTrue(sc.isBlocking(), "Newly created channel is not blocking");
+            sc.configureBlocking(false);
+            assertTrue(!sc.isBlocking(), "Expected non-blocking");
+            sc.configureBlocking(true);
+            assertTrue(sc.isBlocking(), "Expected blocking");
+        }
+    }
+
+    static final Class<IllegalBlockingModeException> IBME = IllegalBlockingModeException.class;
+
+    @Test(dataProvider = "families")
+    public void testSocketChannelRegister(ProtocolFamily family)
+        throws IOException
+    {
+        try (SocketChannel sc = openSocketChannel(family);
+             Selector selector = Selector.open()) {
+            assertThrows(IBME, () -> sc.register(selector, OP_READ));
+            assertThrows(IBME, () -> sc.register(selector, OP_READ, new Object()));
+            sc.configureBlocking(false);
+            sc.register(selector, OP_READ | OP_WRITE);
+            assertThrows(IBME, () -> sc.configureBlocking(true));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/SocketChannel/SocketOptionTests.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2018, 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 8195160
+ * @summary Unit test to check SocketChannel setOption/getOption/options
+ *          methods.
+ * @requires !vm.graal.enabled
+ * @requires (os.family == "linux")
+ * @library .. /test/lib
+ * @build RsocketTest
+ * @run main/othervm SocketOptionTests
+ */
+
+import java.nio.channels.*;
+import java.net.*;
+import java.io.IOException;
+import java.util.*;
+import jdk.net.RdmaSockets;
+import static java.net.StandardSocketOptions.*;
+import static jdk.net.RdmaSocketOptions.*;
+
+import jtreg.SkippedException;
+
+public class SocketOptionTests {
+
+    static void checkOption(SocketChannel sc, SocketOption name, Object expectedValue)
+        throws IOException
+    {
+        Object value = sc.getOption(name);
+        if (!value.equals(expectedValue))
+            throw new RuntimeException("value not as expected");
+    }
+
+    public static void main(String[] args) throws IOException {
+        if (!RsocketTest.isRsocketAvailable())
+            throw new SkippedException("rsocket is not available");
+
+        SocketChannel sc = RdmaSockets.openSocketChannel(StandardProtocolFamily.INET);
+
+        // check supported options
+        Set<SocketOption<?>> options = sc.supportedOptions();
+
+        List<? extends SocketOption> rdmaOptions = List.of(RDMA_SQSIZE,
+                RDMA_RQSIZE, RDMA_INLINE);
+        List<? extends SocketOption> expected;
+        expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, SO_REUSEADDR,
+                    TCP_NODELAY, RDMA_SQSIZE, RDMA_RQSIZE, RDMA_INLINE);
+        for (SocketOption opt: expected) {
+            if (!options.contains(opt))
+                throw new RuntimeException(opt.name() + " should be supported");
+        }
+
+        // check specified defaults
+        checkOption(sc, TCP_NODELAY, false);
+
+        // allowed to change when not bound
+        sc.setOption(SO_SNDBUF, 128*1024);      // can't check
+        sc.setOption(SO_RCVBUF, 256*1024);      // can't check
+        int before, after;
+        before = sc.getOption(SO_SNDBUF);
+        after = sc.setOption(SO_SNDBUF, Integer.MAX_VALUE).getOption(SO_SNDBUF);
+        if (after < before)
+            throw new RuntimeException("setOption caused SO_SNDBUF to decrease");
+        before = sc.getOption(SO_RCVBUF);
+        after = sc.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF);
+        if (after < before)
+            throw new RuntimeException("setOption caused SO_RCVBUF to decrease");
+        sc.setOption(SO_REUSEADDR, true);
+        checkOption(sc, SO_REUSEADDR, true);
+        sc.setOption(SO_REUSEADDR, false);
+        checkOption(sc, SO_REUSEADDR, false);
+        sc.setOption(TCP_NODELAY, true);
+        checkOption(sc, TCP_NODELAY, true);
+        sc.setOption(TCP_NODELAY, false);       // can't check
+
+        sc.setOption(RDMA_SQSIZE, 1024);
+        checkOption(sc, RDMA_SQSIZE, 1024);
+
+        sc.setOption(RDMA_RQSIZE, 1024);
+        checkOption(sc, RDMA_RQSIZE, 1024);
+
+        sc.setOption(RDMA_INLINE, 512);
+        checkOption(sc, RDMA_INLINE, 512);
+        
+        // bind socket
+        sc.bind(new InetSocketAddress(0));
+
+        sc.setOption(TCP_NODELAY, true);        // can't check
+        sc.setOption(TCP_NODELAY, false);       // can't check
+        // NullPointerException
+        try {
+            sc.setOption(null, "value");
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException x) {
+        }
+        try {
+            sc.getOption(null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException x) {
+        }
+
+        // ClosedChannelException
+        sc.close();
+        try {
+            sc.setOption(TCP_NODELAY, true);
+            throw new RuntimeException("ClosedChannelException not thrown");
+        } catch (ClosedChannelException x) {
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/SocketChannel/Stream.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2018, 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 8195160
+ * @summary Test result of read on stream from nonblocking channel
+ * @requires (os.family == "linux")
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @build RsocketTest
+ * @run main/othervm Stream
+ */
+
+import java.io.InputStream;
+import java.net.InetSocketAddress;
+import java.net.StandardProtocolFamily;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.SocketChannel;
+import jdk.net.RdmaSockets;
+
+import jtreg.SkippedException;
+
+public class Stream {
+
+    static void test(TestServers.DayTimeServer daytimeServer) throws Exception {
+        InetSocketAddress isa
+            = new InetSocketAddress(daytimeServer.getAddress(),
+                                    daytimeServer.getPort());
+        SocketChannel sc = RdmaSockets.openSocketChannel(StandardProtocolFamily.INET);
+        sc.connect(isa);
+        sc.configureBlocking(false);
+        InputStream is = sc.socket().getInputStream();
+        byte b[] = new byte[10];
+        try {
+            int n = is.read(b);
+            throw new RuntimeException("Exception expected; none thrown");
+        } catch (IllegalBlockingModeException e) {
+            // expected result
+        }
+        sc.close();
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (!RsocketTest.isRsocketAvailable())
+            throw new SkippedException("rsocket is not available");
+
+        try (TestServers.DayTimeServer dayTimeServer
+                = TestServers.DayTimeServer.startNewServer(100)) {
+            test(dayTimeServer);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/SocketChannel/VectorIO.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2018, 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 8195160
+ * @summary Test socketchannel vector IO (use -Dseed=X to set PRNG seed)
+ * @requires (os.family == "linux")
+ * @library .. /test/lib /test/jdk/java/nio/channels
+ * @build jdk.test.lib.RandomFactory
+ * @build RsocketTest
+ * @run main/othervm VectorIO
+ * @key randomness
+ */
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.StandardProtocolFamily;
+import java.nio.ByteBuffer;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.util.Random;
+import jdk.test.lib.RandomFactory;
+import jdk.net.RdmaSockets;
+
+import jtreg.SkippedException;
+
+public class VectorIO {
+
+    private static Random generator = RandomFactory.getRandom();
+
+    static int testSize;
+
+    // whether to use the write/read variant with a length parameter
+    static boolean setLength;
+
+    public static void main(String[] args) throws Exception {
+        if (!RsocketTest.isRsocketAvailable())
+            throw new SkippedException("rsocket is not available");
+
+        testSize = 1;
+        setLength = false;
+        runTest();
+        for(int i = 15; i < 18; i++) {
+            testSize = i;
+            setLength = !setLength;
+            runTest();
+        }
+    }
+
+    static void runTest() throws Exception {
+        System.err.println("Length " + testSize);
+        Server sv = new Server(testSize);
+        sv.start();
+        bufferTest(sv.port());
+        if (sv.finish(8000) == 0)
+            throw new Exception("Failed: Length = " + testSize);
+    }
+
+    static void bufferTest(int port) throws Exception {
+        ByteBuffer[] bufs = new ByteBuffer[testSize];
+        long total = 0L;
+        for(int i = 0; i < testSize; i++) {
+            String source = "buffer" + i;
+            if (generator.nextBoolean())
+                bufs[i] = ByteBuffer.allocateDirect(source.length());
+            else
+                bufs[i] = ByteBuffer.allocate(source.length());
+
+            bufs[i].put(source.getBytes("8859_1"));
+            bufs[i].flip();
+            total += bufs[i].remaining();
+        }
+
+        ByteBuffer[] bufsPlus1 = new ByteBuffer[bufs.length + 1];
+        System.arraycopy(bufs, 0, bufsPlus1, 0, bufs.length);
+
+        // Get a connection to the server
+        InetAddress lh = InetAddress.getLocalHost();
+        InetSocketAddress isa = new InetSocketAddress(lh, port);
+        SocketChannel sc = RdmaSockets.openSocketChannel(StandardProtocolFamily.INET);
+        sc.connect(isa);
+        sc.configureBlocking(generator.nextBoolean());
+
+        // Write the data out
+        long rem = total;
+        while (rem > 0L) {
+            long bytesWritten;
+            if (setLength) {
+                bytesWritten = sc.write(bufsPlus1, 0, bufs.length);
+            } else {
+                bytesWritten = sc.write(bufs);
+            }
+            if (bytesWritten == 0) {
+                if (sc.isBlocking()) {
+                    throw new RuntimeException("write did not block");
+                } else {
+                    System.err.println("Non-blocking write() wrote zero bytes");
+                }
+                Thread.sleep(50);
+            } else {
+                rem -= bytesWritten;
+            }
+        }
+
+        // Clean up
+        sc.close();
+    }
+
+    static class Server
+        extends TestThread
+    {
+        final int testSize;
+        final ServerSocketChannel ssc;
+
+        Server(int testSize) throws IOException {
+            super("Server " + testSize);
+            this.testSize = testSize;
+            this.ssc = RdmaSockets.openServerSocketChannel(
+                StandardProtocolFamily.INET).bind(new InetSocketAddress(0));
+        }
+
+        int port() {
+            return ssc.socket().getLocalPort();
+        }
+
+        void go() throws Exception {
+            bufferTest();
+        }
+
+        void bufferTest() throws Exception {
+            long total = 0L;
+            ByteBuffer[] bufs = new ByteBuffer[testSize];
+            for(int i=0; i<testSize; i++) {
+                String source = "buffer" + i;
+                if (generator.nextBoolean())
+                    bufs[i] = ByteBuffer.allocateDirect(source.length());
+                else
+                    bufs[i] = ByteBuffer.allocate(source.length());
+                total += bufs[i].capacity();
+            }
+
+            ByteBuffer[] bufsPlus1 = new ByteBuffer[bufs.length + 1];
+            System.arraycopy(bufs, 0, bufsPlus1, 0, bufs.length);
+
+            // Get a connection from client
+            SocketChannel sc = null;
+
+            try {
+
+                ssc.configureBlocking(false);
+
+                for (;;) {
+                    sc = ssc.accept();
+                    if (sc != null) {
+                        System.err.println("accept() succeeded");
+                        break;
+                    }
+                    Thread.sleep(50);
+                }
+
+                sc.configureBlocking(generator.nextBoolean());
+
+                // Read data into multiple buffers
+                long avail = total;
+                while (avail > 0) {
+                    long bytesRead;
+                    if (setLength) {
+                        bytesRead = sc.read(bufsPlus1, 0, bufs.length);
+                    } else {
+                        bytesRead = sc.read(bufs);
+                    }
+                    if (bytesRead < 0)
+                        break;
+                    if (bytesRead == 0) {
+                        if (sc.isBlocking()) {
+                            throw new RuntimeException("read did not block");
+                        } else {
+                            System.err.println
+                                ("Non-blocking read() read zero bytes");
+                        }
+                        Thread.sleep(50);
+                    }
+                    avail -= bytesRead;
+                }
+
+                // Check results
+                for(int i=0; i<testSize; i++) {
+                    String expected = "buffer" + i;
+                    bufs[i].flip();
+                    int size = bufs[i].capacity();
+                    byte[] data = new byte[size];
+                    for(int j=0; j<size; j++)
+                        data[j] = bufs[i].get();
+                    String message = new String(data, "8859_1");
+                    if (!message.equals(expected))
+                        throw new Exception("Wrong data: Got "
+                                            + message + ", expected "
+                                            + expected);
+                }
+
+            } finally {
+                // Clean up
+                ssc.close();
+                if (sc != null)
+                    sc.close();
+            }
+
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/SocketOption/OptionsTest.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2018, 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 8195160
+ * @summary Unit test for SocketOption
+ * @requires (os.family == "linux")
+ * @requires !vm.graal.enabled
+ * @library .. /test/lib
+ * @build RsocketTest
+ * @run main/othervm OptionsTest
+ */
+
+import java.net.StandardProtocolFamily;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketOption;
+import java.net.StandardSocketOptions;
+import java.util.Formatter;
+import java.util.Set;
+import jdk.net.RdmaSockets;
+import jdk.net.RdmaSocketOptions;
+
+import jtreg.SkippedException;
+
+public class OptionsTest {
+
+    static class Test {
+        Test(SocketOption<?> option, Object testValue) {
+            this.option = option;
+            this.testValue = testValue;
+        }
+        static Test create (SocketOption<?> option, Object testValue) {
+            return new Test(option, testValue);
+        }
+        Object option;
+        Object testValue;
+    }
+
+    // The tests set the option using the new API, read back the set value
+    // which could be diferent, and then use the legacy get API to check
+    // these values are the same
+
+    static Test[] socketTests = new Test[] {
+        Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)),
+        Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),
+        Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE),
+    };
+
+    static Test[] serverSocketTests = new Test[] {
+        Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),
+        Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE),
+    };
+
+    static Test[] rdmaSocketOptionTests = new Test[] {
+        Test.create(RdmaSocketOptions.RDMA_SQSIZE, Integer.valueOf(8 * 100)),
+        Test.create(RdmaSocketOptions.RDMA_RQSIZE, Integer.valueOf(10 * 100)),
+        Test.create(RdmaSocketOptions.RDMA_INLINE, Integer.valueOf(20 * 100)),
+    };
+
+    static void doSocketTests() throws Exception {
+        try {
+            Socket c = RdmaSockets.openSocket(StandardProtocolFamily.INET);
+
+            for (int i = 0; i < socketTests.length; i++) {
+                Test test = socketTests[i];
+                c.setOption((SocketOption)test.option, test.testValue);
+                Object getval = c.getOption((SocketOption)test.option);
+                Object legacyget = legacyGetOption(Socket.class, c, test.option);
+                if (!getval.equals(legacyget)) {
+                    Formatter f = new Formatter();
+                    f.format("S Err %d: %s/%s", i, getval, legacyget);
+                    throw new RuntimeException(f.toString());
+                }
+            }
+
+            for (int i = 0; i < rdmaSocketOptionTests.length; i++) {
+                Test test = rdmaSocketOptionTests[i];
+                c.setOption((SocketOption)test.option, test.testValue);
+                Object getval = c.getOption((SocketOption)test.option);
+                if (((Integer)getval).intValue() !=
+                        ((Integer)test.testValue).intValue())
+                    throw new RuntimeException("Test Failed");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException("Test Failed");
+        }
+    }
+
+    static void doServerSocketTests() throws Exception {
+        try {
+            ServerSocket srv = RdmaSockets.openServerSocket(
+                StandardProtocolFamily.INET);
+            for (int i = 0; i < serverSocketTests.length; i++) {
+                Test test = serverSocketTests[i];
+                srv.setOption((SocketOption)test.option, test.testValue);
+                Object getval = srv.getOption((SocketOption)test.option);
+                Object legacyget = legacyGetOption(
+                    ServerSocket.class, srv, test.option
+                );
+                if (!getval.equals(legacyget)) {
+                    Formatter f = new Formatter();
+                    f.format("SS Err %d: %s/%s", i, getval, legacyget);
+                    throw new RuntimeException(f.toString());
+                }
+            }
+
+            for (int i = 0; i < rdmaSocketOptionTests.length; i++) {
+                Test test = rdmaSocketOptionTests[i];
+                srv.setOption((SocketOption)test.option, test.testValue);
+                Object getval = srv.getOption((SocketOption)test.option);
+                if (((Integer)getval).intValue() != 
+                        ((Integer)test.testValue).intValue())
+                    throw new RuntimeException("Test Failed");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException("Test Failed");
+        }
+    }
+
+    static Object legacyGetOption(
+        Class<?> type, Object s, Object option)
+
+        throws Exception
+    {
+        if (type.equals(Socket.class)) {
+            Socket socket = (Socket)s;
+            Set<SocketOption<?>> options = socket.supportedOptions();
+
+            if (option.equals(StandardSocketOptions.SO_SNDBUF)) {
+                return Integer.valueOf(socket.getSendBufferSize());
+            } else if (option.equals(StandardSocketOptions.SO_RCVBUF)) {
+                return Integer.valueOf(socket.getReceiveBufferSize());
+            } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
+                return Boolean.valueOf(socket.getReuseAddress());
+            } else if (option.equals(StandardSocketOptions.TCP_NODELAY)) {
+                return Boolean.valueOf(socket.getTcpNoDelay());
+            } else {
+                throw new RuntimeException("unexecpted socket option");
+            }
+        } else if  (type.equals(ServerSocket.class)) {
+            ServerSocket socket = (ServerSocket)s;
+            Set<SocketOption<?>> options = socket.supportedOptions();
+
+            if (option.equals(StandardSocketOptions.SO_RCVBUF)) {
+                return Integer.valueOf(socket.getReceiveBufferSize());
+            } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
+                return Boolean.valueOf(socket.getReuseAddress());
+            } else {
+                throw new RuntimeException("unexecpted socket option");
+            }
+        }
+        throw new RuntimeException("unexecpted socket type");
+    }
+
+    public static void main(String args[]) throws Exception {
+        if (!RsocketTest.isRsocketAvailable())
+            throw new SkippedException("rsocket is not available");
+
+        doSocketTests();
+        doServerSocketTests();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/SocketOption/UnsupportedOptionsTest.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+import java.io.IOException;
+import java.net.StandardProtocolFamily;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketOption;
+import java.net.StandardSocketOptions;
+import java.util.ArrayList;
+import java.util.List;
+import jdk.net.RdmaSockets;
+import jdk.net.RdmaSocketOptions;
+
+import jtreg.SkippedException;
+
+/* @test
+ * @bug 8195160
+ * @summary Test checks that UnsupportedOperationException for unsupported
+ *          SOCKET_OPTIONS is thrown by both getOption() and setOption() methods.
+ * @requires (os.family == "linux")
+ * @requires !vm.graal.enabled
+ * @library .. /test/lib
+ * @build RsocketTest
+ * @run main/othervm UnsupportedOptionsTest
+ */
+public class UnsupportedOptionsTest {
+
+    private static final List<SocketOption<?>> socketOptions = new ArrayList<>();
+
+    static {
+        socketOptions.add(StandardSocketOptions.SO_RCVBUF);
+        socketOptions.add(StandardSocketOptions.SO_REUSEADDR);
+        socketOptions.add(StandardSocketOptions.SO_SNDBUF);
+        socketOptions.add(StandardSocketOptions.TCP_NODELAY);
+        socketOptions.add(RdmaSocketOptions.RDMA_SQSIZE);
+        socketOptions.add(RdmaSocketOptions.RDMA_RQSIZE);
+        socketOptions.add(RdmaSocketOptions.RDMA_INLINE);
+    }
+
+    public static void main(String[] args) throws IOException {
+        if (!RsocketTest.isRsocketAvailable())
+            throw new SkippedException("rsocket is not available");
+
+        Socket s = RdmaSockets.openSocket(StandardProtocolFamily.INET);
+        ServerSocket ss = RdmaSockets.openServerSocket(
+            StandardProtocolFamily.INET);
+
+        for (SocketOption option : socketOptions) {
+            if (!s.supportedOptions().contains(option)) {
+                testUnsupportedSocketOption(s, option);
+            }
+
+            if (!ss.supportedOptions().contains(option)) {
+                testUnsupportedSocketOption(ss, option);
+            }
+        }
+    }
+
+    /*
+     * Check that UnsupportedOperationException for unsupported option is
+     * thrown from both getOption() and setOption() methods.
+     */
+    private static void testUnsupportedSocketOption(Object socket,
+                                                    SocketOption option) {
+        testSet(socket, option);
+        testGet(socket, option);
+    }
+
+    private static void testSet(Object socket, SocketOption option) {
+        try {
+            setOption(socket, option);
+        } catch (UnsupportedOperationException e) {
+            System.out.println("UnsupportedOperationException was throw " +
+                    "as expected. Socket: " + socket + " Option: " + option);
+            return;
+        } catch (Exception e) {
+            throw new RuntimeException("FAIL. Unexpected exception.", e);
+        }
+        throw new RuntimeException("FAIL. UnsupportedOperationException " +
+                "hasn't been thrown. Socket: " + socket + " Option: " + option);
+    }
+
+    private static void testGet(Object socket, SocketOption option) {
+        try {
+            getOption(socket, option);
+        } catch (UnsupportedOperationException e) {
+            System.out.println("UnsupportedOperationException was throw " +
+                    "as expected. Socket: " + socket + " Option: " + option);
+            return;
+        } catch (Exception e) {
+            throw new RuntimeException("FAIL. Unexpected exception.", e);
+        }
+        throw new RuntimeException("FAIL. UnsupportedOperationException " +
+                "hasn't been thrown. Socket: " + socket + " Option: " + option);
+    }
+
+    private static void getOption(Object socket,
+                                  SocketOption option) throws IOException {
+        if (socket instanceof Socket) {
+            ((Socket) socket).getOption(option);
+        } else if (socket instanceof ServerSocket) {
+            ((ServerSocket) socket).getOption(option);
+        } else {
+            throw new RuntimeException("Unsupported socket type");
+        }
+    }
+
+    private static void setOption(Object socket,
+                                  SocketOption option) throws IOException {
+        if (socket instanceof Socket) {
+            ((Socket) socket).setOption(option, null);
+        } else if (socket instanceof ServerSocket) {
+            ((ServerSocket) socket).setOption(option, null);
+        } else {
+            throw new RuntimeException("Unsupported socket type");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/TestServers.java	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+import java.io.Closeable;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.StandardProtocolFamily;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import jdk.net.RdmaSockets;
+
+import jdk.test.lib.Utils;
+
+
+public class TestServers {
+
+    private TestServers() { }
+
+    /**
+     * An abstract server identifies a server which listens on a port on on a
+     * given machine.
+     */
+    static abstract class AbstractServer {
+
+        private AbstractServer() {
+        }
+
+        public abstract int getPort();
+
+        public abstract InetAddress getAddress();
+    }
+
+    /**
+     * A downgraded type of AbstractServer which will refuse connections. Note:
+     * use it once and throw it away - this implementation opens an anonymous
+     * socket and closes it, returning the address of the closed socket. If
+     * other servers are started afterwards, the address/port might get reused
+     * and become connectable again - so it's not a good idea to assume that
+     * connections using this address/port will always be refused. Connections
+     * will be refused as long as the address/port of the refusing server has
+     * not been reused.
+     */
+    static class RefusingServer extends AbstractServer {
+
+        final InetAddress address;
+        final int port;
+
+        private RefusingServer(InetAddress address, int port) {
+            this.address = address;
+            this.port = port;
+        }
+
+        @Override
+        public int getPort() {
+            return port;
+        }
+
+        @Override
+        public InetAddress getAddress() {
+            return address;
+        }
+
+        public static RefusingServer newRefusingServer() throws IOException {
+            return new RefusingServer(InetAddress.getLocalHost(),
+                       Utils.refusingEndpoint().getPort());
+        }
+    }
+
+    /**
+     * An abstract class for implementing small TCP servers for the nio tests
+     * purposes. Disclaimer: This is a naive implementation that uses the old
+     * networking APIs (not those from {@code java.nio.*}) and shamelessly
+     * extends/creates Threads instead of using an executor service.
+     */
+    static abstract class AbstractTcpServer extends AbstractServer
+            implements Runnable, Closeable {
+
+        protected final long linger; // #of ms to wait before responding
+        private Thread acceptThread; // thread waiting for accept
+        // list of opened connections that should be closed on close.
+        private List<TcpConnectionThread> connections = new ArrayList<>();
+        private ServerSocket serverSocket; // the server socket
+        private boolean started = false; // whether the server is started
+        Throwable error = null;
+
+        /**
+         * Creates a new abstract TCP server.
+         *
+         * @param linger the amount of time the server should wait before
+         * responding to requests.
+         */
+        protected AbstractTcpServer(long linger) {
+            this.linger = linger;
+        }
+
+        /**
+         * The local port to which the server is bound.
+         *
+         * @return The local port to which the server is bound.
+         * @exception IllegalStateException is thrown if the server is not
+         * started.
+         */
+        @Override
+        public final synchronized int getPort() {
+            if (!started) {
+                throw new IllegalStateException("Not started");
+            }
+            return serverSocket.getLocalPort();
+        }
+
+        /**
+         * The local address to which the server is bound.
+         *
+         * @return The local address to which the server is bound.
+         * @exception IllegalStateException is thrown if the server is not
+         * started.
+         */
+        @Override
+        public final synchronized InetAddress getAddress() {
+            if (!started) {
+                throw new IllegalStateException("Not started");
+            }
+            return serverSocket.getInetAddress();
+        }
+
+        /**
+         * Tells whether the server is started.
+         *
+         * @return true if the server is started.
+         */
+        public final synchronized boolean isStarted() {
+            return started;
+        }
+
+        /**
+         * Creates a new server socket.
+         *
+         * @param port local port to bind to.
+         * @param backlog requested maximum length of the queue of incoming
+         * connections.
+         * @param address local address to bind to.
+         * @return a new bound server socket ready to accept connections.
+         * @throws IOException if the socket cannot be created or bound.
+         */
+        protected ServerSocket newServerSocket(int port, int backlog,
+                InetAddress address)
+                throws IOException {
+            ServerSocket ss = RdmaSockets.openServerSocket(StandardProtocolFamily.INET);
+            ss.bind(new InetSocketAddress(address, port), backlog);
+            return ss;
+        }
+
+        /**
+         * Starts listening for connections.
+         *
+         * @throws IOException if the server socket cannot be created or bound.
+         */
+        public final synchronized void start() throws IOException {
+            if (started) {
+                return;
+            }
+            final ServerSocket socket =
+                    newServerSocket(0, 100, InetAddress.getLocalHost());
+            serverSocket = socket;
+            acceptThread = new Thread(this);
+            acceptThread.setDaemon(true);
+            acceptThread.start();
+            started = true;
+        }
+
+        /**
+         * Calls {@code Thread.sleep(linger);}
+         */
+        protected final void lingerIfRequired() {
+            if (linger > 0) {
+                try {
+                    Thread.sleep(linger);
+                } catch (InterruptedException x) {
+                    Thread.interrupted();
+                    final ServerSocket socket = serverSocket();
+                    if (socket != null && !socket.isClosed()) {
+                        System.err.println("Thread interrupted...");
+                    }
+                }
+            }
+        }
+
+        final synchronized ServerSocket serverSocket() {
+            return this.serverSocket;
+        }
+
+        /**
+         * The main accept loop.
+         */
+        @Override
+        public final void run() {
+            final ServerSocket sSocket = serverSocket();
+            try {
+                Socket s;
+                while (isStarted() && !Thread.interrupted()
+                        && (s = sSocket.accept()) != null) {
+                    lingerIfRequired();
+                    listen(s);
+                }
+            } catch (Exception x) {
+                error = x;
+            } finally {
+                synchronized (this) {
+                    if (!sSocket.isClosed()) {
+                        try {
+                            sSocket.close();
+                        } catch (IOException x) {
+                            System.err.println("Failed to close server socket");
+                        }
+                    }
+                    if (started && this.serverSocket == sSocket) {
+                        started = false;
+                        this.serverSocket = null;
+                        this.acceptThread = null;
+                    }
+                }
+            }
+        }
+
+        /**
+         * Represents a connection accepted by the server.
+         */
+        protected abstract class TcpConnectionThread extends Thread {
+
+            protected final Socket socket;
+
+            protected TcpConnectionThread(Socket socket) {
+                this.socket = socket;
+                this.setDaemon(true);
+            }
+
+            public void close() throws IOException {
+                socket.close();
+                interrupt();
+            }
+        }
+
+        /**
+         * Creates a new TcpConnnectionThread to handle the connection through
+         * an accepted socket.
+         *
+         * @param s the socket returned by {@code serverSocket.accept()}.
+         * @return a new TcpConnnectionThread to handle the connection through
+         * an accepted socket.
+         */
+        protected abstract TcpConnectionThread createConnection(Socket s);
+
+        /**
+         * Creates and starts a new TcpConnectionThread to handle the accepted
+         * socket.
+         *
+         * @param s the socket returned by {@code serverSocket.accept()}.
+         */
+        private synchronized void listen(Socket s) {
+            TcpConnectionThread c = createConnection(s);
+            c.start();
+            addConnection(c);
+        }
+
+        /**
+         * Add the connection to the list of accepted connections.
+         *
+         * @param connection an accepted connection.
+         */
+        protected synchronized void addConnection(
+                TcpConnectionThread connection) {
+            connections.add(connection);
+        }
+
+        /**
+         * Remove the connection from the list of accepted connections.
+         *
+         * @param connection an accepted connection.
+         */
+        protected synchronized void removeConnection(
+                TcpConnectionThread connection) {
+            connections.remove(connection);
+        }
+
+        /**
+         * Close the server socket and all the connections present in the list
+         * of accepted connections.
+         *
+         * @throws IOException
+         */
+        @Override
+        public synchronized void close() throws IOException {
+            if (serverSocket != null && !serverSocket.isClosed()) {
+                serverSocket.close();
+            }
+            if (acceptThread != null) {
+                acceptThread.interrupt();
+            }
+            int failed = 0;
+            for (TcpConnectionThread c : connections) {
+                try {
+                    c.close();
+                } catch (IOException x) {
+                    // no matter - we're closing.
+                    failed++;
+                }
+            }
+            connections.clear();
+            if (failed > 0) {
+                throw new IOException("Failed to close some connections");
+            }
+        }
+    }
+
+    /**
+     * A small TCP Server that emulates the echo service for tests purposes. See
+     * http://en.wikipedia.org/wiki/Echo_Protocol This server uses an anonymous
+     * port - NOT the standard port 7. We don't guarantee that its behavior
+     * exactly matches the RFC - the only purpose of this server is to have
+     * something that responds to nio tests...
+     */
+    static class EchoServer extends AbstractTcpServer {
+
+        public EchoServer() {
+            this(0L);
+        }
+
+        public EchoServer(long linger) {
+            super(linger);
+        }
+
+        @Override
+        protected TcpConnectionThread createConnection(Socket s) {
+            return new EchoConnection(s);
+        }
+
+        private final class EchoConnection extends TcpConnectionThread {
+
+            public EchoConnection(Socket socket) {
+                super(socket);
+            }
+
+            @Override
+            public void run() {
+                try {
+                    final InputStream is = socket.getInputStream();
+                    final OutputStream out = socket.getOutputStream();
+                    byte[] b = new byte[255];
+                    int n;
+                    while ((n = is.read(b)) > 0) {
+                        lingerIfRequired();
+                        out.write(b, 0, n);
+                    }
+                } catch (IOException io) {
+                    // fall through to finally
+                } finally {
+                    if (!socket.isClosed()) {
+                        try {
+                            socket.close();
+                        } catch (IOException x) {
+                            System.err.println(
+                                    "Failed to close echo connection socket");
+                        }
+                    }
+                    removeConnection(this);
+                }
+            }
+        }
+
+        public static EchoServer startNewServer() throws IOException {
+            return startNewServer(0);
+        }
+
+        public static EchoServer startNewServer(long linger) throws IOException {
+            final EchoServer echoServer = new EchoServer(linger);
+            echoServer.start();
+            return echoServer;
+        }
+    }
+
+
+    /**
+     * A small TCP Server that accept connections but does not response to any input.
+     */
+    static final class NoResponseServer extends EchoServer {
+        public NoResponseServer() {
+            super(Long.MAX_VALUE);
+        }
+
+        public static NoResponseServer startNewServer() throws IOException {
+            final NoResponseServer noResponseServer = new NoResponseServer();
+            noResponseServer.start();
+            return noResponseServer;
+        }
+    }
+
+
+    /**
+     * A small TCP server that emulates the Day & Time service for tests
+     * purposes. See http://en.wikipedia.org/wiki/Daytime_Protocol This server
+     * uses an anonymous port - NOT the standard port 13. We don't guarantee
+     * that its behavior exactly matches the RFC - the only purpose of this
+     * server is to have something that responds to nio tests...
+     */
+    static final class DayTimeServer extends AbstractTcpServer {
+
+        public DayTimeServer() {
+            this(0L);
+        }
+
+        public DayTimeServer(long linger) {
+            super(linger);
+        }
+
+        @Override
+        protected TcpConnectionThread createConnection(Socket s) {
+            return new DayTimeServerConnection(s);
+        }
+
+        @Override
+        protected void addConnection(TcpConnectionThread connection) {
+            // do nothing - the connection just write the date and terminates.
+        }
+
+        @Override
+        protected void removeConnection(TcpConnectionThread connection) {
+            // do nothing - we're not adding connections to the list...
+        }
+
+        private final class DayTimeServerConnection extends TcpConnectionThread {
+
+            public DayTimeServerConnection(Socket socket) {
+                super(socket);
+            }
+
+            @Override
+            public void run() {
+                try {
+                    final OutputStream out = socket.getOutputStream();
+                    lingerIfRequired();
+                    out.write(new Date(System.currentTimeMillis())
+                            .toString().getBytes("US-ASCII"));
+                    out.flush();
+                } catch (IOException io) {
+                    // fall through to finally
+                } finally {
+                    if (!socket.isClosed()) {
+                        try {
+                            socket.close();
+                        } catch (IOException x) {
+                            System.err.println(
+                                    "Failed to close echo connection socket");
+                        }
+                    }
+                }
+            }
+        }
+
+        public static DayTimeServer startNewServer()
+                throws IOException {
+            return startNewServer(0);
+        }
+
+        public static DayTimeServer startNewServer(long linger)
+                throws IOException {
+            final DayTimeServer daytimeServer = new DayTimeServer(linger);
+            daytimeServer.start();
+            return daytimeServer;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/RdmaSockets/rsocket/libRsocketTest.c	Sat Jan 26 14:02:35 2019 +0000
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/*
+ * Test if rsocket is available
+ */
+#include <stdlib.h>
+#ifdef __linux__
+#include <dlfcn.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <string.h>
+#endif
+#include "jni.h"
+
+jfieldID fid;
+
+/*
+ * Class:     RsocketTest
+ * Method:    isRsocketAvailable0
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean
+Java_RsocketTest_isRsocketAvailable0(JNIEnv *env, jclass cls) {
+    jboolean result = JNI_FALSE;
+#ifdef __linux__
+    void *handle;
+    int (*rs)(int, int, int);
+    char str[74];
+    strcpy(str, "librdmacm.so.1: cannot open shared object file: No such file or directory");
+    fid = (*env)->GetStaticFieldID(env, cls , "libInstalled", "Z");
+
+    handle = dlopen("librdmacm.so.1", RTLD_NOW);
+    if (!handle) {
+        int ret = strncmp(str, dlerror(), 74);
+        if (ret == 0) {
+            (*env)->SetStaticBooleanField(env, cls, fid, JNI_FALSE);
+        }
+        return JNI_FALSE;
+    } else {
+        (*env)->SetStaticBooleanField(env, cls, fid, JNI_TRUE);
+    }
+ 
+    rs = dlsym(handle, "rsocket");
+    if (!rs)
+        return JNI_FALSE;
+  
+    if ((*rs)(AF_INET, SOCK_STREAM, 0) > 0)
+        result = JNI_TRUE;
+
+    dlclose(handle);
+#endif
+    return result;
+}