一个简单的交换机实现,使得交换机将所有收到的数据包在各个端口泛洪发送,代码如下:
from ryu.base import app_manager
from ryu.controller import ofp_event
from ryu.controller.handler import MAIN_DISPATCHER
from ryu.controller.handler import set_ev_cls
class L2Switch(app_manager.RyuApp):
def __init__(self, *args, **kwargs):
super(L2Switch, self).__init__(*args, **kwargs)
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def packet_in_handler(self, ev):
msg = ev.msg
datapath = msg.datapath
ofproto = datapath.ofproto
ofp_parser = datapath.ofproto_parser
actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD)]
out = ofp_parser.OFPPacketOut(
datapath=datapath, buffer_id=msg.buffer_id, in_port=msg.in_port,
actions=actions)
datapath.send_msg(out)
packet_in_handler函数的函数体:
- ev.msg:每一个事件类ev中都有msg成员,用于携带触发事件的数据包,(此处是packet_in的消息对象,存储着消息的数据部分)
- msg.datapath:已经格式化的msg其实就是一个packet_in报文,msg.datapath直接可以获得packet_in报文的datapath结构。datapath用于描述一个交换网桥。也是和控制器通信的实体单元。
- datapath.send_msg():函数用于发送数据到指定datapath。
- datapath.ofproto对象是一个OpenFlow协议数据结构的对象,成员包含OpenFlow协议的数据结构,如动作类型OFPP_FLOOD。
- datapath.ofp_parser则是一个按照OpenFlow解析的数据结构。
- actions是一个列表,用于存放action list,可在其中添加动作。
- 通过ofp_parser类,可以构造构造packet_out数据结构。括弧中填写对应字段的赋值即可。如果datapath.send_msg()函数发送的是一个OpenFlow的数据结构,RYU将把这个数据发送到对应的datapath。
每当RYU控制器收到OpenFlow协议中的packet_in消息时,packet_in_handler函数就会被调用,因为这个函数被注册到装饰器set_ev_cls中,并且装饰器将packet_in_handler注册到packet_in消息上,每当收到packet_in消息时就调用该函数。
set_ev_cls装饰器的参数:
- 第一个参数指触发函数的调用事件,这里指packet_in事件。
- 第二个参数指交换机的状态。比如,当交换机处于与控制器协商(negotiation)阶段时,可能你想忽略此时的packet_in消息,那我们就可以使用MAIN_DISPATCHER作为参数来表明当协商完成后该函数才被调用(即握手后才可以被调用)。
网友评论