floodlight添加模塊實驗

元旦的時候發現floodlight居然更新了,嚇壞我了。V0.91210月更新的,然後在141230日連續發佈了V0.91V1.0OTZ……

根據release note來看,主要最大的更新在於添加了對於of1.3的支持。雖然我尚未驗證(後續會驗證)floodlightof1.3的支持程度,但是release note中的這句話:“ and work with OpenFlow 1.3 features such as groups and meters.”。我猜測大概是能夠識別組表和計量表,但是不作處理。OTZ……還有就是以往一些小bug的修復,最直觀的就是頁面的改進。拓撲結構、ip、流表等信息不再像以往一樣顯不顯示得看臉,可以實時準確的顯示出來。

下面是具體的添加模塊的實驗。

導入工程:

git上直接拉下來的代碼是沒法直接導入到eclipse中的,需要添加.project文件和,classpath文件:

Project文件:

<?xml version="1.0" encoding="UTF-8"?>
    <projectDescription>
        <name>floodlight</name>
        <comment></comment>
        <projects>
        </projects>
        <buildSpec>
            <buildCommand>
                <name>org.python.pydev.PyDevBuilder</name>
                <arguments>
                </arguments>
            </buildCommand>
            <buildCommand>
                <name>org.eclipse.jdt.core.javabuilder</name>
                <arguments>
                </arguments>
             </buildCommand>
        </buildSpec>
        <natures>
            <nature>org.eclipse.jdt.core.javanature</nature>
            <nature>org.python.pydev.pythonNature</nature>
        </natures>
</projectDescription>


Classpath文件:

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
	<classpathentry kind="src" output="target/bin" path="src/main/java"/>
	<classpathentry kind="src" path="src/main/resources"/>
	<classpathentry kind="src" output="target/bin-test" path="src/test/java"/>
	<classpathentry kind="src" path="src/test/resources"/>
	<classpathentry kind="src" output="target/bin" path="lib/gen-java"/>
	<classpathentry exported="true" kind="lib" path="lib/args4j-2.0.16.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/cglib-nodep-2.2.2.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/concurrentlinkedhashmap-lru-1.2.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/derby-10.9.1.0.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/findbugs-annotations-2.0.1.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/findbugs-jsr305-2.0.1.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/guava-13.0.1.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/jackson-annotations-2.1.4.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/jackson-core-2.1.4.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/jackson-databind-2.1.4.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/jackson-dataformat-csv-2.1.4.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/jackson-dataformat-smile-2.1.4.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/jackson-dataformat-xml-2.1.4.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/jackson-dataformat-yaml-2.1.4.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/junit-4.8.2.jar" sourcepath="C:/Users/dell/.m2/repository/junit/junit/4.8.2/junit-4.8.2-sources.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/jython-2.5.2.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/libthrift-0.9.0.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/logback-classic-1.0.0.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/logback-core-1.0.0.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/netty-3.2.6.Final.jar" sourcepath="C:/Users/dell/.m2/repository/org/jboss/netty/netty/3.2.6.Final/netty-3.2.6.Final-sources.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/objenesis-1.2.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/org.easymock-3.1.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/org.restlet-2.2M3.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/org.restlet.ext.jackson-2.2M3.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/org.restlet.ext.simple-2.2M3.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/org.restlet.ext.slf4j-2.2M3.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/simple-5.1.1.jar"/>
	<classpathentry exported="true" kind="lib" path="lib/slf4j-api-1.6.4.jar"/>
	<classpathentry kind="lib" path="lib/asm-3.0.jar"/>
	<classpathentry kind="lib" path="lib/asm-tree-3.0.jar"/>
	<classpathentry kind="lib" path="lib/cobertura-1.9.4.1.jar"/>
	<classpathentry kind="lib" path="lib/hamcrest-core-1.3.jar"/>
	<classpathentry kind="lib" path="lib/hamcrest-integration-1.3.jar"/>
	<classpathentry kind="lib" path="lib/hamcrest-library-1.3.jar"/>
	<classpathentry kind="lib" path="lib/j3dutils.jar"/>
	<classpathentry kind="lib" path="lib/jdeb-1.0.1.jar"/>
	<classpathentry kind="lib" path="lib/log4j-1.2.9.jar"/>
	<classpathentry kind="lib" path="lib/openflowj-0.9.0-SNAPSHOT-javadoc.jar"/>
	<classpathentry kind="lib" path="lib/openflowj-0.9.0-SNAPSHOT-sources.jar"/>
	<classpathentry kind="lib" path="lib/openflowj-0.9.0-SNAPSHOT.jar"/>
	<classpathentry kind="lib" path="lib/packetstreamer-thrift.jar"/>
	<classpathentry kind="lib" path="lib/oro/jakarta-oro-2.0.8.jar"/>
	<classpathentry exported="true" kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
	<classpathentry kind="output" path="target/bin"/>
</classpath>

然後就可以作爲普通的項目導入即可。

實驗過程:

這裏的實驗做的是對packet-in包的數量進行統計並打印到控制檯,功能單一,但能體現出添加新模塊的整個流程。

 

1.添加新服務接口

首先需要定義新加模塊服務的接口:

package net.floodlightcontroller.statics;

import net.floodlightcontroller.core.module.IFloodlightService;

/**
 * The service registry
 * @author yangshuai
 */

public interface IPktinHistoryService extends IFloodlightService {
	/*
	 * 用於統計結果
	 */
	public long getPackINCount();
}



2.添加PktinHistory模塊:因爲這裏添加的新模塊的功能比較單一,只是統計floodlight運行後packet-in包的總數量,並且是持續累計計數的,所以只需在該接口中定義一個用於計算的方法就可以了。

定義PktinHistory模塊:

package net.floodlightcontroller.statics;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

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

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.restserver.IRestApiService;

/*
 * 
 *@author yangshuai
 */ 

public class PktinHistory implements 
	IOFMessageListener,IFloodlightModule,IPktinHistoryService{

	protected static Logger log = LoggerFactory.getLogger(PktinHistory.class);
	protected IFloodlightProviderService FloodlightProvider ;
	protected IRestApiService restApi ;
	private AtomicLong PACKET_IN_COUNT = new AtomicLong() ;
	
	@Override
	public String getName() {
		return "PktinHistory" ;
	}

	@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 long getPackINCount() {
		return PACKET_IN_COUNT.get();
	}

	@Override
	public Collection<Class<? extends IFloodlightService>> getModuleServices() {
		Collection<Class<? extends IFloodlightService>> l = 
				new ArrayList<Class<? extends IFloodlightService>>();
		l.add(IPktinHistoryService.class);
		return l;
	}

	@Override
	public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
		Map<Class<? extends IFloodlightService>,IFloodlightService> m = 
				new  HashMap<Class<? extends IFloodlightService>,IFloodlightService>();
		m.put(IPktinHistoryService.class,this);
		return m;
	}

	@Override
	public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
		Collection<Class<? extends IFloodlightService>> l = 
				new ArrayList<Class<? extends IFloodlightService>>() ;
		l.add(IFloodlightProviderService.class);
		l.add(IRestApiService.class);
		return l ;
	}

	@Override
	public void init(FloodlightModuleContext context)
			throws FloodlightModuleException {
		FloodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
		restApi = context.getServiceImpl(IRestApiService.class) ;
	}

	@Override
	public void startUp(FloodlightModuleContext context)
			throws FloodlightModuleException {
		FloodlightProvider.addOFMessageListener(OFType.PACKET_IN,this) ;
	}

	@Override
	public net.floodlightcontroller.core.IListener.Command receive(
			IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
		long count = PACKET_IN_COUNT.incrementAndGet() ;
		log.info("The total count of packet-in Messages are" + count);
		return Command.CONTINUE ;
	}

}

floodlight中所有的模塊都必須實現IFloodlightModule接口,而這裏新添加的模塊需要監聽數據包,所以也需要實現IOFMessageListener接口。IOFMessageListener接口用於監聽Packet-in消息,並記錄消息遞增數量,IPktinHistoryService接口是業務查詢接口,提供Packet-in數據分組統計結果查詢服務,IFloodLightModule接口標識該類是一個floodlight模塊,繼承該接口的類會在floodlight啓動過程中以模塊形式加載。該類文件可以隨意添加到任何包中,爲了方便管理和演示,這裏將所有添加該模塊所新建的文件全都放在了新建包net.floodlightcontroller.statics中。這個路勁在後面修改配置文件中仍然會使用到。

 

3.rest資源定義

在完成模塊的定義之後,需要對rest服務資源進行定義,這裏將類名定義爲:PktInHistoryResource,繼承抽象類ServerResourceServerResourceJava輕量級REST框架Restlet的抽象類),並實現業務邏輯。該步主要功能是將Packet-in統計接口包裝爲REST資源便於後續資源綁定。

package net.floodlightcontroller.statics;

import java.util.HashMap;
import org.restlet.resource.Get;
import org.restlet.resource.ServerResource;

/*
 * 
 *@author yangshuai
 */ 

public class PktInHistoryResource extends ServerResource{
	@Get("json")
	
	public HashMap<String, String> retrieve(){
		IPktinHistoryService pihr = (IPktinHistoryService) getContext()
				.getAttributes().get(IPktinHistoryService.class.getCanonicalName());
		long count = pihr.getPackINCount();
		HashMap<String, String> resp = new HashMap<String, String>() ;
		resp.put("Total", Long.toString(count)) ;
		return resp;
	}
}

4.綁定urlrest資源

接着定義PktInHistoryWebRoutable類,將上步定義的PktInHistoryResource資源與訪問路徑綁定。該類中定義的路徑包括外部獲取該REST資源的基本路徑和相對路徑

package net.floodlightcontroller.statics;

import net.floodlightcontroller.restserver.RestletRoutable;

import org.restlet.Context;
import org.restlet.Restlet;
import org.restlet.routing.Router;

/*
 * 
 *@author yangshuai
 */ 

public class PktInHistoryWebRoutable implements RestletRoutable{

	public Restlet getRestlet(Context context){
		Router router =new Router(context) ;
		router.attach("/pktinhistory/json", PktInHistoryResource.class) ;
		return router ;
	}
	
	public String basePath(){
		return "/vm/statics" ;
	}
}


5.資源發佈 

資源綁定相應路徑後需要在REST服務中發佈,因此還需要在PktinHistorystartUp方法中註冊PktInHistoryWebRoutable,表明有新的資源加入REST服務

@Override
	public void init(FloodlightModuleContext context)
			throws FloodlightModuleException {
		FloodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
		restApi = context.getServiceImpl(IRestApiService.class) ;
	}


6.定義完上述源碼後還需要在配置文件中指定新增模塊名,該配置文件爲resources/META-INF/services/net.FloodLight.core.module.IFloodLightModule,這裏就是添加net.FloodLightcontroller.statics.PktinHistory模塊配置信息。該配置文件是FloodLight模塊加載系統中加載模塊類的依據,用於告知控制器要加載那些模塊。 


7.除上述配置外,還需要在resources/floodlightdefault.properties中的floodlight.modules配置參數後追加新增模塊名(net.FloodLight.controller.statics.PktinHistory 注:這裏就要根據添加的PktinHistory 類的具體路徑進行修改),表明該配置啓動時必須加載。

 

實驗成果截圖:


問題:

在floodlight的顯示界面上的監聽端口爲6633,在1.0以前的版本中,mininet連接到floodlight遠程控制器時指定的端口號也是6633。但是在floodlight1.0版本的測試時,是使用6653端口連接上的。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章