8284890: Support for Do not fragment IP socket options

Reviewed-by: erikj, ihse, dfuchs
This commit is contained in:
Michael McMahon 2022-04-26 13:49:58 +00:00
parent a7b5157375
commit 67755edd6f
11 changed files with 498 additions and 3 deletions
make/modules/jdk.net
src
java.base/share/classes/sun/net/ext
jdk.net
linux
classes/jdk/net
native/libextnet
macosx
classes/jdk/net
native/libextnet
share/classes/jdk/net
windows
test/jdk
java/net/SocketOption
jdk/net/ExtendedSocketOption

@ -27,7 +27,7 @@ include LibCommon.gmk
################################################################################
ifeq ($(call isTargetOs, linux macosx), true)
ifeq ($(call isTargetOs, linux macosx windows), true)
$(eval $(call SetupJdkLibrary, BUILD_LIBEXTNET, \
NAME := extnet, \
@ -35,8 +35,9 @@ ifeq ($(call isTargetOs, linux macosx), true)
CFLAGS := $(CFLAGS_JDKLIB), \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LIBS := -ljava, \
LIBS_unix := -ljava, \
LIBS_linux := -ljvm, \
LIBS_windows := jvm.lib ws2_32.lib $(WIN_JAVA_LIB), \
))
$(BUILD_LIBEXTNET): $(call FindLib, java.base, java)

@ -108,7 +108,8 @@ public abstract class ExtendedSocketOptions {
}
private static boolean isStreamOption(SocketOption<?> option, boolean server) {
if (option.name().startsWith("UDP_") || isUnixDomainOption(option)) {
if (option.name().startsWith("UDP_") || isUnixDomainOption(option)
|| option.name().equals("IP_DONTFRAGMENT")) {
return false;
} else {
return true;

@ -102,6 +102,16 @@ class LinuxSocketOptions extends PlatformSocketOptions {
return getIncomingNapiId0(fd);
}
@Override
void setIpDontFragment(int fd, final boolean value) throws SocketException {
setIpDontFragment0(fd, value);
}
@Override
boolean getIpDontFragment(int fd) throws SocketException {
return getIpDontFragment0(fd);
}
@Override
UnixDomainPrincipal getSoPeerCred(int fd) throws SocketException {
long l = getSoPeerCred0(fd);
@ -115,9 +125,11 @@ class LinuxSocketOptions extends PlatformSocketOptions {
private static native void setTcpkeepAliveProbes0(int fd, int value) throws SocketException;
private static native void setTcpKeepAliveTime0(int fd, int value) throws SocketException;
private static native void setTcpKeepAliveIntvl0(int fd, int value) throws SocketException;
private static native void setIpDontFragment0(int fd, boolean value) throws SocketException;
private static native int getTcpkeepAliveProbes0(int fd) throws SocketException;
private static native int getTcpKeepAliveTime0(int fd) throws SocketException;
private static native int getTcpKeepAliveIntvl0(int fd) throws SocketException;
private static native boolean getIpDontFragment0(int fd) throws SocketException;
private static native void setQuickAck0(int fd, boolean on) throws SocketException;
private static native boolean getQuickAck0(int fd) throws SocketException;
private static native long getSoPeerCred0(int fd) throws SocketException;

@ -243,3 +243,65 @@ JNIEXPORT jint JNICALL Java_jdk_net_LinuxSocketOptions_getIncomingNapiId0
handleError(env, rv, "get option SO_INCOMING_NAPI_ID failed");
return optval;
}
static int socketFamily(jint fd) {
struct sockaddr_storage st;
struct sockaddr *sa = (struct sockaddr *)&st;
socklen_t sa_len = sizeof(st);
if (getsockname(fd, sa, &sa_len) == 0) {
return sa->sa_family;
}
return -1;
}
/*
* Class: jdk_net_LinuxSocketOptions
* Method: setIpDontFragment0
* Signature: (IZ)V
*/
JNIEXPORT void JNICALL Java_jdk_net_LinuxSocketOptions_setIpDontFragment0
(JNIEnv *env, jobject unused, jint fd, jboolean optval) {
jint rv, optsetting;
jint family = socketFamily(fd);
if (family == -1) {
handleError(env, family, "get socket family failed");
return;
}
optsetting = optval ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
if (family == AF_INET) {
rv = setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, &optsetting, sizeof (optsetting));
} else {
rv = setsockopt(fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &optsetting, sizeof (optsetting));
}
handleError(env, rv, "set option IP_DONTFRAGMENT failed");
}
/*
* Class: jdk_net_LinuxSocketOptions
* Method: getIpDontFragment0
* Signature: (I)Z;
*/
JNIEXPORT jboolean JNICALL Java_jdk_net_LinuxSocketOptions_getIpDontFragment0
(JNIEnv *env, jobject unused, jint fd) {
jint optlevel, optname, optval, rv;
jint family = socketFamily(fd);
if (family == -1) {
handleError(env, family, "get socket family failed");
return JNI_FALSE;
}
if (family == AF_INET) {
optlevel = IPPROTO_IP;
optname = IP_MTU_DISCOVER;
} else {
optlevel = IPPROTO_IPV6;
optname = IPV6_MTU_DISCOVER;
}
socklen_t sz = sizeof(optval);
rv = getsockopt(fd, optlevel, optname, &optval, &sz);
handleError(env, rv, "get option IP_DONTFRAGMENT failed");
return optval == IP_PMTUDISC_DO ? JNI_TRUE : JNI_FALSE;
}

@ -78,6 +78,16 @@ class MacOSXSocketOptions extends PlatformSocketOptions {
return getTcpKeepAliveIntvl0(fd);
}
@Override
void setIpDontFragment(int fd, final boolean value) throws SocketException {
setIpDontFragment0(fd, value);
}
@Override
boolean getIpDontFragment(int fd) throws SocketException {
return getIpDontFragment0(fd);
}
@Override
UnixDomainPrincipal getSoPeerCred(int fd) throws SocketException {
long l = getSoPeerCred0(fd);
@ -91,9 +101,11 @@ class MacOSXSocketOptions extends PlatformSocketOptions {
private static native void setTcpkeepAliveProbes0(int fd, int value) throws SocketException;
private static native void setTcpKeepAliveTime0(int fd, int value) throws SocketException;
private static native void setTcpKeepAliveIntvl0(int fd, int value) throws SocketException;
private static native void setIpDontFragment0(int fd, boolean value) throws SocketException;
private static native int getTcpkeepAliveProbes0(int fd) throws SocketException;
private static native int getTcpKeepAliveTime0(int fd) throws SocketException;
private static native int getTcpKeepAliveIntvl0(int fd) throws SocketException;
private static native boolean getIpDontFragment0(int fd) throws SocketException;
private static native long getSoPeerCred0(int fd) throws SocketException;
private static native boolean keepAliveOptionsSupported0();
static {

@ -30,7 +30,14 @@
#include <jni.h>
#include <netinet/tcp.h>
#define __APPLE_USE_RFC_3542
#include <netinet/in.h>
#ifndef IP_DONTFRAG
#define IP_DONTFRAG 28
#endif
#include "jni_util.h"
/*
@ -170,3 +177,60 @@ JNIEXPORT jint JNICALL Java_jdk_net_MacOSXSocketOptions_getTcpKeepAliveIntvl0
handleError(env, rv, "get option TCP_KEEPINTVL failed");
return optval;
}
static int socketFamily(jint fd) {
struct sockaddr_storage st;
struct sockaddr* sa = (struct sockaddr *)&st;
socklen_t sa_len = sizeof(st);
if (getsockname(fd, sa, &sa_len) == 0) {
return sa->sa_family;
}
return -1;
}
/*
* Class: jdk_net_MacOSXSocketOptions
* Method: setIpDontFragment0
* Signature: (IZ)V
*/
JNIEXPORT void JNICALL Java_jdk_net_MacOSXSocketOptions_setIpDontFragment0
(JNIEnv *env, jobject unused, jint fd, jboolean optval) {
jint rv;
jint family = socketFamily(fd);
jint value = optval ? 1 : 0;
if (family == -1) {
handleError(env, family, "get socket family failed");
return;
}
if (family == AF_INET) {
rv = setsockopt(fd, IPPROTO_IP, IP_DONTFRAG, &value, sizeof(value));
} else {
rv = setsockopt(fd, IPPROTO_IPV6, IPV6_DONTFRAG, &value, sizeof(value));
}
handleError(env, rv, "set option IP_DONTFRAGMENT failed");
}
/*
* Class: jdk_net_MacOSXSocketOptions
* Method: getIpDontFragment0
* Signature: (I)Z;
*/
JNIEXPORT jboolean JNICALL Java_jdk_net_MacOSXSocketOptions_getIpDontFragment0
(JNIEnv *env, jobject unused, jint fd) {
jint optval, rv;
socklen_t sz = sizeof (optval);
jint family = socketFamily(fd);
if (family == -1) {
handleError(env, family, "get socket family failed");
return 0;
}
if (family == AF_INET) {
rv = getsockopt(fd, IPPROTO_IP, IP_DONTFRAG, &optval, &sz);
} else {
rv = getsockopt(fd, IPPROTO_IPV6, IPV6_DONTFRAG, &optval, &sz);
}
handleError(env, rv, "get option IP_DONTFRAGMENT failed");
return optval;
}

@ -199,6 +199,28 @@ public final class ExtendedSocketOptions {
= new ExtSocketOption<UnixDomainPrincipal>
("SO_PEERCRED", UnixDomainPrincipal.class);
/**
* Disable IP packet fragmentation.
*
* <p> The value of this socket option is a {@code Boolean} that represents
* whether the option is enabled or disabled. When {@code true} fragmentation
* of outgoing IPv4 and IPv6 packets does not occur. This option can only be used
* with datagram sockets. When set, care must be taken to limit outgoing packet
* sizes to the {@link java.net.NetworkInterface#getMTU() local MTU}. Depending
* on the implementation and the network interface, packets larger than the MTU
* may be sent or dropped silently or dropped with an exception thrown.
*
* @apiNote
* For IPv4 this option sets the DF (Do not Fragment) flag in the IP packet
* header. This instructs intermediate routers to not fragment the packet.
* IPv6 routers never fragment packets. Instead, fragmentation is handled
* by the sending and receiving nodes exclusively. Setting this option for
* an IPv6 socket ensures that packets to be sent are never fragmented, in
* which case, the local network MTU must be observed.
*/
public static final SocketOption<Boolean> IP_DONTFRAGMENT =
new ExtSocketOption<Boolean>("IP_DONTFRAGMENT", Boolean.class);
private static final PlatformSocketOptions platformSocketOptions =
PlatformSocketOptions.get();
@ -210,6 +232,7 @@ public final class ExtendedSocketOptions {
platformSocketOptions.peerCredentialsSupported();
private static final boolean incomingNapiIdOptSupported =
platformSocketOptions.incomingNapiIdSupported();
private static final Set<SocketOption<?>> extendedOptions = options();
static Set<SocketOption<?>> options() {
@ -226,6 +249,7 @@ public final class ExtendedSocketOptions {
if (peerCredentialsSupported) {
options.add(SO_PEERCRED);
}
options.add(IP_DONTFRAGMENT);
return Collections.unmodifiableSet(options);
}
@ -248,6 +272,8 @@ public final class ExtendedSocketOptions {
setQuickAckOption(fd, (boolean) value);
} else if (option == TCP_KEEPCOUNT) {
setTcpkeepAliveProbes(fd, (Integer) value);
} else if (option == IP_DONTFRAGMENT) {
setIpDontFragment(fd, (Boolean) value);
} else if (option == TCP_KEEPIDLE) {
setTcpKeepAliveTime(fd, (Integer) value);
} else if (option == TCP_KEEPINTERVAL) {
@ -277,6 +303,8 @@ public final class ExtendedSocketOptions {
return getQuickAckOption(fd);
} else if (option == TCP_KEEPCOUNT) {
return getTcpkeepAliveProbes(fd);
} else if (option == IP_DONTFRAGMENT) {
return getIpDontFragment(fd);
} else if (option == TCP_KEEPIDLE) {
return getTcpKeepAliveTime(fd);
} else if (option == TCP_KEEPINTERVAL) {
@ -320,6 +348,11 @@ public final class ExtendedSocketOptions {
platformSocketOptions.setTcpKeepAliveTime(fdAccess.get(fd), value);
}
private static void setIpDontFragment(FileDescriptor fd, boolean value)
throws SocketException {
platformSocketOptions.setIpDontFragment(fdAccess.get(fd), value);
}
private static void setTcpKeepAliveIntvl(FileDescriptor fd, int value)
throws SocketException {
platformSocketOptions.setTcpKeepAliveIntvl(fdAccess.get(fd), value);
@ -329,6 +362,10 @@ public final class ExtendedSocketOptions {
return platformSocketOptions.getTcpkeepAliveProbes(fdAccess.get(fd));
}
private static boolean getIpDontFragment(FileDescriptor fd) throws SocketException {
return platformSocketOptions.getIpDontFragment(fdAccess.get(fd));
}
private static int getTcpKeepAliveTime(FileDescriptor fd) throws SocketException {
return platformSocketOptions.getTcpKeepAliveTime(fdAccess.get(fd));
}
@ -368,6 +405,8 @@ public final class ExtendedSocketOptions {
return newInstance("jdk.net.LinuxSocketOptions");
} else if (osname.startsWith("Mac")) {
return newInstance("jdk.net.MacOSXSocketOptions");
} else if (osname.startsWith("Windows")) {
return newInstance("jdk.net.WindowsSocketOptions");
} else {
return new PlatformSocketOptions();
}
@ -415,6 +454,14 @@ public final class ExtendedSocketOptions {
throw new UnsupportedOperationException("unsupported TCP_KEEPINTVL option");
}
void setIpDontFragment(int fd, final boolean value) throws SocketException {
throw new UnsupportedOperationException("unsupported IP_DONTFRAGMENT option");
}
boolean getIpDontFragment(int fd) throws SocketException {
throw new UnsupportedOperationException("unsupported IP_DONTFRAGMENT option");
}
int getTcpkeepAliveProbes(int fd) throws SocketException {
throw new UnsupportedOperationException("unsupported TCP_KEEPCNT option");
}

@ -0,0 +1,62 @@
/*
* Copyright (c) 2022, 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 jdk.net;
import java.net.SocketException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import jdk.net.ExtendedSocketOptions.PlatformSocketOptions;
@SuppressWarnings("removal")
class WindowsSocketOptions extends PlatformSocketOptions {
public WindowsSocketOptions() {
}
@Override
void setIpDontFragment(int fd, final boolean value) throws SocketException {
setIpDontFragment0(fd, value);
}
@Override
boolean getIpDontFragment(int fd) throws SocketException {
return getIpDontFragment0(fd);
}
private static native void setIpDontFragment0(int fd, boolean value) throws SocketException;
private static native boolean getIpDontFragment0(int fd) throws SocketException;
static {
if (System.getSecurityManager() == null) {
System.loadLibrary("extnet");
} else {
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
System.loadLibrary("extnet");
return null;
});
}
}
}

@ -0,0 +1,126 @@
/*
* Copyright (c) 2022, 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.
*/
#include <windows.h>
#include <winsock2.h>
#include <WS2tcpip.h>
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
static void handleError(JNIEnv *env, jint rv, const char *errmsg) {
if (rv < 0) {
if (errno == ENOPROTOOPT) {
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
"unsupported socket option");
} else {
JNU_ThrowByNameWithLastError(env, "java/net/SocketException", errmsg);
}
}
}
static int socketFamily(jint fd) {
WSAPROTOCOL_INFO info;
socklen_t sa_len = sizeof(info);
if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL_INFO, (char *)&info, &sa_len) == 0) {
return info.iAddressFamily;
}
return -1;
}
/*
* Class: jdk_net_WindowsSocketOptions
* Method: setIpDontFragment0
* Signature: (IZ)V
*/
JNIEXPORT void JNICALL Java_jdk_net_WindowsSocketOptions_setIpDontFragment0
(JNIEnv *env, jobject unused, jint fd, jboolean optval) {
int rv, opt;
jint family = socketFamily(fd);
if (family == -1) {
handleError(env, family, "get socket family failed");
return;
}
if (family == AF_INET) {
opt = optval ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
rv = setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, (char *)&opt, sizeof(int));
if (rv == SOCKET_ERROR && WSAGetLastError() == WSAENOPROTOOPT) {
opt = optval;
rv = setsockopt(fd, IPPROTO_IP, IP_DONTFRAGMENT, (char *)&opt, sizeof(int));
}
} else {
opt = optval ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
rv = setsockopt(fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, (char *)&opt, sizeof(int));
if (rv == SOCKET_ERROR && WSAGetLastError() == WSAENOPROTOOPT) {
/* IPV6_MTU_DISCOVER not supported on W 2016 and older, can use old option */
opt = optval;
rv = setsockopt(fd, IPPROTO_IP, IP_DONTFRAGMENT, (char *)&opt, sizeof(int));
}
}
handleError(env, rv, "set option IP_DONTFRAGMENT failed");
}
/*
* Class: jdk_net_WindowsSocketOptions
* Method: getIpDontFragment0
* Signature: (I)Z;
*/
JNIEXPORT jboolean JNICALL Java_jdk_net_WindowsSocketOptions_getIpDontFragment0
(JNIEnv *env, jobject unused, jint fd) {
int optval, rv, sz = sizeof(optval);
jint family = socketFamily(fd);
if (family == -1) {
handleError(env, family, "get socket family failed");
return JNI_FALSE;
}
if (family == AF_INET) {
rv = getsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, (char *)&optval, &sz);
if (rv == SOCKET_ERROR && WSAGetLastError() == WSAENOPROTOOPT) {
sz = sizeof(optval);
rv = getsockopt(fd, IPPROTO_IP, IP_DONTFRAGMENT, (char *)&optval, &sz);
handleError(env, rv, "get option IP_DONTFRAGMENT failed");
return optval;
}
handleError(env, rv, "get option IP_DONTFRAGMENT failed");
return optval == IP_PMTUDISC_DO ? JNI_TRUE : JNI_FALSE;
} else {
rv = getsockopt(fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, (char *)&optval, &sz);
if (rv == SOCKET_ERROR && WSAGetLastError() == WSAENOPROTOOPT) {
sz = sizeof(optval);
rv = getsockopt(fd, IPPROTO_IP, IP_DONTFRAGMENT, (char *)&optval, &sz);
handleError(env, rv, "get option IP_DONTFRAGMENT failed");
return optval;
}
handleError(env, rv, "get option IP_DONTFRAGMENT failed");
return optval == IP_PMTUDISC_DO ? JNI_TRUE : JNI_FALSE;
}
}

@ -105,6 +105,8 @@ public class AfterClose {
map.put((SocketOption<?>)field.get(null), listOf(10, 100));
field = c.getField("SO_INCOMING_NAPI_ID");
map.put((SocketOption<?>)field.get(null), listOf(RO));
field = c.getField("IP_DONTFRAGMENT");
map.put((SocketOption<?>)field.get(null), listOf(TRUE, FALSE));
} catch (ClassNotFoundException e) {
// ignore, jdk.net module not present
} catch (ReflectiveOperationException e) {

@ -0,0 +1,106 @@
/*
* 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 8243099
* @modules jdk.net
* @run main/othervm DontFragmentTest ipv4
* @run main/othervm DontFragmentTest ipv6
*/
import java.io.IOException;
import java.net.*;
import java.nio.channels.*;
import static java.net.StandardProtocolFamily.INET;
import static java.net.StandardProtocolFamily.INET6;
import static jdk.net.ExtendedSocketOptions.IP_DONTFRAGMENT;
public class DontFragmentTest {
public static void main(String[] args) throws IOException {
testDatagramChannel();
StandardProtocolFamily fam = args[0].equals("ipv4") ? INET : INET6;
System.out.println("Family = " + fam);
testDatagramChannel(args, fam);
try (DatagramSocket c = new DatagramSocket()) {
testDatagramSocket(c);
}
try (DatagramChannel dc = DatagramChannel.open(fam)) {
var c = dc.socket();
testDatagramSocket(c);
}
try (MulticastSocket mc = new MulticastSocket()) {
testDatagramSocket(mc);
}
}
public static void testDatagramChannel() throws IOException {
try (DatagramChannel c1 = DatagramChannel.open()) {
if (c1.getOption(IP_DONTFRAGMENT)) {
throw new RuntimeException("IP_DONTFRAGMENT should not be set");
}
c1.setOption(IP_DONTFRAGMENT, true);
if (!c1.getOption(IP_DONTFRAGMENT)) {
throw new RuntimeException("IP_DONTFRAGMENT should be set");
}
c1.setOption(IP_DONTFRAGMENT, false);
if (c1.getOption(IP_DONTFRAGMENT)) {
throw new RuntimeException("IP_DONTFRAGMENT should not be set");
}
}
}
public static void testDatagramChannel(String[] args, ProtocolFamily fam) throws IOException {
try (DatagramChannel c1 = DatagramChannel.open(fam)) {
if (c1.getOption(IP_DONTFRAGMENT)) {
throw new RuntimeException("IP_DONTFRAGMENT should not be set");
}
c1.setOption(IP_DONTFRAGMENT, true);
if (!c1.getOption(IP_DONTFRAGMENT)) {
throw new RuntimeException("IP_DONTFRAGMENT should be set");
}
c1.setOption(IP_DONTFRAGMENT, false);
if (c1.getOption(IP_DONTFRAGMENT)) {
throw new RuntimeException("IP_DONTFRAGMENT should not be set");
}
}
}
public static void testDatagramSocket(DatagramSocket c1) throws IOException {
if (c1.getOption(IP_DONTFRAGMENT)) {
throw new RuntimeException("IP_DONTFRAGMENT should not be set");
}
c1.setOption(IP_DONTFRAGMENT, true);
if (!c1.getOption(IP_DONTFRAGMENT)) {
throw new RuntimeException("IP_DONTFRAGMENT should be set");
}
c1.setOption(IP_DONTFRAGMENT, false);
if (c1.getOption(IP_DONTFRAGMENT)) {
throw new RuntimeException("IP_DONTFRAGMENT should not be set");
}
c1.close();
}
}