在上一篇具体讲述POX有哪些组件,以及各个组件的功能,这篇文章主要理解POX的启动以及组件是如何启动的,以及组件与事件的关系:
由上图知,of_01 主要是运行一个线程,该线程不断与交换机进行TCP连接, 当某交换机送来一个协议消息时,of_01会触发该消息 所对应的事件。openflow则与所有的物理交换机相连,而控制器可以通过openflow控制所有的交换机,任意交换机传上来的消息都会触发openflow的事件,在设计自己的组件时,如果不需要监听特定的交换机,监听openflow肯定没错。
事件组成:
- source:给组件提供可被监听的事件,通过raise函数触发事件给监听它的组件;
- sink:监听source的组件。
启动pox.py:
Pox.py 里面大部分都是注释,真正只有以下几行代码:
调用pox.boot模块中的boot()函数。
这时就想了解boot函数的作用,下面是进入boot.py里查看的代码:
可以看出里面的内容包括:
第442~444行代码将pox和ext的两个文件夹的路径加入到了系统的path里;
还有启动了POX以及相关组件。
关键代码是第459行的_do_launch()函数启动了相关组件,其中_post_startup()由下图390~392行启动openflow.of_01,core.goUp则启动了core里面的登记Debug信息和事件机制。
在core.py的代码中,有core = POXCore()。代码中还有这个函数的定义class POXCore() (EventMixin)。可以看出,POXCore这个类是revent.py中class EventMixin的一个子类,是处理事件最高层的模块。另外,如果看后面的代码可以知道,POX的启动是由_do_Launch()函数完成的。
组件启动:
组件启动函数:pox.boot.do_launch
这些代码完成了模块的加载+初始化工作,其中:
第135~155行代码创建component_order的列表,用于存放组件的名称。然后再逐个启动,初始化;
第157~164行代码通过创建组件的函数名,并定义了组件的加载顺序;
第166~169行代码使用_do_import()函数将相关组件模块引入;
第171行代码检查了类中是否存在相应的launch函数。其中sys.modules 是一个字典,它包含了从Python 开始运行起,被导入的所有模块。用sys.modules[name]可以获取name模块的引用。由于类的实例会有一个__dict__的特性字典,其中是该类的所有特性。
如:
第172行从特性中初始化函数实例;
第189行代码就是执行初始化函数的语句。
pox的过程如下:
组件启动代码:
以l3_learning组件来举例:
我们观察到最后一行需要注册组件,这时就需要查看core.registerNew()这个函数:
可执行语句很少,基本上注释已经完全涵盖了这个函数的作用。主要是在pox注册一个新的线程,如果已存在名字则重载,返回新的实例。同时我们看到在这个函数里面使用到了register()函数,函数定义如下:
Register()实现了在初始化的时候,将相关组件加入到了pox.core.core之中。这时Core raise了一个ComponentRegistered事件,是以组件为参数注册事件。
注册阶段结束了?还没有,有一个问题还没有解决:组件的event_handler是如何与events绑定在一起的呢?
组件与事件的关系:(事件绑定)
上面可以看出:组件通过监听内核core来注册事件。
这时就需要listenTo()函数,经过查找在revent.py里面:
这时接着调用autoBindEvents()函数:
从注释中我们可以看出这个函数的作用:
无非就是讲handler端的sink和event的source连接起来,方式就是先在sink端将所有event的名字放在一个字典中,然后在sink中寻找带有“__handle__event”的函数,最后,如果两边有对应的event和handler,就建立连接。:
其中又调用了addListener()函数,这个函数的功能最重要:
建立一个与eventType对应的handlers,将带有handler和eid等信息的entry添加到handlers队列中,priority决定这个handlers在处理时的优先级,若无特殊优先级,则按正常顺序放在队尾。
下面还有一个问题:handler在哪?这个问题关系到事件如何被处理。其实,从autoBindEvent的函数定义可以看到,最后addListener函数的执行对象是source。也就是说,handler列表在发起事件的组件中可以看到。因而我们来看source类,即:
第83行代码中使用raiseEvent()函数,其中参数为组件注册。来看raiseEvent函数:
就这样事件就绑定完成了。
POX的过程图如下:
额外的一个小case:在POX中添加新模块,将新模块存入ext文件夹,可以通过参数,直接调用。如:
copy一个模块(forwarding.l2_learning.py)到ext文件夹中,改名为ext/my_component.py,执行新模块为:./pox.py my_component.
以上的学习是在网上看北邮赵伟明的blog,加上自己的理解总结的,看完后发现制定POX控制器团队的优秀,还有就是自己暂时分析到这里,当然还有好多代码也没有看,需要今后边学边看,自己还需要很长的道路需要走,需要更加努力,这样才能在SDN的学习有更多自己的成果。