Ryu------simple_monitor_13.py实现功能为:定期检查网络状态

simple_monitor_13.py实现功能为:定期检查网络状态

定期檢查網路狀態

網路已經成為許多服務或業務的基礎建設,所以維護一個穩定的網路環境是必要的。但是網路問題總是不斷地發生。

網路發生異常的時候,必須快速的找到原因,並且儘速恢復原狀。 這不需要多說,正在閱讀本書的人都知道,找出網路的錯誤、發現真正的原因需要清楚地知道網路的狀態。例如:假設網路中特定的連接埠正處於高流量的狀態,不論是因為他是一個不正常的狀態或是任何原因導致,變成一個由於沒有持續監控所發生的問題。

因此,為了網路的安全以及業務的正常運作,持續注意網路的健康狀況是最基本的工作。當然,網路流量的監視並不能夠保證不會發生任何問題。本章將說明如何使用 OpenFlow 來取得相關的統計資訊。

代码实现

该代码实现的基础是基于simple_switch_13.py的实现

这一部分主要实现的是EventOFPStateChange事件来监听datapath状态,判断交换机的端口连接情况,从而创建datapaths字典存储交换机内部datapath的情况,key是dpid,value是datapath的数据结构的内容

from operator import attrgetter

from ryu.app import simple_switch_13
from ryu.controller import ofp_event
from ryu.controller.handler import MAIN_DISPATCHER, DEAD_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.lib import hub


class SimpleMonitor13(simple_switch_13.SimpleSwitch13):
	# 定期的向交换机发出要求以取得需要统计的数据
	# SimpleMonitor 類別中並繼承自 SimpleSwitch13 ,所以這邊已經沒有轉送相關的處理功能了。
	
    def __init__(self, *args, **kwargs):
        super(SimpleMonitor13, self).__init__(*args, **kwargs)
        self.datapaths = {} # datapaths字典类型存储datapath数据结构,key是dpid,value是datapath数据结构内容
        self.monitor_thread = hub.spawn(self._monitor)  # 建立一个绿色线程,运行监控程序 _monitor 后面有定义
        
	# EventOFPStatureChange的信息类用来监测交换器的连线中断,会被触发在#Dathpath状态改变时
	# 参数二表示 一般状态和连线中断状态
    @set_ev_cls(ofp_event.EventOFPStateChange,
                [MAIN_DISPATCHER, DEAD_DISPATCHER])
    def _state_change_handler(self, ev):   
    
    	# 通过判断当前状态从监测列表添加或移除当前datapath
    	# 连线中断状态用于确认连线中的交换机可以持续被监控
        datapath = ev.datapath
        # 当datapath的状态变成MAIN_DISPATCHER时,代表交换机已经被注册,并且正处于被监视的状态
        if ev.state == MAIN_DISPATCHER:
            if datapath.id not in self.datapaths:
                self.logger.debug('register datapath: %016x', datapath.id)
                self.datapaths[datapath.id] = datapath
        # 当datapath的状态变成DEAD_DISPATCHER时,代表注册状态已经解除
        elif ev.state == DEAD_DISPATCHER:
            if datapath.id in self.datapaths:
                self.logger.debug('unregister datapath: %016x', datapath.id)
                del self.datapaths[datapath.id]

    def _monitor(self):

        while True:
        	# 不断地注册的向交换机发送要求取得的统计信息
            for dp in self.datapaths.values():
                self._request_stats(dp)
            # 每隔10s查询一次当前的监视datapath名单中的各个#datapath状况
            hub.sleep(10)
#在執行緒中 _monitor() 方法確保了執行緒可以在每 10 秒的間隔中,不斷地向註冊的交換器發送要求以取得統計資訊。

#為了確認連線中的交換器都可以被持續監控, EventOFPStateChange 就可以用來監測交換器的連線中
斷。這個事件偵測是 Ryu 框架所提供的功能,會被觸發在 Datapath 的狀態改變時。

#當 Datapath 的狀態變成 MAIN_DISPATCHER 時,代表交換器已經註冊並正處於被監視的狀態。而狀態
變成 DEAD_DISPATCHER 時代表已經從註冊狀態解除。

下面的一部分代码则就是对交换机内部的datapath的状态请求和状态回应

    def _request_stats(self, datapath):
        self.logger.debug('send stats request: %016x', datapath.id)
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
		# 向指定的datapath发送OFPFlowStatsRequest和OFPStatsResquest消息类实体,即对相关统计信息进行请求
		# OFPFlowStatsRequest主要用来对交换机的Flow Entry取得统计信息
		# 对于交换即发出的要求可以使用table ID、output port、cookie 值和 match 条件来限定范围,但是以下实现的是取得所有的 Flow Entry。
		# 这里可以自己试试
        req = parser.OFPFlowStatsRequest(datapath)
        datapath.send_msg(req)
        
		# OFPPortStatsRequest 是用来取得关于交换机的端口相关信息以及统计信息。
		# 使用的使用可以指定端口号,以下使用OFPP_ANY,目的是要取得所有的端口统计信息。
        req = parser.OFPPortStatsRequest(datapath, 0, ofproto.OFPP_ANY)
        # 这里的	0 什么意思?
        datapath.send_msg(req)
	
	# 对FlowStatsReply消息的回复进行事件处理
    @set_ev_cls(ofp_event.EventOFPFlowStatsReply, MAIN_DISPATCHER)
    def _flow_stats_reply_handler(self, ev):
    	# body中存放了OFPFlowStats的列表,存储了每一个Flow Entry的统计资料,并作为OFPFlowStatsRequest的回应
        body = ev.msg.body  

        self.logger.info('datapath         '
                         'in-port  eth-dst           '
                         'out-port packets  bytes')
        self.logger.info('---------------- '
                         '-------- ----------------- '
                         '-------- -------- --------')
        # 对各个优先级非0的流表项按接收端口和目的MAC地址进行排序后遍历
        for stat in sorted([flow for flow in body if flow.priority == 1],
                           key=lambda flow: (flow.match['in_port'],
                                             flow.match['eth_dst'])):
            # 对交换机的datapath.id,目的MAC地址,输出端口和包以及字节流量进行打印
            self.logger.info('%016x %8x %17s %8x %8d %8d',
                             ev.msg.datapath.id,
                             stat.match['in_port'], stat.match['eth_dst'],
                             stat.instructions[0].actions[0].port,
                             stat.packet_count, stat.byte_count)
          	# stat.instructions[0].actions[0].port 这个是下发流表的顺序,用过ODL的yang UI 界面就知道
                             
	# 对PortStatsReply消息的回复事件进行处理
    @set_ev_cls(ofp_event.EventOFPPortStatsReply, MAIN_DISPATCHER)
    def _port_stats_reply_handler(self, ev):
        body = ev.msg.body

        self.logger.info('datapath         port     '
                         'rx-pkts  rx-bytes rx-error '
                         'tx-pkts  tx-bytes tx-error')
        self.logger.info('---------------- -------- '
                         '-------- -------- -------- '
                         '-------- -------- --------')
        # 根据端口号进行排序并遍历
        for stat in sorted(body, key=attrgetter('port_no')):
        # attrgetter attribute getter 属性得到器,可以这么理解
        	# 打印交换机id,端口号和接收及发送的包的数量字节数和错误数
            self.logger.info('%016x %8x %8d %8d %8d %8d %8d %8d',
                             ev.msg.datapath.id, stat.port_no,
                             stat.rx_packets, stat.rx_bytes, stat.rx_errors,
                             stat.tx_packets, stat.tx_bytes, stat.tx_errors)

参考资料:
Ryu eventlet学习总结
SDN(三) RYU控制器相关笔记
Ryubook 1.0 說明文件

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`your_ryu_app.py` 是一个占位符,实际上它应该替换成你编写的Ryu应用程序的文件名。在Ryu框架Ryu应用程序通常是一个Python脚本,其包含了一些处理OpenFlow事件的代码。你可以在任何位置创建这个Python脚本,只需要确保在运行Ryu控制器时指定了正确的文件路径即可。 通常来说,一个Ryu应用程序会继承 `ryu.base.app_manager.RyuApp` 类,并重载其的一些方法来处理OpenFlow事件。例如,下面是一个简单的Ryu应用程序的例子,它能够在交换机连接到控制器时打印一条消息: ``` python 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 MyRyuApp(app_manager.RyuApp): def __init__(self, *args, **kwargs): super(MyRyuApp, self).__init__(*args, **kwargs) @set_ev_cls(ofp_event.EventOFPSwitchFeatures, MAIN_DISPATCHER) def switch_features_handler(self, ev): datapath = ev.msg.datapath self.logger.info("Switch connected: %s", datapath.id) ``` 在这个例子,我们定义了一个名为 `MyRyuApp` 的类,它继承了 `RyuApp` 类。在 `__init__` 方法,我们调用了父类的构造函数来初始化应用程序。在 `switch_features_handler` 方法,我们使用了 `@set_ev_cls` 装饰器来指定处理 `EventOFPSwitchFeatures` 事件的方法。当交换机连接到控制器时,该事件将被触发,并调用 `switch_features_handler` 方法来处理事件。在该方法,我们可以获取到交换机的 datapath 对象,并打印一条连接成功的消息。 你可以将上述代码保存为一个名为 `my_ryu_app.py` 的Python脚本,并在运行Ryu控制器时指定该脚本的路径: ``` ryu-manager my_ryu_app.py --ofp-tcp-listen-port 8888 ``` 这样,Ryu控制器将会启动,并监听端口号为8888的TCP连接。当交换机连接到控制器时,`switch_features_handler` 方法将会被调用,打印一条连接成功的消息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值