sending a message from controller1 to controller2

sending a message from controller1 to controller2



I have a topology in mininet which consists of 2 floodlight controllers (c1 and c2), a switch (s1) which is connected to c1 and 2 hosts (h1 and h2) that are connected to this switch. I'm writing a program in which when c1 receives an ICMP packet from s1, it will send a Hello message to c2.



I'm using this tutorial for this purpose which says:



Messages can be sent from one controller to another using the send
function, and the messages have to be tagged with an ‘m’ “m”. You will send this message TO a particular controller so
the TO address comprises of two parts IP:port. The IP is the machine
IP address of the other controller (HAServer is listening on all ips),
and the port is the corresponding listening port of HAServer on that
machine.



By default, HAServer on controller 1 is listening on 4242, on
controller 2 on 4243, on controller 3 on 4244 … and so on.



recv() function is similar to the send function and you will be giving
the FROM address to hear back FROM a particular controller. The from
address also comprises of two parts, IP:port. The IP is the machine IP
address of the other controller (HAServer is listening on all ips),
and the port is the corresponding listening port of HAServer on that
machine.



Ideally, this function is called after calling a corresponding send()
function, otherwise, a connection might not have been established, and
it will just return an error.



Here is the complete code of my module:


package net.floodlightcontroller.mactracker;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentSkipListSet;

import net.floodlightcontroller.core.FloodlightContext;
import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IOFMessageListener;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.core.module.FloodlightModuleException;
import net.floodlightcontroller.core.module.IFloodlightModule;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.hasupport.IHAControllerService;
import net.floodlightcontroller.hasupport.NetworkNode;
import net.floodlightcontroller.packet.Ethernet;
import net.floodlightcontroller.packet.ICMP;
import net.floodlightcontroller.packet.IPv4;

import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFType;
import org.projectfloodlight.openflow.types.EthType;
import org.projectfloodlight.openflow.types.IpProtocol;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Mactracker implements IFloodlightModule, IOFMessageListener

protected static IHAControllerService hacontroller;
protected static Logger logger = LoggerFactory.getLogger(Mactracker.class);
protected IFloodlightProviderService floodlightProvider;
protected Set<Long> macAddresses;
private static NetworkNode network;

@Override
public Collection<Class<? extends IFloodlightService>> getModuleServices()
// TODO Auto-generated method stub
return null;


@Override
public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls()
// TODO Auto-generated method stubs
return null;


@Override
public Collection<Class<? extends IFloodlightService>> getModuleDependencies()
// TODO Auto-generated method stub
Collection<Class<? extends IFloodlightService>> l =
new ArrayList<Class<? extends IFloodlightService>>();
l.add(IFloodlightProviderService.class);
l.add(IHAControllerService.class);
return l;


@Override
public void init(FloodlightModuleContext context) throws FloodlightModuleException
// TODO Auto-generated method stub
hacontroller = context.getServiceImpl(IHAControllerService.class);
floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
macAddresses = new ConcurrentSkipListSet<Long>();


@Override
public void startUp(FloodlightModuleContext context) throws FloodlightModuleException
// TODO Auto-generated method stub
floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
// After more than 51% of configured controllers are started, this function will return,
// or when a timeout of 60s is reached, whichever is earlier.
hacontroller.pollForLeader();


@Override
public String getName()
// TODO Auto-generated method stub
return Mactracker.class.getSimpleName();


@Override
public boolean isCallbackOrderingPrereq(OFType type, String name)
// TODO Auto-generated method stub
return false;


@Override
public boolean isCallbackOrderingPostreq(OFType type, String name)
// TODO Auto-generated method stub
return false;


@Override
public net.floodlightcontroller.core.IListener.Command receive(IOFSwitch sw, OFMessage msg,
FloodlightContext cntx)
// TODO Auto-generated method stub
Ethernet eth =
IFloodlightProviderService.bcStore.get(cntx,
IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
if (eth.getEtherType() == EthType.IPv4)
IPv4 ipv4 = (IPv4) eth.getPayload();

if ( ipv4.getProtocol().equals(IpProtocol.ICMP))
logger.warn ("ICMP Packet Received!:-)");
ICMP icmp = (ICMP) ipv4.getPayload();
logger.warn ("icmp.getIcmpType: "+icmp.getIcmpType());

hacontroller.send("127.0.0.1:4243", "mHelloWorld");
hacontroller.recv("127.0.0.1:4242");



Long sourceMACHash = eth.getSourceMACAddress().getLong();
if (!macAddresses.contains(sourceMACHash))
macAddresses.add(sourceMACHash);
logger.info("MAC Address: seen on switch: ",
eth.getSourceMACAddress().toString(),
sw.getId().toString());

return Command.CONTINUE;




But after running this code, when c1 receives an ICMP packet, I encounter multiple errors:


2018-09-13 00:39:56.716 WARN [n.f.m.Mactracker] ICMP Packet Received!:-)
2018-09-13 00:39:56.716 WARN [n.f.m.Mactracker] icmp.getIcmpType: 0
2018-09-13 00:39:56.716 INFO [n.f.h.NetworkNode] [NetworkNode] Sending: mHelloWorld sent through port: 127.0.0.1:4243
2018-09-13 00:39:56.720 WARN [i.n.c.DefaultChannelPipeline] An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
java.lang.NullPointerException: null
at net.floodlightcontroller.hasupport.NetworkNode.recv(NetworkNode.java:535) ~[floodlight.jar:1.2-SNAPSHOT]
at net.floodlightcontroller.hasupport.HAController.recv(HAController.java:190) ~[floodlight.jar:1.2-SNAPSHOT]
at net.floodlightcontroller.mactracker.Mactracker.receive(Mactracker.java:121) ~[floodlight.jar:1.2-SNAPSHOT]
at net.floodlightcontroller.core.internal.Controller.handleMessage(Controller.java:411) ~[floodlight.jar:1.2-SNAPSHOT]
at net.floodlightcontroller.core.internal.OFSwitchManager.handleMessage(OFSwitchManager.java:487) ~[floodlight.jar:1.2-SNAPSHOT]
at net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler.dispatchMessage(OFSwitchHandshakeHandler.java:1752) ~[floodlight.jar:1.2-SNAPSHOT]
at net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler.access$24(OFSwitchHandshakeHandler.java:1751) ~[floodlight.jar:1.2-SNAPSHOT]
at net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler$MasterState.processOFPacketIn(OFSwitchHandshakeHandler.java:1488) ~[floodlight.jar:1.2-SNAPSHOT]
at net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler$OFSwitchHandshakeState.processOFMessage(OFSwitchHandshakeHandler.java:839) ~[floodlight.jar:1.2-SNAPSHOT]
at net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler.processOFMessage(OFSwitchHandshakeHandler.java:1790) ~[floodlight.jar:1.2-SNAPSHOT]
at net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler.messageReceived(OFSwitchHandshakeHandler.java:1964) ~[floodlight.jar:1.2-SNAPSHOT]
at net.floodlightcontroller.core.internal.OFConnection.messageReceived(OFConnection.java:414) ~[floodlight.jar:1.2-SNAPSHOT]
at net.floodlightcontroller.core.internal.OFChannelHandler.sendMessageToConnection(OFChannelHandler.java:579) [floodlight.jar:1.2-SNAPSHOT]
at net.floodlightcontroller.core.internal.OFChannelHandler.access$9(OFChannelHandler.java:578) [floodlight.jar:1.2-SNAPSHOT]



What's the problem? There seems to be something wrong with recv() function. Here is the code of in-built send() and receive functions.



send():


/**
* Sends a message to a specified client IP:port, if possible.
*
* @return boolean value that indicates success or failure.
*/

@Override
public Boolean send(String clientPort, String message)
if (message.equals(null))
return Boolean.FALSE;


clientSock = socketDict.get(clientPort);
try
logger.info("[NetworkNode] Sending: "+message+" sent through port: "+clientPort.toString());
clientSock.send(message);
return Boolean.TRUE;

catch (Exception e)
if (clientSock.getSocketChannel() != null)
clientSock.deleteConnection();

logger.debug("[NetworkNode] Send Failed: " + message + " not sent through port: " + clientPort.toString());
return Boolean.FALSE;




recv():


/**
* Receives a message from the specified IP:port, if possible.
*
* @return String containing the received message.
*/

@Override
public String recv(String receivingPort)
clientSock = socketDict.get(receivingPort);
try
response = clientSock.recv();
response.trim();
logger.info("[NetworkNode] Recv on port:"+receivingPort.toString()+response);
return response;
catch (Exception e)
if (clientSock.getSocketChannel() != null)
clientSock.deleteConnection();

logger.debug("[NetworkNode] Recv Failed on port: " + receivingPort.toString());
return "";





The complete code of NetworkNode module where this send() and recv() function are located, is here and the complete package of High availability support is here (In case it's needed)






Please post the full class code for Controller. Based on the error log, it looks like a null pointer exception is being thrown in this class.

– sellc
Sep 15 '18 at 20:19






@sellc I added the full code.

– helen
Sep 15 '18 at 20:43




4 Answers
4



From the logs you posted and the Github repository you made available, it seems that clientSock is null. A first NullPointerException is being thrown in line 529:


clientSock


null


NullPointerException


response = clientSock.recv();



and being catch.



But then in the catch block, clientSock is still null, so when you do:


clientSock


null


if (clientSock.getSocketChannel() != null) {



a second NullPointerException is thrown (the one we see in the logs) hiding the one that was thrown before.


NullPointerException



Can you debug your code to verify if socketDict contains receivingPort? If not, be sure to initialize it properly.


socketDict


receivingPort



Also, it is usually not a good idea to catch Exception cause it is too large. I would advice you to catch a more precise exception (or exceptions) if you can. If you did that you would have seen the source of this bug more easily.


Exception



The first null pointer exception being thrown in NetworkNode.recv() is because clientSock is never initialized. The null comparison on line 535 can't be checked because clientSock doesn't exist and therefore the method getSocketChannel() cannot be called.


NetworkNode.recv()


clientSock


clientSock


getSocketChannel()



Multiple classes are lacking constructor methods to initialize all variables. This seems to be where most of the issues are based. Make sure all init() and preStart() methods are called too. It looks like most variable initialization is taking place in these methods.


init()


preStart()



There are multiple issues in NetworkNode.recv() method:



The receive method may be rewritten as follows:


NioClient receivingSock = socketDict.get(receivingPort);
if (receivingSock == null)
logger.debug("[NetworkNode] No receivingSock on receivingport: " + receivingPort);
return "";

else
response = receivingSock.recv();
if (response != null)
response.trim();

return response;



The problem with this code is that receive() method is called or (let's say) is active when the switch sends a new packet to the controller.



Here when the first controller receives an ICMP packet, it sends a hello message to the second controller through this piece of the code:


hacontroller.send("127.0.0.1:4243", "mHelloWorld");



But since the second controller has not received any message from the switch, it is not implementing this piece of the code (receive()) at the moment and does not see:


hacontroller.recv("127.0.0.1:4242");



And as far as I can understand, this is the reason why clientSock is never initialized and so I'm receiving this error.


clientSock



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)