zoukankan      html  css  js  c++  java
  • 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描述的情况包括:

    Defination Explanation
    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_id
    • duration_sec
    • duration_nsec
    • priority
    • idle_timeout
    • hard_timeout
    • flags
    • cookie
    • packet_count
    • byte_count
    • match
    • instructions

    使用范例:

    @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参数,其他为缺省的默认值。

    小结:

    发起事件 处理事件
    OFPFlowStatsRequest EventOFPFlowStatsReply

    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_packets
    • tx_packets
    • rx_bytes
    • tx_bytes
    • rx_dropped
    • tx_dropped
    • rx_errors
    • tx_errors
    • rx_frame_err
    • tx_overerr
    • rx_crc_err
    • collisions
    • duration_sec
    • duration_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)
    

    小结:

    发起事件 处理事件
    OFPPortStatsRequest EventOFPPortStatsReply
  • 相关阅读:
    Python随笔——Map之键对应多值的处理
    Python操作cx_Oracle笔记
    jmeter进阶之Beanshell引用Java代码
    碎片记录——JMeter之 http post json对象与参数化调用,以及beanshell 引用Java源码
    java源码生成可运行jar
    小记:web安全测试之——固定session漏洞
    Git关联JIRA的issue
    APP稳定性测试-monkey执行
    maven之assembly插件
    wrapper配置文件详解
  • 原文地址:https://www.cnblogs.com/NinWoo/p/9398310.html
Copyright © 2011-2022 走看看