Test Multicast on Private Interconnect (and get maximum MTU)
There are several ways to test multicast communication using udp. I was debugging an oracle Clusterware installation – the clusterware on the second node would not completely start (specifically ocssd and crsd would not start on node2).
All standard/published Oracle tests passed. See Oracle – Clusterware Installation and Configuration
Without going into too much detail, the Clusterware daemons would not start on the second node because the MTU on some of the switches in the network was not configured correctly.
The two java programs below can be used to test whether multicast is working on the network between two servers. More specifically, they can be used to determine the maximum MTU that can be used between the two servers, taking into consideration all network elements (NICs, switches, routers).
Switches/routers may be configured to support Jumbo frames. MTU 9000 (maybe set to 9150 on switch/routers)
The default MTU on switches may be 1400!
Normally, the NICs on the Linux server are set to 1500 MTU.
Private interconnect NICs/bond can be set to 9000 if all intermediate network elements support and are configured for Jumbo frames
MultiCastTestReceiveLoop.java
This program is used to receive udp datagrams on a socket (max. 9150 – covers Jumbo frames).
The communication follows a similar path as that used between Oracle Clusterware processes.
To compile:
To execute:
import sun.net.*; import java.net.*; public class MultiCastTestReceiveLoop { public MultiCastTestReceiveLoop() { MultiCastTestReceiveLoop MultiCastTestReceiveLoop = new MultiCastTestReceiveLoop(42424,"230.0.1.0"); } public MultiCastTestReceiveLoop(int port,String group) { try { while (true) { // Create the socket and bind it to port 'port'. MulticastSocket s = new MulticastSocket(port); // join the multicast group s.setNetworkInterface(NetworkInterface.getByName("<interconnect interface>")); s.joinGroup(InetAddress.getByName(group)); byte buf[] = new byte[9500]; DatagramPacket pack = new DatagramPacket(buf, buf.length); s.receive(pack); System.out.println("Received data from: " + pack.getAddress().toString() + ":" + pack.getPort() + " with length: " + pack.getLength()); System.out.write(pack.getData(),0,pack.getLength()); System.out.println(); s.leaveGroup(InetAddress.getByName(group)); s.close(); } // end while true } // Adding just a catch-all catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { if (args.length == 2) { MultiCastTestReceiveLoop MultiCastTestReceiveLoop = new MultiCastTestReceiveLoop(Integer.parseInt(args[1]),args[0]); } else { MultiCastTestReceiveLoop MultiCastTestReceiveLoop = new MultiCastTestReceiveLoop(); } } }
MultiCastTestSend.java
This program is used to send udp datagrams on a socket. The buffer is filled with the letter ‘a’ (length set with the nbytes argument on the command line
The communication follows a similar path as that used between Oracle Clusterware processes.
To compile:
To execute:
import sun.net.*; import java.net.*; public class MultiCastTestSend { public MultiCastTestSend() { MultiCastTestSend multiCastTestSend = new MultiCastTestSend(42424,"230.0.1.0",10); } public MultiCastTestSend(int port,String group,int nbytes) { int ttl = 1; try { // Create the socket MulticastSocket s = new MulticastSocket(); // set LAN interface to send on s.setNetworkInterface(NetworkInterface.getByName("<interconnect interface>")); // Fill the buffer with some data byte buf[] = new byte[nbytes]; for (int i=0; i<buf.length; i++) buf[i] = (byte)i; // Create a DatagramPacket DatagramPacket pack = new DatagramPacket(buf, buf.length, InetAddress.getByName(group), port); s.setTimeToLive(ttl); s.send(pack); // And when we have finished sending data close the socket System.out.println("Sent bytes to " + pack.getAddress().toString()); s.close(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { if (args.length == 3) { MultiCastTestSend multiCastTestSend = new MultiCastTestSend(Integer.parseInt(args[1]),args[0],Integer.parseInt(args[2])); } else { MultiCastTestSend multiCastTestSend = new MultiCastTestSend(); } } }