zoukankan      html  css  js  c++  java
  • my_monitor_13

    from operator import attrgetterfrom ryu.app import simple_switch_13from ryu.controller.handler import set_ev_clsfrom ryu.controller import ofp_eventfrom ryu.controller.handler import MAIN_DISPATCHER,DEAD_DISPATCHERfrom ryu.lib import hub
    #流量监控原理:控制器向交换机周期下发请求:获取统计消息,请求交换机信息:#1) 端口流量统计信息#2) 请求流表项统计信息
    class MyMonitor13(simple_switch_13.SimpleSwitch13):#继承SimpleSwitch13这个父类就可以帮我们实现二层交换之类的功能,就不用自己写了。    def __init__(self,*args,**kwargs):        super(MyMonitor13, self).__init__(*args,**kwargs)        self.datapaths = {} #字典的格式:key-value:key是dpid,value是交换机:1-s1;2-s2        self.monitor_thread = hub.spawn(self._monitor) #生成协程,进而直接调用_monitor函数
        #这个函数就是想要得到datapath而已:只不过是多了有效和无效datapath之分而已    #要设计监听,使ryu控制器知道有这么一个模块注册,监听了一个事件。设置监听也就相当于控制器进行处理了    @set_ev_cls(ofp_event.EventOFPStateChange,[MAIN_DISPATCHER,DEAD_DISPATCHER])    def _state_change_handler(self,ev):        datapath = ev.datapath        if ev.state == MAIN_DISPATCHER:#代表交换机已经注册并处于被监视的的状态            #类似注册的意思            if datapath.id not in self.datapaths:                self.datapaths[datapath.id] = datapath                self.logger.debug("register datapath: %16x",datapath.id)
            elif ev.state == DEAD_DISPATCHER:#已经从注册状态解除            #类似删除记录            if datapath.id in self.datapaths:                del self.datapaths[datapath.id]                self.logger.debug("unregister datapath: %16x", datapath.id)

        #定期向交换机下发统计信息的请求    def _monitor(self):#写了这个函数,但是还没调用,这里是放在初始化函数那里进行调用执行        while True:            #现在我们要取的是value,不是key(key是dpid)            for dp in self.datapaths.values():                self._request_stats(dp)            hub.sleep(5)


        #向交换机发送请求报文,参数为datapath,向谁发就引入谁    def _request_stats(self,datapath):        ofproto = datapath.ofproto        ofp_parser = datapath.ofproto_parser        #这是不是:控制器向交换机发送请求报文,就是说分别由交换机向端口,流表下发统计流表条目信息的请求,        #还是说控制器向交换机发送请求报文,就相当于直接向交换机端口和流表下发相应的消息        req = ofp_parser.OFPFlowStatsRequest(datapath)#对流表项进行统计,取得所有的流表项        datapath.send_msg(req)        #参数:0:优先级;ofproto.OFPP_ANY:对任何一个端口都可以进行获取,取得所有的端口统计资料。        req = ofp_parser.OFPPortStatsRequest(datapath,0,ofproto.OFPP_ANY)        datapath.send_msg(req)
            self.logger.debug("send stats request to datapapth : %16x", datapath.id)


        #为了接收来自交换机的回应,建立一个event handler来接受从交换机发送的回复信息    #(流表项的统计和端口的统计信息不能混为一谈,流表项的统计不包含被table-miss触发的packet-in以及packet-out传送封包信息。    # 例如h1 ping h2的过程:,host 1 最初的广播信息是 ARP request,而 host 2 回复了 host 1 的 ARP 訊息,host 1 对 host 2 发送了    #  echo request 总共 3 個封包,這些都是透过 Packet-Out 所傳送的。因此端口的流量会远大于 Flow Entry 的流量 )    @set_ev_cls(ofp_event.EventOFPPortStatsReply,MAIN_DISPATCHER)    def _port_stats_reply_handler(self,ev):        #        body = ev.msg.body        #print        self.logger.info('datapath           port  '                         '   rx-pkts       rx-bytes    rx-errors   '                         '   tx-pkts       tx-bytes    tx-errors ')
            self.logger.info('------------   ----------  '                         '  --------     ----------    --------  '                         '   --------    ----------    ----------')
            #attrgetter是python自带的获取属性的工具        for stat in sorted(body,key=attrgetter("port_no")):            self.logger.info("%8x    %8x      %8x      %8x      %8x     %8x     %8x     %8x",                             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)

        #handle the flow entry stats reply msg    @set_ev_cls(ofp_event.EventOFPFlowStatsReply,MAIN_DISPATCHER)    def _flow_stats_reply_handler(self,ev):        #body是OPFFlowStatsReply的一个属性,是OFPFlowStats的列表,当中存储了每一个flow entry的统计信息,并作为flowstatsrequest的回应        #权限为0的table-miss flow除外的全部flow entry将会被选择,通过并符合该flow entry的封包数和位元数统计资料将会被回传,并以接受端口号和目的mac位址的方式排序。        body = ev.msg.body
            self.logger.info('datapath             '                         'in_port        eth-dst       '                         'out_port      packets    bytes     ')
            self.logger.info('-------------    '                         '----------    -------------    '                         '----------   ----------   ----------')
            for stat in sorted([flow for flow in body if flow.priority == 1],                           key=lambda  flow : (flow.match['in_port'],                                               flow.match['eth_dst'])):            self.logger.info("%8x %8x %8d %8d %8d %8d %8d %8d",                             ev.msg.datapath.id,                             stat.match['in_port'],stat.match['eth_dst'],                             stat.instruction[0].actions[0].port,                             stat.packets_count,stat.byte_count)

  • 相关阅读:
    Python中return self的用法
    多分类问题的交叉熵计算
    Python爬虫之足球小将动漫(图片)下载
    Sklearn中二分类问题的交叉熵计算
    TensorFlow.js入门(一)一维向量的学习
    MySql 流程控制经典案列讲解
    MySql 流程控制
    MySql 函数
    MySql 存储过程
    MySql 视图
  • 原文地址:https://www.cnblogs.com/yangrongkuan/p/12009326.html
Copyright © 2011-2022 走看看