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)

來源:源碼ryu\ofproto\ofproto_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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM