編者按:在網絡性能評估中一個巨大的挑戰就是如何生成真實的網絡流量,還好可以通過程式來創造人工的網絡流量,通過建立測試環境來模拟真實的狀況。本文就以資料中心網絡為目标場景,來在mininet仿真環境中盡可能地還原資料中心内部的真實流量情況。目前有兩種常用的流量模型:
随機模型:主機向在網絡中的另一任意主機以等機率發送資料包
機率模型:在網絡中,編号為m的主機分别以機率pt 、pa 、pc 、向主機編号為(m+i)、(m+j)、(m+k)的主機發送資料包

data center two model in mininet realized
我們使用mininet中的iperf工具在網絡中生成udp流量,iperf用戶端傳送資料流到iperf的服務端,由服務端接收并記錄相關信 息。mininet自帶控制台可供使用的指令雖然已經比較豐富,但卻并未給出較為明确的api接口來支援使用者自定義指令。在諸如資料中心這樣複雜、網絡節 點較多的仿真環境中做一些批處理的工作就需要非常大的,比如通過iperf在所有主機之間發生流量。是以我們需要将自定義指令添加到mininet中,在 mininet中完成新指令的拓展。
<a target="_blank"></a>
在mininet中進行功能拓展主要分為3步:
1. 修改mininet/net.py: net子產品實作mininet類,是仿真平台mininet的主體類,該類完成節點添加配置、網絡基本功能和一些選項功能的實作。我們需要将我們自定義的函數定義在該類中。
<code>class mininet(object): def function(self,**kwargs): #function code</code>
2. 修改mininet/cli.py: cli子產品定義了cli類,為米你呢他提供指令行接口,用于解析使用者輸入的指令,之前定義的自定義指令需要在cli類中通過注冊函數注冊這條自定義指令。
<code>class cli(cmd): def do_function(self,line): #do_function code</code>
完成指令注冊與綁定。
3. 修改bin/mn: 在完成指令注冊與綁定後,需要在mininet執行解釋器中注冊指令與對應執行函數的映射關系。
<code>altspelling = {'pingall':'pingall', 'pingpair':'pingpair', 'iperfudp':'iperfudp', 'function':'function'}</code>
net.py和cli.py均在mininet/mininet目錄,mn檔案在在mininet/bin目錄中。在代碼修改完成後需要重新編譯安裝一遍mininet,即運作:
<code>$~/mininet/util/install.sh -n</code>
二、 兩種流量模型在mininet中的實作
任意一台主機以等機率随機地向另外一台主機發起一條udp資料流。
首先,先在兩個主機之間進行iperf測試,并且在server端記錄,實作iperf_single函數:
<code>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 +'&')</code>
着為mininet添加自定義指令iperfmulti,依次為每一台主機随機選擇另一台主機作為iperf的伺服器端,通過調用 iperf_single,自身以用戶端身份按照指定參數發送udp流,伺服器生成的報告以重定向的方式輸出到檔案中,使用iperfmulti指令,主 機随機地向另一台主機發起一條恒定帶寬的udp資料流。
<code>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"</code>
修改mininet/cli.py
<code>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')</code>
修改bin/mn
在mininet/bin目錄下修改mn檔案,将iperfpb加入到對應的清單中。
<code>altspelling = { 'pingall': 'pingall', 'pingpair': 'pingpair', 'iperfudp': 'iperfudp', 'iperfudp': 'iperfudp', 'iperfpb':'iperfpb' }</code>
最後,進入mininet/util目錄,重新編譯安裝mininet
重新開機mininet,輸入iperf,可用table補全iperfpb,進而可使用iperfpb進行流量随機模型的測試。
為mininet添加自定義指令iperfpb,依次為每一台主機(編号為m)分别以機率pt 、pa 、pc 向主機編号為(m+i)、(m+j)、(m+k)的主機發送資料包,通過調用iperf_single,自身以用戶端身份按照指定參數發送udp流,服務 器生成的報告以重定向的方式輸出到檔案中,使用iperfpb指令,主機按機率向其他被選擇的主機發起一條恒定帶寬的udp資料流。
為完成以一定機率選擇主機,我們需要實作一個機率選擇函數randompick,這個函數可用于以不同的機率從一個清單中随機地選擇一些元素。下面為randompick的實作過程:
<code>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</code>
修改mininet/net.py
<code>base_port = 5001</code>
<code>server_list = []</code>
<code>client_list = []</code>
<code>client_list = [h for h in self.hosts]</code>
<code>cli_outs = []</code>
<code>ser_outs = []</code>
<code>host_list = []</code>
<code>host_list = [h for h in self.hosts]</code>
<code>pc = 1 - pt - pa</code>
<code>p_list = [pt,pa,pc]</code>
<code>_len = len(self.hosts)</code>
<code>for key in xrange(_len):</code>
<code>client = host_list[key]</code>
<code>access_host = [host_list[(key+i)%_len],host_list[(key+j)%_len],host_list[(key+k)%_len]]</code>
<code>server = self.random_pick(access_host,p_list)</code>
<code>server_list.append(server)</code>
<code>self.iperf_single(hosts = [client, server], udpbw=bw, port=base_port)</code>
<code>sleep(.05)</code>
<code>sleep(period)</code>
<code>print "test has done"</code>
<code>def do_iperfpb(self, line): """multi iperf udp test with probablity"""</code>
<code>args = line.split()</code>
<code>if len(args) == 1:</code>
<code>udpbw = args[ 0 ]</code>
<code>self.mn.iperfmulti(udpbw)</code>
<code>elif len(args) == 2:</code>
<code>period = args[ 1 ]</code>
<code>err = false</code>
<code>self.mn.iperfpb(udpbw, float(period))</code>
<code>else:</code>
<code>error('invalid number of args: iperfmulti udpbw period\n' +</code>
<code>'udpbw examples: 1m 120\n')</code>
<code>altspelling = { 'pingall': 'pingall',</code>
<code>'pingpair': 'pingpair',</code>
<code>'iperfudp': 'iperfudp',</code>
最後,進入mininet/util目錄,重新編譯安裝mininet:
重新開機mininet,輸入iperf,可用table補全iperfpb,進而可使用iperfpb進行流量的機率模型的測試。
原文釋出時間:2015-04-30
本文來自雲栖合作夥伴“linux中國”