Mininetのインストールと使用方法

# はじめに
[Mininet](http://mininet.org/)は、端末上に仮想的なSDN(Software Defined Network)、即ちホストとスイッチから構成される論理ネットワークを簡易的に構築することができ、SDNの動作検証に用いることができる。本稿では、Mininetのインストール方法と使用方法を整理する。


# インストール方法
[公式ページ](http://mininet.org/download/)には、インストール済みの仮想マシンを利用する方法やパッケージインストールをする方法等が記載されているが、ここではソースコードからインストールする方法を記載する。Ubuntu 16.04 デスクトップ版で動作確認済みである。

まずはGitHubからソースコードを入手する。

```bash:
# mininetのリポジトリをクローン
$ git clone git://github.com/mininet/mininet
Cloning into 'mininet'...
remote: Counting objects: 9295, done.
remote: Compressing objects: 100% (74/74), done.
remote: Total 9295 (delta 130), reused 186 (delta 126), pack-reused 9093
Receiving objects: 100% (9295/9295), 2.93 MiB | 1.35 MiB/s, done.
Resolving deltas: 100% (6133/6133), done.
Checking connectivity... done.
```

利用可能なMininetのバージョンを確認する。ここでは、2.2.2を利用する。

```bash:
$ cd mininet

# タグ一覧の表示
$ git tag
1.0.0
2.0.0
2.1.0
2.1.0p1
2.1.0p2
2.2.0
2.2.1
2.2.2
2.2.2rc1
cs244-spring-2012-final

# 指定のタグからブランチを作成
$ git checkout -b 2.2.2 2.2.2
Switched to a new branch '2.2.2'
```

Mininetではインストール用のスクリプト`install.sh`が用意されている。

```bash:
# スクリプトの実行
$ util/install.sh
Detected Linux distribution: Ubuntu 16.04 xenial amd64
Ubuntu
Installing all packages except for -eix (doxypy, ivs, nox-classic)...
Install Mininet-compatible kernel if necessary
~~~ (省略) ~~~
Enjoy Mininet!
```

これでインストールは完了したので、動作確認をする。

```bash:
# mininetのバージョンを確認
$ sudo mn --version
2.2.2

# 動作テスト(ping)を実施
$ sudo mn --test pingall
*** Creating network
*** Adding controller
*** Adding hosts:
h1 h2 
*** Adding switches:
s1 
*** Adding links:
(h1, s1) (h2, s1) 
*** Configuring hosts
h1 h2 
*** Starting controller
c0 
*** Starting 1 switches
s1 ...
*** Waiting for switches to connect
s1 
*** Ping: testing ping reachability
h1 -> h2 
h2 -> h1 
*** Results: 0% dropped (2/2 received)
*** Stopping 1 controllers
c0 
*** Stopping 2 links
..
*** Stopping 1 switches
s1 
*** Stopping 2 hosts
h1 h2 
*** Done
completed in 5.425 seconds
```

無事インストールと動作確認が終了した。

# Wireshark
OpenFlowの動作を検証するために、パケットキャプチャツールであるWiresharkを使用する。
Mininet 2.2.2では、`install.sh`でWiresharkもインストールしてはくれるが、いくつか設定が古いので、以下の変更を加える。

##### root権限実行時にWarningが出る時
[こちら](http://nanakira.hatenablog.com/entry/2017/06/10/145334)を参考に。

```bash:
$ sudo dpkg-reconfigure wireshark-common
# 非rootユーザにwireshark実行権限を与えるか → yes

# ユーザをwiresharkグループに追加
$ sudo gpasswd -a [username] wireshark
```

##### Wiresharkのcolorfiltersの変更
`install.sh`の中で、`cp -n $MININET_DIR/mininet/util/colorfilters $HOME/.wireshark`を実行しているが、colorfiltersの設定が古く、WiresharkでWarningが出る。

```bash:
13:25:05          Warn Could not compile "of" in colorfilters file "/home/user/.wireshark/colorfilters".
"of" is neither a field nor a protocol name.
13:25:05          Warn Could not compile "Checksum Errors" in colorfilters file "/home/user/.wireshark/colorfilters".
Neither "cdp.checksum_bad" nor "1" are field or protocol names.
```

なので、暫定的に以下の変更を加える。

```diff:~/.wireshark/colorfilters
- @of@of@[0,5,65535][65535,65535,65535]
+ @openflow@openflow@[0,5,65535][65535,65535,65535]
```

> Checksum Errorsが出現するが動作そのものには影響がない。


OS再起動後、Wiresharkの起動

```bash:
$ wireshark &
# filterにopenflow_v1、監視インターフェースをloopbackとする。
```


# 使用方法
Mininetのネットワーク構築方法を説明する。
コマンドラインからネットワークを構築する方法と、APIを介して構築する方法の2種類がある。

### コマンドライン
`$ sudo mn [オプション]`で実行する。
オプションに何も指定しなければ、最小構成のネットワーク(1つのOpenFlowスイッチとコントローラ、2つのホスト)

| コマンド | 機能 |
|-------|------|
|nodes|ノード一覧を表示|
|net|リンク一覧を表示|
|dump|ノードの詳細を表示|
|[ホスト] ifconfig -a|[ホスト]のインターフェース情報を表示|
|[ホスト1] ping [オプション] [ホスト2]|[ホスト1]から[ホスト2]へのping|
|pingall|全ホストにping|


##### 構成
![構成.jpg](https://qiita-image-store.s3.amazonaws.com/0/105429/05d081b9-ad28-d697-51e0-5c0a839edd69.jpeg)

##### h1 → h2へのping

```
mininet> h1 ping -c 1 h2
```

<img width="1280" alt=" 2018-08-16 18.38.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/105429/d7728ef4-abc1-ed58-11aa-9f9dfe214993.png">

##### h1 → h2へのHTTPアクセス

```bash:
mininet> h1 python -m SimpleHTTPServer 80 &
mininet> h2 wget -O - h1
mininet> h1 kill %python
```

##### ノード間の疎通テスト

```bash:
# pingテスト
$ sudo mn --test pingpair

# TCP帯域テスト
$ sudo mn --test iperf
```

##### トポロジの変更
`--topo`オプションでトポロジを指定

```bash:
# 1つのスイッチに3台のホストが接続
$ sudo mn --test pingall --topo single,3

# 1つのスイッチに1台のホストが接続、スイッチがリニアに接続
$ sudo mn --test pingall --topo linear,4
```

##### 帯域制限

```bash:
$ sudo mn --link tc,bw=10,delay=10ms
```

##### トポロジのカスタマイズ
Pythonスクリプトを活用して、任意のトポロジを作成できる。
サンプルスクリプトが`~/mininet/custom/`にある。

```
$ sudo mn --custom ~/mininet/custom/topo-2sw-2host.py --topo mytopo --test pingall
```

##### ホストやスイッチのターミナル利用

```bash:
$ sudo mn -x
```

```bash:
mininet> xterm [ホスト]
```

##### スイッチの種類
`--switch`オプションでスイッチの種類を指定できる。

```bash:
$ sudo mn --switch ovsk --test iperf
```

| スイッチ | 説明 |
|--------|-----|
|user|user-space switch|
|ovsk|Open vSwitch (OVS)|

##### リング制御

```bash:
# リンクダウン
mininet> link s1 h1 down

# リンクアップ
mininet> link s1 h1 up
```

### Python API
https://github.com/mininet/mininet/wiki/Introduction-to-Mininet