• 实验3:Mininet 实验——测量路径的损耗率


    实验3:Mininet 实验——测量路径的损耗率

    一、实验 目的

    实验 2 的基础上进一步熟悉 Mininet 自定义拓扑脚本,以及与损耗率相关的设定;初步了解 Mininet 安装时自带的 POX 控制器脚本编写,测试路径损耗率。

    二 、实验 任务

    h0 向 h1 发送数据包,由于在 Mininet 脚本中设置了连接损耗率,在传输过程中会丢失一些包,本次实验的目的是展示如何通过控制器计算路径损耗速率(h0-s0-s1-h1)。这里假设控制器预先知道网络拓扑。控制器将向 s0 和 s1 发送flow_stats_request,当控制器接收到来自 s0 的 response 时,将特定流的数据包数保存在 input_pkts 中,当控制器接收到来自 s1 的 response 时,将接收到特定流的数据包数保存在 output_pkts 中,差值就是丢失的数据包数量。

    基于上述拓扑,编写 Mininet 脚本,设置特定的交换机间的路径损耗速率,然后编写 POX 控制器脚本,实现对路径的损耗率的测量。

    三 、实验步骤

    1. 实验环境

    安装了 Ubuntu 18.04.5 Desktop amd64 的虚拟机

    2. 实验过程

    (1)新建并编辑 pox 脚本 flowstat.py:

    • __步骤一:__在 pox 安装目录下(Mininet 完整安装包含了 pox),执行一下指令,在装有POX的虚拟机里新建文件flow_stats.py

      $cd pox
      $touch flow_stats.py
      
    • __步骤二:__编辑文件flow_stats.py,内容如下:

      #!/usr/bin/python
      # Copyright 2012 William Yu
      # wyu@ateneo.edu
      #
      # This file is part of POX.
      #
      # POX is free software: you can redistribute it and/or modify
      # it under the terms of the GNU General Public License as published by
      # the Free Software Foundation, either version 3 of the License, or
      # (at your option) any later version.
      #
      # POX is distributed in the hope that it will be useful,
      # but WITHOUT ANY WARRANTY; without even the implied warranty of
      # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      # GNU General Public License for more details.
      #
      # You should have received a copy of the GNU General Public License
      # along with POX. If not, see <http://www.gnu.org/licenses/>.
      #
       
      """
      This is a demonstration file created to show how to obtain flow 
      and port statistics from OpenFlow 1.0-enabled switches. The flow
      statistics handler contains a summary of web-only traffic.
      """
       
      # standard includes
      from pox.core import core
      from pox.lib.util import dpidToStr
      import pox.openflow.libopenflow_01 as of
      from pox.lib.addresses import IPAddr, EthAddr
       
      # include as part of the betta branch
      from pox.openflow.of_json import *
      from pox.lib.recoco import Timer
      import time
       
      log = core.getLogger()
       
      src_dpid = 0
      dst_dpid = 0
      input_pkts = 0
      output_pkts = 0
       
      def getTheTime():  #fuction to create a timestamp
        flock = time.localtime()
        then = "[%s-%s-%s" %(str(flock.tm_year),str(flock.tm_mon),str(flock.tm_mday))
        
        if int(flock.tm_hour)<10:
          hrs = "0%s" % (str(flock.tm_hour))
        else:
          hrs = str(flock.tm_hour)
        if int(flock.tm_min)<10:
          mins = "0%s" % (str(flock.tm_min))
        else:
          mins = str(flock.tm_min)
        if int(flock.tm_sec)<10:
          secs = "0%s" % (str(flock.tm_sec))
        else:
          secs = str(flock.tm_sec)
        then +="]%s.%s.%s" % (hrs,mins,secs)
        return then
       
      # handler for timer function that sends the requests to all the
      # switches connected to the controller.
      def _timer_func ():
        for connection in core.openflow._connections.values():
          connection.send(of.ofp_stats_request(body=of.ofp_flow_stats_request()))
          connection.send(of.ofp_stats_request(body=of.ofp_port_stats_request()))
        log.debug("Sent %i flow/port stats request(s)", len(core.openflow._connections))
       
      # handler to display flow statistics received in JSON format
      # structure of event.stats is defined by ofp_flow_stats()
      def _handle_flowstats_received (event):
         #stats = flow_stats_to_list(event.stats)
         #log.debug("FlowStatsReceived from %s: %s", dpidToStr(event.connection.dpid), stats)
         global src_dpid, dst_dpid, input_pkts, output_pkts
         #print "src_dpid=", dpidToStr(src_dpid), "dst_dpid=", dpidToStr(dst_dpid)
         for f in event.stats:
           if f.match.dl_type==0x0800 and f.match.nw_dst==IPAddr("192.168.123.2") and f.match.nw_tos==0x64 and event.connection.dpid==src_dpid: 
             #print "input: ", f.byte_count, f.packet_count
             input_pkts = f.packet_count
           if f.match.dl_type==0x0800 and f.match.nw_dst==IPAddr("192.168.123.2") and f.match.nw_tos==0x64 and event.connection.dpid==dst_dpid:
             #print "output: ", f.byte_count, f.packet_count  
             output_pkts = f.packet_count
             if input_pkts !=0:
               print getTheTime(), "Path Loss Rate =", (input_pkts-output_pkts)*1.0/input_pkts*100, "%"
       
      # handler to display port statistics received in JSON format
      def _handle_portstats_received (event):
         #print "
      <<<STATS-REPLY: Return PORT stats for Switch", event.connection.dpid,"at ",getTheTime()
         #for f in event.stats:
            #if int(f.port_no)<65534:
              #print "   PortNo:", f.port_no, " Fwd's Pkts:", f.tx_packets, " Fwd's Bytes:", f.tx_bytes, " Rc'd Pkts:", f.rx_packets, " Rc's Bytes:", f.rx_bytes
              #print "   PortNo:", f.port_no,  " TxDrop:", f.tx_dropped, " RxDrop:", f.rx_dropped, " TxErr:", f.tx_errors, " RxErr:", f.rx_errors, " CRC:", f.rx_crc_err, " Coll:", f.collisions 
        stats = flow_stats_to_list(event.stats)
        log.debug("PortStatsReceived from %s: %s", dpidToStr(event.connection.dpid), stats)
       
      def _handle_ConnectionUp (event):
        global src_dpid, dst_dpid
        print "ConnectionUp: ", dpidToStr(event.connection.dpid)
        for m in event.connection.features.ports:
          if m.name == "s0-eth0":
            src_dpid = event.connection.dpid
          elif m.name == "s1-eth0":
            dst_dpid = event.connection.dpid
       
        msg = of.ofp_flow_mod()
        msg.priority =1
        msg.idle_timeout = 0
        msg.match.in_port =1
        msg.actions.append(of.ofp_action_output(port = of.OFPP_ALL))
        event.connection.send(msg)
       
        msg = of.ofp_flow_mod()
        msg.priority =1
        msg.idle_timeout = 0
        msg.match.in_port =2
        msg.actions.append(of.ofp_action_output(port = of.OFPP_ALL))
        event.connection.send(msg)
       
        msg = of.ofp_flow_mod()
        msg.priority =10
        msg.idle_timeout = 0
        msg.hard_timeout = 0
        msg.match.dl_type = 0x0800
        msg.match.nw_tos = 0x64
        msg.match.in_port=1
        msg.match.nw_dst = "192.168.123.2"
        msg.actions.append(of.ofp_action_output(port = 2))
        event.connection.send(msg)
       
        msg = of.ofp_flow_mod()
        msg.priority =10
        msg.idle_timeout = 0
        msg.hard_timeout = 0
        msg.match.dl_type = 0x0800
        msg.match.nw_tos = 0x64
        msg.match.nw_dst = "192.168.123.1"
        msg.actions.append(of.ofp_action_output(port = 1))
        event.connection.send(msg)
          
      # main functiont to launch the module
      def launch ():
        # attach handsers to listners
        core.openflow.addListenerByName("FlowStatsReceived", 
          _handle_flowstats_received) 
        core.openflow.addListenerByName("PortStatsReceived", 
          _handle_portstats_received) 
        core.openflow.addListenerByName("ConnectionUp", _handle_ConnectionUp)
       
        # timer set to execute every five seconds
        Timer(1, _timer_func, recurring=True)
      
    • __步骤3:__运行脚本flow_stats.py。

      $./pox.py flow_stats
      
    • 运行结果

    (2)新建脚本 mymininet3.py:

    • __步骤一:__在装有Mininet的虚拟机里新建文件mymininet3.py

      $touch mymininet.py
      
    • __步骤二:__编辑文件mymininet3.py,内容如下:

      #!/usr/bin/python
       
      from mininet.net import Mininet
      from mininet.node import Node
      from mininet.link import TCLink
      from mininet.log import  setLogLevel, info
      from threading import Timer
      from mininet.util import quietRun
      from time import sleep
       
      def myNet(cname='controller', cargs='-v ptcp:'):
          "Create network from scratch using Open vSwitch."
          info( "*** Creating nodes
      " )
          controller = Node( 'c0', inNamespace=False )
          switch = Node( 's0', inNamespace=False )
          switch1 = Node( 's1', inNamespace=False )
          h0 = Node( 'h0' )
          h1 = Node( 'h1' )
          
          info( "*** Creating links
      " )
          linkopts0=dict(bw=100, delay='1ms', loss=0)
          linkopts1=dict(bw=100, delay='1ms', loss=10)
          link0=TCLink( h0, switch, **linkopts0)
          link1 = TCLink( switch, switch1, **linkopts1)     
          link2 = TCLink( h1, switch1, **linkopts0)
          #print link0.intf1, link0.intf2
          link0.intf2.setMAC("0:0:0:0:0:1")
          link1.intf1.setMAC("0:0:0:0:0:2")
          link1.intf2.setMAC("0:1:0:0:0:1") 
          link2.intf2.setMAC("0:1:0:0:0:2")
       
          info( "*** Configuring hosts
      " )
          h0.setIP( '192.168.123.1/24' )
          h1.setIP( '192.168.123.2/24' )
             
          info( "*** Starting network using Open vSwitch
      " )
          switch.cmd( 'ovs-vsctl del-br dp0' )
          switch.cmd( 'ovs-vsctl add-br dp0' )
          switch1.cmd( 'ovs-vsctl del-br dp1' )
          switch1.cmd( 'ovs-vsctl add-br dp1' )
       
          controller.cmd( cname + ' ' + cargs + '&' )     
          for intf in switch.intfs.values():
              print intf
              print switch.cmd( 'ovs-vsctl add-port dp0 %s' % intf )
          for intf in switch1.intfs.values():
              print intf
              print switch1.cmd( 'ovs-vsctl add-port dp1 %s' % intf )
         
          # Note: controller and switch are in root namespace, and we
          # can connect via loopback interface
          switch.cmd( 'ovs-vsctl set-controller dp0 tcp:10.0.0.13:6633' )
          switch1.cmd( 'ovs-vsctl set-controller dp1 tcp:10.0.0.13:6633' )
        
          info( '*** Waiting for switch to connect to controller' )
          while 'is_connected' not in quietRun( 'ovs-vsctl show' ):
              sleep( 1 )
              info( '.' )
          info( '
      ' )
       
          #info( "*** Running test
      " )
          h0.cmdPrint( 'ping -Q 0x64 -c 20 ' + h1.IP() )
          
          sleep( 1 ) 
          info( "*** Stopping network
      " )
          controller.cmd( 'kill %' + cname )
          switch.cmd( 'ovs-vsctl del-br dp0' )
          switch.deleteIntfs()
          switch1.cmd( 'ovs-vsctl del-br dp1' )
          switch1.deleteIntfs()
          info( '
      ' )
       
      if __name__ == '__main__':
          setLogLevel( 'info' )
          info( '*** Scratch network demo (kernel datapath)
      ' )
          Mininet.init()
          myNet()
      

    (2)编辑脚本 mymininet3.py:

    • 参照拓扑图,新建并编辑 Mininet 脚本 mymininet3.py,控制器因为安装在本机,
      所以需修改参考资料代码中的控制器地址为 127.0.0.1:6633。
    switch.cmd( 'ovs-vsctl set-controller dp0 tcp:127.0.0.1:6633' )
    switch1.cmd( 'ovs-vsctl set-controller dp1 tcp:127.0.0.1:6633' )
    
    • 设置 s0 和 s1 之间链路的丢包率为 0
    info( "*** Creating links
    " )
    linkopts0=dict(bw=100, delay='1ms', loss=0)
    linkopts1=dict(bw=100, delay='1ms', loss=0)
    link0=TCLink( h0, switch, **linkopts0)
    link1 = TCLink( switch, switch1, **linkopts1)
    link2 = TCLink( h1, switch1, **linkopts0)
    
    • 再执行命令运行 Mininet 脚本 mymininet3.py
    $ sudo python mymininet3.py
    
    • POX端的结果
    • 如果修改代码中 s0 和 s1 之间链路的丢包率为 10。
    info( "*** Creating links
    " )
    linkopts0=dict(bw=100, delay='1ms', loss=0)
    linkopts1=dict(bw=100, delay='1ms', loss=10)
    link0=TCLink( h0, switch, **linkopts0)
    link1 = TCLink( switch, switch1, **linkopts1)
    link2 = TCLink( h1, switch1, **linkopts0)
    
    • POX 端重新测试,会发现出现丢包现象,但是实际测量出的丢包率会有浮动,链
      路的性能总体受到了限制。

    四、总结

    当丢包率设置为0的时候,实际上测试数据中还是会有一定程度的丢包的。

  • 相关阅读:
    linux
    【转】三种地理参考信息模型:WMS,WFS,WCS
    Flex工程与Asp.net工程集成发布时若干注意事项
    招聘Asp.NET高级开发人员
    【转】2008'中国地理信息系统优秀工程公示
    推荐一本GIS的好书《空间数据库》
    集中推荐一些Map Projection方面资源
    收藏几篇虚拟化的文章
    征集“地图制图”WEB站点、BBS
    [转]NHibernate文章转载
  • 原文地址:https://www.cnblogs.com/juejues/p/13714302.html
Copyright © 2020-2023  润新知