Pox架构:
Pox由内核(core)、组件(component)组成,内核是所有组件的集结地,有了内核,一个组件想使用另一个组件无需通过import,而只需向内核注册,组件之间可以通过内核来交互。内核主要模块有:openflow和of_01(与openflow1.0 交换机通信)。
of_01:运行一个线程,该线程循环监听与交换机的tcp连接,当交换机送来某个协议消息时,of_01会 触发该消息所对应的事件。of_01在此处会触发两个source事件:1)该交换机的connection, 2)任意交换机传上来的消息会触发openflow的事件。
openflow:是一个source事件,它能被任何交换机的任意消息触发事件。openflow可以控制所有已经 连接到pox上的交换机,而connection只能控制某一个交换机
Pox启动:
Pox启动是从pox.py执行起的,pox.py代码里面就只有一句boot():
boot.py
boot()函数主要功能:
a.处理pox路径,添加源码pox文件夹和ext文件夹到系统路径,ext文件夹用于存储用户自己开发的模块。
b.处理命令行参数。
c.根据命令行参数启动pox及组件。
d.启动of_01,用于监听交换机的事件。( _post_startup() )
e.启动core内核 ( core.goUp() )
组件启动:_do_launch()
这个函数完成了模块的加载+初始化工作
Pox启动过程可以归纳为下图:
Pox事件机制:
事件组成:
• source:给组件提供可被监听的事件,通过raise函数触发事件给监听它的组件;
• sink:监听source的组件。
先举个事件例子:
该例中Chef就是一个source,sink只给出了一个处理函数spam_ready。Chef是一个实例,对事件SpamFinished添加了监听者,这样当事件SpamFinished触发了时,spam_ready就会被执行。
下面再以l2_learning.py为例:
在_init_()函数中,core.openflow添加了监听者:l2_learning,也就是l2_learning监听core.openflow触发的事件,在core.openflow里有以下的事件:(见openflow/of_01.py)
当交换机连接上pox时,connection类(source)会触发ConnectionUp事件,当l2_learning(sink)监听到该事件后会执行_handle_ConnectionUp函数。
触发了事件ConnectionUp,就执行_handle_ConnectionUp,为什么不会执行_handle_ConnectionDown,这就需要一个绑定,那么事件是如何跟handle函数绑定的呢?
下面看看addListener()函数(见revent.py)
该函数中有autoBindEvents(),下面再看看该函数:
绑定机制:
Source触发了一个事件,有一个名称(比如ConnectionUp),sink的handler函数就是 _handle_事件名(比如_handle_ConnectionUp),就是通过这种方法实现绑定
代码:
listener.append( source.addListener ( events[event], a,weak=weak, priority=priority ) )
events[event]就是一个事件,a就是一个handler处理函数
创建自己的组件:
POX提供一系列API,使用户可以创建自己的组件,实现自己的功能。创建的组件需要注册到控制器上,launch函数中通常有两种方法注册:core.register()、core.registerNew()。这两个函数的区别是:Register()第二个参数传的是组件的实例对象,launch()多次被调用的时候会出现多次注册,我们需要用 core.hasComponent()来检查是不是已经注册了该组件;而registerNew()传的是类名,launch()多次调用时,当组件名已经注册了时,registerNew()函数不调用。
组件需要监听事件,这里可以用到listenTo()函数
举个例子:
from pox.core import core
class MyComponent(object):
def __init__(self, an_arg):
self.arg = an_arg
print "MyComponent instance registered with arg:", self.arg
def message(self):
print "MyComponent with arg:", self.arg
def launch():
component = MyComponent("chosen")
core.register("square", component)
core.square.message()
该例子就创建了一个组件:MyComponent,并且注册到core上。