1.在src/main/java目录下新建一个package,目录结构如下:
2.在新建的package下,新建一个class,名字就是自定义的module,接下来implements想实现的service或listener,但是一定要implements自IFloodlightModule。这个类如下所示:
1 package net.floodlightcontroller.mactracker; 2 3 import java.util.ArrayList; 4 import java.util.Collection; 5 import java.util.Map; 6 import java.util.Set; 7 import java.util.concurrent.ConcurrentSkipListSet; 8 9 import org.projectfloodlight.openflow.protocol.OFMessage; 10 import org.projectfloodlight.openflow.protocol.OFType; 11 import org.projectfloodlight.openflow.util.HexString; 12 import org.slf4j.Logger; 13 import org.slf4j.LoggerFactory; 14 15 import net.floodlightcontroller.core.FloodlightContext; 16 import net.floodlightcontroller.core.IFloodlightProviderService; 17 import net.floodlightcontroller.core.IOFMessageListener; 18 import net.floodlightcontroller.core.IOFSwitch; 19 import net.floodlightcontroller.core.module.FloodlightModuleContext; 20 import net.floodlightcontroller.core.module.FloodlightModuleException; 21 import net.floodlightcontroller.core.module.IFloodlightModule; 22 import net.floodlightcontroller.core.module.IFloodlightService; 23 import net.floodlightcontroller.packet.Ethernet; 24 25 public class MACTracker implements IOFMessageListener, IFloodlightModule{ 26 27 protected IFloodlightProviderService floodlightProvider; 28 protected Set macAddresses; 29 protected static Logger logger; 30 31 /** 32 * 添加本module的id 33 */ 34 @Override 35 public String getName() { 36 return "MACTracker"; 37 } 38 @Override 39 public boolean isCallbackOrderingPrereq(OFType type, String name) { 40 // TODO Auto-generated method stub 41 return false; 42 } 43 @Override 44 public boolean isCallbackOrderingPostreq(OFType type, String name) { 45 // TODO Auto-generated method stub 46 return false; 47 } 48 @Override 49 public Collection<Class<? extends IFloodlightService>> getModuleServices() { 50 // TODO Auto-generated method stub 51 return null; 52 } 53 @Override 54 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() { 55 // TODO Auto-generated method stub 56 return null; 57 } 58 59 /** 60 * 把依赖关系告诉模块加载系统 61 */ 62 @Override 63 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { 64 Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>(); 65 l.add(IFloodlightProviderService.class); 66 return l; 67 } 68 /** 69 * 实现init初始化,这个方法会在controller启动时调用,以加载依赖和数据结构 70 */ 71 @Override 72 public void init(FloodlightModuleContext context) throws FloodlightModuleException { 73 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class); 74 macAddresses = new ConcurrentSkipListSet<Long>(); 75 logger = LoggerFactory.getLogger(MACTracker.class); 76 } 77 /** 78 * 实现startUp方法,为packet_in消息绑定事件处理委托,在这之前我们必须保证所有依赖的模块已经初始化 79 * 主要是用来添加监听器 80 */ 81 @Override 82 public void startUp(FloodlightModuleContext context) throws FloodlightModuleException { 83 floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this); 84 } 85 /** 86 * 处理packet_in消息,返回Command.CONTINUE以便其它事件处理程序继续处理 87 * 这里是用来搜集源MAC地址 88 */ 89 @Override 90 public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) { 91 Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD); 92 Long sourceMACHash = Ethernet.toLong(eth.getSourceMACAddress().getBytes()); 93 if(!macAddresses.contains(sourceMACHash)) { 94 macAddresses.add(sourceMACHash); 95 logger.info("开始所搜集MAC地址:" 96 + "MAC Address: {} seen on switch:{}", HexString.toHexString(sourceMACHash), sw.getId()); 97 } 98 return Command.CONTINUE; 99 } 100 101 }
这个module由receive方法驱动,具体功能是搜集MAC地址,结果如下所示: