# HG changeset patch # User chegar # Date 1254932582 -3600 # Node ID cf907ac8ca4c17f3206274cb747838ce4d6fcf46 # Parent 778ecee935faa8630cc250f82ad9a45ac63ec1cb 6887364: SetOutgoingIf.java fails if run on multihomed machine without PIv6 on all interfaces Reviewed-by: alanb diff -r 778ecee935fa -r cf907ac8ca4c jdk/test/java/net/MulticastSocket/SetOutgoingIf.java --- a/jdk/test/java/net/MulticastSocket/SetOutgoingIf.java Tue Oct 06 22:01:18 2009 -0400 +++ b/jdk/test/java/net/MulticastSocket/SetOutgoingIf.java Wed Oct 07 17:23:02 2009 +0100 @@ -27,7 +27,6 @@ * @summary Re-test IPv6 (and specifically MulticastSocket) with latest Linux & USAGI code */ import java.net.*; -import java.util.concurrent.*; import java.util.*; @@ -68,38 +67,61 @@ // We need 2 or more network interfaces to run the test // - List nics = new ArrayList(); + List netIfs = new ArrayList(); + int index = 1; for (NetworkInterface nic : Collections.list(NetworkInterface.getNetworkInterfaces())) { // we should use only network interfaces with multicast support which are in "up" state - if (!nic.isLoopback() && nic.supportsMulticast() && nic.isUp()) - nics.add(nic); + if (!nic.isLoopback() && nic.supportsMulticast() && nic.isUp()) { + NetIf netIf = NetIf.create(nic); + + // now determine what (if any) type of addresses are assigned to this interface + for (InetAddress addr : Collections.list(nic.getInetAddresses())) { + if (addr instanceof Inet4Address) { + netIf.ipv4Address(true); + } else if (addr instanceof Inet6Address) { + netIf.ipv6Address(true); + } + } + if (netIf.ipv4Address() || netIf.ipv6Address()) { + netIf.index(index++); + netIfs.add(netIf); + debug("Using: " + nic); + } + } } - if (nics.size() <= 1) { + if (netIfs.size() <= 1) { System.out.println("Need 2 or more network interfaces to run. Bye."); return; } - // We will send packets to one ipv4, one ipv4-mapped, and one ipv6 + // We will send packets to one ipv4, and one ipv6 // multicast group using each network interface :- // 224.1.1.1 --| - // ::ffff:224.1.1.2 -----> using network interface #1 - // ff02::1:1 --| + // ff02::1:1 --|--> using network interface #1 // 224.1.2.1 --| - // ::ffff:224.1.2.2 -----> using network interface #2 - // ff02::1:2 --| + // ff02::1:2 --|--> using network interface #2 // and so on. // - List groups = new ArrayList(); - for (int i = 0; i < nics.size(); i++) { - InetAddress groupv4 = InetAddress.getByName("224.1." + (i+1) + ".1"); - InetAddress groupv4mapped = InetAddress.getByName("::ffff:224.1." + (i+1) + ".2"); - InetAddress groupv6 = InetAddress.getByName("ff02::1:" + (i+1)); - groups.add(groupv4); - groups.add(groupv4mapped); - groups.add(groupv6); + for (NetIf netIf : netIfs) { + int NetIfIndex = netIf.index(); + List groups = new ArrayList(); - // use a separated thread to send to those 3 groups - Thread sender = new Thread(new Sender(nics.get(i), groupv4, groupv4mapped, groupv6, PORT)); + if (netIf.ipv4Address()) { + InetAddress groupv4 = InetAddress.getByName("224.1." + NetIfIndex + ".1"); + groups.add(groupv4); + } + if (netIf.ipv6Address()) { + InetAddress groupv6 = InetAddress.getByName("ff02::1:" + NetIfIndex); + groups.add(groupv6); + } + + debug("Adding " + groups + " groups for " + netIf.nic().getName()); + netIf.groups(groups); + + // use a separated thread to send to those 2 groups + Thread sender = new Thread(new Sender(netIf, + groups, + PORT)); sender.setDaemon(true); // we want sender to stop when main thread exits sender.start(); } @@ -108,75 +130,135 @@ // from the expected network interface // byte[] buf = new byte[1024]; - for (InetAddress group : groups) { - MulticastSocket mcastsock = new MulticastSocket(PORT); - mcastsock.setSoTimeout(5000); // 5 second - DatagramPacket packet = new DatagramPacket(buf, 0, buf.length); - - mcastsock.joinGroup(new InetSocketAddress(group, PORT), nics.get(groups.indexOf(group) / 3)); + 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 { - mcastsock.receive(packet); - } catch (Exception e) { - // test failed if any exception - throw new RuntimeException(e); - } + // 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 = nics.get(groups.indexOf(group) / 3); - if (!from.equals(shouldbe)) { - System.out.println("Packets on group " - + group + " should come from " - + shouldbe.getName() + ", but came from " - + from.getName()); - //throw new RuntimeException("Test failed."); + // now check which network interface this packet comes from + NetworkInterface from = NetworkInterface.getByInetAddress(packet.getAddress()); + NetworkInterface shouldbe = nic; + if (!from.equals(shouldbe)) { + System.out.println("Packets on group " + + group + " should come from " + + shouldbe.getName() + ", but came from " + + from.getName()); + //throw new RuntimeException("Test failed."); + } + + mcastsock.leaveGroup(new InetSocketAddress(group, PORT), nic); } + } + } - mcastsock.leaveGroup(new InetSocketAddress(group, PORT), nics.get(groups.indexOf(group) / 3)); - } + private static boolean debug = true; + + static void debug(String message) { + if (debug) + System.out.println(message); } } class Sender implements Runnable { - private NetworkInterface nic; - private InetAddress group1; - private InetAddress group2; - private InetAddress group3; + private NetIf netIf; + private List groups; private int port; - public Sender(NetworkInterface nic, - InetAddress groupv4, InetAddress groupv4mapped, InetAddress groupv6, - int port) { - this.nic = nic; - group1 = groupv4; - group2 = groupv4mapped; - group3 = groupv6; + public Sender(NetIf netIf, + List groups, + int port) { + this.netIf = netIf; + this.groups = groups; this.port = port; } public void run() { try { MulticastSocket mcastsock = new MulticastSocket(); - mcastsock.setNetworkInterface(nic); + mcastsock.setNetworkInterface(netIf.nic()); + List packets = new LinkedList(); byte[] buf = "hello world".getBytes(); - DatagramPacket packet1 = new DatagramPacket(buf, buf.length, - new InetSocketAddress(group1, port)); - DatagramPacket packet2 = new DatagramPacket(buf, buf.length, - new InetSocketAddress(group2, port)); - DatagramPacket packet3 = new DatagramPacket(buf, buf.length, - new InetSocketAddress(group3, port)); + for (InetAddress group : groups) { + packets.add(new DatagramPacket(buf, buf.length, new InetSocketAddress(group, port))); + } for (;;) { - mcastsock.send(packet1); - mcastsock.send(packet2); - mcastsock.send(packet3); + for (DatagramPacket packet : packets) + mcastsock.send(packet); - Thread.currentThread().sleep(1000); // sleep 1 second + Thread.sleep(1000); // sleep 1 second } } catch (Exception e) { throw new RuntimeException(e); } } } + +@SuppressWarnings("unchecked") +class NetIf { + private boolean ipv4Address; //false + private boolean ipv6Address; //false + private int index; + List groups = Collections.EMPTY_LIST; + private final NetworkInterface nic; + + private NetIf(NetworkInterface nic) { + this.nic = nic; + } + + static NetIf create(NetworkInterface nic) { + return new NetIf(nic); + } + + NetworkInterface nic() { + return nic; + } + + boolean ipv4Address() { + return ipv4Address; + } + + void ipv4Address(boolean ipv4Address) { + this.ipv4Address = ipv4Address; + } + + boolean ipv6Address() { + return ipv6Address; + } + + void ipv6Address(boolean ipv6Address) { + this.ipv6Address = ipv6Address; + } + + int index() { + return index; + } + + void index(int index) { + this.index = index; + } + + List groups() { + return groups; + } + + void groups(List groups) { + this.groups = groups; + } +} +