Skip to content
Permalink
Browse files
8239355: (dc) Initial value of SO_SNDBUF should allow sending large d…
…atagrams (macOS)

Updates DatagramChannel so that the SO_SNDBUF is set to a minimum value of 65527 for IPv6 sockets and 65507 for IPv4 sockets on macOS.

Reviewed-by: alanb, dfuchs
  • Loading branch information
pconcannon committed Mar 12, 2020
1 parent e5ab701 commit 0ed44d0aeed83f273b1bbe67960593f193115bcd
@@ -265,6 +265,24 @@ Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
}
}
#endif

#ifdef __APPLE__
/**
* Attempt to set SO_SNDBUF to a minimum size to allow sending large datagrams
* (net.inet.udp.maxdgram defaults to 9216).
*/
if (type == SOCK_DGRAM) {
int size;
socklen_t arglen = sizeof(size);
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, &arglen) == 0) {
int minSize = (domain == AF_INET6) ? 65527 : 65507;
if (size < minSize) {
setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &minSize, sizeof(minSize));
}
}
}
#endif

return fd;
}

@@ -1,5 +1,5 @@
//
// Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 2019, 2020, 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
@@ -24,5 +24,6 @@
grant codeBase "file:${test.classes}/../../../../test/lib/-" {
permission java.net.SocketPermission "localhost:0", "listen,resolve";
permission java.util.PropertyPermission "java.net.preferIPv4Stack", "read";
permission java.util.PropertyPermission "java.net.preferIPv6Addresses", "read";
};

@@ -0,0 +1,166 @@
/*
* Copyright (c) 2020, 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 8239355
* @summary Check that new SO_SNDBUF limit on macOS is adhered to
* @library /test/lib
* @build jdk.test.lib.net.IPSupport
* @requires os.family == "mac"
* @run testng/othervm MinSendBufferSize
* @run testng/othervm -Djava.net.preferIPv4Stack=true MinSendBufferSize
*/

import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.io.IOException;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.ProtocolFamily;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.util.ArrayList;
import java.util.List;

import static java.net.StandardSocketOptions.SO_SNDBUF;
import static jdk.test.lib.net.IPSupport.hasIPv4;
import static jdk.test.lib.net.IPSupport.hasIPv6;
import static jdk.test.lib.net.IPSupport.preferIPv4Stack;
import static java.net.StandardProtocolFamily.INET;
import static java.net.StandardProtocolFamily.INET6;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.expectThrows;

public class MinSendBufferSize {
private int EXPECTED_SNDBUF;
private DatagramChannel datagramChannel, datagramChannelIPv4,
datagramChannelIPv6;

private final static int IPV4_SNDBUF = 65507;
private final static int IPV6_SNDBUF = 65527;
private final static Class<IOException> IOE = IOException.class;

@BeforeTest
public void setUp() throws IOException {
datagramChannel = DatagramChannel.open();
if (hasIPv4())
datagramChannelIPv4 = DatagramChannel.open(INET);
if (hasIPv6())
datagramChannelIPv6 = DatagramChannel.open(INET6);

EXPECTED_SNDBUF = hasIPv6() && !preferIPv4Stack()
? IPV6_SNDBUF : IPV4_SNDBUF;
}

private void populateDataProvider(List<Object[]> testcases,
DatagramChannel datagramChannel,
int payloadSize,
ProtocolFamily family) {

testcases.add(new Object[]{datagramChannel, payloadSize - 1,
family, null});
testcases.add(new Object[]{datagramChannel, payloadSize,
family, null});
testcases.add(new Object[]{datagramChannel, payloadSize + 1,
family, IOE});
}

@DataProvider(name = "testGetOptionProvider")
public Object[][] providerIO() {
var testcases = new ArrayList<Object[]>();

testcases.add(new Object[]{datagramChannel, EXPECTED_SNDBUF});
if (hasIPv4())
testcases.add(new Object[]{datagramChannelIPv4, IPV4_SNDBUF});
if (hasIPv6())
testcases.add(new Object[]{datagramChannelIPv6, IPV6_SNDBUF});

return testcases.toArray(Object[][]::new);
}

@DataProvider(name = "testSendPayloadProvider")
public Object[][] providerIO_Payload() {
var testcases = new ArrayList<Object[]>();

if (hasIPv4())
populateDataProvider(testcases, datagramChannel,
IPV4_SNDBUF, INET);
if (hasIPv6() && !preferIPv4Stack())
populateDataProvider(testcases, datagramChannel,
IPV6_SNDBUF, INET6);

if (hasIPv4())
populateDataProvider(testcases, datagramChannelIPv4,
IPV4_SNDBUF, INET);
if (hasIPv6())
populateDataProvider(testcases, datagramChannelIPv6,
IPV6_SNDBUF, INET6);

return testcases.toArray(Object[][]::new);
}

@Test(dataProvider = "testGetOptionProvider")
public void testGetOption(DatagramChannel channel, int sendBuf)
throws IOException {

assertTrue(channel.getOption(SO_SNDBUF) >= sendBuf);
}

@Test(dataProvider = "testSendPayloadProvider")
public void testSend(DatagramChannel channel, int sendBuf,
ProtocolFamily family,
Class<? extends Throwable> exception)
throws IOException {

InetAddress targetAddress;
assert family != null;
if (family == INET) {
targetAddress = InetAddress.getByName("127.0.0.1");
} else {
targetAddress = InetAddress.getByName("::1");
}

try (var receiver = new DatagramSocket(0, targetAddress)) {
var buf = ByteBuffer.allocate(sendBuf);
var addr = receiver.getLocalSocketAddress();
if (exception != null) {
expectThrows(exception, () -> channel.send(buf, addr));
} else {
channel.send(buf, addr);
}
}
}

@AfterTest
public void tearDown() throws IOException {
datagramChannel.close();
if (hasIPv4())
datagramChannelIPv4.close();
if (hasIPv6())
datagramChannelIPv6.close();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2020, 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
@@ -29,7 +29,6 @@
import java.io.UncheckedIOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
@@ -47,6 +46,7 @@
private static final boolean hasIPv4;
private static final boolean hasIPv6;
private static final boolean preferIPv4Stack;
private static final boolean preferIPv6Addresses;

static {
try {
@@ -64,6 +64,8 @@
}
preferIPv4Stack = runPrivilegedAction(() -> Boolean.parseBoolean(
System.getProperty("java.net.preferIPv4Stack")));
preferIPv6Addresses = runPrivilegedAction(() -> Boolean.parseBoolean(
System.getProperty("java.net.preferIPv6Addresses")));
if (!preferIPv4Stack && !hasIPv4 && !hasIPv6) {
throw new AssertionError("IPv4 and IPv6 both not available and java.net.preferIPv4Stack is not true");
}
@@ -112,6 +114,13 @@ public static final boolean preferIPv4Stack() {
return preferIPv4Stack;
}

/**
* Whether or not the "java.net.preferIPv6Addresses" system property is set.
*/
public static final boolean preferIPv6Addresses() {
return preferIPv6Addresses;
}


/**
* Whether or not the current networking configuration is valid or not.
@@ -152,6 +161,7 @@ public static void printPlatformSupport(PrintStream out) {
out.println("IPSupport - IPv4: " + hasIPv4());
out.println("IPSupport - IPv6: " + hasIPv6());
out.println("preferIPv4Stack: " + preferIPv4Stack());
out.println("preferIPv6Addresses: " + preferIPv6Addresses());
}

}

0 comments on commit 0ed44d0

Please sign in to comment.