我在mininet中有一个拓扑结构,包括2个泛光灯控制器(c1和c2),一个连接到c1的开关(s1)和连接到该开关的2个主机(h1和h2).我正在编写一个程序,当c1从s1收到ICMP数据包时,它会向c2发送一条Hello消息.
我正在使用本教程来说明:
可以使用send功能将消息从一个控制器发送到另一个控制器,并且消息必须用"m""m"标记.您将此消息发送到特定控制器,因此TO地址包含两部分IP:端口.IP是另一个控制器的机器IP地址(HAServer正在侦听所有ips),该端口是该机器上HAServer的相应侦听端口.
默认情况下,控制器1上的HAServer正在侦听4242,在4243上的控制器2上,在4244上的控制器3上侦听......依此类推.
recv()函数类似于send函数,您将提供FROM地址以收听特定控制器.来自地址还包括两部分,IP:端口.IP是另一个控制器的机器IP地址(HAServer正在侦听所有ips),该端口是该机器上HAServer的相应侦听端口.
理想情况下,在调用相应的send()函数之后调用此函数,否则,可能尚未建立连接,并且它只会返回错误.
这是我的模块的完整代码:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
但是在运行此代码后,当c1收到ICMP数据包时,我遇到了多个错误:
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]
Run Code Online (Sandbox Code Playgroud)
有什么问题?recv()函数似乎有问题.这是内置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;
}
}
Run Code Online (Sandbox Code Playgroud)
的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 "";
}
}
Run Code Online (Sandbox Code Playgroud)
NetworkNode模块的完整源代码,其中本的send()和recv()函数的位置,是在这里和高可用性支持完整的包是在这里(如果它的需要)
此代码的问题在于,当交换机向控制器发送新数据包时,receive() 方法被调用或(比方说)处于活动状态。
这里,当第一个控制器收到 ICMP 数据包时,它通过这段代码向第二个控制器发送 hello 消息:
hacontroller.send("127.0.0.1:4243", "mHelloWorld");
Run Code Online (Sandbox Code Playgroud)
但由于第二个控制器尚未从交换机接收到任何消息,因此它目前没有实现这段代码(receive()),并且看不到:
hacontroller.recv("127.0.0.1:4242");
Run Code Online (Sandbox Code Playgroud)
据我所知,这就是为什么clientSock从未初始化的原因,所以我收到了这个错误。
| 归档时间: |
|
| 查看次数: |
269 次 |
| 最近记录: |