弈心:從事計算機網絡工作十年(新加坡7年,沙特3年),2013年考取CCIE,在新加坡先後任職于AT&T,新加坡交通部,蘋果,Equinix,蘇格蘭皇家銀行等大型企業、銀行和政府部門。 目前供職于“世界第一土豪大學“沙特阿蔔杜拉國王科技大學(KAUST),擔任Senior Network Engineer,爲KAUST校史上第一位也是唯一一位華人IT部門高級職員。2019年6月在知乎發布了華語圈第一本專門爲編程零基礎的網絡工程師量身打造的Python教程《網絡工程師的Python之路》。
還記得我2013年考下CCIE RS後,在國外一個技術論壇偶然讀到了一篇介紹SDN的文章,作者把SDN寫得神乎其神,中心思想就是:完全靠網絡工程師手動配置和手動排錯,效率低下的傳統網絡遲早有”壽終正寢“的一天,而取而代之的就是能夠帶來”革命性改變“的SDN。的確,IT技術日新月異,當年CCIE RS v1 v2考試大綱裏的那些古董級別的Apple Talk, FDDI, Token Ring, X.25, ATM等等,現在還有幾個人有興趣去花時間理解它們?由此自己開始關注Software Defined Network (軟件定義網絡)。
本篇文章是我2014年自學Mininet時的一些心得和筆記,溫故知新,如今回味起來依然能學到不少東西:
1. SDN和傳統網絡最大的區別在于:SDN具有靈活的軟件編程能力,讓網絡的自動化管理和控制能力獲得空前的提升,能夠有效地解決當前網絡系統所面臨的資源規模擴展受限、組網靈活性差的問題。
2. 傳統網絡設備的Control Plane和Data Plane在SDN中被完全拆開,互不幹涉。
3. SDN的轉發機制不再是Destination-based,而是Flow-based。
4. SDN的Control logic由SDN Controller(類似于現在的IOS之類的命令行操作系統,但運行方式不同)掌控。
5. Openflow, Opendaylight, OpenContrail等都是SDN的一部分。
6. 。。。。。。。。。。。
理論太多,不想贅述,因爲學再多理論也比不過親自動手嘗試,還好最近找到了一款叫做Mininet的東西,這對所有SDN的初學者是一個福音。作爲一個輕量級網絡研究平台,Mininet已經出現很多年了,有志于研究SDN(openflow)的都知道它的來曆和用途,關于Mininet的背景就不多做介紹了。下面是自己使用Mininet時做的一些筆記:
安裝Mininet的步驟:
1. 下載Mininet(版本2.1.0)的鏡像文件 (https://github.com/mininet/mininet/wiki/Mininet-VM-Images),這是一個基于Ubuntu的虛擬機文件。
2. 用VMware或者Virtual Box打開
Mininet使用筆記:
1. 學習Mininet之前,最好將Mininet官方的Walkthrough過一遍(http://mininet.org/walkthrough/)
2. sudo mn命令將創建一個最簡單的拓撲,包括一個SDN Controller (c0),一個交換機 (s1),兩台主機 (h1和h2)
3. Mininet幾個比較重要的選項和參數總結如下:
–topo= 這個是Mininet創建的虛擬網絡的拓撲,有4種類型:
minimal – 即上面提到的sudo mn命令,包括一個SDN Controller (c0),一個交換機 (s1),兩台主機 (h1和h2)
single,X – 一個交換機,下面直連X個主機(自已定義)
linear,X – 創建X個環狀鏈路的交換機,每個交換機下面直連一個主機
tree,X – 樹狀型拓撲,有X個fanout
–switch= 創建不同類型的交換機
ovsk – Mininet默認自帶的Open vSwitch,已經預裝在VM裏面
user – 比ovsk慢很多,不推薦使用
–controller= 即SDN Controller,三個參數
ovsc – Mininet默認自帶的OVS Controller,已經預裝在VM裏面
nox – 顧名思義,NOX controller
remote – 不創建Controller,嘗試連接外部Controller
–mac 創建自定義的MAC地址
來做個實驗具體說明,首先創建一個交換機,3個主機,無Controller的拓撲。
命令: Sudo mn –topo=single,3 –mac –controller=remote
在SDN中,交換機是沒有Control Plane的,也就是說它僅是一個純粹的轉發設備, 並且這種”無腦型“的Openflow交換機只有在收到SDN controller的指示後,才能做出轉發決定。遇到未知traffic時,Openflow交換機只會做一件事:就是把它們轉發給SDN controller,自己什麽也不管。這大大降低了習慣在傳統網絡的交換機中做各種2層排錯的網工們的工作量。
既然Controller是SDN網絡的大腦,那麽創建一個沒有controller的SDN拓撲還能玩嗎?當然可以,這裏要用到dptcl這個工具,dptcl的作用是可以跳過controller,直接通過TCP 6634這個端口來控制和查看openflow交換機的flow table(記住SDN網絡的轉發機制是flow-based,不是destination-based),不過dptcl和SDN controller是完全不同的兩種東西,不能劃等號,這點切記。
DPTCL的命令格式:
dptcl [show/dump-flows/add-flow] tcp:127.0.0.1:6634
最終實驗拓撲如下:
具體配置和驗證命令:
1. 開啓Wireshark,讓它在後台運行
mininet@mininet-vm:~$ sudo wireshark
2. 創建一個交換機(ovsk類型),3個主機,無Controller的SDN網絡
mininet@mininet-vm:~$ sudo mn –topo=single,3 –mac –switch=ovsk –controller=remote*** Creating network*** Adding controllerUnable to contact the remote controller at 127.0.0.1:6633 //無controller的拓撲*** Adding hosts:h1 h2 h3*** Adding switches:s1*** Adding links:(h1, s1) (h2, s1) (h3, s1)*** Configuring hostsh1 h2 h3*** Starting controller*** Starting 1 switchess1*** Starting CLI:mininet>
3. 查看網絡節點
mininet> nodesavailable nodes are:c0 h1 h2 h3 s1mininet>
4. 查看物理拓撲
mininet> neth1 h1-eth0:s1-eth1h2 h2-eth0:s1-eth2h3 h3-eth0:s1-eth3s1 lo: s1-eth1:h1-eth0 s1-eth2:h2-eth0 s1-eth3:h3-eth0c0mininet>
5. 查看各個節點的信息
mininet> dump<Host h1: h1-eth0:10.0.0.1 pid=9730><Host h2: h2-eth0:10.0.0.2 pid=9731><Host h3: h3-eth0:10.0.0.3 pid=9732><OVSSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=9735><RemoteController c0: 127.0.0.1:6633 pid=9723>mininet>
驗證SDN交換機工作原理
Scenario #1 (SDN交換機flow table爲空)
1. 首先在三個主機(h1,h2,h3)上開啓Xterm (Windows用戶需要安裝Xming,並在putty裏開啓X-forwarding)
mininet> xterm h1 h2 h3
2. 用dpctl查看交換機當前的flow table信息 (由于還沒有手動添加flow entry,該flow table爲空)
mininet> dpctl dump-flows*** s1 ——————————————–NXST_FLOW reply (xid=0x4):
3. 在h1上ping h2,在h2上用tcpdump抓包,查看結果
結論: Ping失敗,h2上沒有收到任何ICMP echo request packet.
原因: 拓撲裏沒有SDN controller,我們也沒有用dptcl給openflow交換機添加任何flow entry, 所以交換機不會做轉發決定,並直接丟棄h1到h2的ping包。
Scenario #2 (爲SDN交換機添加flow entry)
1. 用dpctl給SDN交換機添加雙向的flow entry, 因爲ping包除了echo request還有echo reply
mininet@mininet-vm:~$ dpctl add-flow tcp:127.0.0.1:6634 in_port=1,actions=output:2mininet@mininet-vm:~$ dpctl add-flow tcp:127.0.0.1:6634 in_port=2,actions=output:1
2. 查看SDN交換機的flow table,兩條flow entry添加成功。
mininet> dpctl dump-flows*** s1 ——————————————–NXST_FLOW reply (xid=0x4):cookie=0x0, duration=27,213s, table=0, n_packets=5, n_bytes=378, idle_timeout=60, idle_age=7, in_port=1 actions=output:2cookie=0x0, duration=27,213s, table=0, n_packets=5, n_bytes=378, idle_timeout=60, idle_age=7, in_port=2 actions=output:1
3. 在h1上ping h2,在h2和h3上用tcpdump抓包,查看結果
結論:h1成功ping到h2,並且h3沒收到任何ping包。
其他一些常用dpctl命令及功能 (拓撲同上)
1. 關閉或開啓openflow交換機的端口(等于對一個端口shutdown / no shutdown)
dpctl mod-port [port num] up/down
2. 關閉交換機的端口1(下接h1),
mininet> dpctl mod-port 1 down
關閉端口1後再來h1 ping h2,結果當然fail
*** s1 ————————————————————————mininet> h1 ping h2PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.— 10.0.0.2 ping statistics —3 packets transmitted, 0 received, 100% packet loss, time 2000ms
3. 開啓交換機的端口1
mininet> dpctl mod-port 1 up
ping成功
*** s1 ————————————————————————mininet> h1 ping -c 2 h2PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=8.37 ms64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=1.02 ms— 10.0.0.2 ping statistics —2 packets transmitted, 2 received, 0% packet loss, time 1002msrtt min/avg/max/mdev = 1.026/4.698/8.370/3.672 ms
4. 查看端口的統計信息,包括Tx,Rx counters, bytes以及Error counters等等
mininet> dpctl dump-ports*** s1 ————————————————————————OFPST_PORT reply (xid=0x2): 4 portsport 3: rx pkts=7, bytes=558, drop=0, errs=0, frame=0, over=0, crc=0 tx pkts=0, bytes=0, drop=0, errs=0, coll=0port 1: rx pkts=32, bytes=2076, drop=0, errs=0, frame=0, over=0, crc=0 tx pkts=14, bytes=1092, drop=0, errs=0, coll=0port 2: rx pkts=33, bytes=2154, drop=0, errs=0, frame=0, over=0, crc=0 tx pkts=26, bytes=1596, drop=0, errs=0, coll=0port LOCAL: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0 tx pkts=0, bytes=0, drop=0, errs=0, coll=0
5. 查看端口的一層和二層信息
mininet> dpctl show*** s1 ————————————————————————OFPT_FEATURES_REPLY (xid=0x2): dpid:0000000000000001n_tables:254, n_buffers:256capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IPactions: OUTPUT SET_VLAN_VID SET_VLAN_PCP STRIP_VLAN SET_DL_SRC SET_DL_DST SET_NW_SRC SET_NW_DST SET_NW_TOS SET_TP_SRC SET_TP_DST ENQUEUE1(s1-eth1): addr:66:9a:a3:e0:64:8fconfig: 0state: 0current: 10GB-FD COPPERspeed: 10000 Mbps now, 0 Mbps max2(s1-eth2): addr:26:bb:36:e0:99:4econfig: 0state: 0current: 10GB-FD COPPERspeed: 10000 Mbps now, 0 Mbps max3(s1-eth3): addr:76:c9:ca:0e:92:4bconfig: 0state: 0current: 10GB-FD COPPERspeed: 10000 Mbps now, 0 Mbps maxLOCAL(s1): addr:fe:3f:bf:f6:26:42config: 0state: 0speed: 0 Mbps now, 0 Mbps maxOFPT_GET_CONFIG_REPLY (xid=0x4): frags=normal miss_send_len=0
開篇時曾提到:默認情況下,SDN交換機的flow table爲空,在沒有controller的情況下,可以使用dpctl來查詢和管理交換機的flow table,之前的實驗裏我用dpctl給交換機加了兩個flow,讓h1可以ping通h2。兩條命令如下:
dpctl add-flow in_port=1,actions=output:2dpctl add-flow in_port=2,actions=output:1
第一條命令的意思是:用dpctl對交換機添加flow,讓交換機從s1-eth1這個端口接收到的所有traffic都從s1-eth2這個端口發出去。
第二條命令的意思是:用dpctl對交換機添加flow,讓交換機從s1-eth2這個端口接收到的所有traffic都從s1-eth1這個端口發出去。(這裏重點強調“所有traffic”,原因後面解釋)
添加這兩條flow後,h1能夠ping通h2.
mininet> h1 ping h2PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=3.80 ms64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.915 ms64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=1.50 ms^C— 10.0.0.2 ping statistics —3 packets transmitted, 3 received, 0% packet loss, time 2005msrtt min/avg/max/mdev = 0.915/2.073/3.805/1.248 ms
除了這種匹配所有traffic的方法外,dpctl還允許自定義更詳細的traffic類型,比如ARP,IPv4, IPv6, MPLS等等,用dpctl的命令來匹配這些traffic不難,關鍵是要弄懂交換機是怎樣識別它收到的traffci是屬于哪種類型的,從而參照自己的flowtable然後對該traffic進行轉發。要弄懂這點,就必須了解EtherType(以太網類型字段)這個東西,首先來回顧一下二層幀(frame)的結構:
如圖,我已經把EtherType標記出來了,它就在Source MAC字段的後面。
根據IEEE 802.3定義,EtherType字段長度爲2Byte,它的作用是用來指明應用于Payload這個字段裏的是什麽協議,它的起始值是0x0800,指代的是IPv4這個協議,常見的EtherType數值和所對應的協議如下:
0x0800 = IPv4
0x0806 = ARP
0x86DD = IPv6
0x8847 = MPLS (unicast)
0x8848 = MPLS (multicast)
在dpctl裏面,我們使用dl_type來指代EtherType,下面來做個試驗,具體說明一下怎麽在dpctl裏面根據EtherType來自定義traffic的協議類型。
首先把之前添加的兩條匹配所有traffic的flow拿掉,這裏用dpctl del-flows這個命令,刪除後用dpctl dump-flows驗證,確保交換機flow table爲空。
mininet> dpctl del-flows*** s1 ————————————————————————mininet> dpctl dump-flows*** s1 ————————————————————————NXST_FLOW reply (xid=0x4):
然後用dpctl給交換機添加兩條traffic類型爲IPv4的flow,命令如下:
dpctl add-flow dl_type=0x0800,nw_dst=10.0.0.2,actions=output:2dpctl add-flow dl_type=0x0800,nw_dst=10.0.0.1,actions=output:1
第一條命令的意思是:用dpctl對交換機添加flow,讓交換機把所有EtherType爲0x0800(IPv4)並且destiation IP爲10.0.0.2的traffic從s1-eth2這個端口發出去。
第二條命令的意思是:用dpctl對交換機添加flow,讓交換機把所有EtherType爲0x0800(IPv4)並且destiation IP爲10.0.0.1的traffic從s1-eth1這個端口發出去。
添加完後驗證一下交換機的flow table:
mininet> dpctl dump-flows*** s1 ————————————————————————NXST_FLOW reply (xid=0x4):cookie=0x0, duration=477.255s, table=0, n_packets=0, n_bytes=0, idle_age=477, ip,nw_dst=10.0.0.2 actions=output:2cookie=0x0, duration=469.45s, table=0, n_packets=0, n_bytes=0, idle_age=469, ip,nw_dst=10.0.0.1 actions=output:1
然後再次嘗試h1是否能ping通h2
mininet> h1 ping -c 3 h2PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.— 10.0.0.2 ping statistics —3 packets transmitted, 0 received, 100% packet loss, time 2013ms
結論:Ping失敗!
原因:衆所周知,處在同一網段下的host,它們之間的交流是L2 forwarding,是要靠ARP來解析MAC地址的,之前我們只匹配了0x0800 (IPv4) 這個協議,並沒有匹配到0x0806(ARP),這樣當交換機收到h1的ARP包後,因爲沒有controller,flow table裏面也沒有相應的flow告訴它如何轉發這個ARP包,交換機只能將它丟棄,從而導致h1 ping h2失敗。
添加ARP的dpctl命令如下:
dpctl add-flow dl_type=0x0806,actions=NORMAL
這條命令的意思是:用dpctl對交換機添加flow,讓交換機以NORMAL形式(即廣播)將所有ARP包從各個端口廣播出去。
老規矩,添加完flow後,馬上驗證flow table
mininet> dpctl dump-flows
*** s1 ————————————————————————NXST_FLOW reply (xid=0x4):cookie=0x0, duration=1288.291s, table=0, n_packets=22, n_bytes=2156, idle_age=703, ip,nw_dst=10.0.0.2 actions=output:2cookie=0x0, duration=1280.486s, table=0, n_packets=8, n_bytes=784, idle_age=727, ip,nw_dst=10.0.0.1 actions=output:1cookie=0x0, duration=8.772s, table=0, n_packets=0, n_bytes=0, idle_age=8, arp actions=NORMAL
再次嘗試h1是否能ping通h2
mininet> h1 ping -c 3 h2PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=6.34 ms64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.991 ms64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=1.08 ms— 10.0.0.2 ping statistics —3 packets transmitted, 3 received, 0% packet loss, time 2006msrtt min/avg/max/mdev = 0.991/2.807/6.345/2.502 ms
結論:IP和ARP的flow都添加完畢後,h1 ping h2成功!
用WIRESHARK抓包,靠實戰理解openflow交換機和Controller之間的工作原理。
1. 首先創建一個最簡單的拓撲,1個Controller, 1個交換機,2台HOST
mininet@mininet-vm:~$ sudo mn*** Creating network*** Adding controller*** Adding hosts:h1 h2*** Adding switches:s1*** Adding links:(h1, s1) (h2, s1)*** Configuring hostsh1 h2*** Starting controller*** Starting 1 switchess1*** Starting CLI:mininet>
2. 重開一個putty窗口(記住enable X forwarding),ssh進入VM後開啓wireshark
mininet@mininet-vm:~$ sudo wireshark &
3. Wireshark啓動後,Interface List選lo0 (127.0.0.1),然後點Start,如下圖
4.回到第一個putty窗口 (mininet>)下,用pingall命令來讓h1(10.0.0.1)和h2(10.0.0.2)互相ping對方,因爲這次的實驗拓撲已經有了一台controller,所以無需再用dpctl來手動對交換機添加flow,h1已經可以直接ping通h2了。
mininet> pingall*** Ping: testing ping reachabilityh1 -> h2h2 -> h1*** Results: 0% dropped (2/2 received)
5. 回到Wireshark,這個時候應該capture到了很多TCP包,先不管它們,在Filter裏輸入of進行過濾,目的是爲了抓到OFP (即Openflow Protocol)的包,如下圖:
6. 點開第一個包,即Echo Request (SM)(8B)這個包,如下圖:
從這個包裏可以看出的信息是:
a.這個Echo Request是openflow交換機(127.0.0.1:60497) 發給Controller (127.0.0.1:6633)的,之間已經提到過,dpctl是靠TCP 6634這個端口來控制交換機的,而Controller則是用TCP 6633這個端口來控制交換機,而爲了監控交換機和Controller之間的connectivity,交換機會不間斷地向Controller發出Echo Request (注意這個不是ICMP的Echo Request),Controller收到Echo Request包後會向交換機返回一個Echo Reply包。
b. 點開最下面的Openflow Protocol(就不截圖了),可以看到OFP的一些基本信息,比如version爲0x01,Type爲Echo Request (SM) (2),Length爲8等等等。
7. 看完交換機和Echo Request和Echo Reply包後,接下來來看剛才用pingall命令,讓h1 (10.0.0.1)和(10.0.0.2)互ping後出現的包。
如上圖,在我抓的包裏面:
a. 把序號爲436,437,439,440的包分爲一組,這一組是10.0.0.1 ping 10.0.0.2的Ping Echo Request以及Ping Echo Reply的包。
b. 把序號爲441,442,443,444的包分爲一組,這一組是10.0.0.2 ping 10.0.0.1的Ping Echo Request以及Ping Echo Reply的包。
8. 點開436這個包,如下圖:
這裏你會感到奇怪,爲什麽剛才在第7步裏看到的該包,Source爲10.0.0.1,Destination爲10.0.0.2,爲什麽點開該包後,裏面的內容卻是Source127.0.0.1:60497(交換機), Destination 127.0.0.1:6633(Controller)?要回答這個問題,就需要回到第7步去看436這個包的Protocol,你會發現它已不再是我們在傳統網絡裏理解的那個單獨的ICMP包了,在SDN裏,它已經變成了OFP+ICMP包。對這個OFP+ICMP包應該這樣理解:當10.0.0.1 ping 10.0.0.2的時候,“無腦”的交換機(127.0.0.1:60497) 因爲不知道怎麽轉發這個ICMP包,它唯一能做的就是用OFP包將這個ICMP包封裝,將它轉發給Controller (127.0.0.1:6633) 做決定,而這個由交換機重新封裝後的ICMP包就叫做OFP+ICMP包。
9. 點開437這個包, 如下圖:
這個包是接436這個包的,它是由Controller收到交換機發給它的OFP+ICMP後,Controller再返回給一個OFP包給交換機,所以它的Source127.0.0.1:6634,Destination127.0.0.1:60497。這裏需要重點關注的是該包OpenFlow Protocol裏面的內容。如圖,依次點開OpenFlow Protocol>Output Actions(s)>Action,這裏可以看到Output port:2 ,顧名思義,它的意思就是說:Controller現在告訴交換機,“關于這個10.0.0.1 ping 10.0.0.2的ICMP包,你把它從s1-eth2這個端口發出去”,這樣h1 (10.0.0.1)的Ping echo request包就能到達h2 (10.0.0.2)了,因爲h2就是直連在s1-eth2這個端口下的。
10. 後面的438-444就無需多解釋了,有網絡基礎的都懂,它們和436還有437這兩個包其實都是一個原理,只是source和destination不同。
要把SDN學精,學會寫代碼是必不可少的。整個Mininet的架構基本是用Python 2.0寫出來的(注意不是3.0,前後兩者差別很大),而自己的Python水平大概還停留在入門階段。任重道遠,下面是自己總結的Mininet中常見的一些Class, Methods, Functions還有Variables:
Topo: 用來創建拓撲,Mininet API中最基本的Class
addSwitch(): 在拓撲中創建一個switch,並返回switch name。
addHost(): 在拓撲中創建一個host,並返回host name。
addLink(): 在拓撲中創建一個雙向的link,並返回link key,默認情況下link都是雙向的(bidirectional)。
Mininet: 用來創建和管理一個拓撲的Main Class。
start(): 啓動網絡
pingAll():所有host相互ping對方,用來測試網絡連接性
stop(): 關閉網絡
net.hosts: 表示拓撲內所有的host
dumpNodeConnections(): 顯示指定節點(Node)的connection
setLogLevel( ‘info’ | ‘debug’ | ‘output’ ): 設定Mininet默認的ouput level,一般用info。
舉個簡單的例子,用python寫一個單交換機,下接N個host的拓撲的代碼:
#!/usr/bin/pythonfrom mininet.topo import Topofrom mininet.net import Mininetfrom mininet.util import dumpNodeConnectionsfrom mininet.log import setLogLevel
# 用from import導入python的模塊
class SingleSwitchTopo(Topo):def __init__(self, n=2, **opts)Topo.__init__(self, **opts) # 初始化拓撲以及默認的optionswitch = self.addSwitch(‘s1’) # 添加一個名爲s1的交換機for h in range(n):host = self.addHost(‘h%s’ % (h + 1)) #添加主機self.addLink(host, switch) #添加雙向連接def simpleTest():topo = SingleSwitchTopo(n=4)net = Mininet(topo) #用Main Class來創建拓撲net.start() #啓動網絡print “Dumping host connections”dumpNodeConnections(net.hosts) #顯示拓撲內所有節點(host)的connection信息print “Testing network connectivity”net.pingAll() #所有host相互ping對方,用來測試網絡連接性net.stop()if __name__ == ‘__main__’:setLogLevel(‘info’) # 設置 Mininet 默認輸出級別爲infosimpleTest()
驗證:
# python test-single.py*** Creating network*** Adding controller*** Adding hosts:h1 h2 h3 h4*** Adding switches:s1*** Adding links:(h1, s1) (h2, s1) (h3, s1) (h4, s1)*** Configuring hostsh1 h2 h3 h4*** Starting controller*** Starting 1 switchess1Dumping host connectionsh1 h1-eth0:s1-eth1h2 h2-eth0:s1-eth2h3 h3-eth0:s1-eth3h4 h4-eth0:s1-eth4Testing network connectivity*** Ping: testing ping reachabilityh1 -> h2 h3 h4h2 -> h1 h3 h4h3 -> h1 h2 h4h4 -> h1 h2 h3*** Results: 0% dropped (12/12 received)