日博滚球日博滚球

日博体育
日博电竞

Ryu学习总结(持续更新)

Ryu学习总结

该篇学习笔记,与其他分析Ryu控制器代码的笔记不同,主要按照程序的构成来进行分块总结,由于本人为新手入门,不能保证没有错误,如果发现错误,欢迎指教。

以下的内容主要来源:

源码官方文档OpenFlow1.3.3 手册

处理一个事件的标准模板

首先,我们来看一个标准的控制器处理事件的模板

@set_ev_cls(ofp_event.Event, DISPATCHER(s))def your_function(self, ev):...

简单说,@set_ev_cls(ofp_event.Event, DISPATCHER(s))的含义就是,当接收到DISPATCHER(s)情况的Event事件进行your_function处理。

DISPATCHER(s)可以为单独一个,也可以为由多个DISPATCHER组成的列表,DISPATCHER描述的情况包括:

DefinationExplanation
HANDSHAKE_DISPATCHER交换HELLO消息
CONFIG_DISPATCHER等待接收SwitchFeatures消息
MAIN_DISPATCHER正常状态
DEAD_DISPATCHER连接断开

其中your_function是由你自己定义的函数处理过程,命名可以任意指定;ofp_event.Event是由ofp_event.py提供的一系列事件,在学习了几个Ryu的程序之后,深感,其核心就在于对这些事件的理解。所以,接下来,在分析学习官方案例的同时,也会整合Ryu源码与OpenFlow1.3.3协议的内容,对这些事件进行深入的理解与分析。

ofp_event

ofp_event类位于ryu/controller/ofp_event.py,主要定义了OpenFlow中的各种事件,配合set_cls_ev可以对指定事件进行处理。

ofp_event.EventOFPSwitchFeatures

ofp_event.EventOFPPacketIn

ofp_event.EventOFPStateChange

在源码中,对EventOFPStateChange这样进行介绍:

An event class for negotiation phase change notification. An instance of this class is sent to observer after changing the negotiation phase. An instance has at least the following attributes. ========= ================================================================= Attribute Description ========= ================================================================= datapath ryu.controller.controller.Datapath instance of the switch ========= =================================================================

意思说,该class是处理协商阶段变更通知的事件,在协商更改后发生此消息给观察者。

当我们使用一下的命令,我们就成为了观察者,发生此类消息时,便可以进行接收和处理

@set_ev_cls(ofp_event.EventOFPStateChange, [MAIN_DISPATCHER, DEAD_DISPATCHER])

详细案例见Traffic Monitor

在协商阶段,MAIN_DISPATCHER意味着有新的交换机接入,DEAD_DISPATCHER意味着有交换机脱离连接。

总结:

发起事件处理事件
交换机状态变化EventOFPStateChange

ofp_event.EventOFPFlowStatsReply

在源码中,对EventOFPFlowStatsReply这样介绍:

Individual flow statistics reply message The switch responds with this message to an individual flow statistics request.

意思说,该事件用于处理个体流量统计回复消息,即统计某一交换机上的流量信息。而流量统计信息存储在bodyev.msg.body)结构体中。具体包括:

table_idduration_secduration_nsecpriorityidle_timeouthard_timeoutflagscookiepacket_countbyte_countmatchinstructions

使用范例:

@set_ev_cls(ofp_event.EventOFPFlowStatsReply, MAIN_DISPATCHER)def flow_stats_reply_handler(self, ev): flows = [] for stat in ev.msg.body: flows.append("table_id=%s " "duration_sec=%d duration_nsec=%d " "priority=%d " "idle_timeout=%d hard_timeout=%d flags=0x%04x " "cookie=%d packet_count=%d byte_count=%d " "match=%s instructions=%s" % (stat.table_id, stat.duration_sec, stat.duration_nsec, stat.priority, stat.idle_timeout, stat.hard_timeout, stat.flags, stat.cookie, stat.packet_count, stat.byte_count, stat.match, stat.instructions)) self.logger.debug("FlowStats: %s", flows)

来源:源码ryuofprotoofproto_v1_3_parser.py

与上一个事件的产生来源不同,该事件并不是由交换机状态改变而产生,而是由控制器主动发出,触发该事件并接收处理的。控制器主动发出的命令为OFPFlowStatsRequest函数。

同样,查看源码中该函数的文档

""" Individual flow statistics request message The controller uses this message to query individual flow statistics. ================ ====================================================== Attribute Description ================ ====================================================== flags Zero or ``OFPMPF_REQ_MORE`` table_id ID of table to read out_port Require matching entries to include this as an output port out_group Require matching entries to include this as an output group cookie Require matching entries to contain this cookie value cookie_mask Mask used to restrict the cookie bits that must match match Instance of ``OFPMatch`` ================ ======================================================

看见,该函数作用就是发出流量统计请求的。文档同样给出范例程序:

Example:: def send_flow_stats_request(self, datapath): ofp = datapath.ofproto ofp_parser = datapath.ofproto_parser cookie = cookie_mask = 0 match = ofp_parser.OFPMatch(in_port=1) req = ofp_parser.OFPFlowStatsRequest(datapath, 0, ofp.OFPTT_ALL, ofp.OFPP_ANY, ofp.OFPG_ANY, cookie, cookie_mask, match) datapath.send_msg(req)

查看构造函数:

def __init__(self, datapath, flags=0, table_id=ofproto.OFPTT_ALL, out_port=ofproto.OFPP_ANY, out_group=ofproto.OFPG_ANY, cookie=0, cookie_mask=0, match=None, type_=None):

实际使用过程中,如果没有特定需要,这里我们可以只指定一个datapath参数,其他为缺省的默认值。

小结:

发起事件处理事件
OFPFlowStatsRequestEventOFPFlowStatsReply

ofp_event.EventOFPPortStatsReply

在源码中对该函数的说明如下:

""" Port statistics reply message The switch responds with this message to a port statistics request. ================ ====================================================== Attribute Description ================ ====================================================== body List of ``OFPPortStats`` instance ================ ======================================================

该函数为端口统计应答消息,文档中给的范例程序如下:

Example:: @set_ev_cls(ofp_event.EventOFPPortStatsReply, MAIN_DISPATCHER) def port_stats_reply_handler(self, ev): ports = [] for stat in ev.msg.body: ports.append("port_no=%d " "rx_packets=%d tx_packets=%d " "rx_bytes=%d tx_bytes=%d " "rx_dropped=%d tx_dropped=%d " "rx_errors=%d tx_errors=%d " "rx_frame_err=%d rx_over_err=%d rx_crc_err=%d " "collisions=%d duration_sec=%d duration_nsec=%d" % (stat.port_no, stat.rx_packets, stat.tx_packets, stat.rx_bytes, stat.tx_bytes, stat.rx_dropped, stat.tx_dropped, stat.rx_errors, stat.tx_errors, stat.rx_frame_err, stat.rx_over_err, stat.rx_crc_err, stat.collisions, stat.duration_sec, stat.duration_nsec)) self.logger.debug("PortStats: %s", ports)

通过案例程序,我们可以看到,从该消息中,我们可以获取到:

rx_packetstx_packetsrx_bytestx_bytesrx_droppedtx_droppedrx_errorstx_errorsrx_frame_errtx_overerrrx_crc_errcollisionsduration_secduration_nsec

同样该事件同样对应存在一个端口统计请求事件OFPPortStatsRequest,源码中对该函数的说明如下:

""" Port statistics request message The controller uses this message to query information about ports statistics. ================ ====================================================== Attribute Description ================ ====================================================== flags Zero or ``OFPMPF_REQ_MORE`` port_no Port number to read (OFPP_ANY to all ports) ================ ======================================================

使用范例如下:

Example:: def send_port_stats_request(self, datapath): ofp = datapath.ofproto ofp_parser = datapath.ofproto_parser req = ofp_parser.OFPPortStatsRequest(datapath, 0, ofp.OFPP_ANY) datapath.send_msg(req)

小结:

发起事件处理事件
OFPPortStatsRequestEventOFPPortStatsReply

欢迎阅读本文章: 黄成全

365bet官方网址

日博体育