Floodlight 入門 之 起步篇 - 建立一個Floodlight模塊

Floodlight 入門 之 起步篇 - 建立一個Floodlight模塊

  • 2017-3-1

網上也有不少關於Floodlight的入門教程了,我寫該博文的目的主要是問了整理個人在學習和使用Floodlight時掌握的知識,如果這些文字能爲大家帶來幫助是最好不過的了。

博文會持續更新,如果想要跟蹤該博文的進度,推薦使用RSS。每次更新會在博文開始出更改時間戳。

該博文系列是從Floodlight官網的官方教程翻譯而來,想嚼原味教程請點擊鏈接Tutorials


前提條件

我們在進行下面的實驗前,首先要檢查我們的實驗環境是否滿足下面的條件:

  • 成功地完成了Getting Started的教程,包括配置Eclipse。
  • 安裝了Mininet或者有一個可以使用的OpenFlow物理交換機。

確保滿足上述條件後,就可以進行下面的實驗了。

創建一個監聽器

在Eclipse中添加一個Class

  1. 展開floodlight項,你會看到“src/main/java”文件夾。
  2. 選中“src/main/java”文件夾,然後右擊,在彈出的菜單中選中 “New/Class”。
  3. 在“Package”欄寫入net.floodlightcontroller.mactracker。
  4. 在“Name”欄寫入MACTracker。
  5. 然後就是“Interfaces”欄,我們點擊旁邊的“Add..”爲該類添加接口。
  6. 添加”IOFMessageListener”和”IFloodlightModule”,然後點擊OK。
  7. 點擊“Finish”完成類的創建。

上面的步驟完成後,你將會看到下面的代碼:

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來編寫代碼,你就需要手動將下面的依賴項添加到java文件的開頭:

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;

現在我們有了必需的依賴項,而且通過之前創建類的操作,我們有了一個有框架的類。然而這樣的類肯定還是不能正常使用的,我們需要實現一些方法來確保我們創建的模塊可以被加載。首先,我們需要在該類中添加一些必要的成員變量。我們現在要創建的模塊是要實現跟蹤MAC地址的功能,所以我們需要監聽Openflow messages,需要添加一個FloodlightProvider((IFloodlightProviderService class)。我們還需要一個數據結構存儲我們監聽到的MAC地址,需要一個logger來輸出我們監聽到的信息。最後我們需要的成員變量如下所示:

protected IFloodlightProviderService floodlightProvider;
protected Set<Long> macAddresses;
protected static Logger logger;

現在我們需要完成模塊被加載的功能。我們對getModuleDependencies()方法進行更改,以此來告訴模塊加載器我們依賴於它:

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

現在我們的模塊可以被加載了。一般來說,一個模塊被加載時是要進行初始化的。所以接下來我們來對初始化方法進行實現:

@Override
public void init(FloodlightModuleContext context) throws FloodlightModuleException {
    floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
    macAddresses = new ConcurrentSkipListSet<Long>();
    logger = LoggerFactory.getLogger(MACTracker.class);
}

處理Packet-In消息

經過上面的操作,我們的模塊已經可以作爲一個模塊正常的運行了。然而我們的目的是創建一個能跟蹤MAC地址的模塊,所以我們接下來還要對模塊的功能進行實現。首先,我們需要實現一個簡單的監聽器(用來監聽OpenFlow消息)。我們將會在我們的startUp方法中註冊一個監聽PACKET_IN消息的監聽器。這裏我們假定我們依賴的其他模塊已經初始化好了:

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

我們還須要爲我們的OFMessage監聽器放入一個ID什麼的(原文:We also have to put in an ID for our OFMessage listener.)。這裏可以在在回調函數getName()中完成:

@Override
public String getName() {
    return MACTracker.class.getSimpleName();
}

現在我們就可以叫我們的PACKET_IN消息與特定的行爲進行綁定了。這在receive方法中實現,注意:我們這裏要返回Command.CONTINUE,這樣在我們之後模塊纔可以繼續執行鍼對該PACKET_IN消息的操作:

@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;
    }

在處理Openflow消息是模塊的序列

這一段說明在該教程中並不是必要的,但當我們用IOFMessageListeners處理OpenFlow消息時,定義處理順序往往是必要的。IOFMessageListeners的isCallbackOrderingPrereq(OFType type, String name)和isCallbackOrderingPostreq(OFType type, String name)方法定義了處理來自交換機的消息的模塊的處理順序。

isCallbackOrderingPrereq()定義了在處理某一類的OpenFlow消息時,哪些模塊應該跑在我們的模塊前。 isCallbackOrderingPostreq()定義了在處理某一類的OpenFlow消息時,哪些模塊應該跑在我們的模塊後。

註冊模塊

經過上面的操作,我們差不多已經完成了模塊的實現。現在我們只需要告訴Floodlight我們要在啓動時加載該模塊。首先我們要告訴加載器這些模塊的存在。我們打開src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule,然後添加下面一行文字:

net.floodlightcontroller.mactracker.MACTracker

然後我們還需要修改配置文件src/main/resources/floodlightdefault.properties:

floodlight.modules = <leave the default list of modules in place>, net.floodlightcontroller.mactracker.MACTracker

最後,我們啓動控制器(選中Run As…/Java Application,然後選中Main.java)。

如何將Mininet與Floodlight控制器相連

Floodlight默認的監聽端口是6653(可以在配置文件中查看和修改src/main/resources/floodlightdefault.properties),我們連接Floodlight需要知道Floodlight所在主機的IP地址(如果是本地,就輸入127.0.0.1或0.0.0.0),注意:好像只有Floodlight v1.2版本支持OpenFlow1.3協議,如果使用早期版本的Floodlight如v1.0,建議將protocols=OpenFlow13改爲protocols=OpenFlow10

mininet@mininet:~$ sudo mn --controller=remote,ip=<Floodlight IP Address>,port=6653 --switch=ovsk,protocols=OpenFlow13
*** Loading ofdatapath
*** Adding controller
*** Creating network
*** Adding hosts:
h2 h3
*** Adding switches:
s1
*** Adding edges:
(s1, h2) (s1, h3)
*** Configuring hosts
h2 h3
*** Starting controller
*** Starting 1 switches
s1
*** Starting CLI:
mininet>pingall

連接成功後,輸入pingall,則可以在Eclipse的Console中看到模塊的輸出信息。

練習

作爲練習,我寫了一個模塊,但並不是MACtracer,而是監聽所有Packet-In然後輸出Payload,輸出結果如下:

13:56:05.521 INFO [n.f.p.m.NetMonitor:nioEventLoopGroup-3-4] Switch Id:00:00:00:00:00:00:00:01,Payload:IPv6 [version=6, trafficClass=0, flowLabel=0, payloadLength=16, nextHeader=0x3a, hopLimit=-1, sourceAddress=fe80::ac97:c0ff:fe0b:a39b, destinationAddress=ff02::2, parent=
0x86dd
dl_vlan: untagged
dl_vlan_pcp: 0
dl_src: ae:97:c0:0b:a3:9b
dl_dst: 33:33:00:00:00:02
nw_src: fe80::ac97:c0ff:fe0b:a39b
nw_dst: ff02::2
nw_tclass: 0
nw_proto: 0x3a, payload=net.floodlightcontroller.packet.Data@da31eb25]
13:56:08.717 INFO [n.f.p.m.NetMonitor:nioEventLoopGroup-3-4] Switch Id:00:00:00:00:00:00:00:01,Payload:IPv6 [version=6, trafficClass=0, flowLabel=0, payloadLength=16, nextHeader=0x3a, hopLimit=-1, sourceAddress=fe80::ac7d:88ff:fe59:6165, destinationAddress=ff02::2, parent=
0x86dd
dl_vlan: untagged
dl_vlan_pcp: 0
dl_src: ae:7d:88:59:61:65
dl_dst: 33:33:00:00:00:02
nw_src: fe80::ac7d:88ff:fe59:6165
nw_dst: ff02::2
nw_tclass: 0
nw_proto: 0x3a, payload=net.floodlightcontroller.packet.Data@f8ec7dee]
13:56:09.529 INFO [n.f.p.m.NetMonitor:nioEventLoopGroup-3-4] Switch Id:00:00:00:00:00:00:00:01,Payload:IPv6 [version=6, trafficClass=0, flowLabel=0, payloadLength=16, nextHeader=0x3a, hopLimit=-1, sourceAddress=fe80::ac97:c0ff:fe0b:a39b, destinationAddress=ff02::2, parent=
0x86dd
dl_vlan: untagged
dl_vlan_pcp: 0
dl_src: ae:97:c0:0b:a3:9b
dl_dst: 33:33:00:00:00:02
nw_src: fe80::ac97:c0ff:fe0b:a39b
nw_dst: ff02::2
nw_tclass: 0
nw_proto: 0x3a, payload=net.floodlightcontroller.packet.Data@da31eb25]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章