1 /* 2 * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package rdma.ch; 27 28 import java.io.*; 29 import java.net.*; 30 import java.nio.channels.*; 31 import java.util.*; 32 import java.security.AccessController; 33 import java.security.PrivilegedAction; 34 import sun.net.ext.RdmaSocketOptions; 35 import sun.nio.ch.Net; 36 import sun.nio.ch.IOUtil; 37 38 public class RdmaNet extends Net { 39 protected RdmaNet() { } 40 41 static final ProtocolFamily UNSPEC = new ProtocolFamily() { 42 public String name() { 43 return "UNSPEC"; 44 } 45 }; 46 47 static boolean isReusePortAvailable() { 48 return false; 49 } 50 51 private static volatile boolean checkedRdma; 52 private static volatile boolean isRdmaAvailable; 53 54 static boolean isRdmaAvailable() { 55 if (!checkedRdma) { 56 isRdmaAvailable = isRdmaAvailable0(); 57 checkedRdma = true; 58 } 59 return isRdmaAvailable; 60 } 61 62 private static native boolean isRdmaAvailable0(); 63 64 /** 65 * Returns true if exclusive binding is on 66 */ 67 static boolean useExclusiveBind() { 68 return false; 69 } 70 71 // -- Socket options 72 73 static final RdmaSocketOptions rdmaOptions = 74 RdmaSocketOptions.getInstance(); 75 76 static void setSocketOption(FileDescriptor fd, ProtocolFamily family, 77 SocketOption<?> name, Object value) 78 throws IOException 79 { 80 if (value == null) 81 throw new IllegalArgumentException("Invalid option value"); 82 83 Class<?> type = name.type(); 84 85 if (rdmaOptions.isOptionSupported(name)) { 86 rdmaOptions.setOption(fd, name, value); 87 return; 88 } 89 90 if (type != Integer.class && type != Boolean.class) 91 throw new AssertionError("Should not reach here"); 92 93 if (name == StandardSocketOptions.SO_RCVBUF || 94 name == StandardSocketOptions.SO_SNDBUF) 95 { 96 int i = ((Integer)value).intValue(); 97 if (i < 0) 98 throw new IllegalArgumentException("Invalid send/receive buffer size"); 99 } 100 RdmaOptionKey key = RdmaSocketOptionRegistry.findOption(name, family); 101 if (key == null) 102 throw new AssertionError("Option not found"); 103 104 int arg; 105 if (type == Integer.class) { 106 arg = ((Integer)value).intValue(); 107 } else { 108 boolean b = ((Boolean)value).booleanValue(); 109 arg = (b) ? 1 : 0; 110 } 111 112 boolean mayNeedConversion = (family == UNSPEC); 113 boolean isIPv6 = (family == StandardProtocolFamily.INET6); 114 setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg, isIPv6); 115 } 116 117 static Object getSocketOption(FileDescriptor fd, ProtocolFamily family, 118 SocketOption<?> name) 119 throws IOException 120 { 121 Class<?> type = name.type(); 122 123 if (rdmaOptions.isOptionSupported(name)) { 124 return rdmaOptions.getOption(fd, name); 125 } 126 127 if (type != Integer.class && type != Boolean.class) 128 throw new AssertionError("Should not reach here"); 129 130 RdmaOptionKey key = RdmaSocketOptionRegistry.findOption(name, family); 131 if (key == null) 132 throw new AssertionError("Option not found"); 133 134 boolean mayNeedConversion = (family == UNSPEC); 135 int value = getIntOption0(fd, mayNeedConversion, key.level(), key.name()); 136 137 if (type == Integer.class) { 138 return Integer.valueOf(value); 139 } else { 140 return (value == 0) ? Boolean.FALSE : Boolean.TRUE; 141 } 142 } 143 144 // -- Socket operations -- 145 146 static FileDescriptor socket(boolean stream) throws IOException { 147 return socket(UNSPEC, stream); 148 } 149 150 static FileDescriptor socket(ProtocolFamily family, boolean stream) 151 throws IOException { 152 boolean preferIPv6 = isIPv6Available() && 153 (family != StandardProtocolFamily.INET); 154 return IOUtil.newFD(socket0(preferIPv6, stream, false, false)); 155 } 156 157 static FileDescriptor serverSocket(boolean stream) { 158 return IOUtil.newFD(socket0(isIPv6Available(), stream, true, false)); 159 } 160 161 private static native int socket0(boolean preferIPv6, boolean stream, boolean reuse, 162 boolean fastLoopback); 163 164 public static void bind(FileDescriptor fd, InetAddress addr, int port) 165 throws IOException 166 { 167 bind(UNSPEC, fd, addr, port); 168 } 169 170 static void bind(ProtocolFamily family, FileDescriptor fd, 171 InetAddress addr, int port) throws IOException 172 { 173 boolean preferIPv6 = isIPv6Available() && 174 (family != StandardProtocolFamily.INET); 175 bind0(fd, preferIPv6, false, addr, port); 176 } 177 178 private static native void bind0(FileDescriptor fd, boolean preferIPv6, 179 boolean useExclBind, InetAddress addr, 180 int port) 181 throws IOException; 182 183 static native void listen(FileDescriptor fd, int backlog) throws IOException; 184 185 static int connect(FileDescriptor fd, InetAddress remote, int remotePort) 186 throws IOException 187 { 188 return connect(UNSPEC, fd, remote, remotePort); 189 } 190 191 static int connect(ProtocolFamily family, FileDescriptor fd, InetAddress remote, int remotePort) 192 throws IOException 193 { 194 boolean preferIPv6 = isIPv6Available() && 195 (family != StandardProtocolFamily.INET); 196 return connect0(preferIPv6, fd, remote, remotePort); 197 } 198 199 public static InetSocketAddress localAddress(FileDescriptor fd) 200 throws IOException 201 { 202 return new InetSocketAddress(localInetAddress(fd), localPort(fd)); 203 } 204 205 private static native int connect0(boolean preferIPv6, 206 FileDescriptor fd, 207 InetAddress remote, 208 int remotePort) 209 throws IOException; 210 211 static native void shutdown(FileDescriptor fd, int how) throws IOException; 212 213 private static native int localPort(FileDescriptor fd) 214 throws IOException; 215 216 private static native InetAddress localInetAddress(FileDescriptor fd) 217 throws IOException; 218 219 private static native int getIntOption0(FileDescriptor fd, boolean mayNeedConversion, 220 int level, int opt) 221 throws IOException; 222 223 private static native void setIntOption0(FileDescriptor fd, boolean mayNeedConversion, 224 int level, int opt, int arg, boolean isIPv6) 225 throws IOException; 226 227 static native int poll(FileDescriptor fd, int events, long timeout) 228 throws IOException; 229 230 public static native void configureBlocking(FileDescriptor fd, boolean blocking); 231 232 private static native void initIDs(); 233 234 static { 235 java.security.AccessController.doPrivileged( 236 new java.security.PrivilegedAction<>() { 237 public Void run() { 238 System.loadLibrary("extnet"); 239 return null; 240 } 241 }); 242 IOUtil.load(); 243 initIDs(); 244 } 245 }