Mercurial > hg > openjdk > jdk8u > jdk
changeset 11106:a6665011c99f jdk8u45-b37
8072384: Setting IP_TOS on java.net sockets not working on unix
Reviewed-by: michaelm
author | coffeys |
---|---|
date | Fri, 12 Jun 2015 12:39:41 +0100 |
parents | c05a28757ba5 |
children | 8dd0918b97a4 |
files | make/mapfiles/libnet/mapfile-vers src/share/classes/java/net/AbstractPlainSocketImpl.java src/share/classes/java/net/DatagramSocket.java src/share/classes/java/net/Socket.java src/solaris/classes/java/net/PlainDatagramSocketImpl.java src/solaris/classes/java/net/PlainSocketImpl.java src/solaris/native/java/net/PlainDatagramSocketImpl.c src/solaris/native/java/net/PlainSocketImpl.c src/solaris/native/java/net/net_util_md.c test/jdk/net/Sockets/Test.java |
diffstat | 10 files changed, 82 insertions(+), 50 deletions(-) [+] |
line wrap: on
line diff
--- a/make/mapfiles/libnet/mapfile-vers Thu Jun 04 12:04:57 2015 -0700 +++ b/make/mapfiles/libnet/mapfile-vers Fri Jun 12 12:39:41 2015 +0100 @@ -42,7 +42,7 @@ Java_java_net_Inet4Address_init; Java_java_net_Inet6Address_init; Java_java_net_PlainDatagramSocketImpl_setTTL; - Java_java_net_PlainDatagramSocketImpl_socketSetOption; + Java_java_net_PlainDatagramSocketImpl_socketSetOption0; Java_java_net_PlainDatagramSocketImpl_bind0; Java_java_net_PlainSocketImpl_socketAccept; Java_java_net_DatagramPacket_init; @@ -73,7 +73,7 @@ Java_java_net_SocketOutputStream_init; Java_java_net_PlainDatagramSocketImpl_peek; Java_java_net_PlainDatagramSocketImpl_peekData; - Java_java_net_PlainSocketImpl_socketSetOption; + Java_java_net_PlainSocketImpl_socketSetOption0; Java_java_net_PlainSocketImpl_socketSendUrgentData; Java_java_net_PlainDatagramSocketImpl_datagramSocketCreate; Java_java_net_PlainSocketImpl_socketGetOption;
--- a/src/share/classes/java/net/AbstractPlainSocketImpl.java Thu Jun 04 12:04:57 2015 -0700 +++ b/src/share/classes/java/net/AbstractPlainSocketImpl.java Fri Jun 12 12:39:41 2015 +0100 @@ -312,11 +312,16 @@ ret = socketGetOption(opt, null); return new Integer(ret); case IP_TOS: - ret = socketGetOption(opt, null); - if (ret == -1) { // ipv6 tos - return new Integer(trafficClass); - } else { - return new Integer(ret); + try { + ret = socketGetOption(opt, null); + if (ret == -1) { // ipv6 tos + return trafficClass; + } else { + return ret; + } + } catch (SocketException se) { + // TODO - should make better effort to read TOS or TCLASS + return trafficClass; // ipv6 tos } case SO_KEEPALIVE: ret = socketGetOption(opt, null);
--- a/src/share/classes/java/net/DatagramSocket.java Thu Jun 04 12:04:57 2015 -0700 +++ b/src/share/classes/java/net/DatagramSocket.java Fri Jun 12 12:39:41 2015 +0100 @@ -1182,7 +1182,14 @@ if (isClosed()) throw new SocketException("Socket is closed"); - getImpl().setOption(SocketOptions.IP_TOS, new Integer(tc)); + try { + getImpl().setOption(SocketOptions.IP_TOS, tc); + } catch (SocketException se) { + // not supported if socket already connected + // Solaris returns error in such cases + if(!isConnected()) + throw se; + } } /**
--- a/src/share/classes/java/net/Socket.java Thu Jun 04 12:04:57 2015 -0700 +++ b/src/share/classes/java/net/Socket.java Fri Jun 12 12:39:41 2015 +0100 @@ -1378,7 +1378,14 @@ if (isClosed()) throw new SocketException("Socket is closed"); - getImpl().setOption(SocketOptions.IP_TOS, new Integer(tc)); + try { + getImpl().setOption(SocketOptions.IP_TOS, tc); + } catch (SocketException se) { + // not supported if socket already connected + // Solaris returns error in such cases + if(!isConnected()) + throw se; + } } /**
--- a/src/solaris/classes/java/net/PlainDatagramSocketImpl.java Thu Jun 04 12:04:57 2015 -0700 +++ b/src/solaris/classes/java/net/PlainDatagramSocketImpl.java Fri Jun 12 12:39:41 2015 +0100 @@ -69,6 +69,15 @@ return (T)flow; } + protected void socketSetOption(int opt, Object val) throws SocketException { + try { + socketSetOption0(opt, val); + } catch (SocketException se) { + if (!connected) + throw se; + } + } + protected synchronized native void bind0(int lport, InetAddress laddr) throws SocketException; @@ -101,7 +110,7 @@ protected native void datagramSocketClose(); - protected native void socketSetOption(int opt, Object val) + protected native void socketSetOption0(int opt, Object val) throws SocketException; protected native Object socketGetOption(int opt) throws SocketException;
--- a/src/solaris/classes/java/net/PlainSocketImpl.java Thu Jun 04 12:04:57 2015 -0700 +++ b/src/solaris/classes/java/net/PlainSocketImpl.java Fri Jun 12 12:39:41 2015 +0100 @@ -83,6 +83,15 @@ return (T)flow; } + protected void socketSetOption(int opt, boolean b, Object val) throws SocketException { + try { + socketSetOption0(opt, b, val); + } catch (SocketException se) { + if (socket == null || !socket.isConnected()) + throw se; + } + } + native void socketCreate(boolean isServer) throws IOException; native void socketConnect(InetAddress address, int port, int timeout) @@ -103,7 +112,7 @@ static native void initProto(); - native void socketSetOption(int cmd, boolean on, Object value) + native void socketSetOption0(int cmd, boolean on, Object value) throws SocketException; native int socketGetOption(int opt, Object iaContainerObj) throws SocketException;
--- a/src/solaris/native/java/net/PlainDatagramSocketImpl.c Thu Jun 04 12:04:57 2015 -0700 +++ b/src/solaris/native/java/net/PlainDatagramSocketImpl.c Fri Jun 12 12:39:41 2015 +0100 @@ -1321,11 +1321,11 @@ /* * Class: java_net_PlainDatagramSocketImpl - * Method: socketSetOption + * Method: socketSetOption0 * Signature: (ILjava/lang/Object;)V */ JNIEXPORT void JNICALL -Java_java_net_PlainDatagramSocketImpl_socketSetOption(JNIEnv *env, +Java_java_net_PlainDatagramSocketImpl_socketSetOption0(JNIEnv *env, jobject this, jint opt, jobject value) {
--- a/src/solaris/native/java/net/PlainSocketImpl.c Thu Jun 04 12:04:57 2015 -0700 +++ b/src/solaris/native/java/net/PlainSocketImpl.c Fri Jun 12 12:39:41 2015 +0100 @@ -885,11 +885,11 @@ /* * Class: java_net_PlainSocketImpl - * Method: socketSetOption + * Method: socketSetOption0 * Signature: (IZLjava/lang/Object;)V */ JNIEXPORT void JNICALL -Java_java_net_PlainSocketImpl_socketSetOption(JNIEnv *env, jobject this, +Java_java_net_PlainSocketImpl_socketSetOption0(JNIEnv *env, jobject this, jint cmd, jboolean on, jobject value) { int fd;
--- a/src/solaris/native/java/net/net_util_md.c Thu Jun 04 12:04:57 2015 -0700 +++ b/src/solaris/native/java/net/net_util_md.c Fri Jun 12 12:39:41 2015 +0100 @@ -1005,12 +1005,10 @@ int i; - /* - * Different multicast options if IPv6 is enabled - */ #ifdef AF_INET6 if (ipv6_available()) { switch (cmd) { + // Different multicast options if IPv6 is enabled case java_net_SocketOptions_IP_MULTICAST_IF: case java_net_SocketOptions_IP_MULTICAST_IF2: *level = IPPROTO_IPV6; @@ -1021,6 +1019,13 @@ *level = IPPROTO_IPV6; *optname = IPV6_MULTICAST_LOOP; return 0; +#if (defined(__solaris__) || defined(MACOSX)) + // Map IP_TOS request to IPV6_TCLASS + case java_net_SocketOptions_IP_TOS: + *level = IPPROTO_IPV6; + *optname = IPV6_TCLASS; + return 0; +#endif } } #endif @@ -1196,9 +1201,6 @@ * Wrapper for getsockopt system routine - does any necessary * pre/post processing to deal with OS specific oddities :- * - * IP_TOS is a no-op with IPv6 sockets as it's setup when - * the connection is established. - * * On Linux the SO_SNDBUF/SO_RCVBUF values must be post-processed * to compensate for an incorrect value returned by the kernel. */ @@ -1208,21 +1210,6 @@ { int rv; -#ifdef AF_INET6 - if ((level == IPPROTO_IP) && (opt == IP_TOS)) { - if (ipv6_available()) { - - /* - * For IPv6 socket option implemented at Java-level - * so return -1. - */ - int *tc = (int *)result; - *tc = -1; - return 0; - } - } -#endif - #ifdef __solaris__ rv = getsockopt(fd, level, opt, result, len); #else @@ -1273,8 +1260,7 @@ * * For IP_TOS socket option need to mask off bits as this * aren't automatically masked by the kernel and results in - * an error. In addition IP_TOS is a NOOP with IPv6 as it - * should be setup as connection time. + * an error. */ int NET_SetSockOpt(int fd, int level, int opt, const void *arg, @@ -1305,9 +1291,9 @@ /* * IPPROTO/IP_TOS :- - * 1. IPv6 on Solaris/Mac OS: NOOP and will be set - * in flowinfo field when connecting TCP socket, - * or sending UDP packet. + * 1. IPv6 on Solaris/Mac OS: + * Set the TOS OR Traffic Class value to cater for + * IPv6 and IPv4 scenarios. * 2. IPv6 on Linux: By default Linux ignores flowinfo * field so enable IPV6_FLOWINFO_SEND so that flowinfo * will be examined. We also set the IPv4 TOS option in this case. @@ -1317,12 +1303,6 @@ if (level == IPPROTO_IP && opt == IP_TOS) { int *iptos; -#if defined(AF_INET6) && (defined(__solaris__) || defined(MACOSX)) - if (ipv6_available()) { - return 0; - } -#endif - #if defined(AF_INET6) && defined(__linux__) if (ipv6_available()) { int optval = 1; @@ -1330,6 +1310,16 @@ (void *)&optval, sizeof(optval)) < 0) { return -1; } + /* + * Let's also set the IPV6_TCLASS flag. + * Linux appears to allow both IP_TOS and IPV6_TCLASS to be set + * This helps in mixed environments where IPv4 and IPv6 sockets + * are connecting. + */ + if (setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, + arg, len) < 0) { + return -1; + } } #endif @@ -1422,7 +1412,7 @@ * On Linux the receive buffer is used for both socket * structures and the the packet payload. The implication * is that if SO_RCVBUF is too small then small packets - * must be discard. + * must be discarded. */ #ifdef __linux__ if (level == SOL_SOCKET && opt == SO_RCVBUF) { @@ -1605,7 +1595,7 @@ * NET_WAIT_READ, NET_WAIT_WRITE & NET_WAIT_CONNECT. * * The function will return when either the socket is ready for one - * of the specified operation or the timeout expired. + * of the specified operations or the timeout expired. * * It returns the time left from the timeout (possibly 0), or -1 if it expired. */
--- a/test/jdk/net/Sockets/Test.java Thu Jun 04 12:04:57 2015 -0700 +++ b/test/jdk/net/Sockets/Test.java Fri Jun 12 12:39:41 2015 +0100 @@ -23,8 +23,9 @@ /* * @test - * @bug 8032808 + * @bug 8032808 8072384 * @run main/othervm -Xcheck:jni Test + * @run main/othervm -Xcheck:jni -Djava.net.preferIPv4Stack=true Test * @run main/othervm/policy=policy.fail -Xcheck:jni Test fail * @run main/othervm/policy=policy.success -Xcheck:jni Test success */ @@ -100,6 +101,10 @@ System.out.println ("Set SO_RCVBUF to 5000\ngetting returns: "); System.out.println (Sockets.getOption(s, StandardSocketOptions.SO_RCVBUF)); + Sockets.setOption(ss, StandardSocketOptions.IP_TOS, 128); + System.out.println ("Setting TOS to 128\ngetting returns: "); + System.out.println (Sockets.getOption(ss, StandardSocketOptions.IP_TOS)); + try { Sockets.setOption(ss, StandardSocketOptions.TCP_NODELAY, true); throw new RuntimeException("TCP_NODELAY should not be supported for ServerSocket");