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 if (name == StandardSocketOptions.SO_LINGER) { 101 int i = ((Integer)value).intValue(); 102 if (i < 0) 103 value = Integer.valueOf(-1); 104 if (i > 65535) 105 value = Integer.valueOf(65535); 106 } 107 RdmaOptionKey key = RdmaSocketOptionRegistry.findOption(name, family); 108 if (key == null) 109 throw new AssertionError("Option not found"); 110 111 int arg; 112 int maxValue = 1024 * 1024 * 1024 - 1; 113 if (type == Integer.class) { 114 arg = ((Integer)value).intValue(); 115 if (arg > maxValue) 116 arg = maxValue; 117 } else { 118 boolean b = ((Boolean)value).booleanValue(); 119 arg = (b) ? 1 : 0; 120 } 121 122 boolean mayNeedConversion = (family == UNSPEC); 123 boolean isIPv6 = (family == StandardProtocolFamily.INET6); 124 setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg, isIPv6); 125 } 126 127 static Object getSocketOption(FileDescriptor fd, ProtocolFamily family, 128 SocketOption<?> name) 129 throws IOException 130 { 131 Class<?> type = name.type(); 132 133 if (rdmaOptions.isOptionSupported(name)) { 134 return rdmaOptions.getOption(fd, name); 135 } 136 137 if (type != Integer.class && type != Boolean.class) 138 throw new AssertionError("Should not reach here"); 139 140 RdmaOptionKey key = RdmaSocketOptionRegistry.findOption(name, family); 141 if (key == null) 142 throw new AssertionError("Option not found"); 143 144 boolean mayNeedConversion = (family == UNSPEC); 145 int value = getIntOption0(fd, mayNeedConversion, key.level(), key.name()); 146 147 if (type == Integer.class) { 148 return Integer.valueOf(value); 149 } else { 150 return (value == 0) ? Boolean.FALSE : Boolean.TRUE; 151 } 152 } 153 154 // -- Socket operations -- 155 156 static FileDescriptor socket(boolean stream) throws IOException { 157 return socket(UNSPEC, stream); 158 } 159 160 static FileDescriptor socket(ProtocolFamily family, boolean stream) 161 throws IOException { 162 boolean preferIPv6 = isIPv6Available() && 163 (family != StandardProtocolFamily.INET); 164 return IOUtil.newFD(socket0(preferIPv6, stream, false, false)); 165 } 166 167 static FileDescriptor serverSocket(boolean stream) { 168 return IOUtil.newFD(socket0(isIPv6Available(), stream, true, false)); 169 } 170 171 private static native int socket0(boolean preferIPv6, boolean stream, boolean reuse, 172 boolean fastLoopback); 173 174 public static void bind(FileDescriptor fd, InetAddress addr, int port) 175 throws IOException 176 { 177 bind(UNSPEC, fd, addr, port); 178 } 179 180 static void bind(ProtocolFamily family, FileDescriptor fd, 181 InetAddress addr, int port) throws IOException 182 { 183 boolean preferIPv6 = isIPv6Available() && 184 (family != StandardProtocolFamily.INET); 185 bind0(fd, preferIPv6, false, addr, port); 186 } 187 188 private static native void bind0(FileDescriptor fd, boolean preferIPv6, 189 boolean useExclBind, InetAddress addr, 190 int port) 191 throws IOException; 192 193 static native void listen(FileDescriptor fd, int backlog) throws IOException; 194 195 static int connect(FileDescriptor fd, InetAddress remote, int remotePort) 196 throws IOException 197 { 198 return connect(UNSPEC, fd, remote, remotePort); 199 } 200 201 static int connect(ProtocolFamily family, FileDescriptor fd, InetAddress remote, int remotePort) 202 throws IOException 203 { 204 boolean preferIPv6 = isIPv6Available() && 205 (family != StandardProtocolFamily.INET); 206 return connect0(preferIPv6, fd, remote, remotePort); 207 } 208 209 public static InetSocketAddress localAddress(FileDescriptor fd) 210 throws IOException 211 { 212 return new InetSocketAddress(localInetAddress(fd), localPort(fd)); 213 } 214 215 private static native int connect0(boolean preferIPv6, 216 FileDescriptor fd, 217 InetAddress remote, 218 int remotePort) 219 throws IOException; 220 221 static native void shutdown(FileDescriptor fd, int how) throws IOException; 222 223 private static native int localPort(FileDescriptor fd) 224 throws IOException; 225 226 private static native InetAddress localInetAddress(FileDescriptor fd) 227 throws IOException; 228 229 private static native int getIntOption0(FileDescriptor fd, boolean mayNeedConversion, 230 int level, int opt) 231 throws IOException; 232 233 private static native void setIntOption0(FileDescriptor fd, boolean mayNeedConversion, 234 int level, int opt, int arg, boolean isIPv6) 235 throws IOException; 236 237 static native int poll(FileDescriptor fd, int events, long timeout) 238 throws IOException; 239 240 public static native void configureBlocking(FileDescriptor fd, boolean blocking); 241 242 private static native void initIDs(); 243 244 static { 245 java.security.AccessController.doPrivileged( 246 new java.security.PrivilegedAction<>() { 247 public Void run() { 248 System.loadLibrary("extnet"); 249 return null; 250 } 251 }); 252 IOUtil.load(); 253 initIDs(); 254 } 255 }