--- /dev/null 2018-06-04 09:38:58.268495706 -0700 +++ new/src/jdk.net/share/classes/rdma/ch/RdmaNet.java 2018-06-04 11:02:33.186275445 -0700 @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2000, 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 rdma.ch; + +import java.io.*; +import java.net.*; +import java.nio.channels.*; +import java.util.*; +import java.security.AccessController; +import java.security.PrivilegedAction; +import sun.net.ext.RdmaSocketOptions; +import sun.nio.ch.Net; +import sun.nio.ch.IOUtil; + +public class RdmaNet extends Net { + protected 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(); + + /** + * Returns true if exclusive binding is on + */ + static boolean useExclusiveBind() { + return false; + } + + // -- 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; + if (type == Integer.class) { + arg = ((Integer)value).intValue(); + } else { + boolean b = ((Boolean)value).booleanValue(); + arg = (b) ? 1 : 0; + } + + boolean mayNeedConversion = (family == UNSPEC); + boolean isIPv6 = (family == StandardProtocolFamily.INET6); + setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg, isIPv6); + } + + 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(boolean stream) throws IOException { + return socket(UNSPEC, stream); + } + + static FileDescriptor socket(ProtocolFamily family, boolean stream) + throws IOException { + boolean preferIPv6 = isIPv6Available() && + (family != StandardProtocolFamily.INET); + return IOUtil.newFD(socket0(preferIPv6, stream, false, false)); + } + + static FileDescriptor serverSocket(boolean stream) { + return IOUtil.newFD(socket0(isIPv6Available(), stream, true, false)); + } + + private static native int socket0(boolean preferIPv6, boolean stream, boolean reuse, + boolean fastLoopback); + + public static void bind(FileDescriptor fd, InetAddress addr, int port) + throws IOException + { + bind(UNSPEC, fd, addr, port); + } + + static void bind(ProtocolFamily family, FileDescriptor fd, + InetAddress addr, int port) throws IOException + { + boolean preferIPv6 = isIPv6Available() && + (family != StandardProtocolFamily.INET); + bind0(fd, preferIPv6, false, addr, port); + } + + private static native void bind0(FileDescriptor fd, boolean preferIPv6, + boolean useExclBind, 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 = 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, boolean isIPv6) + 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(); + } +}