mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 02:54:35 +02:00
8241786: Improve heuristic to determine default network interface on macOS
DefaultInetrface.getDefault is updated to prefer interfaces that have non link-local addresses. NetworkConfiguration is updated to skip interface that have only link-local addresses, whether IPv4 or IPv6, for multicasting. Reviewed-by: chegar, alanb
This commit is contained in:
parent
553ea1e891
commit
f541970b31
8 changed files with 243 additions and 107 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 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
|
||||
|
@ -26,11 +26,14 @@
|
|||
* @bug 4686717
|
||||
* @summary Test MulticastSocket.setLoopbackMode
|
||||
* @library /test/lib
|
||||
* @modules java.base/java.net:+open
|
||||
* @build jdk.test.lib.NetworkConfiguration
|
||||
* jdk.test.lib.Platform
|
||||
* @run main/othervm SetLoopbackMode
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.net.*;
|
||||
import java.io.IOException;
|
||||
import jdk.test.lib.NetworkConfiguration;
|
||||
|
@ -99,38 +102,75 @@ public class SetLoopbackMode {
|
|||
int failures = 0;
|
||||
NetworkConfiguration nc = NetworkConfiguration.probe();
|
||||
|
||||
MulticastSocket mc = new MulticastSocket();
|
||||
InetAddress grp = InetAddress.getByName("224.80.80.80");
|
||||
try (MulticastSocket mc = new MulticastSocket()) {
|
||||
InetAddress grp = InetAddress.getByName("224.80.80.80");
|
||||
|
||||
|
||||
/*
|
||||
* If IPv6 is available then use IPv6 multicast group - needed
|
||||
* to workaround Linux IPv6 bug whereby !IPV6_MULTICAST_LOOP
|
||||
* doesn't prevent loopback of IPv4 multicast packets.
|
||||
*/
|
||||
/*
|
||||
* If IPv6 is available then use IPv6 multicast group - needed
|
||||
* to workaround Linux IPv6 bug whereby !IPV6_MULTICAST_LOOP
|
||||
* doesn't prevent loopback of IPv4 multicast packets.
|
||||
*/
|
||||
|
||||
if (canUseIPv6(nc)) {
|
||||
grp = InetAddress.getByName("ff01::1");
|
||||
if (canUseIPv6(nc)) {
|
||||
System.out.println("IPv6 can be used");
|
||||
grp = InetAddress.getByName("ff01::1");
|
||||
} else {
|
||||
System.out.println("IPv6 cannot be used: using IPv4");
|
||||
}
|
||||
System.out.println("Default network interface: " + DefaultInterface.getDefaultName());
|
||||
System.out.println("\nTest will use multicast group: " + grp);
|
||||
try {
|
||||
System.out.println("NetworkInterface.getByInetAddress(grp): "
|
||||
+ getName(NetworkInterface.getByInetAddress(grp)));
|
||||
} catch (Exception x) {
|
||||
// OK
|
||||
}
|
||||
mc.joinGroup(grp);
|
||||
|
||||
System.out.println("\n******************\n");
|
||||
|
||||
mc.setLoopbackMode(true);
|
||||
if (test(mc, grp) == FAILED) failures++;
|
||||
|
||||
System.out.println("\n******************\n");
|
||||
|
||||
mc.setLoopbackMode(false);
|
||||
if (test(mc, grp) == FAILED) failures++;
|
||||
|
||||
System.out.println("\n******************\n");
|
||||
|
||||
if (failures > 0) {
|
||||
throw new RuntimeException("Test failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//mc.setNetworkInterface(NetworkInterface.getByInetAddress(lb));
|
||||
System.out.println("\nTest will use multicast group: " + grp);
|
||||
mc.joinGroup(grp);
|
||||
static String getName(NetworkInterface nif) {
|
||||
return nif == null ? null : nif.getName();
|
||||
}
|
||||
|
||||
System.out.println("\n******************\n");
|
||||
|
||||
mc.setLoopbackMode(true);
|
||||
if (test(mc, grp) == FAILED) failures++;
|
||||
|
||||
System.out.println("\n******************\n");
|
||||
|
||||
mc.setLoopbackMode(false);
|
||||
if (test(mc, grp) == FAILED) failures++;
|
||||
|
||||
System.out.println("\n******************\n");
|
||||
|
||||
if (failures > 0) {
|
||||
throw new RuntimeException("Test failed");
|
||||
static class DefaultInterface {
|
||||
static final Method GET_DEFAULT;
|
||||
static {
|
||||
try {
|
||||
GET_DEFAULT = Class.forName("java.net.DefaultInterface")
|
||||
.getDeclaredMethod("getDefault");
|
||||
GET_DEFAULT.setAccessible(true);
|
||||
} catch (Exception x) {
|
||||
throw new ExceptionInInitializerError(x);
|
||||
}
|
||||
}
|
||||
static NetworkInterface getDefault() {
|
||||
try {
|
||||
return (NetworkInterface) GET_DEFAULT
|
||||
.invoke(null);
|
||||
} catch (Exception x) {
|
||||
throw new UndeclaredThrowableException(x);
|
||||
}
|
||||
}
|
||||
static String getDefaultName() {
|
||||
return getName(getDefault());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 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
|
||||
|
@ -23,9 +23,10 @@
|
|||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4686717
|
||||
* @bug 4686717 8241786
|
||||
* @summary Test MulticastSocket.setLoopbackMode with IPv4 addresses
|
||||
* @library /test/lib
|
||||
* @modules java.base/java.net:+open
|
||||
* @build jdk.test.lib.NetworkConfiguration
|
||||
* jdk.test.lib.Platform
|
||||
* SetLoopbackMode
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 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
|
||||
|
@ -23,13 +23,15 @@
|
|||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4742177
|
||||
* @bug 4742177 8241786
|
||||
* @library /test/lib
|
||||
* @run main/othervm SetOutgoingIf
|
||||
* @summary Re-test IPv6 (and specifically MulticastSocket) with latest Linux & USAGI code
|
||||
*/
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import jdk.test.lib.NetworkConfiguration;
|
||||
|
||||
|
||||
|
@ -37,6 +39,7 @@ public class SetOutgoingIf implements AutoCloseable {
|
|||
private static String osname;
|
||||
private final MulticastSocket SOCKET;
|
||||
private final int PORT;
|
||||
private final Map<NetIf, MulticastSender> sendersMap = new ConcurrentHashMap<>();
|
||||
private SetOutgoingIf() {
|
||||
try {
|
||||
SOCKET = new MulticastSocket();
|
||||
|
@ -71,7 +74,11 @@ public class SetOutgoingIf implements AutoCloseable {
|
|||
|
||||
@Override
|
||||
public void close() {
|
||||
SOCKET.close();
|
||||
try {
|
||||
SOCKET.close();
|
||||
} finally {
|
||||
sendersMap.values().stream().forEach(MulticastSender::close);
|
||||
}
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
|
@ -148,9 +155,9 @@ public class SetOutgoingIf implements AutoCloseable {
|
|||
netIf.groups(groups);
|
||||
|
||||
// use a separated thread to send to those 2 groups
|
||||
Thread sender = new Thread(new Sender(netIf,
|
||||
groups,
|
||||
PORT));
|
||||
var multicastSender = new MulticastSender(netIf, groups, PORT);
|
||||
sendersMap.put(netIf, multicastSender);
|
||||
Thread sender = new Thread(multicastSender);
|
||||
sender.setDaemon(true); // we want sender to stop when main thread exits
|
||||
sender.start();
|
||||
}
|
||||
|
@ -162,42 +169,44 @@ public class SetOutgoingIf implements AutoCloseable {
|
|||
for (NetIf netIf : netIfs) {
|
||||
NetworkInterface nic = netIf.nic();
|
||||
for (InetAddress group : netIf.groups()) {
|
||||
MulticastSocket mcastsock = new MulticastSocket(PORT);
|
||||
mcastsock.setSoTimeout(5000); // 5 second
|
||||
DatagramPacket packet = new DatagramPacket(buf, 0, buf.length);
|
||||
try (MulticastSocket mcastsock = new MulticastSocket(PORT)) {
|
||||
mcastsock.setSoTimeout(5000); // 5 second
|
||||
DatagramPacket packet = new DatagramPacket(buf, 0, buf.length);
|
||||
|
||||
// the interface supports the IP multicast group
|
||||
debug("Joining " + group + " on " + nic.getName());
|
||||
mcastsock.joinGroup(new InetSocketAddress(group, PORT), nic);
|
||||
// the interface supports the IP multicast group
|
||||
debug("Joining " + group + " on " + nic.getName());
|
||||
mcastsock.joinGroup(new InetSocketAddress(group, PORT), nic);
|
||||
|
||||
try {
|
||||
mcastsock.receive(packet);
|
||||
debug("received packet on " + packet.getAddress());
|
||||
} catch (Exception e) {
|
||||
// test failed if any exception
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
// now check which network interface this packet comes from
|
||||
NetworkInterface from = NetworkInterface.getByInetAddress(packet.getAddress());
|
||||
NetworkInterface shouldbe = nic;
|
||||
if (from != null) {
|
||||
if (!from.equals(shouldbe)) {
|
||||
System.out.println("Packets on group "
|
||||
+ group + " should come from "
|
||||
+ shouldbe.getName() + ", but came from "
|
||||
+ from.getName());
|
||||
try {
|
||||
mcastsock.receive(packet);
|
||||
debug("received packet on " + packet.getAddress());
|
||||
} catch (Exception e) {
|
||||
// test failed if any exception
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
mcastsock.leaveGroup(new InetSocketAddress(group, PORT), nic);
|
||||
// now check which network interface this packet comes from
|
||||
NetworkInterface from = NetworkInterface.getByInetAddress(packet.getAddress());
|
||||
NetworkInterface shouldbe = nic;
|
||||
if (from != null) {
|
||||
if (!from.equals(shouldbe)) {
|
||||
System.out.println("Packets on group "
|
||||
+ group + " should come from "
|
||||
+ shouldbe.getName() + ", but came from "
|
||||
+ from.getName());
|
||||
}
|
||||
}
|
||||
|
||||
mcastsock.leaveGroup(new InetSocketAddress(group, PORT), nic);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isTestExcludedInterface(NetworkInterface nif) {
|
||||
return !NetworkConfiguration.isTestable(nif)
|
||||
|| isMacOS() && nif.getName().startsWith("utun");
|
||||
|| isMacOS() && nif.getName().startsWith("utun")
|
||||
|| !NetworkConfiguration.hasNonLinkLocalAddress(nif);
|
||||
}
|
||||
|
||||
private static boolean debug = true;
|
||||
|
@ -208,12 +217,14 @@ public class SetOutgoingIf implements AutoCloseable {
|
|||
}
|
||||
}
|
||||
|
||||
class Sender implements Runnable {
|
||||
private NetIf netIf;
|
||||
private List<InetAddress> groups;
|
||||
private int port;
|
||||
class MulticastSender implements Runnable, AutoCloseable {
|
||||
private final NetIf netIf;
|
||||
private final List<InetAddress> groups;
|
||||
private final int port;
|
||||
private volatile boolean closed;
|
||||
private long count;
|
||||
|
||||
public Sender(NetIf netIf,
|
||||
public MulticastSender(NetIf netIf,
|
||||
List<InetAddress> groups,
|
||||
int port) {
|
||||
this.netIf = netIf;
|
||||
|
@ -221,10 +232,15 @@ class Sender implements Runnable {
|
|||
this.port = port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
closed = true;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
MulticastSocket mcastsock = new MulticastSocket();
|
||||
mcastsock.setNetworkInterface(netIf.nic());
|
||||
var nic = netIf.nic();
|
||||
try (MulticastSocket mcastsock = new MulticastSocket()) {
|
||||
mcastsock.setNetworkInterface(nic);
|
||||
List<DatagramPacket> packets = new LinkedList<DatagramPacket>();
|
||||
|
||||
byte[] buf = "hello world".getBytes();
|
||||
|
@ -232,14 +248,23 @@ class Sender implements Runnable {
|
|||
packets.add(new DatagramPacket(buf, buf.length, new InetSocketAddress(group, port)));
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
for (DatagramPacket packet : packets)
|
||||
while (!closed) {
|
||||
for (DatagramPacket packet : packets) {
|
||||
mcastsock.send(packet);
|
||||
|
||||
count++;
|
||||
}
|
||||
System.out.printf("Sent %d packets from %s\n", count, nic.getName());
|
||||
Thread.sleep(1000); // sleep 1 second
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
if (!closed) {
|
||||
System.err.println("Unexpected exception for MulticastSender("
|
||||
+ nic.getName() + "): " + e);
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} finally {
|
||||
System.out.printf("Sent %d packets from %s\n", count, nic.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue