SDN開発エンジニアを目指した活動ブログ

〜SDNなオープンソース製品を実際に使って試してみる〜

OpenFlow簡易ルータの実践活用(1) 〜OpenvSwitch導入編〜

前回まで、Ryu SDN Frameworkを活用したOpenFlow簡易ルータ作成を行ってきましたが、OpenFlow勉強の素材として、当初想定していた必要機能は一通り具備できたと思います。早速、OpenFlow簡易ルータを自宅ネットワークに導入して、その使い勝手を確認してみたいと思います。

◆導入形態

OpenFlow簡易ルータの自宅ネットワークへの導入形態としては、新たなサブネットと既存サブネットとをゲートウェイ的に相互接続し、新セグメント上に配備したMacBookからインターネットにアクセスできる形態を目指します。

◆導入にあたっての準備

OpenFlowコントローラやOpenFlowスイッチを動作できる環境を構築します。
また、自宅ネットワーク側でのBBルータでのルーティング追加などが必要ですが、ここでは設定方法などは割愛します。

f:id:ttsubo:20140302143041j:plain

1. Ryuコントローラの環境構築

まずは、Ryuコントローラ構築からはじめます。

$ sudo apt-get -y install python-pip python-dev libxml2-dev libxslt1-dev python-lxml
$ sudo pip install ryu

2. OpenvSwitch(2.0.0)の環境構築

つぎに、OpenvSwitch環境手順ですが、こちらのブログ記事を参考にさせて頂きました。本来であれば、Ubuntu Server版でOpenvSwitchを構築すべきなんですが、今回が初回ということもあり、環境構築の準備中に、Wiresharkを動作させたかったので、まずは実績つくりを優先してDesktop版を使用しました。
Ubuntu-12.04.3にopenvswitch-2.0.0をインストール | 迷い庭

あと、datapath-idもデフォルト値を使用せず、敢えて、「0000000000000001」を前提としております。
OpenvSwitch設定パラメータは以下の通りです。
(OpenFlowチャネルも、昔のポート番号6633のままとしております)

$ sudo ovs-vsctl add-br br0
$ sudo ovs-vsctl add-port br0 eth1
$ sudo ovs-vsctl add-port br0 eth2
$ sudo ovs-vsctl set-controller br0 tcp:192.168.0.100:6633
$ sudo ovs-vsctl set bridge br0 other-config:datapath-id=0000000000000001
$ sudo ovs-vsctl set bridge br0 protocols=OpenFlow13

3. OpenFlow簡易ルータの動作準備

Ryu SDN Frameworkが動作する環境に、OpenFlow簡易ルータのプログラム一式を以下のサイトからダウンロードした上で、 Ryuコントローラを起動します。
Release OpenFlow簡易ルータ(基本動作版) · ttsubo/simpleRouter · GitHub

  • Ryuコントローラの起動
$ cd simpleRouter-0.1/ryu-app/
$ ryu-manager openflowRouter.py 
loading app openflowRouter.py
loading app ryu.controller.ofp_handler
loading app ryu.controller.ofp_handler
creating context wsgi
instantiating app None of SimpleMonitor
creating context monitor
instantiating app openflowRouter.py of OpenflowRouter
instantiating app ryu.controller.ofp_handler of OFPHandler
(10256) wsgi starting up on http://0.0.0.0:8080/

OpenFlow簡易ルータの物理ポートにIPアドレスを付与して、デフォルトゲートウェイ設定を行います。通常のルータ機器であれば、CLIで実施する作業でしょうけど、ここでは、RESTful-IFにて、パラメータ設定を行っております。
注)ポート番号とIPアドレスの対応付けは、ここで指定することになります。よって、実際の物理ポートとケーブル結線が一致していないと通信できません。

  • eth1側の物理ポート設定
$ curl -s -X POST -d '{"interface": {"macaddress": "00:00:00:00:00:01", "ipaddress": "192.168.100.100", "port": "1", "opposite_ipaddress": "192.168.100.1"}}' http://localhost:8080/openflow/0000000000000001/interface | python -mjson.tool
{
    "id": "0000000000000001", 
    "interface": {
        "ipaddress": "192.168.100.100", 
        "macaddress": "00:00:00:00:00:01", 
        "opposite_ipaddress": "192.168.100.1", 
        "port": "1"
    }
}
  • eth2側の物理ポート設定
$ curl -s -X POST -d '{"interface": {"macaddress": "00:00:00:00:00:02", "ipaddress": "192.168.101.100", "port": "2", "opposite_ipaddress": "192.168.101.1"}}' http://localhost:8080/openflow/0000000000000001/interface | python -mjson.tool
{
    "id": "0000000000000001", 
    "interface": {
        "ipaddress": "192.168.101.100", 
        "macaddress": "00:00:00:00:00:02", 
        "opposite_ipaddress": "192.168.101.1", 
        "port": "2"
    }
}
$ curl -s -X POST -d '{"gateway": {"ipaddress": "192.168.100.1"}}' http://localhost:8080/openflow/0000000000000001/gateway | python -mjson.tool
{
    "gateway": {
        "ipaddress": "192.168.100.1"
    }, 
    "id": "0000000000000001"
}

◆OpenFlow簡易ルータの動作確認

基本的な準備が完了したところで、正しくOpenFlow簡易ルータが動作しているかを確認してみましょう。
なお、動作確認で使用したスクリプトは、こちらから利用可能です。
simpleRouter/rest-client at master · ttsubo/simpleRouter · GitHub
(1) Arpテーブル確認
 : 物理ポート毎の接続先ホスト(MacBook, BBルータ)のMacアドレスが取得できていることを確認します。

$ ./get_arp.sh 
/openflow/0000000000000001/arp
-----------------------------------------------------------
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: application/json; charset=UTF-8
header: Content-Length: 238
header: Date: Sat, 01 Mar 2014 23:25:44 GMT
+++++++++++++++++++++++++++++++
2014/03/02 08:25:44 : ArpTable 
+++++++++++++++++++++++++++++++
portNo   MacAddress        IpAddress
-------- ----------------- ------------
       1 10:66:82:93:c4:f0 192.168.100.1
       2 7c:c3:a1:87:8f:65 192.168.101.1

注)さきほど、RESTful-IFで設定したポート番号とIPアドレスの対応付けが、実際の物理ポートとケーブル結線が一致していない場合には、Arpテーブルに該当情報が表示されません。

◆実際、使ってみて ...

OpenFlow簡易ルータの動作確認を終了したので、いよいよ、実際にインターネットにアクセスしてみました。
結論としては、普段のインターネット利用での操作感と、まったく遜色ありませんでした。
通常の検索ポータルでのキーワード検索や、YouTubeなども、普通に利用できました。
今朝のustreamでの鈴鹿サーキット公式レースのライブ映像も、ストレスなく閲覧できておりました。
f:id:ttsubo:20140302153236j:plain

あと、ざっくりですが、OpenvSwitchでのトラフィックカウンタも確認してみました。
(1) PortStats確認
 : 物理ポート毎のトラフィックカウンタが取得できていることを確認しました

$ ./get_port_stats.sh 
/openflow/0000000000000001/stats/port
-----------------------------------------------------------
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: application/json; charset=UTF-8
header: Content-Length: 443
header: Date: Sat, 01 Mar 2014 23:35:25 GMT
+++++++++++++++++++++++++++++++
2014/03/02 08:35:25 : PortStats
+++++++++++++++++++++++++++++++
portNo   rxPackets rxBytes  rxErrors txPackets txBytes  txErrors
-------- --------- -------- -------- --------- -------- --------
       1     31631 41554372        0     16960  2475911        0
       2     17342  2553369        0     30423 41169870        0
fffffffe        10      844        0       164    38702        0

(2) FlowStats確認
 : Flowエントリ毎のトラフィックカウンタが取得できていることを確認しました

$ ./get_flow_stats.sh 
/openflow/0000000000000001/stats/flow
-----------------------------------------------------------
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: application/json; charset=UTF-8
header: Content-Length: 454
header: Date: Sat, 01 Mar 2014 23:35:32 GMT
+++++++++++++++++++++++++++++++
2014/03/02 08:35:32 : FlowStats
+++++++++++++++++++++++++++++++
inPort   ethSrc             ethDst             ipv4Dst         packets  bytes
-------- ------------------ ------------------ --------------- -------- --------
       1  10:66:82:93:c4:f0  00:00:00:00:00:01   192.168.101.1    29859 41033174
       2  7c:c3:a1:87:8f:65  00:00:00:00:00:02   192.168.100.1      159    13110
       *                  *                  *       0.0.0.0/0    17345  2659435

◆簡単な動作検証

iperf等でOpenFlow簡易ルータの簡単なパフォーマンスを測ってみました。
(ちなみに、ここでの通信はすべて、Flowエントリに基づいた転送処理になっています。)

f:id:ttsubo:20140302154957j:plain

$ iperf -c 192.168.100.1
------------------------------------------------------------
Client connecting to 192.168.100.1, TCP port 5001
TCP window size:  129 KByte (default)
------------------------------------------------------------
[  4] local 192.168.101.1 port 57447 connected with 192.168.100.1 port 5001
[ ID] Interval       Transfer     Bandwidth
[  4]  0.0-10.0 sec   112 MBytes  94.3 Mbits/sec
  • iperf確認結果(ThinkPad T61側)
$ iperf -c 192.168.101.1
------------------------------------------------------------
Client connecting to 192.168.101.1, TCP port 5001
TCP window size: 23.5 KByte (default)
------------------------------------------------------------
[  3] local 192.168.100.1 port 51676 connected with 192.168.101.1 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec   114 MBytes  95.2 Mbits/sec
$ ping 192.168.100.1
PING 192.168.100.1 (192.168.100.1): 56 data bytes
64 bytes from 192.168.100.1: icmp_seq=0 ttl=64 time=0.907 ms
64 bytes from 192.168.100.1: icmp_seq=1 ttl=64 time=0.989 ms
64 bytes from 192.168.100.1: icmp_seq=2 ttl=64 time=0.908 ms
64 bytes from 192.168.100.1: icmp_seq=3 ttl=64 time=0.873 ms
64 bytes from 192.168.100.1: icmp_seq=4 ttl=64 time=0.892 ms
64 bytes from 192.168.100.1: icmp_seq=5 ttl=64 time=1.196 ms
^C
--- 192.168.100.1 ping statistics ---
6 packets transmitted, 6 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.873/0.961/1.196/0.111 ms

MacBookThinkPad間でのRTTは、概ね、1ms程度でした。

◆終わりに

実際にOpenFlow簡易ルータを使ってみて、想定通りの動作を確認できました。
前回まで、仮想VM環境で同等の動作確認を行ってきたわけですし、OpenvSwitch動作環境として、それなりのスペックを取り揃えたわけですから、今回の結果は最初から想定できた内容なのですが、実際に実機と繋がったワクワク感は、純粋に楽しいですよね。まあ、今後の課題は、如何にコモディティ化を図った安価な機器に置き換えられるというところでしょうけど ...

あと、Mininet環境だと、ちゃんと動作したのに実機だと想定どおり動作しない場面もよく遭遇しまよね。この時のトラブルシューティング経験が、SDN開発エンジニアとしての技術知識の糧になるものだと思いますので、これからも実機での作業を大切にしていきたいです。

次回からは、OpenFlowスイッチとして、LINC-Switch環境を導入していきたいと思います。