最近看了Opendaylight的源碼,仔細(xì)研讀openflow_plugin,SAL,上層服務(wù)(Arphandler)。以下分析是基于Opendaylight的Hydrogen版本。不過(guò)講的這些插件應(yīng)該可以在Helium適用,畢竟各個(gè)成熟的bundle不會(huì)大幅度變化。
Opendaylight使用OSGi框架,這個(gè)框架的巨大好處是可以熱插拔各個(gè)組件,即不用關(guān)閉應(yīng)用就能為ODL安裝各個(gè)應(yīng)用。其結(jié)構(gòu)如下:
ODL控制器有多個(gè)小項(xiàng)目,每個(gè)小項(xiàng)目是一個(gè)bundle(組件),組件之間可以為其他組件提供服務(wù)。openflow1.0插件屬于其南向各種plugin的一個(gè)。
首先Openflow插件的結(jié)構(gòu)如下:
這個(gè)插件的位置位于controller/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/,它里面有兩個(gè)文件夾,core和internal。
core是openflow1.0的核心代碼,里面有一些重要java文件講一下,
■IController.java定義了openflow控制器與交換機(jī)交互的抽象接口,無(wú)具體實(shí)現(xiàn)代碼
■Controller.java控制器核心操作
■ControllerIO.java主要是處理交換機(jī)的連接請(qǐng)求,一個(gè)java的線(xiàn)程,每五秒檢測(cè)一次
internal是openflow1.0插件上層的服務(wù)
■DataPacketMuxDemux.java
下面分析一下幾個(gè)重要的文件:
ControllerIO.java,這是一個(gè)java的線(xiàn)程,每五秒檢測(cè)一次,是否有新連接請(qǐng)求進(jìn)來(lái),有則處理。
它會(huì)調(diào)用Controller.java的handlerNewConnection,這里會(huì)給這一個(gè)新的交換機(jī)生成一個(gè)SwitchHandler,它是一個(gè)線(xiàn)程,專(zhuān)門(mén)和交換機(jī)進(jìn)行通信。SwitchHandler的handleMessages()函數(shù)用來(lái)處理各類(lèi)消息;SwitchHandler用MessageReadWriteService.java文件實(shí)現(xiàn)與交換機(jī)的Socket連接,這也是為什么一個(gè)交換機(jī)對(duì)應(yīng)一個(gè)SwitchHandler。SwitchHandler就在SwitchHandler.java文件內(nèi)。
在Internal里的核心在Controller.java,他的主要作用:
■處理交換機(jī)發(fā)來(lái)的event,保存一個(gè)event隊(duì)列
■控制器啟動(dòng)一個(gè)線(xiàn)程處理Event隊(duì)列
■每種消息使用一個(gè)listener
處理Event的隊(duì)列線(xiàn)程也在Controller.java實(shí)現(xiàn),Switch_message就是交換機(jī)發(fā)送來(lái)的openflow消息。Event隊(duì)列的Event定義在SwithEvent.java文件。
Event隊(duì)列的Event是從哪里來(lái)的呢?來(lái)自SwitchHandler.java,因?yàn)槊總€(gè)Switch有一個(gè)SwitchHandler的線(xiàn)程,SwitchHandler收到消息就封裝成Event后加入到Controller的Event隊(duì)列里。請(qǐng)仔細(xì)閱讀SwitchHandler.java的代碼,它里面會(huì)區(qū)分各個(gè)openflow的消息。
Controller對(duì)的Event的處理中,假如是消息的Event,也就是MessageEvent,調(diào)用receive(ISwitch sw, OFMessage msg),這個(gè)函數(shù)在DataPacketMuxDemux.java實(shí)現(xiàn)。
這里大家一定很奇怪,為什么DataPacketMuxDemux.java能收到消息,我們需要明白,opendaylight定義了很多接口,DataPacketMuxDemux.java里實(shí)現(xiàn)了接口IMessageListener,而Opendaylight為每個(gè)openflow消息都定義了一種IMessageListener,如果要監(jiān)聽(tīng)這種消息,我們只需要設(shè)置addMessageListener(OFType,?this)函數(shù)里加上自己要監(jiān)聽(tīng)的Openflow的消息類(lèi)型,不信你看看DataPacketMuxDemux是否有這個(gè)函數(shù),它因此可以收到Pack_in消息。
這個(gè)函數(shù)處理中,調(diào)用receiveDataPacket,數(shù)據(jù)就會(huì)進(jìn)入SAL層,SAL層收到openflow_plugin發(fā)出的Pack_in消息同樣是實(shí)現(xiàn)了一個(gè)接口IPluginOutDataPacketService,這個(gè)接口由SAL層的DataPacketService.java實(shí)現(xiàn),大家看了代碼肯定會(huì)發(fā)現(xiàn)它還實(shí)現(xiàn)了另一個(gè)接口IDataPacketService,這個(gè)接口是接收從SAL上層各個(gè)服務(wù)發(fā)送的數(shù)據(jù)包。所以SAL層起到了一個(gè)處理分發(fā)的作用。在SAL層收到下層plugin發(fā)送到包后,會(huì)送入上層的各個(gè)服務(wù)
各個(gè)服務(wù)(如ArpHandler)會(huì)通過(guò)監(jiān)聽(tīng)I(yíng)ListenDataPacket接口來(lái)收到從SAL層發(fā)來(lái)的數(shù)據(jù)。這里有個(gè)問(wèn)題講明白,上層監(jiān)聽(tīng)這個(gè)端口的可能有很多個(gè)服務(wù),那么每個(gè)監(jiān)聽(tīng)此接口的服務(wù)都會(huì)收到SAL轉(zhuǎn)發(fā)的數(shù)據(jù)包備份。
下面是整個(gè)數(shù)據(jù)傳輸結(jié)構(gòu)圖:
SAL層中處理數(shù)據(jù)包的是DataPacketService,而處理流表操作FlowProgrammerService。所以SAL的每個(gè)Service都可以看成是處理南北數(shù)據(jù)通路的一種服務(wù)。關(guān)鍵需要搞懂的是南北通路中的數(shù)據(jù)傳輸過(guò)程和機(jī)制。上面組件之間傳輸通過(guò)接口實(shí)現(xiàn)。
需要主要注意的是Openflow_plugin內(nèi)的Controller.java,ContrllerIO.java,SwitchHandler.java,MessageReadWriteService.java(這里是和Switch通信的Socket的實(shí)現(xiàn)),DataPacketServices.java這幾個(gè)文件,需要認(rèn)真閱讀。
基本上ODL的代碼還算易懂。
作者簡(jiǎn)介:
王鈺琪,2013/07-至今?北京郵電大學(xué)網(wǎng)絡(luò)技術(shù)研究院?網(wǎng)絡(luò)與交換技術(shù)國(guó)家重點(diǎn)實(shí)驗(yàn)室攻讀碩士研究生
點(diǎn)擊閱讀原文