from mininet.topo import Topo from mininet.net import Mininet from mininet.util import dumpNodeConnections from mininet.log import setLogLevel,info from mininet.node import CPULimitedHost from mininet.node import RemoteController from mininet.link import TCLink from mininet.cli import CLI class MyTopo( Topo ): def __init__( self ): "Create custom topo." # initilaize topology Topo.__init__( self ) # add hosts and switches host1 = self.addHost( 'h1' ) host2 = self.addHost( 'h2' ) switch1 = self.addSwitch( 's1' ) switch2 = self.addSwitch( 's2' ) # add links self.addLink(host1,switch1, bw=100) self.addLink(host2,switch2, bw=100) self.addLink(switch1,switch2, bw=50) if __name__=='__main__': setLogLevel('info') info( '*** Creating network\n' ) topo=MyTopo() net=Mininet(topo=topo,controller=None) net.addController('c0',controller=RemoteController,ip='192.168.161.1',port=6653) net.start() CLI(net)
Topo:Mininet基本的拓撲類。
addSwitch():添加一個switch到拓撲中並返回switch名。
addHost():添加一個host到拓撲中並返回host名。
addLink():添加雙向鏈路到拓撲中,在Mininet中鏈路都是雙向的,除非特別注明。
Mininet:主類,用來創建和管理網絡。
start():開始運行網絡。
setLogLevel( 'info' | 'debug' | 'output' ):Mininet設置的默認輸出等級,”info“是推薦的,因為它提供了有用的信息。
from mininet.topo import Topo from mininet.net import Mininet from mininet.node import CPULimitedHost from mininet.link import TCLink from mininet.util import dumpNodeConnections from mininet.log import setLogLevel class SingleSwitchTopo( Topo ): # switch鏈接到n個host def __init__(self, n = 2, **opts): Topo.__init__(self, **opts) switch = self.addSwitch('s1') for h in range(n): # 每個host獲得系統50%/n的CPU占用 host = self.addHost('h%s'%(h+1), cpu=.5/n) # 10Mbps, 5ms的延遲,100%損失,1000包隊列 self.addLink(host, switch, bw = 10, delay = '5ms', loss = 10, max_queue_size = 1000, use_htb = True) def perfTest(): topo = SingleSwitchTopo(n=4) net = Mininet(topo = topo, host = CPULimitedHost, link = TCLink) net.start() print "Dumping host connections" dumpNodeConnections(net.hosts) print "Testing network connectivity" net.pingAll() print "Testing bandwidth between h1 and h4" h1, h4 = net.get('h1', 'h4') net.iperf((h1, h4)) net.stop() if __name__=='__main__': setLogLevel('info') perfTest()
該topo運行結果如下所示:
pingAll():通過各個節點的互相ping來檢測網絡連通性。
stop():結束網絡。
net.hosts:網絡中的所有host。
self.addHost(name, cpu = f):指定小部分整個CPU所分配給host的資源。
self.addLink(node1, node2, bw = 10, delay = '5ms', max_queue_size = 1000, loss = 10, use_htb = True):添加雙向鏈路、延遲和損失特性。bw表示帶寬的數值;delay表示一串計量字符,例如‘5ms',’1s‘;loss表示丟失百分比(數值在0~100之間);max_queue_size表示數據包。
net.get():檢索一個節點(host或switch)對象的名字。
下面詳解一下:
import re from mininet.cli import CLI from mininet.log import setLogLevel, info,error from mininet.net import Mininet from mininet.link import Intf from mininet.topolib import TreeTopo from mininet.util import quietRun from mininet.node import RemoteController, OVSKernelSwitch
re:提供python正則表達式的支持。
CLI:命令行服務的文件。
log:一些日志信息。
net:包含了最重要的類,Mininet類,這是定義一個網絡的類。
class Mininet( object ): "Network emulation with hosts spawned in network namespaces." def __init__( self, topo=None, switch=OVSKernelSwitch, host=Host, controller=Controller, link=Link, intf=Intf, build=True, xterms=False, cleanup=False, ipBase='10.0.0.0/8', inNamespace=False, autoSetMacs=False, autoStaticArp=False, autoPinCpus=False, listenPort=None ):
以上的參數是基本的參數,也是最重要的參數。除了這些數據成員,Mininet類還有一些重要函數如:
def addHost( self, name, cls=None, **params ): def addSwitch( self, name, cls=None, **params ): def addController( self, name='c0', controller=None, **params ): def ping( self, hosts=None, timeout=None ): def addLink( self, node1, node2, port1=None, port2=None, cls=None, **params ):
link:用於定義一個網絡接口。
Tree Topo:支持快速生成一個網絡樹的函數。
class TreeTopo( Topo ): "Topology for a tree network with a given depth and fanout." def __init__( self, depth=1, fanout=2 ):
depth 定義的是樹的深度,fanout是每一層的分支數。 mininet中便捷使用是, --tree(n,m),可以生成n層的m叉樹。
node:RemoteController類定義遠程連接的控制器。
class RemoteController( Controller ): "Controller running outside of Mininet's control." def __init__( self, name, ip='127.0.0.1',port=6633, **kwargs):
默認的控制器是本地控制器。ip =127.0.0.1。注意,你可以自己定義你的控制器的名字。
完整topo解說如下:
if __name__ == "__main__": setLogLevel("info") OVSKernelSwitch.setup() //開啟一個網絡 intfName_1 = "eth2" //將虛擬機eth2賦值給為變量intfName_1 intfName_3 = "eth3" info("****checking****", intfName_1, '\n') checkIntf(intfName_1) //檢查是否可用 info("****checking****", intfName_3, '\n') checkIntf(intfName_3) info("****creating network****\n") net = Mininet(listenPort = 6633) //創建一個Mininet的實例,端口為6633 mycontroller = RemoteController("muziController", ip = "192.168.0.1")//創建遠程控制器,ip=192.168.0.1,端口是6633。 switch_1 = net.addSwitch('s1') //在net里添加交換機s1,mininet中規則為:如果不填充dpid參數,則dpid參數默認取sn的n.即s1的dpid為1。 switch_2 = net.addSwitch('s2') switch_3 = net.addSwitch('s3') switch_4 = net.addSwitch('s4') net.controllers = [mycontroller] //將遠程控制器添加到網絡中 net.addLink(switch_1, switch_2, 2, 1)# node1, node2, port1, port2 net.addLink(switch_2, switch_3, 2, 1)//將s2的2端口跟s3的1端口連接起來。(物理連接) net.addLink(switch_1, switch_4, 3, 1) //需要注意的是,以上連接的鏈路是一個環形的鏈路,在沒有解決風暴的情況下,會出問題。 info("*****Adding hardware interface ", intfName_1, "to switch:" ,switch_1.name, '\n') info("*****Adding hardware interface ", intfName_3, "to switch:" ,switch_3.name, '\n') _intf_1 = Intf(intfName_1, node = switch_1, port = 1)//將intfName_1和s1的端口1相連,形成一個接口_intf_1 _intf_3 = Intf(intfName_3, node = switch_3, port = 2) net.addLink(switch_4, switch_3, 2, 3)//為什么放在這里呢?因為mininet中允許的端口分配方式是從小到大分配,所以,s3的3端口的配置應該放在s3的2端口之后,雖然難看,但是必須這么做,當然你也可以從新分配端口,只要保證端口是從小到大分配就好了。 info("Node: you may need to reconfigure the interfaces for the Mininet hosts:\n", net.hosts, '\n') net.start() //啟動net CLI(net) //等待鍵入命令 net.stop() //關閉net