实验参考:
基于Mininet测量路径的损耗率
SDN常用控制器安装部署之POX篇
实验步骤:
1. 在装有mininet的虚拟机中新建文件mymininet.py并编辑以下内容,这里要注意一点,文中的dp0与dp1须填POX安装的虚拟机的地址,由于本次实验是在同一台虚拟机中安装,因此地址为127.0.0.1:
#!/usr/bin/pythonfrom 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 sleepdef myNet(cname='controller', cargs='-v ptcp:'):"Create network from scratch using Open vSwitch."info( "*** Creating nodes\n" )controller = Node( 'c0', inNamespace=False )switch = Node( 's0', inNamespace=False )switch1 = Node( 's1', inNamespace=False )h0 = Node( 'h0' )h1 = Node( 'h1' )info( "*** Creating links\n" )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.intf2link0.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\n" )h0.setIP( '192.168.123.1/24' )h1.setIP( '192.168.123.2/24' )info( "*** Starting network using Open vSwitch\n" )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 intfprint switch.cmd( 'ovs-vsctl add-port dp0 %s' % intf )for intf in switch1.intfs.values():print intfprint switch1.cmd( 'ovs-vsctl add-port dp1 %s' % intf )# Note: controller and switch are in root namespace, and we# can connect via loopback interfaceswitch.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' )info( '*** Waiting for switch to connect to controller' )while 'is_connected' not in quietRun( 'ovs-vsctl show' ):sleep( 1 )info( '.' )info( '\n' )#info( "*** Running test\n" )h0.cmdPrint( 'ping -Q 0x64 -c 20 ' + h1.IP() )sleep( 1 ) info( "*** Stopping network\n" )controller.cmd( 'kill %' + cname )switch.cmd( 'ovs-vsctl del-br dp0' )switch.deleteIntfs()switch1.cmd( 'ovs-vsctl del-br dp1' )switch1.deleteIntfs()info( '\n' )if __name__ == '__main__':setLogLevel( 'info' )info( '*** Scratch network demo (kernel datapath)\n' )Mininet.init()myNet()
2. 在装有POX的虚拟机(本次实验与mininet安装在同一台虚拟机)里新建文件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 timelog = core.getLogger()src_dpid = 0
dst_dpid = 0
input_pkts = 0
output_pkts = 0def getTheTime(): #fuction to create a timestampflock = 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_countinput_pkts = f.packet_countif 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_countif 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 "\n<<<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_dpidprint "ConnectionUp: ", dpidToStr(event.connection.dpid)for m in event.connection.features.ports:if m.name == "s0-eth0":src_dpid = event.connection.dpidelif m.name == "s1-eth0":dst_dpid = event.connection.dpidmsg = of.ofp_flow_mod()msg.priority =1msg.idle_timeout = 0msg.match.in_port =1msg.actions.append(of.ofp_action_output(port = of.OFPP_ALL))event.connection.send(msg)msg = of.ofp_flow_mod()msg.priority =1msg.idle_timeout = 0msg.match.in_port =2msg.actions.append(of.ofp_action_output(port = of.OFPP_ALL))event.connection.send(msg)msg = of.ofp_flow_mod()msg.priority =10msg.idle_timeout = 0msg.hard_timeout = 0msg.match.dl_type = 0x0800msg.match.nw_tos = 0x64msg.match.in_port=1msg.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 =10msg.idle_timeout = 0msg.hard_timeout = 0msg.match.dl_type = 0x0800msg.match.nw_tos = 0x64msg.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 listnerscore.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 secondsTimer(1, _timer_func, recurring=True)
3. 运行脚本flow_stats.py。
4. 运行脚本mymininet.py:
5. 查看POX控制台信息:
实验结论:
基于Mininet的脚本设计拓扑,主要是对交换机间传输数据包的路径损耗速率进行设置,并且通过控制器POX进行测量。