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

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

RouterBOARD (RB750GL)のOpenFlow化へのチャレンジ 〜OpenFlow動作確認編〜

前回は、RouterBOARD (RB750GL)のOpenvSwitch環境を構築しましたので、実際に、OpenFlowプロトコル動作させてみて、各種挙動を確認してみたいと思います。

◆OpenFlowコントローラ環境準備

OpenFlowを確認するためには、OpenFlowコントローラを構築する必要があります。
ここでは、Ryu Controllerを使用したOpenFlow動作確認環境を構築します。
f:id:ttsubo:20141108081044j:plain

1. Ryu Controllerインストール

"ubuntu 14.04 desktop"に、Ryu Controllerをインストールした際の手順を記載します。
ほかのOSでも動作すると思います。ちなみに、OS X Yosemiteでも問題なく動作しております。

tsubo@RyuSDN:~$ sudo apt-get install git
tsubo@RyuSDN:~$ sudo apt-get install python-dev
tsubo@RyuSDN:~$ sudo apt-get install python-pip

tsubo@RyuSDN:~$ git clone https://github.com/osrg/ryu.git
tsubo@RyuSDN:~$ cd ryu/tools/
tsubo@RyuSDN:~/ryu/tools$ sudo pip install -r pip-requires
tsubo@RyuSDN:~/ryu$ cd ..
tsubo@RyuSDN:~/ryu$ sudo python ./setup.py install
tsubo@RyuSDN:~/ryu$ sudo pip install --upgrade six
tsubo@RyuSDN:~/ryu$ ryu-manager --version
ryu-manager 3.15

2. ネットワーク設定

Ryu ControllerとOpenvSwitchが通信できるように、ネットワーク設定を行っておきます。
ちなみに、ここでは、"192.168.0.0/24"とネットワークとしました。

  • OpenvSwitch: 192.168.0.1
  • Ryu Controller: 192.168.0.100
tsubo@RyuSDN:~$ ifconfig
eth0      Link encap:Ethernet  HWaddr 00:0c:29:e1:e9:32  
          inet addr:192.168.0.100  Bcast:192.168.0.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fee1:e932/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:22771 errors:0 dropped:0 overruns:0 frame:0
          TX packets:17676 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:5252189 (5.2 MB)  TX bytes:1375840 (1.3 MB)

eth1      Link encap:Ethernet  HWaddr 00:0c:29:e1:e9:3c  
          inet addr:172.16.115.203  Bcast:172.16.115.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fee1:e93c/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:40598 errors:0 dropped:0 overruns:0 frame:0
          TX packets:21620 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:17019999 (17.0 MB)  TX bytes:2683644 (2.6 MB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:1346 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1346 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:156583 (156.5 KB)  TX bytes:156583 (156.5 KB)

3. OpenFlow簡易ルータ構築

以前、ブログで紹介したOpenFllow簡易ルータを構築します。
まずは、OpenFlow簡易ルータのプログラム一式を以下のサイトからダウンロードします。

Release OpenFlow簡易ルータ(基本動作版) · ttsubo/simpleRouter · GitHub

4. OpenFlow簡易ルータ起動

とりあえず、OpenFlow簡易ルータを起動しておきます。

tsubo@RyuSDN:~$ cd simpleRouter-0.1/ryu-app/
tsubo@RyuSDN:~/simpleRouter-0.1/ryu-app$ ryu-manager openflowRouter.py
loading app openflowRouter.py
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
(5156) wsgi starting up on http://0.0.0.0:8080/

5. ルータコンフィグ設定の準備

今回l構築するルータ構成は、こんな感じを想定します。
f:id:ttsubo:20141108081141j:plain

OpenFlow簡易ルータを起動したら、別ターミナルから、ルータコンフィグ作業場所まで移動しておきます。

tsubo@RyuSDN:~$ cd simpleRouter-0.1/rest-client/
tsubo@RyuSDN:~/simpleRouter-0.1/rest-client$ ls -l
total 40
-rw-rw-r-- 1 tsubo tsubo  278 Nov  3 16:15 OpenFlow.ini
-rw-rw-r-- 1 tsubo tsubo  933 Nov  3 14:33 common_func.py
-rw-rw-r-- 1 tsubo tsubo  974 Nov  3 14:33 common_func.pyc
-rwxrwxr-x 1 tsubo tsubo 1068 Nov  3 14:26 get_arp.sh
-rwxrwxr-x 1 tsubo tsubo 1493 Nov  3 14:25 get_flow_stats.sh
-rwxrwxr-x 1 tsubo tsubo 1170 Nov  3 14:27 get_interface.sh
-rwxrwxr-x 1 tsubo tsubo 1630 Nov  3 14:28 get_port_stats.sh
-rwxrwxr-x 1 tsubo tsubo 1114 Nov  3 16:18 post_gateway.sh
-rwxrwxr-x 1 tsubo tsubo 2570 Nov  3 16:21 post_interface.sh
-rwxrwxr-x 1 tsubo tsubo  924 Nov  3 15:10 put_ping.sh

つづいて、ルータコンフィグ設定を行います。
それでは、具体的にルータコンフィグ設定として、OpenFlow.iniファイルを編集します。
物理ポートとOpenFlowポートが一致していない点は、注意が必要です。

tsubo@RyuSDN:~/simpleRouter-0.1/rest-client$ vi OpenFlow.ini
--------------------------
[Port2]
port = "1"
macaddress = "00:00:00:00:00:01"
ipaddress = "192.168.100.100"
opposite_ipaddress = "192.168.100.1"

[Port3]
port = "2"
macaddress = "00:00:00:00:00:02"
ipaddress = "192.168.101.100"
opposite_ipaddress = "192.168.101.1"

[Gateway]
ipaddress = "192.168.100.1"

ちなみに、RB750GL上のOpenvSwitch側での物理ポートとOpenFlowポートとの関係を再掲しておきます。

root@OpenWrt:~# ovs-ofctl dump-ports-desc br0 --protocols=OpenFlow13
OFPST_PORT_DESC reply (OF1.3) (xid=0x2):
 1(eth0.2): addr:d4:ca:6d:73:14:8b
     config:     0
     state:      0
     current:    1GB-FD AUTO_NEG
     advertised: 1GB-FD
     supported:  1GB-FD
     speed: 1000 Mbps now, 1000 Mbps max
 2(eth0.3): addr:d4:ca:6d:73:14:8b
     config:     0
     state:      0
     current:    1GB-FD AUTO_NEG
     advertised: 1GB-FD
     supported:  1GB-FD
     speed: 1000 Mbps now, 1000 Mbps max
 LOCAL(br0): addr:d4:ca:6d:73:14:8b
     config:     PORT_DOWN
     state:      LINK_DOWN
     speed: 0 Mbps now, 0 Mbps max

6. ルータコンフィグ反映

実際に、ルータコンフィグ情報を、Ryu Controllerに反映します。
まずは、インタフェース情報からです。

tsubo@RyuSDN:~/simpleRouter-0.1/rest-client$ ./post_interface.sh 
======================================================================
create_interface
======================================================================
/openflow/0000000000000001/interface

{
"interface": {
"port": "1",
"macaddress": "00:00:00:00:00:01",
"ipaddress": "192.168.100.100",
"opposite_ipaddress": "192.168.100.1"
}
}
----------
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: application/json; charset=UTF-8
header: Content-Length: 160
header: Date: Mon, 03 Nov 2014 08:29:33 GMT
----------
{
    "interface": {
        "macaddress": "00:00:00:00:00:01", 
        "ipaddress": "192.168.100.100", 
        "port": "1", 
        "opposite_ipaddress": "192.168.100.1"
    }, 
    "id": "0000000000000001"
}

======================================================================
create_interface
======================================================================
/openflow/0000000000000001/interface

{
"interface": {
"port": "2",
"macaddress": "00:00:00:00:00:02",
"ipaddress": "192.168.101.100",
"opposite_ipaddress": "192.168.101.1"
}
}
----------
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: application/json; charset=UTF-8
header: Content-Length: 160
header: Date: Mon, 03 Nov 2014 08:29:38 GMT
----------
{
    "interface": {
        "macaddress": "00:00:00:00:00:02", 
        "ipaddress": "192.168.101.100", 
        "port": "2", 
        "opposite_ipaddress": "192.168.101.1"
    }, 
    "id": "0000000000000001"
}

つづいて、DefaultGateway情報です。

tsubo@RyuSDN:~/simpleRouter-0.1/rest-client$ ./post_gateway.sh 
======================================================================
create_gateway
======================================================================
/openflow/0000000000000001/gateway

{
"gateway": {
"ipaddress": "192.168.100.1"
}
}
----------
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: application/json; charset=UTF-8
header: Content-Length: 69
header: Date: Mon, 03 Nov 2014 08:30:56 GMT
----------
{
    "id": "0000000000000001", 
    "gateway": {
        "ipaddress": "192.168.100.1"
    }
}

7. ルータコンフィグ結果確認

OpenFlow簡易ルータのポート情報を確認します。

tsubo@RyuSDN:~/simpleRouter-0.1/rest-client$ ./get_interface.sh 
======================================================================
get_interface
======================================================================
/openflow/0000000000000001/interface
----------
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: application/json; charset=UTF-8
header: Content-Length: 256
header: Date: Mon, 03 Nov 2014 08:32:01 GMT
+++++++++++++++++++++++++++++++
2014/11/03 17:32:01 : PortTable
+++++++++++++++++++++++++++++++
portNo   IpAddress       MacAddress
-------- --------------- -----------------
       1 192.168.100.100 00:00:00:00:00:01
       2 192.168.101.100 00:00:00:00:00:02

つづいて、OpenFlow簡易ルータポート毎のAPR学習結果として、対向機器(PC.BBルータ)のMACアドレスが正しく表示されていることを確認します。

tsubo@RyuSDN:~/simpleRouter-0.1/rest-client$ ./get_arp.sh 
======================================================================
get_arp
======================================================================
/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: Mon, 03 Nov 2014 08:33:51 GMT
+++++++++++++++++++++++++++++++
2014/11/03 17:33:51 : ArpTable 
+++++++++++++++++++++++++++++++
portNo   MacAddress        IpAddress
-------- ----------------- ------------
       1 10:66:82:93:c4:f0 192.168.100.1
       2 00:23:81:14:e8:17 192.168.101.1

最後に、Flowエントリ情報を確認します。各Flowエントリでのパケット転送量も同時に確認できます。

tsubo@RyuSDN:~/simpleRouter-0.1/rest-client$ ./get_flow_stats.sh 
======================================================================
get_flowstats
======================================================================
/openflow/0000000000000001/stats/flow
----------
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: application/json; charset=UTF-8
header: Content-Length: 443
header: Date: Mon, 03 Nov 2014 08:34:44 GMT
+++++++++++++++++++++++++++++++
2014/11/03 17:34:44 : FlowStats
+++++++++++++++++++++++++++++++
inPort   ethSrc             ethDst             ipv4Dst         packets  bytes
-------- ------------------ ------------------ --------------- -------- --------
       1  10:66:82:93:c4:f0  00:00:00:00:00:01   192.168.101.1       67    10506
       2  00:23:81:14:e8:17  00:00:00:00:00:02   192.168.100.1       18     3803
       *                  *                  *       0.0.0.0/0      430   143408

"0.0.0.0/0"が、DefaultGatewayに該当するFlowエントリになります。
このFlowエントリが表示されない場合には、原因として対向PC端末がネットワークにつながっていないことが想定されます。ネットワーク接続後に、OpenFlowコントローラ再起動からの再作業が必要になります。

以上で、OpenFlow簡易ルータ環境構築は、完了です。

◆OpenFlow動作確認

さっそく、OpenFlow動作確認してみます。

1. IPルーティング動作確認

まず、 IPルーティング動作を確認してみます。
f:id:ttsubo:20141108084950j:plain

PC端末(192.168.101.1)から、BBルータ(192.168.100.1)にpingを行ってみます。

Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:¥Users¥tsuboi>ping 192.168.100.1

192.168.100.1 に ping を送信しています 32 バイトのデータ:
192.168.100.1 からの応答: バイト数 =32 時間 =1ms TTL=255
192.168.100.1 からの応答: バイト数 =32 時間 <1ms TTL=255
192.168.100.1 からの応答: バイト数 =32 時間 <1ms TTL=255
192.168.100.1 からの応答: バイト数 =32 時間 <1ms TTL=255

192.168.100.1 の ping 統計:
    パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 0ms、最大 = 1ms、平均 = 0ms

さらに、ARP情報を確認してみると、OpenFlow簡易ルータの物理ポート3番(OpenFlowポート2番)に設定したMACアドレスが表示されています。

C:¥Users¥tsuboi>arp -a

インターフェイス: 192.168.101.1 --- 0xa
  インターネット アドレス      物理アドレス      種類
  192.168.101.100       00-00-00-00-00-02     動的
  192.168.101.255       ff-ff-ff-ff-ff-ff     静的
  224.0.0.2             01-00-5e-00-00-02     静的
  224.0.0.22            01-00-5e-00-00-16     静的
  224.0.0.251           01-00-5e-00-00-fb     静的
  224.0.0.252           01-00-5e-00-00-fc     静的
  239.255.255.250       01-00-5e-7f-ff-fa     静的
  255.255.255.255       ff-ff-ff-ff-ff-ff     静的

つづいて、internetにアクセスしてみます。
ひととり、Webブラウジング / Mail / Ustream / YouTube等が正しく動作するところまで確認できました。

f:id:ttsubo:20141108085538p:plain

2. OpenFlow簡易ルータ側での疎通診断

つぎに、疎通診断です。
f:id:ttsubo:20141108090420j:plain

OpenFlow簡易ルータから、BBルータ(192.168.100.1)にpingを行ってみます。
コマンド引数には、[宛先IPアドレス] , [OpenFlowポート番号], [転送データ]の順で指定します。

tsubo@RyuSDN:~/simpleRouter-0.1/rest-client$ ./put_ping.sh 192.168.100.1 1 From_Port2
======================================================================
ping
======================================================================
/openflow/0000000000000001/ping

{
"ping": {
"hostIp": "192.168.100.1",
"data": "From_Port2",
"outPort": "1"
}
}
----------
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: application/json; charset=UTF-8
header: Content-Length: 479
header: Date: Mon, 03 Nov 2014 08:15:56 GMT
----------
{
    "ping": [
        "PING 192.168.100.1 : 10 data bytes", 
        "ping ok ( 18 bytes from 192.168.100.1: icmp_req=1 ttl=255 data=[From_Port2] )", 
        "ping ok ( 18 bytes from 192.168.100.1: icmp_req=2 ttl=255 data=[From_Port2] )", 
        "ping ok ( 18 bytes from 192.168.100.1: icmp_req=3 ttl=255 data=[From_Port2] )", 
        "ping ok ( 18 bytes from 192.168.100.1: icmp_req=4 ttl=255 data=[From_Port2] )", 
        "ping ok ( 18 bytes from 192.168.100.1: icmp_req=5 ttl=255 data=[From_Port2] )"
    ], 
    "id": "0000000000000001"
}

事前に、PC端末側のFirewall設定を無効にして、OpenFlow簡易ルータからPC端末(192.168.101.1)にpingを行ってみます。

tsubo@RyuSDN:~/simpleRouter-0.1/rest-client$ ./put_ping.sh 192.168.101.1 2 From_Port3
======================================================================
ping
======================================================================
/openflow/0000000000000001/ping

{
"ping": {
"hostIp": "192.168.101.1",
"data": "From_Port3",
"outPort": "2"
}
}
----------
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: application/json; charset=UTF-8
header: Content-Length: 479
header: Date: Mon, 03 Nov 2014 08:16:21 GMT
----------
{
    "ping": [
        "PING 192.168.101.1 : 10 data bytes", 
        "ping ok ( 18 bytes from 192.168.101.1: icmp_req=1 ttl=128 data=[From_Port3] )", 
        "ping ok ( 18 bytes from 192.168.101.1: icmp_req=2 ttl=128 data=[From_Port3] )", 
        "ping ok ( 18 bytes from 192.168.101.1: icmp_req=3 ttl=128 data=[From_Port3] )", 
        "ping ok ( 18 bytes from 192.168.101.1: icmp_req=4 ttl=128 data=[From_Port3] )", 
        "ping ok ( 18 bytes from 192.168.101.1: icmp_req=5 ttl=128 data=[From_Port3] )"
    ], 
    "id": "0000000000000001"
}

ためしに、PC端末側のFirewall設定を有効にして、疎通確認を行ってみますと...

tsubo@RyuSDN:~/simpleRouter-0.1/rest-client$ ./put_ping.sh 192.168.101.1 2 From_Port3
======================================================================
ping
======================================================================
/openflow/0000000000000001/ping

{
"ping": {
"hostIp": "192.168.101.1",
"data": "From_Port3",
"outPort": "2"
}
}
----------
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: application/json; charset=UTF-8
header: Content-Length: 304
header: Date: Mon, 03 Nov 2014 08:17:24 GMT
----------
{
    "ping": [
        "PING 192.168.101.1 : 10 data bytes", 
        "ping ng ( Request Timeout for icmp_seq 1 )", 
        "ping ng ( Request Timeout for icmp_seq 2 )", 
        "ping ng ( Request Timeout for icmp_seq 3 )", 
        "ping ng ( Request Timeout for icmp_seq 4 )", 
        "ping ng ( Request Timeout for icmp_seq 5 )"
    ], 
    "id": "0000000000000001"
}

"ping ng"となり、疎通性NGがOpenFlow簡易ルータ側でも把握できました。

3. 統計情報の確認

最後に、統計情報の確認です。
しばらく、Internetにアクセスしたのちに、OpenFlowのFlowエントリのカウンタ値を確認してみます。
f:id:ttsubo:20141108090614j:plain

まずは、RB750GLのOpenvSwitch上で、Flowエントリをダンプします。

root@OpenWrt:~# ovs-ofctl dump-flows br0 --protocols=OpenFlow13
OFPST_FLOW reply (OF1.3) (xid=0x2):
 cookie=0x0, duration=2187.318s, table=0, n_packets=31449, n_bytes=6582008, priority=1,ip actions=set_field:00:00:00:00:00:01->eth_src,set_field:10:66:82:93:c4:f0->eth_dst,output:1,dec_ttl
 cookie=0x0, duration=2207.717s, table=0, n_packets=159, n_bytes=12108, priority=16,ip,nw_dst=192.168.100.100 actions=CONTROLLER:65535
 cookie=0x0, duration=2202.700s, table=0, n_packets=45, n_bytes=2860, priority=16,ip,nw_dst=192.168.101.100 actions=CONTROLLER:65535
 cookie=0x0, duration=2215.974s, table=0, n_packets=3187, n_bytes=644067, priority=0 actions=CONTROLLER:65535
 cookie=0x0, duration=2202.687s, table=0, n_packets=48696, n_bytes=67103272, priority=255,ip,in_port=1,dl_src=10:66:82:93:c4:f0,dl_dst=00:00:00:00:00:01,nw_dst=192.168.101.1 actions=set_field:00:00:00:00:00:02->eth_src,set_field:00:23:81:14:e8:17->eth_dst,output:2,dec_ttl
 cookie=0x0, duration=2202.687s, table=0, n_packets=203, n_bytes=21422, priority=255,ip,in_port=2,dl_src=00:23:81:14:e8:17,dl_dst=00:00:00:00:00:02,nw_dst=192.168.100.1 actions=set_field:00:00:00:00:00:01->eth_src,set_field:10:66:82:93:c4:f0->eth_dst,output:1,dec_ttl

さらに、ほぼ同時のタイミングで、OpenFlow簡易ルータ上でも統計情報を取得してみます。

tsubo@RyuSDN:~/simpleRouter-0.1/rest-client$ ./get_flow_stats.sh 
======================================================================
get_flowstats
======================================================================
/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: Mon, 03 Nov 2014 07:56:04 GMT
+++++++++++++++++++++++++++++++
2014/11/03 16:56:04 : FlowStats
+++++++++++++++++++++++++++++++
inPort   ethSrc             ethDst             ipv4Dst         packets  bytes
-------- ------------------ ------------------ --------------- -------- --------
       1  10:66:82:93:c4:f0  00:00:00:00:00:01   192.168.101.1    48694 67103132
       2  00:23:81:14:e8:17  00:00:00:00:00:02   192.168.100.1      203    21422
       *                  *                  *       0.0.0.0/0    31441  6580664

OpenFlowスイッチ〜コントロール間でのflowエントリ上の統計情報の比較してみると、だいたいカウンタ値は一致していました。
微妙なズレの主要因は、OpenFlow〜OpenvSwirch間でのFlowStatsリクエスト発行間隔を10秒としているためです。

◆おわりに

ひととおり、OpenFlow動作を試してみましたが、問題なく動作するようです。
f:id:ttsubo:20141108091626j:plain
RouterBOARD (RB750GL)をOpenFlow化して、実際の家庭ネットワークにつないでみるとOpenFlowでのパケット転送がリアルに体感できて面白いと思います。