zoukankan      html  css  js  c++  java
  • RYU 灭龙战 fourth day (1)

    RYU 灭龙战 fourth day (1)

    前言

    对于流量的监控,对于一个网络管理人员来说是非常重要的,可以从可视化的角度,方便检测出哪里的设备出了问题;而在传统网络中,如果是哪里的设备出了问题的话,则需要进行人工的排查,这种排查往往绝大部分依赖于经验上,这也是SDN一个小小的好处吧。这次实验就基于上次实验的基础上,加入流量监控。

    实现方案

    附录源码

    • 交换机状态

    # Copyright (C) 2016 Nippon Telegraph and Telephone Corporation.
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #    http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    # implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    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
    
    
    #继承simple_switch_13,OpenFlow1.3 mac学习
    class SimpleMonitor13(simple_switch_13.SimpleSwitch13):
    
        #初始化函数
        def __init__(self, *args, **kwargs):
            super(SimpleMonitor13, self).__init__(*args, **kwargs)
            #数据路径的集合
            self.datapaths = {}
            #每次流表监控的时间戳
            self.monitor_thread = hub.spawn(self._monitor)
    
        #消息类型StateChange,交换机的状态为一般状态(MAIN_DISPATCHER) 或者连接中断状态(DEAD_DISPATCHER)
        @set_ev_cls(ofp_event.EventOFPStateChange,
                    [MAIN_DISPATCHER, DEAD_DISPATCHER])
        def _state_change_handler(self, ev):
            #得到数据路径
            datapath = ev.datapath
            #如果交换机状态为一般连接状态,并且该消息的数据路径id不在数据路径集合中,则把该数据路径id加入数据路径集合中
            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
            #如果交换机状态为断开链接状态,且该消息的数据路径在数据路径集合中,则把该数据路径id从数据路径集合中去除
            elif ev.state == DEAD_DISPATCHER:
                if datapath.id in self.datapaths:
                    self.logger.debug('unregister datapath: %016x', datapath.id)
                    del self.datapaths[datapath.id]
    
        #对于在数据路径集合中的交换机每间隔10s发送请求,来获得交换机的消息
        def _monitor(self):
            while True:
                for dp in self.datapaths.values():
                    self._request_stats(dp)
                hub.sleep(10)
    
        #_request_stats方法用来定期发送,OFPFlowStatsRequest、OFPPortStatsRequest消息给交换机
        def _request_stats(self, datapath):
            self.logger.debug('send stats request: %016x', datapath.id)
            ofproto = datapath.ofproto
            parser = datapath.ofproto_parser
    
            req = parser.OFPFlowStatsRequest(datapath)
            datapath.send_msg(req)
    
            req = parser.OFPPortStatsRequest(datapath, 0, ofproto.OFPP_ANY)
            datapath.send_msg(req)
    
        #用来处理EventOFPFlowStatsReply数据包,在交换机状态为一般链接状态
        @set_ev_cls(ofp_event.EventOFPFlowStatsReply, MAIN_DISPATCHER)
        def _flow_stats_reply_handler(self, ev):
            body = ev.msg.body
    
            self.logger.info('datapath         '
                             'in-port  eth-dst           '
                             'out-port packets  bytes')
            self.logger.info('---------------- '
                             '-------- ----------------- '
                             '-------- -------- --------')
    
            #输出消息的数据路径id,入端口,目的mac,出端口,packets数目,以及byte大小,并按入端口,目的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'])):
                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)
    
        # 用来处理EventOFPPortStatsReply数据包,在交换机状态为一般链接状态
        @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('---------------- -------- '
                             '-------- -------- -------- '
                             '-------- -------- --------')
            #打印出对应的数据的数据路径id,以及交换机端口,以及接收数据包数目,接收字节数目,接收数据错误率,以及相应的发送数据包数目,发送字节数目,发送错误数
            for stat in sorted(body, key=attrgetter('port_no')):
                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)
    
    

    实验过程

    • 打开一终端,打开mininet
    sudo mn --topo single,3 --mac --switch ovsk,protocols=OpenFlow13 --controller remote
    

    此时还没有执行ryu应用,所以对应的6633端口无应用相应,在wireshark查看可得各种TCP握手失败

    • 另一种 执行ryu应用,目录为.../ryu/app
    ryu-manager --verbose ./simple_monitor_13.py
    

    上次实验可知,此时还没有优先级大于0的流表,所以没有显示出来。此时模仿上次一样h1 ping h2让其下发流表

    • mininet端口互ping,触发控制器下发流表
    h1 ping h2
    

    可以看到流表增加了,可看到实时的流量检测

    总结

    基于上次实验的扩展吧

    利用OpenFlow的相应消息可以做的一些特定功能

  • 相关阅读:
    【HTML5】html5在ie8及以下的兼容性问题
    【前端】从登录框看前端
    批量插入
    Mongodb地理空间索引
    Mongodb添加地理位置索引
    记一 次docker-compose build报错
    The method's class, com.google.common.collect.FluentIterable, is available from the following locations
    如果在chrome的新标签中继续打开开发工具
    设置idea 2018 的vmoptions无效
    spring boot(2):activiti整合
  • 原文地址:https://www.cnblogs.com/wpqwpq/p/6493134.html
Copyright © 2011-2022 走看看