目标
这里完成一个floodligth模块,这个模块可以监听新的MAC地址,并且打印出新的MAC地址以及发现这些MAC地址的交换机的DPID信息.
事前准备
-
已经装好floodlight,并且把floodlight导入到eclipse中
-
已经安装了mininet或者是物理ovs交换机
创建一个listener
在eclipse中增加一个类
1. 在eclipse项目中增加一个package,叫做net.floodlightcontroller.mactracker
2. 在这个package下增加一个类,叫做MACTracker
(或者以上两步也可直接合为一步来做,即直接创建一个类)
3.MACTracker
需要实现IOFMessageListener, IFloodlightModule
两个接口。
以上步骤详细具体的做法是:
a). 将“floodlight”项目导入Eclipse中,并在包管理器中展开,然后找到“src/main/java”目录。
b). 右键单击“src/main/java”目录,选择“New / Class”(即 步骤1,2 合为一步进行)。
c). 在“Package”框中输入“net.floodlightcontroller.mactracker”。(即 包名)
d). 在“Name”框中输入“MACTracker”。(即 类名)
e). 接下来找到“Interface”那一栏,点击旁边的“Add...”按钮。
f). 添加“IOFMessageListener”和“IFloodlightModule”,如果点开是一片空白的话,直接在“choose interfaces”里面搜索这两个接口的名字即可,再add一下,然后点击“OK”按钮。
h). 注意这里勾选“Inherited abstract methods” 最后点击对话框上的“Finish”按钮。
创建好MACTracker
类之后,我们在eclipse中会得到如下代码:
package net.floodlightcontroller.mactracker;
import java.util.Collection;
import java.util.Map;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFType;
import org.projectfloodlight.openflow.types.MacAddress;
import net.floodlightcontroller.core.FloodlightContext;
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;
public class MACTracker implements IOFMessageListener, IFloodlightModule {
@Override
public String getName() {
// TODO Auto-generated method stub
return null;
}
@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 Collection<Class<? extends IFloodlightService>> getModuleServices() {
// TODO Auto-generated method stub
return null;
}
@Override
public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
// TODO Auto-generated method stub
return null;
}
@Override
public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
// TODO Auto-generated method stub
return null;
}
@Override
public void init(FloodlightModuleContext context)
throws FloodlightModuleException {
// TODO Auto-generated method stub
}
@Override
public void startUp(FloodlightModuleContext context) {
// TODO Auto-generated method stub
}
@Override
public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
// TODO Auto-generated method stub
return null;
}
}
设置模块的依赖和初始化函数
在开始前,我们需要引入一些依赖包。使用像eclipse一样的工具可以很方便的添加,如果你没有使用eclipse,只需要将下面的代码添加到类的前面。
import net.floodlightcontroller.core.IFloodlightProviderService;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.Set;
import net.floodlightcontroller.packet.Ethernet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
下面往MACTracker这个类中增加三个成员变量,如下
protected IFloodlightProviderService floodlightProvider;
protected Set<Long> macAddresses;
protected static Logger logger;
为了监听OpenFlow消息,所以需要一个FloodlightProvider(IFloodlightProviderService class)
对象.
为了保存当前发现的mac地址,需要一个set对象来保存mac地址。
为了显示日志信息,打印mac地址以及交换机的信息,所以需要要给Logger对象
下面我们在getModuleDependencies
函数中告诉floodlight,我们需要依赖那些模块。代码如下:
@Override
public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
l.add(IFloodlightProviderService.class);
return l;
}
下面修改init函数,init函数在startup函数之前被调用。init函数的作用是加载依赖项以及初始化成员变量。如下:
@Override
public void init(FloodlightModuleContext context) throws FloodlightModuleException {
floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
macAddresses = new ConcurrentSkipListSet<Long>();
logger = LoggerFactory.getLogger(MACTracker.class);
}
处理Packet-In消息
下面来实现基本监听功能。首先在startUp函数中注册PACKET_IN消息的处理,负责处理的对象就是this,也就是MacTracerk。这边在startUp中,可以保证所有的依赖项都已经加载完毕。
@Override
public void startUp(FloodlightModuleContext context) {
floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
}
对与这个OFMessage监听器,我们也给他起个名字,覆盖父类的getName函数,如下:
@Override
public String getName() {
return MACTracker.class.getSimpleName();
}
下面来实现具体的处理逻辑
@Override
public net.floodlightcontroller.core.IListener.Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
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;
}
处理完成之后,为了让后续的流程可以继续处理OFMessage,我们需要return一个Command.CONTINUE
;
注册模块
首先告诉floodlight我们的模块存在
修改 src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
文件,在结尾增加包名net.floodlightcontroller.mactracker.MACTracker
。如图
告诉floodlight启动的时候,把我们的模块启动起来。修改src/main/resources/floodlightdefault.properties
,增加类名net.floodlightcontroller.mactracker.MACTracker(注意这里一定要保证所以模块都变蓝)
,如图所示:
这样新的模块就已经完成。
检验模块功能(把mininet连接到floodlight上)
1.启动floodlight
2. 建立网络拓扑
打开mininet虚拟机,输入命令
sudo mn --topo single,3 --controller=remote,ip=<你本机的ip地址>,port=6653 --switch ovsk,protocols=OpenFlow13
结果如下图所示:
3 查看floodlight输出结果
在Eclipse的控制台输出信息里,查找MACTracker,可以看到如下信息,可以看到网络中新接入设备的MAC地址和相关交换机