文章目录
Writing Your Ryu Application
第一个应用
你的应用告诉Ryu如何管理the gear(switches, routers, etc),Ryu用OpenFlow协议来配置它们
开始啦
下面是使一个OpenFlow switch作为layer 2 switch的例子
Ryu应用就是个Python脚本,你可以把它以任意名字、任意扩展保存在任意位置
from ryu.base import app_manager
class L2Switch(app_manager.RyuApp):
def __init_ _(self, *args, **kwargs):
super(L2Switch, self).__init__(*args, **kwargs)
这些什么都没做,但是这样就创建了一个完整的Ryu application,现在就可以运行了
现在我们来增加一些功能,将受到的包转到所有端口
from ryu.base import app_manager #Ryu应用程序可以通过调用适当的ryu.base.app_manager.RyuApp的方法(例如send_event或send_event_to_observers)来发起事件。
from ryu.controller import ofp_event # OpenFlow事件定义
from ryu.controller.handler import MAIN_DISPATCHER # handler用于处理、协商
from ryu.controller.handler import set_ev_cls
from ryu.ofproto import ofproto_v1_0
class L2Switch(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_0.OPF_VERSION]
def __init__(self, *args, **kwargs):
super(L2Switch, self).__init__(*args, **kwargs)
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER) #想接受的是EventOFPPacketIn事件类的实例,
def packet_in_handler(self, ev):
msg = ev.msg #switch送来的消息ev
dp = msg.datapath #是哪个switch送来的,下面就送回哪去
ofp = dp.ofproto #
ofp_parser = dp.ofproto_parser
actions = [ofp_parser.OPFActionOutput(ofp.OFPP_FLOOD)]
out = ofp_parser.OPFPacketOut(
datapath=dp, buffer_id=msg.buffer_id, in_port=msg.in_port,
actions=actions
)
dp.send_msg(out)
当Ryu收到OpenFlow packet_in 消息的时候,packet_in_handler函数就会被调用。由装饰器@set_ev_cls实现
第一个参数是指什么类型的事件发生了才调用这个函数,第二个参数指的是交换机的状态, 'MAIN_DISPATCHER’意味着只有当Ryu和switch之间的协商完成了之后才调用。
packet_in_handler函数第一部分:
- ev.msg 是表示packet_in数据结构的一个对象
- msg.dp是表示switch Datapath的一个对象
- dp.ofproto 和 dp.ofproto_parser是表示Ryu与switch协商的OpenFlow协议对象,包含的是OpenFlow协商信息
packet_in_handler函数第二部分: - OPFActionOutput类的作用是:指定把包送出去的交换机端口,用OFPP_FLOOD标志以为着送到所有端口
- OPFPacketOut类的作用是构建一个出包消息
- 调用Datapath类的send_msg方法时,Ryu构建并且把包送给switch
Components of Ryu
可执行文件
bin/ryu
基本组件
ryu.base.app_manager Ryu应用程序的中央管理
- 加载Ryu应用程序
- 为Ryu应用程序提供上下文
- 在Ryu应用程序之间路由消息
1.app_manager.RyuApp是所有Ryu Applications的基类,我们要实现一个控制器应用,必须继承该基类
2.我们自定义的子类(继承于RyuAPP的子类),将在ryu-manager命令加载中被实例化(它是在ryu管理器加载所有请求的ryu应用程序模块后实例化的)
OpenFlow 控制器
ryu.controller.controller:
OpenFlow控制器的主要组件。
- 处理来自交换机的连接
- 生成事件并将事件路由到适当的实体,例如Ryu应用程序
ryu.controller.dpset:
管理交换机。
计划由ryu / topology取代。
ryu.controller.ofp_event
OpenFlow事件定义。
ryu.controller.ofp_handler
基本的OpenFlow处理,包括协商。
OpenFlow有线协议编码器和解码器
ryu.ofproto.ofproto_v1_0
OpenFlow 1.0定义。
ryu.ofproto.ofproto_v1_0_parser
OpenFlow 1.0的解码器/编码器实现。
一直到v1_5类似
库
ryu.lib.packet
Ryu数据包库。流行协议(如TCP / IP)的解码器/编码器实现。
ryu.lib.ovs
ovsdb交互库。
ryu.lib.of_config
OF-Config实现。
ryu.lib.netconf
ryu / lib / of_config使用的NETCONF定义。
ryu.lib.xflow
sFlow和NetFlow的实现。
第三方库
ryu.contrib.ovs
打开vSwitch python绑定。由ryu.lib.ovs使用。
ryu.contrib.oslo.config
oslo配置库。用于ryu-manager的命令行选项和配置文件。
ryu.contrib.ncclient
NETCONF客户端的Python库。由ryu.lib.of_config使用。
Ryu应用程序
ryu.topology
交换和链接发现模块。计划替换ryu / controller / dpset
Ryu application API
Ryu application programming model
线程,事件,事件队列
Ryu应用程序是单线程实体,可在Ryu中实现各种功能。事件是它们之间的消息。
Ryu应用程序相互发送异步事件。除此之外,还有一些Ryu内部事件源,它们不是Ryu应用程序。OpenFlow控制器就是事件源的一种。尽管事件当前可以包含任意python对象,但不建议在Ryu应用程序之间传递复杂的对象(例如,无法修复的对象)。
每个Ryu应用程序都有一个事件接收队列。队列FIFO,并保留事件的顺序。每个Ryu应用程序都有一个用于事件处理的线程。线程通过使事件出队并为事件类型调用适当的事件处理程序来不断消耗接收队列。由于事件处理程序是在事件处理线程的上下文中调用的,因此在阻塞时应格外小心。当事件处理程序被阻止时,将不处理Ryu应用程序的其他事件。
人话就是有个队列,先入先出事件,然后用@set_ev_cls装饰器调用响应的事件处理函数。
有多种事件用于实现Ryu应用程序之间的同步应用程序间调用。尽管此类请求使用与普通事件相同的机制,但它们的答复被放入专用于事务的队列中,以避免死锁。
虽然线程和队列当前是通过eventlet / greenlet实现的,但强烈建议不要在Ryu应用程序中直接使用它们。
总结: Ryu应用程序单线程,事件是它们之间的消息。每个应用程序有个事件接收队列,FIFO。
上下文
上下文是Ryu应用程序之间共享的普通python对象。 不建议在新代码中使用上下文。
Create a Ryu application
A Ryu application is a python module which defines a subclass of ryu.base.app_manager.RyuApp. If two or more such classes are defined in a module, the first one (by name order) will be picked by app_manager. Ryu application is singleton: only single instance of a given Ryu application is supported.
意思是我写了一个执行l2switch,一个l2_learning_switch,只能调用第一个?
Observe events 监测事件
Ryu应用程序可以使用ryu.controller.handler.set_ev_cls装饰器进行注册,以侦听特定事件。
Generate events 生成事件
Ryu应用程序可以通过调用适当的ryu.base.app_manager.RyuApp的方法(例如send_event或send_event_to_observers)来发起事件。
Event classes Event类
事件类描述系统中生成的Ryu事件。 按照约定,事件类名称以“ Event”为前缀。 事件由Ryu或Ryu应用程序的核心部分生成。 通过使用ryu.controller.handler.set_ev_cls装饰器提供处理程序方法
OpenFlow 事件类ryu.controller.ofp_event
ryu.controller.ofp_event模块导出事件类,这些事件类描述了从已连接的交换机接收OpenFlow消息的过程。 按照约定,它们被命名为ryu.controller.ofp_event.EventOFPxxxx,其中xxxx是相应的OpenFlow消息的名称。 例如,EventOFPPacketIn用于packet_in消息。 Ryu的OpenFlow控制器部分自动解码从交换机接收到的OpenFlow消息,并将这些事件发送到Ryu应用程序,该应用程序使用ryu.controller.handler.set_ev_cls进行下一步处理。 OpenFlow事件类是以下类的子类。
classryu.controller.ofp_event.EventOFPMsgBase(msg) OpenFlow事件类的基类
至少有以下属性
- msg 描述openflow消息的对象 ~switch给我送来了啥鸭
- msg.datapath 描述是哪个OpenFlow switch发来消息的ryu.controller.controller.Datapath实例 ~每个switch都有个Datapath ID,是哪个switch送来的鸭
- timestamp Datapath实例啥时候创建的鸭
喔噢,是酱紫呀,switch给controller发OpenFlow消息,controller自动解码,然后传给application,让application响应。
EventOFPPacketIn是事件类鸭
ryu.controller.handler.set_ev_cls
ryu.controller.handler.set_ev_cls(ev_cls, dispatchers=None)
用于声明事件处理器的装饰器
ev_cls 是RyuApp想接受的事件类的实例。dispatchers指定了在协商的哪个阶段生成事件传给处理器。
谈判阶段 | 描述 |
---|---|
ryu.controller.handler.HANDSHAKE_DISPATCHER | 发送和等待hello消息 |
ryu.controller.handler.CONFIG_DISPATCHER | 协商版本并发送功能请求消息 |
ryu.controller.handler.MAIN_DISPATCHER | 接收交换机功能信息并发送set-config消息 |
ryu.controller.handler.DEAD_DISPATCHER | 与对等体断开连接。或由于某些不可恢复的错误而断开连接。 |
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
ryu.controller.controller.Datapath
classryu.controller.controller.Datapath(socket, address)
此类:描述连接到控制器的交换机。实例具有以下属性:
- id 64为的Datapath ID ,只在MAIN_DISPATCHER阶段有
- ofproto 导出OpenFlow定义(主要是常量)的模块,用于协商的OpenFlow版本。例如,对于OpenFlow 1.0,为ryu.ofproto.ofproto_v1_0。
- ofproto_parser 一个模块,用于为协商的OpenFlow版本导出OpenFlow有线消息编码器和解码器。例如,用于OpenFlow 1.0的ryu.ofproto.ofproto_v1_0_parser。
- ofproto_parser.OFPxxxx(datapath,…) 咳咳,准备给switch发数据啦。为给定交换机准备OpenFlow消息的可调用对象。可以稍后与Datapath.send_msg发送。xxxx是消息的名称。例如,用于流程信息的OFPFlowMod。参数取决于消息。
- set_xid(self, msg) : xid是数据包的编号,生成一个OpenFlow XID并将其放在msg.xid中。
- send_msg(self,msg):将OpenFlow消息排队以发送到相应的交换机。如果msg.xid为None,则在排队之前会自动在消息上调用set_xid。
- send_barrier :将OpenFlow barrier消息排队发至交换机
- 其他弃用了
ryu.controller.event.EventBase
所有事件的基类
剩下的类等我遇到了我再去学
Library
OpenFLow protocol API reference
Modify State Messages
classryu.ofproto.ofproto_v1_3_parser.OFPFlowMod(datapath, cookie=0, cookie_mask=0, table_id=0, command=0, idle_timeout=0, hard_timeout=0, priority=32768, buffer_id=4294967295, out_port=0, out_group=0, flags=0, match=None, instructions=None)
controller发出这条消息来修改流表
Attribute | Description |
---|---|
cookie | Opaque controller-issued identifier |
cookie_mask | Mask used to restrict the cookie bits that must match when the command is OPFFC_MODIFY* or OFPFC_DELETE* |
table_id | ID of the table to put the flow in |
command | One of the following values.
OFPFC_ADD
OFPFC_MODIFY
OFPFC_MODIFY_STRICT
OFPFC_DELETE
OFPFC_DELETE_STRICT
|
idle_timeout | Idle time before discarding (seconds) |
hard_timeout | Max time before discarding (seconds) |
priority | Priority level of flow entry |
buffer_id | Buffered packet to apply to (or OFP_NO_BUFFER) |
out_port | For OFPFC_DELETE* commands, require matching entries to include this as an output port |
out_group | For OFPFC_DELETE* commands, require matching entries to include this as an output group |
flags | Bitmap of the following flags.
OFPFF_SEND_FLOW_REM
OFPFF_CHECK_OVERLAP
OFPFF_RESET_COUNTS
OFPFF_NO_PKT_COUNTS
OFPFF_NO_BYT_COUNTS
|
match | Instance of OFPMatch |
instructions | list of OFPInstruction* instance |
RYU系列2 openFlow13简单交换机源码
switch features消息:features消息是controller-to-switch消息。在建立TIs会话时,控制器发送features请求消息给交换机,交换机需要应答自身支持的功能。
- ev.msg中存储着与事件相对应的openFlow消息的实例。如ofp_event.EventOFPSwitchFeatures事件对应着ryu.ofproto.ofproto_v1 3 parser.OFPSwtichFeatures
- ev.msg.datapath存储着发送这条消息的openFlow交换机实例。Datapath类发挥着重要作用,如与openFlow交换机的实际通信,和收到openFlow消息时,发起相应事件
otable-miss流表项
#添加table-miss流表项
match= parser.OFPMatch()#创建了空的match,匹配所有数据包
actions=(parser-OFPActionOutput(ofproto.OFPD_CONTROLLER,OFDrOtO.OFPCML_NO_BUEEE R)]#指定输出动作,当数据包不匹配任何流我项时,给控制器发送Packet-In
self.add_flow(datapath,0,match,actions)
- table-miss流表项的优先级最低(priority=0),这个流表项匹配所有的数据包。在table-miss流表项中,指定了输出端口是控制器的端口,可以实现,当数据包不匹配流表中所有的流表项时,交换机就会控制器发送迎packet-ln消息。
- match是OFPMatch类的实例。
- actions:产生一个OUTPUT action(OFPActionOutput类的实例,把数据包转发给控制器端口。目的地址设置为控制器,且OFPCML NOBUFFER被设为max len,从而可以把所有的数据包都发送给控斜器。
最后,设置priority=0(add flow函数的第二个参数),并执行add flow()方法来发送flow mo消息。
常用API解读:
流instruction结构
还有好几个别的
classryu.ofproto.ofproto_v1_3_parser.OFPInstructionActions(type_, actions=None, len_=None)
流action结构
classryu.ofproto.ofproto_v1_3_parser.OFPActionOutput(port, max_len=65509, type_=None, len_=None)
流match结构
classryu.ofproto.ofproto_v1_3_parser.OFPMatch(type_=None, length=None, _ordered_fields=None, **kwargs)
您可以通过关键字参数定义流匹配。