Mininet教程(六):多数据中心带宽实验
SDNLAB:Mininet入门与实战 笔记
拓扑结构
在mininet/custom文件夹中新建py脚本(命名为fattree.py):
from mininet.topo import Topo
from mininet.net import Mininet
from mininet.node import RemoteController,CPULimitedHost
from mininet.link import TCLink
from mininet.util import dumpNodeConnections
class MyTopo(Topo):
def __init__(self):
# Initialize topology
Topo.__init__(self)
L1=2
L2=L1*2
L3=L2
Core_Switches=[]
Aggregation_Switches=[]
Edge_Switches=[]
# add swithes
for i in range(L1):
sw=self.addSwitch('C{}'.format(i+1))
Core_Switches.append(sw)
for i in range(L2):
sw=self.addSwitch('A{}'.format(i+1))
Aggregation_Switches.append(sw)
for i in range(L3):
sw=self.addSwitch('E{}'.format(i+1))
Edge_Switches.append(sw)
# add links
for sw1 in Core_Switches:
for sw2 in Aggregation_Switches:
self.addLink(sw1,sw2)
for i in range(0,L2,2):
for sw1 in Aggregation_Switches[i:i+2]:
for sw2 in Edge_Switches[i:i+2]:
self.addLink(sw1,sw2)
# add hosts and links
count=1
for sw1 in Edge_Switches:
for i in range(2):
host=self.addHost('H{}'.format(count))
self.addLink(sw1,host)
count+=1
topos={'mytopo':(lambda:MyTopo())}
使能生成树协议(STP)
在终端执行命令生成拓扑:
sudo mn --custom fattree.py --topo mytopo
进行主机互ping测试,发现不能ping通:
mininet> pingall
*** Ping: testing ping reachability
H1 -> X X X X X X X
H2 -> X X X X X X X
H3 -> X X X X X X X
H4 -> X X X X X X X
H5 -> X X X X X X X
H6 -> X X X X X X X
H7 -> X X X X X X X
H8 -> X X X X X X X
*** Results: 100% dropped (0/56 received)
如果使用iperf测试TCP带宽,会报错Could not connect to iperf on port 5001:
mininet> iperf H1 H2
*** Iperf: testing TCP bandwidth between H1 and H2
no route to 10.0.0.2:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 H1-eth0
--------------------------------------------------------------------------------
Caught exception. Cleaning up...
Exception: Could not connect to iperf on port 5001
这是因为该拓扑中包含了很多环路loop,不加抑制会有广播风暴的风险。查询mininet的接口手册,发现默认的ovs设置是:
def mininet.node.OVSSwitch.__init__ ( self,
name,
failMode = 'secure',
datapath = 'kernel',
inband = False,
protocols = None,
reconnectms = 1000,
stp = False,
batch = False,
params
)
#Parameters
#name name for switch
#failMode controller loss behavior (secure|standalone)
#datapath userspace or kernel mode (kernel|user)
#inband use in-band control (False)
#protocols use specific OpenFlow version(s) (e.g. OpenFlow13) Unspecified (or old OVS version) uses OVS default
#reconnectms max reconnect timeout in ms (0/None for default)
#stp enable STP (False, requires failMode=standalone)
#batch enable batch startup (False)
可以看到抑制环路的生成树协议(STP)是关闭的。使能STP还需要设置failMode属性为standalone。那么在什么地方设置呢?一种可行的方法是在运行mn的时候指定switch及属性,通过查询mn的帮助文件:
mn -h
Usage: mn [options]
(type mn -h for details)
The mn utility creates Mininet network from the command line. It can create
parametrized topologies, invoke the Mininet CLI, and run tests.
Options:
-h, --help show this help message and exit
--switch=SWITCH default|ivs|lxbr|ovs|ovsbr|ovsk|user[,param=value...]
ovs=OVSSwitch default=OVSSwitch ovsk=OVSSwitch
lxbr=LinuxBridge user=UserSwitch ivs=IVSSwitch
ovsbr=OVSBridge
在–switch里面,除了指定switch外,还可以附带param=value进行设置,所以在终端执行的命令里面额外加上switch设置:
sudo mn --custom=fattree.py --topo=mytopo --switch=ovsk,failMode='standalone',stp=True
此时再进行连通性测试:
mininet> pingall
*** Ping: testing ping reachability
H1 -> H2 H3 H4 H5 H6 H7 H8
H2 -> H1 H3 H4 H5 H6 H7 H8
H3 -> H1 H2 H4 H5 H6 H7 H8
H4 -> H1 H2 H3 H5 H6 H7 H8
H5 -> H1 H2 H3 H4 H6 H7 H8
H6 -> H1 H2 H3 H4 H5 H7 H8
H7 -> H1 H2 H3 H4 H5 H6 H8
H8 -> H1 H2 H3 H4 H5 H6 H7
*** Results: 0% dropped (56/56 received)
带宽测试
同一边缘交换机内部主机间的带宽:
mininet> iperf H1 H2
*** Iperf: testing TCP bandwidth between H1 and H2
*** Results: ['52.2 Gbits/sec', '52.3 Gbits/sec']
同一汇聚交换机不同边缘交换机的主机之间带宽:
mininet> iperf H1 H3
*** Iperf: testing TCP bandwidth between H1 and H3
*** Results: ['45.3 Gbits/sec', '45.4 Gbits/sec']
同一核心交换机不同汇聚交换机的主机之间带宽:
mininet> iperf H1 H5
*** Iperf: testing TCP bandwidth between H1 and H5
*** Results: ['39.7 Gbits/sec', '39.8 Gbits/sec']
自定义命令拓展
接下来进行mininet自定义命令功能的拓展,生成一个流量随机模型,主机向在网络中的其他任意主机以等概率发送数据包。在mininet中进行自定义命令拓展分为四步:
- 修改mininet/net.py, 实现功能代码;
- 修改mininet/cli.py,注册命令
- 修改mininet/bin/mn,加入到可执行文件中
- install.sh -n,重新安装mininet核心文件
- 修改mininet/net.py文件,在Mininet类中添加方法iperf_single和iperfMulti。这里将它们放到iperf方法的后面,因为这些都是一类方法。
def iperf_single( self, hosts=None, udpBw='10M', period=60, port=5001):
""" Run iperf between two hosts using UDP and record communications.
hosts: list of hosts; if None, uses opposite hosts
returns: results two-element array of server and client speeds
"""
if not hosts:
return
else:
assert len( hosts ) == 2
client, server = hosts
filename = client.name[1:]+'.out'
output( '*** Iperf: testing bandwidth between ' )
output( "%s and %s\n" % ( client.name, server.name ) )
iperfArgs = 'iperf -u '
bwArgs = '-b ' + udpBw + ' '
print( "***start server***" )
server.cmd( iperfArgs + '-s -i 1' + ' > /home/App/mininet/log/' + filename + '&')
print( "***start client***" )
client.cmd( iperfArgs + '-t ' + str(period) + ' -c ' +server.IP() + ' ' + bwArgs +\
'> /home/App/mininet/log/' + 'client' + filename + '&')
def iperfMulti( self, bw, period=60 ):
base_port = 5001
server_list = []
host_list = [h for h in self.hosts]
_len = len(host_list)
for i in xrange(0, _len):
client = host_list[i]
server = client
while( server == client ):
server = random.choice(host_list)
server_list.append(server)
self.iperf_single(hosts=[client,server],udpBw=bw,period=period,port=base_port)
sleep(.05)
base_port += 1
sleep(period)
print("test has done")
其中,iperf_single方法主要实现了两个主机之间的UDP带宽测试,并将测试的结果存储在"/home/App/mininet/log/"目录下。iperfMulti则从Host1开始,随机选取UDP数据流的发送对象。持续测试period时长,默认是60秒。
- 修改mininet/cli.py,注册iperfMulti命令,对用户输入的指令进行解析。
def do_iperfmulti( self, line ):
"""Multi iperf UDP test between nodes"""
args = line.split()
if len(args) == 1:
udpBw = args[0]
self.mn.iperfMulti(udpBw)
elif len(args) == 2:
udpBw = args[0]
period = args[1]
err = False
self.mn.iperfMulti(udpBw, float(period))
else:
error('invalid number of args: iperfmulti udpBw period\n' +\
'udpBw examples: 1M 120\n' )
- 修改mininet/bin/mn,将iperfmulti加入TEST和ALTSPELLING列表中:
# TESTS dict can contain functions and/or Mininet() method names
# XXX: it would be nice if we could specify a default test, but
# this may be tricky
TESTS = { name: True
for name in ( 'pingall', 'pingpair', 'iperf', 'iperfudp', 'iperfmulti' ) }
# Map to alternate spellings of Mininet() methods
ALTSPELLING = { 'pingall': 'pingAll', 'pingpair': 'pingPair',
'iperfudp': 'iperfUdp', 'iperfmulti': 'iperfMulti' }
- 进入mininet/util目录下,执行:
sudo ./install.sh -n
重新编译mininet
流量随机模型下UDP带宽测试
再次启动mn并执行iperfmulti,这里指定了带宽0.025M,测试时长10秒:
mininet> iperfmulti 0.025M 10
*** Iperf: testing bandwidth between H1 and H5
***start server***
***start client***
*** Iperf: testing bandwidth between H2 and H8
***start server***
***start client***
*** Iperf: testing bandwidth between H3 and H1
***start server***
***start client***
*** Iperf: testing bandwidth between H4 and H2
***start server***
***start client***
*** Iperf: testing bandwidth between H5 and H6
***start server***
***start client***
*** Iperf: testing bandwidth between H6 and H3
***start server***
***start client***
*** Iperf: testing bandwidth between H7 and H4
***start server***
***start client***
*** Iperf: testing bandwidth between H8 and H6
***start server***
***start client***
test has done
测试完成后,可以查看log中的记录文件:
ls
1.out 3.out 5.out 7.out client1.out client3.out client5.out client7.out
2.out 4.out 6.out 8.out client2.out client4.out client6.out client8.out
查看1.out:
------------------------------------------------------------
Server listening on UDP port 5001
Receiving 1470 byte datagrams
UDP buffer size: 2.00 MByte (default)
------------------------------------------------------------
[ 3] local 10.0.0.5 port 5001 connected with 10.0.0.1 port 58102
[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams
[ 3] 0.0- 1.0 sec 4.31 KBytes 35.3 Kbits/sec 0.027 ms 0/ 3 (0%)
[ 3] 1.0- 2.0 sec 2.87 KBytes 23.5 Kbits/sec 0.026 ms 0/ 2 (0%)
[ 3] 2.0- 3.0 sec 2.87 KBytes 23.5 Kbits/sec 0.026 ms 0/ 2 (0%)
[ 3] 3.0- 4.0 sec 2.87 KBytes 23.5 Kbits/sec 0.025 ms 0/ 2 (0%)
[ 3] 4.0- 5.0 sec 2.87 KBytes 23.5 Kbits/sec 0.024 ms 0/ 2 (0%)
[ 3] 5.0- 6.0 sec 2.87 KBytes 23.5 Kbits/sec 0.024 ms 0/ 2 (0%)
[ 3] 6.0- 7.0 sec 2.87 KBytes 23.5 Kbits/sec 0.021 ms 0/ 2 (0%)
[ 3] 7.0- 8.0 sec 4.31 KBytes 35.3 Kbits/sec 0.021 ms 0/ 3 (0%)
[ 3] 8.0- 9.0 sec 2.87 KBytes 23.5 Kbits/sec 0.021 ms 0/ 2 (0%)
[ 3] 9.0-10.0 sec 2.87 KBytes 23.5 Kbits/sec 0.022 ms 0/ 2 (0%)
[ 3] 0.0-10.8 sec 33.0 KBytes 25.0 Kbits/sec 0.021 ms 0/ 23 (0%)
这里记录了Server 10.0.0.5 (Host5) 侦听端口5001的记录,即与10.0.0.1 (Host1)的测试记录。一共测试了10秒,每隔1秒记录一次,记录内容有转发包的大小,带宽,延时抖动和丢包率等。
查看client1.out:
------------------------------------------------------------
Client connecting to 10.0.0.5, UDP port 5001
Sending 1470 byte datagrams, IPG target: 470400.00 us (kalman adjust)
UDP buffer size: 2.00 MByte (default)
------------------------------------------------------------
[ 3] local 10.0.0.1 port 58102 connected with 10.0.0.5 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-10.8 sec 33.0 KBytes 25.0 Kbits/sec
[ 3] Sent 23 datagrams
[ 3] Server Report:
[ 3] 0.0-10.8 sec 33.0 KBytes 25.0 Kbits/sec 0.020 ms 0/ 23 (0%)
这里记录了Client 10.0.0.1 (Host1)的测试记录。