当Controller和SW建立连接之后,就可以处理来自SW的各种OF msg。当接收到 packetin 消息之后,会将其分发给各个监听了这个OFMessage的listeners,所以如果我们要设计自己的控制器模块,只需要实现相应的接口方法,约定执行顺序即可。接口IListener 主要抽象了监听器模块的名字,执行顺序,接口IOFMessageListener则抽象了我们的Controller如何处理具体的这个openflow消息。这里通过阅读代码来判断这些模块处理packetin消息的相对顺序。
public
interface
IListener<T> {
public
enum
Command {
CONTINUE
,
STOP
}
//这个监听者的名字
public
String getName();
//名为name的module在处理这个消息的时候,要在这个module之前
public
boolean
isCallbackOrderingPrereq(T type, String name);
//在处理type消息的时候,name_module 要在这个模块之后
public
boolean
isCallbackOrderingPostreq(T type, String name);
}
public
interface
IOFMessageListener
extends
IListener< OFType> {
//Floodlight利用这个方法呼叫这些listeners来处理这个OF MSG;
public
Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx);
}
通过查看type hierarchy可以知道所有实现了这个接口的模块。
接下来看看具体细节。
1.Divice manager 要在topology之前。
@Override
public
String getName() {
return
"devicemanager"
;
}
@Override
public
boolean
isCallbackOrderingPrereq(OFType type, String name) {
return
((type == OFType.PACKET_IN || type == OFType.FLOW_MOD)
&& name.equals(
"topology"
));
}
@Override
public
boolean
isCallbackOrderingPostreq(OFType type, String name) {
return
false
;
}
@Override
public
Command receive(IOFSwitch sw, OFMessage msg,FloodlightContext cntx) {
switch
(msg.getType()) {
case
PACKET_IN:
return
this
.processPacketInMessage(sw,(OFPacketIn) msg, cntx);
}
logger.error(
"received an unexpected message {} from switch {}"
,
msg, sw);
return
Command.CONTINUE;
}
2. LinkDiscoveryManager 中没有做出对顺序的规定,由其他模块来约束的。
@Override
public
String getName() {
return
"linkdiscovery"
;
}
@Override
public
Command receive( IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
switch
(msg.getType()) {
case
PACKET_IN:
return
this
.handlePacketIn(sw, (OFPacketIn) msg, cntx);
case
PORT_STATUS:
return
this
.handlePortStatus(sw, (OFPortStatus) msg);
}
log.error(
"Received an unexpected message {} from switch {}"
, msg, sw);
return
Command.CONTINUE;
}
3. TopologyManager要在 LinkDiscoveryManager 之后操作。
@Override
public
String getName() {
return
"topology"
;
}
@Override
public
boolean
isCallbackOrderingPrereq(OFType type, String name) {
return
"linkdiscovery"
.equals(name);
}
@Override
public
boolean
isCallbackOrderingPostreq(OFType type, String name) {
return
false
;
}
@Override
public
Command receive(IOFSwitch sw, OFMessage msg,
FloodlightContext cntx) {
switch
(msg.getType()) {
case
PACKET_IN:
return
this
.processPacketInMessage(sw,
(OFPacketIn) msg, cntx);
}
log.error(
"received an unexpected message {} from switch {}"
,
msg, sw);
return
Command.CONTINUE;
}
4.OFMessageFilterManager 模块在处理packetin消息时的顺序在 DeviceManager 之后,LearningSwitch 之前。这个模块的作用是允许我们添加一些过滤规则。
@Override
public
String getName() {
return
"messageFilterManager"
;
}
@Override
public
boolean
isCallbackOrderingPrereq(OFType type, String name) {
return
(type == OFType.PACKET_IN && name.equals(
"devicemanager"
));
}
@Override
public
boolean
isCallbackOrderingPostreq(OFType type, String name) {
return
(type == OFType.PACKET_IN && name.equals(
"learningswitch"
));
}
@Override
public
Command receive( IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
if
(filterMap ==
null
|| filterMap.isEmpty())
return
Command.CONTINUE;
HashSet<String> matchedFilters =
null
;
if
(log.isDebugEnabled()) {
log.debug(
"Received packet {} from switch {}"
, msg, sw.getStringId());
}
matchedFilters = getMatchedFilters(msg, cntx);
if
(matchedFilters ==
null
) {
return
Command.CONTINUE;
}
else
{
try
{
sendPacket(matchedFilters, sw, msg, cntx,
true
);
}
catch
(TException e) {
log.error(
"sendPacket Texception: {}"
, e);
}
catch
(Exception e) {
log.error(
"sendPacket exception: {}"
, e);
}
}
return
Command.CONTINUE;
}
5. VirtualNetworkFilter(二层虚拟网络模块,对于不属于这个虚拟网络的packetin会丢弃)的执行顺序在forwarding之前,在devicemanager,linkdiscoveryManager之后。
@Override
public
String getName() {
return
"virtualizer"
;
}
@Override
public
boolean
isCallbackOrderingPrereq(OFType type, String name) {
// Link discovery should go before us so we don't block LLDPs
return
(type.equals(OFType.PACKET_IN) &&
(name.equals(
"linkdiscovery"
) || (name.equals(
"devicemanager"
))));
}
@Override
public
boolean
isCallbackOrderingPostreq(OFType type, String name) {
// We need to go before forwarding
return
(type.equals(OFType.PACKET_IN) && name.equals(
"forwarding"
));
}
@Override
public
Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
switch
(msg.getType()) {
case
PACKET_IN:
return
processPacketIn(sw, (OFPacketIn)msg, cntx);
}
log.warn(
"Received unexpected message {}"
, msg);
return
Command.CONTINUE;
}
6.ForwardingBase 路由模块未对顺序做限制。
7.其他的没有查看。
总结,通过上面的代码阅读可以得到如下的结构图:
7.通过调试得到的Listeners有序输出结果是(最后的Distributing是我们自己添加的模块):
OF msg PACKET_IN have listeners:[
net.floodlightcontroller.linkdiscovery.internal.LinkDiscoveryManager@543d8ee8, net.floodlightcontroller.topology.TopologyManager@ea5e9e7, net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl@74e551a4, net.floodlightcontroller.forwarding.Forwarding@76eb235,
net.floodlightcontroller.dedu.Distributing@76115ae0]