編者按:在網絡性能評估中一個巨大的挑戰就是如何生成真實的網絡流量,還好可以通過程序來創造人工的網絡流量,通過建立測試環境來模擬真實的狀況。本文就以數據中心網絡為目標場景,來在mininet仿真環境中盡可能地還原數據中心內部的真實流量情況。目前有兩種常用的流量模型:
■隨機模型:主機向在網絡中的另一任意主機以等概率發送數據包
■概率模型:在網絡中,編號為m的主機分別以概率Pt、Pa、Pc、向主機編號為(m+i)、(m+j)、(m+k)的主機發送數據包
我們使用mininet中的iperf工具在網絡中生成UDP流量,iperf客戶端傳送數據流到iperf的服務端,由服務端接收并記錄相關信息。mininet自帶控制臺可供使用的命令雖然已經比較豐富,但卻并未給出較為明確的API接口來支持用戶自定義命令。在諸如數據中心這樣復雜、網絡節點較多的仿真環境中做一些批處理的工作就需要非常大的,比如通過iperf在所有主機之間發生流量。所以我們需要將自定義命令添加到mininet中,在mininet中完成新命令的拓展。
一、mininet功能拓展
在mininet中進行功能拓展主要分為3步:
1.修改mininet/net.py:?net模塊實現Mininet類,是仿真平臺mininet的主體類,該類完成節點添加配置、網絡基本功能和一些選項功能的實現。我們需要將我們自定義的函數定義在該類中。
class?Mininet(object):
def?function(self,?**kwargs):
#function?code
2.修改mininet/cli.py:?cli模塊定義了CLI類,為米你呢他提供命令行接口,用于解析用戶輸入的命令,之前定義的自定義命令需要在CLI類中通過注冊函數注冊這條自定義命令。
class?CLI(Cmd):
def?do_function(self,?line):
#do_function?code
完成命令注冊與綁定。
3.修改bin/mn:在完成命令注冊與綁定后,需要在mininet執行解釋器中注冊命令與對應執行函數的映射關系。
ALTSPELLING?=?{?'pingall':'pingAll',
'pingpair':'pingPair',
'iperfudp':'iperfUdp',
'function':'function}
net.py和cli.py均在mininet/mininet目錄,mn文件在在mininet/bin目錄中。在代碼修改完成后需要重新編譯安裝一遍mininet,即運行:
$~/mininet/util/install.sh?-n
二、?兩種流量模型在mininet中的實現
2.1隨機模型
任意一臺主機以等概率隨機地向另外一臺主機發起一條UDP數據流。
修改mininet/net.py
首先,先在兩個主機之間進行iperf測試,并且在server端記錄,實現iperf_single函數:
def?iperf_single(?self,hosts=None,?udpBw='10M',?period=60,?port=5001):
"""Run?iperf?between?two?hosts?using?UDP.
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/zg/log/'?+?filename?+?'&')
print?"***start?client***"
client.cmd(
iperfArgs?+?'-t?'+?str(period)?+?'?-c?'?+?server.IP()?+?'?'?+?bwArgs
+'?>?/home/zg/log/'?+?'client'?+?filename?+'&')
接著為mininet添加自定義命令iperfmulti,依次為每一臺主機隨機選擇另一臺主機作為iperf的服務器端,通過調用iperf_single,自身以客戶端身份按照指定參數發送UDP流,服務器生成的報告以重定向的方式輸出到文件中,使用iperfmulti命令,主機隨機地向另一臺主機發起一條恒定帶寬的UDP數據流。
def?iperfMulti(self,?bw,?period=60):
base_port?=?5001
server_list?=?[]
client_list?=?[h?for?h?in?self.hosts]
host_list?=?[]
host_list?=?[h?for?h?in?self.hosts]
cli_outs?=?[]
ser_outs?=?[]
_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"
修改mininet/cli.py
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')
修改bin/mn
在mininet/bin目錄下修改mn文件,將iperfpb加入到對應的列表中。
ALTSPELLING?=?{?'pingall':?'pingAll',
'pingpair':?'pingPair',
'iperfudp':?'iperfUdp',
'iperfUDP':?'iperfUdp',
'iperfpb':'iperfPb'?}
最后,進入mininet/util目錄,重新編譯安裝mininet
$~/mininet/util/install.sh?-n
重啟mininet,輸入iperf,可用table補全iperfpb,從而可使用iperfpb進行流量隨機模型的測試。
2.2概率模型
為mininet添加自定義命令iperfpb,依次為每一臺主機(編號為m)分別以概率Pt、Pa、Pc向主機編號為(m+i)、(m+j)、(m+k)的主機發送數據包,通過調用iperf_single,自身以客戶端身份按照指定參數發送UDP流,服務器生成的報告以重定向的方式輸出到文件中,使用iperfpb命令,主機按概率向其他被選擇的主機發起一條恒定帶寬的UDP數據流。
概率選擇函數
為完成以一定概率選擇主機,我們需要實現一個概率選擇函數randompick,這個函數可用于以不同的概率從一個列表中隨機地選擇一些元素。下面為randompick的實現過程:
def?random_pick(?self,?_list,?probabilities):
x?=?random.uniform(0,1)
p?=?None
cumulative_probability?=?0.0
for?item,?item_probability?in?zip(_list,?probabilities):
cumulative_probability?+=?item_probability
p?=?item
if?x?<?cumulative_probability:break
return?p
修改mininet/net.py
def?iperfPb?(self,?bw,?period?=?60,?i?=?1,j?=?4,k?=?64,pt?=?0.5,pa?=?0.3):
base_port?=?5001
server_list?=?[]
client_list?=?[]
client_list?=?[h?for?h?in?self.hosts]
cli_outs?=?[]
ser_outs?=?[]
host_list?=?[]
host_list?=?[h?for?h?in?self.hosts]
pc?=?1?-?pt?-?pa
p_list?=?[pt,pa,pc]
_len?=?len(self.hosts)
for?key?in?xrange(_len):
client?=?host_list[key]
access_host?=?[host_list[(key+i)%_len],host_list[(key+j)%_len],host_list[(key+k)%_len]]
server?=?self.random_pick(access_host,p_list)
server_list.append(server)
self.iperf_single(hosts?=?[client,?server],?udpBw=bw,?port=base_port)
sleep(.05)
sleep(period)
print?"test?has?done"
修改mininet/cli.py
def?do_iperfpb(self,?line):
"""Multi?iperf?UDP?test?with?probablity"""
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.iperfPb(udpBw,?float(period))
else:
error('invalid?number?of?args:?iperfmulti?udpBw?period\n'?+
'udpBw?examples:?1M?120\n')
修改bin/mn
在mininet/bin目錄下修改mn文件,將iperfpb加入到對應的列表中。
ALTSPELLING?=?{?'pingall':?'pingAll',
'pingpair':?'pingPair',
'iperfudp':?'iperfUdp',
'iperfUDP':?'iperfUdp',
'iperfpb':'iperfPb'?}
最后,進入mininet/util目錄,重新編譯安裝mininet:
$~/mininet/util/install.sh?-n
重啟mininet,輸入iperf,可用table補全iperfpb,從而可使用iperfpb進行流量的概率模型的測試。
作者簡介:
張歌,2014/09-至今,北京郵電大學網絡技術研究院?網絡與交換技術國家重點實驗室攻讀碩士研究生
本文轉載自SDNLAB