轉自https://blog.csdn.net/xjtuse2014/article/details/53729001
OpenFlowJ-Loxigen簡介
Floodlight v1.0及以上版本的依靠新的OpenFlowJ-Loxigen庫。OpenFlowJ-Loxigen支持的OpenFlow版本由1.0到1.4。所有OpenFlow的概念和類型都可以通過OpenFlowJ-Loxigen來獲得。OpenFlowJ-Loxigen支持更新,更優化地方式去創建OpenFlow消息,匹配域(Matches),動作集(Actions),流表更改(FlowMods)等等。本文主要分析OpenFlowJ-Loxigen庫當中一些常用的類和構造方法。
OFFactory
幾乎所有OpenFlow概念(OFObject,例如:Match, OFAction, OFMessage, etc.)可以被構造器構造,所有的構造器都通過OFFactory暴露。由於不同版本的OpenFlow協議存在差異性,所以每個OpenFlow協議版本對應一個特地的工廠類:
OFFactoryVer10
OFFactoryVer11
OFFactoryVer12
OFFactoryVer13
OFFactoryVer14(在floodlight中不被官方支持)
這些都實現了OFFactory接口,所以你可以簡單地使用OFFactory接口,忽略存在不同版本的工廠類。
有很多種方法可以得到你想要的OFFactory實例。你可以從OpenFlowJ-Loxigen,通過指定OFVersion的枚舉值來請求一個特定版本的OFFactory。
OFFactory my13Factory = OFFactories.getOFFactory(OFVersion.OF_13); //取得一個OpenFlow 1.3的工廠類
更加實用的是,你可以從IOFSwitch中取得工廠類。
IOFSwitch mySwitch = switchService.getSwitch(DatapathId.of("00:00:00:00:00:00:00:01"));
OFFactory myFactory = mySwitch.getOFFactory(); //取得與請求交換機版本相符的工廠類版本
也可以從由OFFactory生成的已存在對象中取得一個特定的OFFactory,所有從OFFactory構造的對象中得到的OFVersion和用OFFactory構造出來的相同。
OFVersion flowModVersion = myFlowMod.getVersion(); //假設myFlowMod已經被構造好
OFFactory myFactory = OFFactories.getFactory(flowModVersion);
Match
匹配域(Match)通常用在OpenFlow當中用於表示和定義包的頭部域的特徵。如上所說,大部分OpenFlow的概念都可以使用工廠類去構造。所以創建一個工廠類的引用是構造一個匹配域的準備工作。
Match myMatch = myFactory.buildMatch()
.setExact(MatchField.IN_PORT, OFPort.of(1))
.setExact(MatchField.ETH_TYPE, EthType.IPv4)
.setMasked(MatchField.IPV4_SRC, IPv4AddressWithMask.of("192.168.0.1/24"))
.setExact(MatchField.IP_PROTO, IpProtocol.TCP)
.setExact(MatchField.TCP_DST, TransportPort.of(80))
.build();
可以看到,OFFactory的實例myFactory包含一個構造器(Match.builder),這個構造器可以使用buildMatch方法返回。通過調用構造器的setExact和setMasked方法可以分別指定精確匹配和掩碼匹配。
Actions
OFAction’s,像匹配域一樣,通過OFFactory構造。注意:有一個類叫做OFAction以及另一個類叫做OFActions。爲了表示OFAction的複數形式,此處採用OFAction’s。雖然語法上存在問題,但不會和OFActions混淆。
OFActions allActions = myFactory.actions();
actions的調用可以返回一個已實現的OFActions接口。這個返回的實現完全取決與OFFactoy的版本。(本文僅介紹OpenFlow v1.3的Actions構造)
OpenFlow 1.2引入了OXM(OpenFlow Extensible Match)。通過OXM,所有導致已存在頭部域修改的Actions都會被用一個新的set-field動作說明,set-field動作包含了OXM指定了頭部域和新的寫入該頭部域的值。注意此處Oxm’s和Oxms的區別,和OFAction’s和OFActions的區別一樣,Oxms是一個接口包含了所有獨立的Oxm’s。
ArrayList<OFAction> actionList = new ArrayList<OFAction>(); //actionList用來存儲不同的動作
OFActions actions = myOF13Factory.actions(); //actions爲實例化的接口,此接口當中包含了所有獨立的OFAction
OFOxms oxms = myOF13Factory.oxms(); //oxms爲實例化的接口,此接口當中包含了所有獨立的Oxm
/* 使用OXM去修改數據鏈路層的目地地址 */
OFActionSetField setDlDst = actions.buildSetField()
.setField(
oxms.buildEthDst()
.setValue(MacAddress.of("ff:ff:ff:ff:ff:ff"))
.build()
)
.build();
actionList.add(setDlDst);
/* 使用OXM去修改網絡層的目地地址 */
OFActionSetField setNwDst = actions.buildSetField()
.setField(
oxms.buildIpv4Dst()
.setValue(IPv4Address.of("255.255.255.255"))
.build()
)
.build();
actionList.add(setNwDst);
/* 去VLAN加標不是OXM而是一個OFAction */
OFActionPopVlan popVlan = actions.popVlan();
actionList.add(popVlan);
/* 向一個端口發送不是OXM而是一個OFAction */
OFActionOutput output = actions.buildOutput()
.setMaxLen(0xFFffFFff)
.setPort(OFPort.of(1))
.build();
actionList.add(output);
FlowMods
OpenFlowJ-Loxigen庫提供了一個版本無關的OFFlowMod接口,它由很多子接口允許你寫入一個與特定OFFlowModCommand相關的特定類型的OFFlowMod:
OFFlowAdd
OFFlowModify
OFFlowModifyStrict
OFFlowDelete
OFFlowDeleteStrict
關於OFFlowMods需要注意:OpenFlow 1.3移除了默認的table-miss操作(packet-in到控制器),OpenFlow 1.3指定了控制器必須插入一條特定的優先級爲0的table-miss流表,通配所有匹配域,由OFAction’s定義的action列表
OFFlowAdd flowAdd = myFactory.buildFlowAdd()
與其他OpenFlow概念類似,OFFactory可以用於產生一種特定類型的OFFlowMod。
OFFactory可以返回你指定的OFFlowMod類型的構造器。但一般情況下,我們會發現將OFFlowMod從一種OFFlowModCommand轉換成另一種會更實用。這個特性目前OpenFlowJ-Loxigen還不支持,但是可以通過net.floodlightcontroller.util.FlowModUtils.java來實現
OFFlowAdd flowAdd = myFactory.buildFlowAdd().build();
/* 將FlowAdd轉換爲FloodModify. */
OFFlowModify flowModify = FlowModUtils.toFlowModify(flowAdd);
OFFlowModifyStrict flowModifyStrict = FlowModUtils.toFlowModifyStrict(flowAdd);
OFFlowDelete flowDelete = FlowModUtils.toFlowDelete(flowAdd);
OFFlowDeleteStrict flowDelStrict = FlowModUtils.toFlowDeleteStrict(flowAdd);
OFFlowAdd flowAdd2 = FlowModUtils.toFlowAdd(flowModify);
下面討論如何組成一個OFFlowMod
OFFlowAdd flowAdd = my13Factory.buildFlowAdd()
.setBufferId(OFBufferId.NO_BUFFER)
.setHardTimeout(3600)
.setIdleTimeout(10)
.setPriority(32768)
.setMatch(myMatch)
.setActions(actionList)
.setOutPort(OFPort.FLOOD)
.setTableId(TableId.of(1))
.build();