Atom Login Admin

Above the clouds

Mininetの使い方について(1)

Mininet 2.0 Introduction(1)

概要

Mininetとは、ネットワークエミュレータで、一つのLinux カーネル上で、複数のホスト、スイッチ、ルーターを組み合わせて仮想的にネットワークを構築することができる。
Mininet上のホストは実際のホスト同様にSSHで接続でき、実際に任意のプログラムを実行できたりする。
また、Ethernetインターフェース、スイッチ、ルーター、キューイングなどを用いて、
本物のような遅延やリンクスピードでパケットを送信できる。
2つのプログラムが、iperfのクライアントとサーバのように、Mininetを介して通信する場合、測定された性能は、2つ(遅い)ネイティブマシンに一致させる必要がある。

なぜMininetが良いか?

1.早い。シンプルなネットワークなら数秒で構築できる。すなわち修正、デバッグが素早くできる。
2.任意のトポロジを作ることができる。例えば、大規模なネットワーク、スタンフォードバックボーン、データセンターなど。
3.本物のプログラムを実行できる。Webサーバーや、TCPモニタリングツール、Wiresharkなど、Linuxマシンで動くプログラムであれば何でも実行できる。
4.任意のパケット操作ができる。MininetのスイッチはOpenFlowプロトコルを使っている。
よって、Mininetでは実機のOpenFlowスイッチへのline-rateパケット転送などの任意のSDNの設計を簡単にできる。
5.Mininetはlaptop、サーバー上、VM、Linux、クラウド上で動作することができる。
6.結果を共有できる。Mininetのプログラミングコードを共有することができるので、だれでも実行できる。
7.簡単に使える。PythonのスクリプトでMininetは構築できる。
8.Mininetはオープンソース。試験やなどをして、改修、機能要望などを報告できる。
9.Mininetは開発中。mininet-disucusで開発者とコミュニケーションが取れる。要望やパッチなどを受け付けてくれる。

Mininetの制限事項

・一つのシステムで動作させるのは便利だが、リソースの限りがある。例えば、3GHzのCPUで、およそ3Gbpsのスイッチのトラフィックをシュミレーションすると、仮想ホスト、スイッチのリソースを公平に共有する必要がある。
・Linux上でしか動かない。
・Mininetは任意のOpenFlowコントローラを書き込みまない​​、ルーティングまたはスイッチングのカスタムが必要な場合は、必要とする機能を持つコントローラを見つけたり、開発する必要がある。
・直近のMininetは外部へのNATを行わない。仮想ホストはLANから分離されている為で、時にこれは良いが、直接インターネット接続を行うように仕向けない限りできない。
・直近のMininetのホストはPIDスペースとファイルシステムを共有している。よってミスによって実行中のデーモンや設定を削除しないように気をつけなくてはならない
・シュミレーターではない。Mininetは仮想時間の強力な概念を持っていないが、これはタイミング測定を、即座に基づいてされることを意味し、それよりも速いリアルタイム結果(例えば100 Gbpsのネットワーク)を簡単にエミュレートできない。

Working with Mininet

トポロジを作る

Mininetはパラメタ化したトポロジーを数行のPythonコードで構築できる。
パラメタを渡してあげることにより、トポロジの再利用や、パラメタによる動的なトポロジを構築できる。

例えば、シンプルなネットワークトポロジで、一つのスイッチ(s1)に複数のホスト(h1 hN)が接続されている
構成となっている。

#!/usr/bin/python

from mininet.topo import Topo
from mininet.net import Mininet
from mininet.util import dumpNodeConnections
from mininet.log import setLogLevel

class SingleSwitchTopo(Topo):
    "Single switch connected to n hosts."
    def __init__(self, n=2, **opts):
        # Initialize topology and default options
        Topo.__init__(self, **opts)
        switch = self.addSwitch('s1')
        # Python's range(N) generates 0..N-1
        for h in range(n):
            host = self.addHost('h%s' % (h + 1))
            self.addLink(host, switch)

def simpleTest():
    "Create and test a simple network"
    topo = SingleSwitchTopo(n=4)
    net = Mininet(topo)
    net.start()
    print "Dumping host connections"
    dumpNodeConnections(net.hosts)
    print "Testing network connectivity"
    net.pingAll()
    net.stop()

if __name__ == '__main__':
    # Tell mininet to print useful information
    setLogLevel('info')
    simpleTest()
*** Creating network
*** Adding controller
*** Adding hosts:
h1 h2 h3 h4 
*** Adding switches:
s1 
*** Adding links:
(h1, s1) (h2, s1) (h3, s1) (h4, s1) 
*** Configuring hosts
h1 h2 h3 h4 
*** Starting controller
*** Starting 1 switches
s1 
Dumping host connections
h1 h1-eth0:s1-eth1
h2 h2-eth0:s1-eth2
h3 h3-eth0:s1-eth3
h4 h4-eth0:s1-eth4
Testing network connectivity
*** Ping: testing ping reachability
h1 -> h2 h3 h4 
h2 -> h1 h3 h4 
h3 -> h1 h2 h4 
h4 -> h1 h2 h3 
*** Results: 0% dropped (0/12 lost)
*** Stopping 4 hosts
h1 h2 h3 h4 
*** Stopping 1 switches
s1 .....
*** Stopping 1 controllers
c0 
*** Done

重要なクラス、メソッド、ファンクション、値は上記にも含まれている。
Topo:Mininetトポロジのベースクラス
addSwitch():トポロジへスイッチを追加し、スイッチの名前が返却される。
addHost():トポロジへホストを追加し、ホストの名前が返却される。
addLink():トポロジへ双方向のリンクを追加する。Mininetのリンクは双方向で他に注意は必要ない
Mininet:ネットワークを構築、管理するメインクラス
start():ネットワークの開始
pingAll():pingをお互い送信し、接続を確認する。
stop():ネットワークを停止する/
net.hosts:ネットワーク上の全てのホスト
dumpNodeConnections():各ノードのto/Fromセットをダンプする。
setLogLevel( 'info' | 'debug' | 'output' ):ログレベルを設定する。

他にもmininet/examplesにコードが同封されている。

パフォーマンスパラメータを設定する。

更に、CPULimitedHostやTCLinkクラスを用いて、Mininetが提供するパフォーマンスの制限や、分離などのネットワークの振る舞いを設定する。
多様に方法はあるが、簡単な方法は、Mininet()のコンストラクタにデフォルトホスト、スイッチを指定し、適当なパラメータをトポロジへ設定することである。

#!/usr/bin/python

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):
    "Single switch connected to n hosts."
    def __init__(self, n=2, **opts):
        Topo.__init__(self, **opts)
        switch = self.addSwitch('s1')
        for h in range(n):
            # Each host gets 50%/n of system CPU
            host = self.addHost('h%s' % (h + 1),
               cpu=.5/n)
            # 10 Mbps, 5ms delay, 10% loss, 1000 packet queue
            self.addLink(host, switch,
               bw=10, delay='5ms', loss=10, max_queue_size=1000, use_htb=True)

def perfTest():
    "Create network and run simple performance test"
    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()
*** Creating network
*** Adding controller
*** Adding hosts:
h1 h2 h3 h4 
*** Adding switches:
s1 
*** Adding links:
(10.00Mbit 5ms delay 10% loss) (10.00Mbit 5ms delay 10% loss) (h1, s1) (10.00Mbit 5ms delay 10% loss) (10.00Mbit 5ms delay 10% loss) (h2, s1) (10.00Mbit 5ms delay 10% loss) (10.00Mbit 5ms delay 10% loss) (h3, s1) (10.00Mbit 5ms delay 10% loss) (10.00Mbit 5ms delay 10% loss) (h4, s1) 
*** Configuring hosts
h1 (cfs 12500/100000us) h2 (cfs 12500/100000us) h3 (cfs 12500/100000us) h4 (cfs 12500/100000us) 
*** Starting controller
*** Starting 1 switches
s1 (10.00Mbit 5ms delay 10% loss) (10.00Mbit 5ms delay 10% loss) (10.00Mbit 5ms delay 10% loss) (10.00Mbit 5ms delay 10% loss) 
Dumping host connections
h1 h1-eth0:s1-eth1
h2 h2-eth0:s1-eth2
h3 h3-eth0:s1-eth3
h4 h4-eth0:s1-eth4
Testing network connectivity
*** Ping: testing ping reachability
h1 -> h2 h3 h4 
h2 -> h1 X X 
h3 -> h1 h2 X 
h4 -> h1 X h3 
*** Results: 33% dropped (4/12 lost)
Testing bandwidth between h1 and h4
*** Iperf: testing TCP bandwidth between h1 and h4
waiting for iperf to start up...*** Results: ['49.3 Kbits/sec', '67.8 Kbits/sec']
*** Stopping 4 hosts
h1 h2 h3 h4 
*** Stopping 1 switches
s1 .....
*** Stopping 1 controllers
c0 
*** Done

重要なメソッドとパラメータは、

self.addHost(name, cpu=f):

これは、仮想ホストへ割り当てる、CPUリソースの割合を指定できる。

self.self.addLink( node1, node2, bw=10, delay='5ms', max_queue_size=1000, loss=10, use_htb=True):

これは、双方向リンクの帯域、遅延、ロスを設定し、
Hierarchical Token Bucket rate limiterとnetem遅延・ロスのエミュレータを使って、最大1000パケットのキューに制限している。パラメータのbeはMb/sを表していて、delayは、'5ms','100us'のような文字列を指定し、lossはパーセンテージ、max_queue_sizeはパケットの量を指定する。

下記のように便利なPythonコードを使う事もできる。

linkopts = dict(bw=10, delay='5ms', loss=10, max_queue_size=1000, use_htb=True)
# alternately: linkopts = {'bw':10, 'delay':'5ms', 'loss':10,
# max_queue_size=1000, 'use_htb':True}
self.addLink(node1, node2, **linkopts)

Pythonの(**dict)は便利で、Matplotlibなどの他のライブラリーにパラメータを渡すこともできる。
net.get():はノードオブジェクトを名前で取得できる。
これは、ホストに対するコマンドを送信するときに重要である。
現在のMininetではnet['h1']でノードを取得できる。

ホストでプログラムを実行する。

試験を行うにあたって重要な事柄の一つは、ホスト上でプログラムを実行することである。
シンプルなpingAll()やiperf()テストよりも多くのテストを行うことができる。
それぞれMininetのホストは本質的にbashシェルプロセスが与えられていて、cmd()メソッドを使って1つ、またそれ以上のネットワークインターフェースと相互に入力を送信することができる。

cmdメソッドをつかって、ホストにコマンドを送り、出力を得る例

h1 = net.get('h1')  
result = h1.cmd('ifconfig')
print result

多くのケースでは、コマンドを停止、しばらくの間
バックグラウンドでコマンドを実行して、ファイルへの出力を保存したくなるであろう。

from time import sleep
...
print "Starting test..."
h1.cmd('while true; do date; sleep 1; done > /tmp/date.out &')
sleep(10)
print "Stopping test"
h1.cmd('kill %while')
print "Reading output"
f = open('/tmp/date.out')
lineno = 1
for line in f.readlines():
    print "%d: %s" % ( lineno, line.strip() )
    lineno += 1
f.close()

シェルの出力リダイレクション機能をつかって/tmp/date.outや、&を用いたバックグラウンド動作、プログラムを停止するkill %whileは、バックグラウンドで動作するので注意が必要だ。
残念ながら、Mininetを出てもそれらのジョブが残っている場合に残ってしまうので、ジョブを全て停止してクリーンすることを確認する必要がある。

シェルプロセスを持つことは、それが簡単にだけでなく、他のタスクを実行することができる。
たとえば、バックグラウンドコマンドのPIDを調べることができる

pid = int( h1.cmd('echo $!') )

また、waitを用いて実行が終了するのを待つ事ができる。

h1.cmd('wait', pid)

さらにシェルのwaitメカニズムを使って、sendCmd()をつかって、フォアグラウンドのコマンドを許可し、waitOutput()をつかって、それらが完了するのを待つことができる。

for h in hosts:
    h.sendCmd('sleep 20')

results = {}
for h in hosts:
    results[h.name] = h.waitOutput()

もし、出力ファイルを用いて、テストのモニタリングを行っている場合、インタラクティブにモニタリングができる。
examples/multipoll.pyはmonitorFiles()ファンクションを使って、複数の出力ファイルを監視している。下記は複数のホストから出力されるファイルをインタラクティブに監視している
簡単なテストの実装である。

def monitorTest( N=3, seconds=3 ):
    "Run pings and monitor multiple hosts"
    topo = SingleSwitchTopo( N )
    net = Mininet( topo )
    net.start()
    hosts = net.hosts
    print "Starting test..."
    server = hosts[ 0 ]
    outfiles, errfiles = {}, {}
    for h in hosts:
        # Create and/or erase output files
        outfiles[ h ] = '/tmp/%s.out' % h.name
        errfiles[ h ] = '/tmp/%s.err' % h.name
        h.cmd( 'echo >', outfiles[ h ] )
        h.cmd( 'echo >', errfiles[ h ] )
        # Start pings
        h.cmdPrint('ping', server.IP(),
                   '>', outfiles[ h ],
                   '2>', errfiles[ h ],
                   '&' )
    print "Monitoring output for", seconds, "seconds"
    for h, line in monitorFiles( outfiles, seconds, timeoutms=500 ):
        if h:
            print '%s: %s' % ( h.name, line )
    for h in hosts:
        h.cmd('kill %ping')
    net.stop()
  • multipool.pyの実行結果
*** Creating network
*** Adding controller
*** Adding hosts:
h1 h2 h3 
*** Adding switches:
s1 
*** Adding links:
(h1, s1) (h2, s1) (h3, s1) 
*** Configuring hosts
h1 h2 h3 
*** Starting controller
*** Starting 1 switches
s1 
Starting test...
*** h1 : ('ping', '10.0.0.1', '>', '/tmp/h1.out', '2>', '/tmp/h1.err', '&')
*** h2 : ('ping', '10.0.0.1', '>', '/tmp/h2.out', '2>', '/tmp/h2.err', '&')
*** h3 : ('ping', '10.0.0.1', '>', '/tmp/h3.out', '2>', '/tmp/h3.err', '&')
Monitoring output for 3 seconds
h1: PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
h2: PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
h1: 64 bytes from 10.0.0.1: icmp_req=1 ttl=64 time=0.020 ms
h2: 64 bytes from 10.0.0.1: icmp_req=1 ttl=64 time=6.00 ms
h3: PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
h3: 64 bytes from 10.0.0.1: icmp_req=1 ttl=64 time=4.99 ms
h1: 64 bytes from 10.0.0.1: icmp_req=2 ttl=64 time=0.025 ms
h2: 64 bytes from 10.0.0.1: icmp_req=2 ttl=64 time=0.209 ms
h3: 64 bytes from 10.0.0.1: icmp_req=2 ttl=64 time=0.267 ms
h1: 64 bytes from 10.0.0.1: icmp_req=3 ttl=64 time=0.030 ms
h2: 64 bytes from 10.0.0.1: icmp_req=3 ttl=64 time=0.073 ms
h3: 64 bytes from 10.0.0.1: icmp_req=3 ttl=64 time=0.042 ms
h1: 64 bytes from 10.0.0.1: icmp_req=4 ttl=64 time=0.034 ms
h2: 64 bytes from 10.0.0.1: icmp_req=4 ttl=64 time=0.049 ms
h3: 64 bytes from 10.0.0.1: icmp_req=4 ttl=64 time=0.038 ms
*** Stopping 3 hosts
h1 h2 h3 
*** Stopping 1 switches
s1 ....
*** Stopping 1 controllers
c0 
*** Done

他の例、examples/multiping.pyは、Node.monitor()メソッドを使って、上記とは違うアプローチで、ホストからの出力をモニタリングしている。こちらも試してみたい。
* multiping.pyの実行結果

*** Creating network
*** Adding controller
*** Adding hosts:
h1 h2 h3 
*** Adding switches:
s1 
*** Adding links:
(h1, s1) (h2, s1) (h3, s1) 
*** Configuring hosts
h1 h2 h3 
*** Starting controller
*** Starting 1 switches
s1 
Starting test...
*** h1 : ('ping', '10.0.0.1', '>', '/tmp/h1.out', '2>', '/tmp/h1.err', '&')
*** h2 : ('ping', '10.0.0.1', '>', '/tmp/h2.out', '2>', '/tmp/h2.err', '&')
*** h3 : ('ping', '10.0.0.1', '>', '/tmp/h3.out', '2>', '/tmp/h3.err', '&')
Monitoring output for 3 seconds
h1: PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
h2: PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
h1: 64 bytes from 10.0.0.1: icmp_req=1 ttl=64 time=0.020 ms
h2: 64 bytes from 10.0.0.1: icmp_req=1 ttl=64 time=6.00 ms
h3: PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
h3: 64 bytes from 10.0.0.1: icmp_req=1 ttl=64 time=4.99 ms
h1: 64 bytes from 10.0.0.1: icmp_req=2 ttl=64 time=0.025 ms
h2: 64 bytes from 10.0.0.1: icmp_req=2 ttl=64 time=0.209 ms
h3: 64 bytes from 10.0.0.1: icmp_req=2 ttl=64 time=0.267 ms
h1: 64 bytes from 10.0.0.1: icmp_req=3 ttl=64 time=0.030 ms
h2: 64 bytes from 10.0.0.1: icmp_req=3 ttl=64 time=0.073 ms
h3: 64 bytes from 10.0.0.1: icmp_req=3 ttl=64 time=0.042 ms
h1: 64 bytes from 10.0.0.1: icmp_req=4 ttl=64 time=0.034 ms
h2: 64 bytes from 10.0.0.1: icmp_req=4 ttl=64 time=0.049 ms
h3: 64 bytes from 10.0.0.1: icmp_req=4 ttl=64 time=0.038 ms
*** Stopping 3 hosts
h1 h2 h3 
*** Stopping 1 switches
s1 ....
*** Stopping 1 controllers
c0 
*** Done
mininet@mininet-vm:~/mininet/examples$ 
mininet@mininet-vm:~/mininet/examples$ sudo python multiping.py 
*** Creating network
*** Adding controller
*** Adding hosts:
h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 h19 h20 
*** Adding switches:
s1 
*** Adding links:
(h1, s1) (h2, s1) (h3, s1) (h4, s1) (h5, s1) (h6, s1) (h7, s1) (h8, s1) (h9, s1) (h10, s1) (h11, s1) (h12, s1) (h13, s1) (h14, s1) (h15, s1) (h16, s1) (h17, s1) (h18, s1) (h19, s1) (h20, s1) 
*** Configuring hosts
h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 h19 h20 
*** Starting controller
*** Starting 1 switches
s1 
*** Host h1 (10.0.0.1) will be pinging ips: 10.0.0.1 10.0.0.2 10.0.0.3 10.0.0.4 10.0.0.200
*** Host h2 (10.0.0.2) will be pinging ips: 10.0.0.1 10.0.0.2 10.0.0.3 10.0.0.4 10.0.0.200 10.0.0.200
*** Host h3 (10.0.0.3) will be pinging ips: 10.0.0.1 10.0.0.2 10.0.0.3 10.0.0.4 10.0.0.200 10.0.0.200 10.0.0.200
*** Host h4 (10.0.0.4) will be pinging ips: 10.0.0.1 10.0.0.2 10.0.0.3 10.0.0.4 10.0.0.200 10.0.0.200 10.0.0.200 10.0.0.200
*** Host h5 (10.0.0.5) will be pinging ips: 10.0.0.5 10.0.0.6 10.0.0.7 10.0.0.8 10.0.0.200
*** Host h6 (10.0.0.6) will be pinging ips: 10.0.0.5 10.0.0.6 10.0.0.7 10.0.0.8 10.0.0.200 10.0.0.200
*** Host h7 (10.0.0.7) will be pinging ips: 10.0.0.5 10.0.0.6 10.0.0.7 10.0.0.8 10.0.0.200 10.0.0.200 10.0.0.200
*** Host h8 (10.0.0.8) will be pinging ips: 10.0.0.5 10.0.0.6 10.0.0.7 10.0.0.8 10.0.0.200 10.0.0.200 10.0.0.200 10.0.0.200
*** Host h9 (10.0.0.9) will be pinging ips: 10.0.0.9 10.0.0.10 10.0.0.11 10.0.0.12 10.0.0.200
*** Host h10 (10.0.0.10) will be pinging ips: 10.0.0.9 10.0.0.10 10.0.0.11 10.0.0.12 10.0.0.200 10.0.0.200
*** Host h11 (10.0.0.11) will be pinging ips: 10.0.0.9 10.0.0.10 10.0.0.11 10.0.0.12 10.0.0.200 10.0.0.200 10.0.0.200
*** Host h12 (10.0.0.12) will be pinging ips: 10.0.0.9 10.0.0.10 10.0.0.11 10.0.0.12 10.0.0.200 10.0.0.200 10.0.0.200 10.0.0.200
*** Host h13 (10.0.0.13) will be pinging ips: 10.0.0.13 10.0.0.14 10.0.0.15 10.0.0.16 10.0.0.200
*** Host h14 (10.0.0.14) will be pinging ips: 10.0.0.13 10.0.0.14 10.0.0.15 10.0.0.16 10.0.0.200 10.0.0.200
*** Host h15 (10.0.0.15) will be pinging ips: 10.0.0.13 10.0.0.14 10.0.0.15 10.0.0.16 10.0.0.200 10.0.0.200 10.0.0.200
*** Host h16 (10.0.0.16) will be pinging ips: 10.0.0.13 10.0.0.14 10.0.0.15 10.0.0.16 10.0.0.200 10.0.0.200 10.0.0.200 10.0.0.200
*** Host h17 (10.0.0.17) will be pinging ips: 10.0.0.17 10.0.0.18 10.0.0.19 10.0.0.20 10.0.0.200
*** Host h18 (10.0.0.18) will be pinging ips: 10.0.0.17 10.0.0.18 10.0.0.19 10.0.0.20 10.0.0.200 10.0.0.200
*** Host h19 (10.0.0.19) will be pinging ips: 10.0.0.17 10.0.0.18 10.0.0.19 10.0.0.20 10.0.0.200 10.0.0.200 10.0.0.200
*** Host h20 (10.0.0.20) will be pinging ips: 10.0.0.17 10.0.0.18 10.0.0.19 10.0.0.20 10.0.0.200 10.0.0.200 10.0.0.200 10.0.0.200
h1: 10.0.0.1 -> 10.0.0.1 1 packets transmitted, 1 received, 0% packet loss, time 0ms
h2: 10.0.0.2 -> 10.0.0.1 1 packets transmitted, 1 received, 0% packet loss, time 0ms
h3: 10.0.0.3 -> 10.0.0.1 1 packets transmitted, 1 received, 0% packet loss, time 0ms
h5: 10.0.0.5 -> 10.0.0.5 1 packets transmitted, 1 received, 0% packet loss, time 0ms
h11: 10.0.0.11 -> 10.0.0.9 1 packets transmitted, 1 received, 0% packet loss, time 0ms
h12: 10.0.0.12 -> 10.0.0.9 1 packets transmitted, 1 received, 0% packet loss, time 0ms
h17: 10.0.0.17 -> 10.0.0.17 1 packets transmitted, 1 received, 0% packet loss, time 0ms
h13: 10.0.0.13 -> 10.0.0.13 1 packets transmitted, 1 received, 0% packet loss, time 0ms
h10: 10.0.0.10 -> 10.0.0.9 1 packets transmitted, 1 received, 0% packet loss, time 0ms
h9: 10.0.0.9 -> 10.0.0.9 1 packets transmitted, 1 received, 0% packet loss, time 0ms
h6: 10.0.0.6 -> 10.0.0.5 1 packets transmitted, 1 received, 0% packet loss, time 0ms
h4: 10.0.0.4 -> 10.0.0.1 1 packets transmitted, 1 received, 0% packet loss, time 0ms
h15: 10.0.0.15 -> 10.0.0.13 1 packets transmitted, 1 received, 0% packet loss, time 0ms
h8: 10.0.0.8 -> 10.0.0.5 1 packets transmitted, 1 received, 0% packet loss, time 0ms
h20: 10.0.0.20 -> 10.0.0.17 1 packets transmitted, 1 received, 0% packet loss, time 0ms
h7: 10.0.0.7 -> 10.0.0.5 1 packets transmitted, 1 received, 0% packet loss, time 0ms
h16: 10.0.0.16 -> 10.0.0.13 1 packets transmitted, 1 received, 0% packet loss, time 0ms
h18: 10.0.0.18 -> 10.0.0.17 1 packets transmitted, 1 received, 0% packet loss, time 0ms
h19: 10.0.0.19 -> 10.0.0.17 1 packets transmitted, 1 received, 0% packet loss, time 0ms
h14: 10.0.0.14 -> 10.0.0.13 1 packets transmitted, 1 received, 0% packet loss, time 0ms
h3: 10.0.0.3 -> 10.0.0.2 1 packets transmitted, 1 received, 0% packet loss, time 0ms
h2: 10.0.0.2 -> 10.0.0.2 1 packets transmitted, 1 received, 0% packet loss, time 0ms
…..
*** Stopping 20 hosts
h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 h19 h20 
*** Stopping 1 switches
s1 .....................
*** Stopping 1 controllers
c0 
*** Done

続く。