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

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

Docker環境で、MPLS-VPNネットワークを体験してみる

今回は、巷で流行りのDockerのネタです。
以前より、Dockerを活用すれば、SDN技術要素を習得するための自前SDNラボ環境を簡易に構築することが可能となるので、ぜひ習得しておきたい技術だと考えておりました。
そんな折に、たまたま、過去の沖縄オープンラボラトリのイベント企画で、第2回ハンズオンセミナー(SDN編)が開催されたことに気がつきました。ハンズオンのタイトルは、すばり「SDN編/Dockerで箱庭実験ネットワークを作ろう」とのこと。公開情報が、こちらです。www.okinawaopenlabs.org

というこので、ここでのハンズオン資料などを参考にさせていただきながら、自前SDNラボ環境を構築してみます。

▪️まずは、SDNラボ環境ネタをどうするか...

あまり在り来たりな素材だとモチベーションが停滞してしまいます。
そこで、Docker活用事例として、過去に前例のないSDN技術要素ということで、SDNと親和性が高いMPLSネットワーク環境を構築したいと思います。さらに、RyuBGPSpeakerやLagopusSwitchといったオープンソースを活用することも視野に入れて、SDNラボ環境を検討していきます。あと、以前、SlideShareで公開したmpBGP/MPLS-VPNプロトコル動作を簡単に体験できる環境も考慮に入れたいところです。

www.slideshare.net

▪️Docker-simpleRouter環境構築メモ

これまでのブログ記事でも題材に取り上げてきたBGP版OpenFlow簡易ルータ(通称:simpleRouter)をベースにDocker化に着手することとしました。github.com

まずは、UbuntuへのDockerインストールですが、こちらは、前出のハンズオンを思いっきり参考にさせて頂きました。(^_^;)

$ git clone https://github.com/ttsubo/docker-simpleRouter.git
$ cd docker-simpleRouter
$ ./simpleRouter.sh install
... snip
ubuntu:14.04.2: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
Digest: sha256:cc15bd0f821cdecf7d7346211fbb4f9c4a0f32d29259f1fe57c87cabb9ce26b4
Status: Downloaded newer image for ubuntu:14.04.2

インストール後は、一度ログアウトして再ログインします。
(dockerグループへの所属を反映させるため)

$ docker version
Client version: 1.6.0
Client API version: 1.18
Go version (client): go1.4.2
Git commit (client): 4749651
OS/Arch (client): linux/amd64
Server version: 1.6.0
Server API version: 1.18
Go version (server): go1.4.2
Git commit (server): 4749651
OS/Arch (server): linux/amd64

Docker-Hubから、Dockerイメージを取得します。
まずは、simpleRouteイメージ本体から...
こちらは、BGP面を構成するBGPルータ想定したDockerイメージになります。

$ docker pull ttsubo/simple-router:latest
...snip
Digest: sha256:aecd207cc4390b345b6840db45099253edd4c8b8a8330ecee0ecd6f8a1f97c61
Status: Downloaded newer image for ttsubo/simple-router:latest

つぎに、pc-termイメージを取得します。
こちらは、BGP面に接続するPC端末を想定したDockerイメージになります。

$ docker pull ttsubo/pc-term:latest
...snip
Digest: sha256:6924f979906b3576ead6fff55020516f303e9fd83ba33d8d38f040cd9621ef7e
Status: Downloaded newer image for ttsubo/pc-term:latest

最後に、test-serverイメージを取得します。
こちらは、BGPルータ監視用に活用します。

$ docker pull ttsubo/test-server:latest
...snip
Digest: sha256:0f916b800b4fae5bfa8973366588299cfeab75ceae628ed020adba225e146d90
Status: Downloaded newer image for ttsubo/test-server:latest

Dockerイメージの取得が完了したので、いちおう内容を確認しておきます。

$ docker images
REPOSITORY             TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ttsubo/simple-router   latest              d713bbabb51a        23 hours ago        844.7 MB
ttsubo/test-server     latest              fc3db66f9ef8        25 hours ago        506.8 MB
ttsubo/pc-term         latest              7559c9022200        26 hours ago        253.6 MB
ubuntu                 14.04.2             07f8e8c5e660        5 days ago          188.3 MB

以上で、環境構築は終了です。

▪️早速、Dockerを動かしてみる

Docker環境の起動用スクリプトを実行するだけです。
5分程度待つと、9つのDockerコンテナが自動生成されて必要なトポロジ情報も設定されます。

$ ./simpleRouter.sh start
76472b045e38724cb0dd5c4dcaeb8df79a50248147ddaed01aedbbe076f7549e
[sudo] password for tsubo: 
a6cf21d3fcf0114350e767e51d42febaf8ab2d5e86e12cfcca1bcf366ce6ac26
92ec4528d4a87fae3d609f889a8890935569d47078c6a35168fd9038668b0fec
cb110daaf7bfe2e2b18f5e217591cee8cca5804f886c3060532b5dc0e740589e
4d597bb57e13f35965d91e6924ca5e1a7464a7b61adaadc15fb920395d640245
7ea4819f81212a6d96fe5fce4bec8f7f13f5c36a52218c6072adcf909de913c2
b73eb44a1998606122666cbc6fd1849ebc27acfc8f1634dbd34c5f4e9222a5f8
45e6942c3516d869ce54786db9dcbeb69cfafb87e62672ff215cc6562dd4004d
237a076d04f90253cef3533ad06d98beb2186e4110fa71dacdb8ab6b0dfce46f
####################
start BGP1 ...
####################
2015-05-06 07:53:43,601 - ryu.base.app_manager - INFO - loading app openflowRouter.py
2015-05-06 07:53:43,936 - ryu.base.app_manager - INFO - loading app ryu.controller.ofp_handler
2015-05-06 07:53:43,941 - ryu.base.app_manager - INFO - creating context wsgi
2015-05-06 07:53:43,941 - ryu.base.app_manager - INFO - instantiating app None of SimpleMonitor
2015-05-06 07:53:43,954 - ryu.base.app_manager - INFO - creating context monitor
2015-05-06 07:53:43,955 - ryu.base.app_manager - INFO - instantiating app None of SimpleBGPSpeaker
2015-05-06 07:53:43,956 - ryu.base.app_manager - INFO - creating context bgps
2015-05-06 07:53:43,956 - ryu.base.app_manager - INFO - instantiating app openflowRouter.py of OpenflowRouter
2015-05-06 07:53:43,961 - ryu.base.app_manager - INFO - instantiating app ryu.controller.ofp_handler of OFPHandler
2015-05-06 07:53:43,964 - ryu.lib.hub - INFO - (79) wsgi starting up on http://0.0.0.0:8080/
2015-05-06 07:53:46,470 - ryu.lib.hub - INFO - (79) accepted ('127.0.0.1', 57391)
2015-05-06 07:53:46,490 - bgpspeaker.api.base - INFO - API method core.start called with args: {'router_id': '10.0.1.1', 'label_range': (100, 199), 'waiter': <ryu.lib.hub.Event object at 0x7f40af45a090>, 'local_as': 65011, 'bgp_server_port': 179, 'refresh_max_eor_time': 0, 'refresh_stalepath_time': 0}
2015-05-06 07:53:46,775 - ryu.lib.hub - INFO - 127.0.0.1 - - [06/May/2015 07:53:46] "POST /openflow/0000000000000001/bgp HTTP/1.1" 200 260 0.302049
2015-05-06 07:53:51,971 - ryu.lib.hub - INFO - (79) accepted ('127.0.0.1', 57392)
2015-05-06 07:53:51,977 - bgpspeaker.api.base - INFO - API method neighbor.create called with args: {'connect_mode': 'both', 'remote_as': 65010, 'cap_mbgp_vpnv6': False, 'cap_mbgp_vpnv4': True, 'cap_mbgp_ipv6': False, 'is_next_hop_self': True, 'cap_mbgp_ipv4': True, 'multi_exit_disc': 100, 'is_route_server_client': False, 'peer_next_hop': None, 'password': None, 'ip_address': '192.168.101.101'}
2015-05-06 07:53:51,981 - ryu.lib.hub - INFO - 127.0.0.1 - - [06/May/2015 07:53:51] "POST /openflow/0000000000000001/interface HTTP/1.1" 200 459 0.007098
.
..snip

Dockerコンテナを確認してみます

$ docker ps
CONTAINER ID        IMAGE                         COMMAND             CREATED             STATUS              PORTS               NAMES
237a076d04f9        ttsubo/test-server:latest     "/bin/bash"         7 minutes ago       Up 7 minutes                            TestServer          
45e6942c3516        ttsubo/simple-router:latest   "/bin/bash"         7 minutes ago       Up 7 minutes                            BGP6                
b73eb44a1998        ttsubo/simple-router:latest   "/bin/bash"         7 minutes ago       Up 7 minutes                            BGP5                
7ea4819f8121        ttsubo/simple-router:latest   "/bin/bash"         7 minutes ago       Up 7 minutes                            BGP4                
4d597bb57e13        ttsubo/simple-router:latest   "/bin/bash"         7 minutes ago       Up 7 minutes                            BGP3                
cb110daaf7bf        ttsubo/simple-router:latest   "/bin/bash"         7 minutes ago       Up 7 minutes                            BGP2                
92ec4528d4a8        ttsubo/simple-router:latest   "/bin/bash"         7 minutes ago       Up 7 minutes                            BGP1                
a6cf21d3fcf0        ttsubo/pc-term:latest         "/bin/bash"         7 minutes ago       Up 7 minutes                            pc2                 
76472b045e38        ttsubo/pc-term:latest         "/bin/bash"         7 minutes ago       Up 7 minutes                            pc1

Dockerコンテナが正しく動作すると、こんな感じのトポロジ構成が自動構築されます。
f:id:ttsubo:20150506172710j:plain

▪️基本動作を確認してみる

Docker起動が完了したら、新たなターミナルからDockerコンテナにアクセスしてみます。
以降、Docker環境を起動したターミナルを使用してしまうとデバック情報などの標準出力が割り込まれてしまい可読性が低下してしまいます。ご注意ください。
まずは、PC1のコンテナに入ってみて、PC2に宛にping疎通を行ってみます。

$ docker exec -it pc1 bash
root@pc1:/# ping 192.168.2.101
PING 192.168.2.101 (192.168.2.101) 56(84) bytes of data.
64 bytes from 192.168.2.101: icmp_seq=1 ttl=64 time=38.1 ms
64 bytes from 192.168.2.101: icmp_seq=2 ttl=64 time=51.8 ms
64 bytes from 192.168.2.101: icmp_seq=3 ttl=64 time=30.2 ms
64 bytes from 192.168.2.101: icmp_seq=4 ttl=64 time=40.4 ms
64 bytes from 192.168.2.101: icmp_seq=5 ttl=64 time=30.2 ms
^C
--- 192.168.2.101 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4007ms
rtt min/avg/max/mdev = 30.230/38.175/51.809/7.965 ms

次に、PC1が直結されたBGP3のコンテナに入ってみて、show-ribを確認してみます。
PC2宛の通信は、ネクストホップとしてBGP1経由のルーティング経路が選定されている様子が確認できます。

$ docker exec -it BGP3 bash
root@BGP3:~# cd simpleRouter/rest-client/
root@BGP3:~/simpleRouter/rest-client# ./get_rib.sh 
======================================================================
get_rib
======================================================================
/openflow/0000000000000001/rib
----------
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: application/json; charset=UTF-8
header: Content-Length: 459
header: Date: Wed, 06 May 2015 08:06:01 GMT
+++++++++++++++++++++++++++++++
2015/05/06 08:06:01 : Show rib 
+++++++++++++++++++++++++++++++
Status codes: * valid, > best
Origin codes: i - IGP, e - EGP, ? - incomplete
     Network                          Labels   Next Hop             Reason          Metric LocPrf Path
 *>  65010:101:192.168.2.101/32       [600]    192.168.105.101      Only Path       100    100    65010 ?
 *>  65010:101:192.168.1.102/32       [300]    0.0.0.0              Only Path                     ?

さらに、BGP1をコンテナ停止させてみて、直後に、PC1のコンテナから再度、ping疎通を実行してみます。すると、しばらくの間は、ping疎通が失敗してしまいますが、数十秒後に、ping疎通が成功するようになります。

$ docker kill BGP1
BGP1
$ docker exec -it pc1 bash
root@pc1:/# ping 192.168.2.101
PING 192.168.2.101 (192.168.2.101) 56(84) bytes of data.
64 bytes from 192.168.2.101: icmp_seq=33 ttl=64 time=35.9 ms
64 bytes from 192.168.2.101: icmp_seq=34 ttl=64 time=38.8 ms
64 bytes from 192.168.2.101: icmp_seq=35 ttl=64 time=37.4 ms
64 bytes from 192.168.2.101: icmp_seq=36 ttl=64 time=34.7 ms
64 bytes from 192.168.2.101: icmp_seq=37 ttl=64 time=36.0 ms
^C
--- 192.168.2.101 ping statistics ---
37 packets transmitted, 5 received, 86% packet loss, time 36080ms
rtt min/avg/max/mdev = 34.770/36.627/38.837/1.401 ms
root@pc1:/# exit

再度、BGP3のコンテナからshow-ribを確認してみます。
PC2宛の通信は、ネクストホップとしてBGP2経由のルーティング経路が選定されている様子が確認できます。

$ docker exec -it BGP3 bash
root@BGP3:~# cd simpleRouter/rest-client/
root@BGP3:~/simpleRouter/rest-client# ./get_rib.sh 
======================================================================
get_rib
======================================================================
/openflow/0000000000000001/rib
----------
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: application/json; charset=UTF-8
header: Content-Length: 459
header: Date: Wed, 06 May 2015 08:12:31 GMT
+++++++++++++++++++++++++++++++
2015/05/06 08:12:31 : Show rib 
+++++++++++++++++++++++++++++++
Status codes: * valid, > best
Origin codes: i - IGP, e - EGP, ? - incomplete
     Network                          Labels   Next Hop             Reason          Metric LocPrf Path
 *>  65010:101:192.168.2.101/32       [600]    192.168.106.101      Only Path       200    100    65010 ?
 *>  65010:101:192.168.1.102/32       [300]    0.0.0.0              Only Path                     ?

ひととおり、MPLS-VPNが正しく動作していることが確認できたので、Docker環境を停止します。
このあたりの操作感については、Immutable Infrastructureな体験が実感できて、ナイスです。

$ ./simpleRouter.sh stop
...snip

▪️おわりに

今回は、Docker環境を活用すれば、面倒な設定手順をスキップしてお手軽に、MPLS-VPNが体験できることが確認できました。

Ryu BGPSpeakerの実践活用へのチャレンジ 〜BMPの基本確認編〜

以前、Ryu BGPSpeakerを活用して、OpenFlowベースのBGPルータとして動作するところまで確認できました。
詳細は、slideshareにアップしておきました。
今回は、BGPプロトコルモニタリング機能を試してみます。

RyuBGPSpeakerを活用したOpenFlow簡易ルータを試してみた

◆BGPネットワーク環境準備

本来、BMPクライアントが動作可能なBGPルータ機器を手に入れるには、金銭面で相当ハードルが高いところです。
ところが、Ryu BGPSpeakerでは、すでに、BMP(BGP Monitoring Protocol)機能が利用できます。
以下に、Ryu BGPSpeakerを活用したBMP環境構築の一例を記載しておきます。
simpleRouter/README.md at v0.4 · ttsubo/simpleRouter · GitHub

◆Ryuアプリ"bmpstation.py"を試してみる

本家、Ryuプロジェクトでは、すでにBMP Serverがリリースされております。
Ryu BMP Server

早速、BMPを動かしてみます。カレントディレクトリに、ryu_bmp.log が保存されます。
確かに、BGPプロトコルモニタリングは可能みたいですが、知りたい情報が直感的に把握しずらいのが難点です。
(BGPメッセージが実際にやりとりされたタイムスタンプも確認しずらい...)

$ ryu-manager --verbose bmpstation.py
loading app bmpstation.py
instantiating app bmpstation.py of BMPStation
BRICK bmpstation
listening on 0.0.0.0:11019
BMP client connected, ip=192.168.0.101, port=57509
2014 Dec 28 08:54:48 | 192.168.0.101 | BMPInitiation(info=[{'type': 0, 'value': u'This is Ryu BGP BMP message', 'len': 27}],len=37,type=4,version=3)

2014 Dec 28 08:54:48 | 192.168.0.101 | BMPPeerUpNotification(is_post_policy=False,len=162,local_address='192.168.201.101',local_port=59505,peer_address='192.168.201.1',peer_as=65001,peer_bgp_id='10.0.0.1',peer_distinguisher=0,peer_type=0,received_open_message=BGPOpen(bgp_identifier='10.0.0.1',hold_time=180,len=53,my_as=65001,opt_param=[BGPOptParamCapabilityMultiprotocol(afi=1,cap_code=1,cap_length=4,length=6,reserved=0,safi=1,type=2), BGPOptParamCapabilityCiscoRouteRefresh(cap_code=128,cap_length=0,length=2,type=2), BGPOptParamCapabilityRouteRefresh(cap_code=2,cap_length=0,length=2,type=2), BGPOptParamCapabilityFourOctetAsNumber(as_number=65001,cap_code=65,cap_length=4,length=6,type=2)],opt_param_len=24,type=1,version=4),remote_port=179,sent_open_message=BGPOpen(bgp_identifier='10.0.1.1',hold_time=40,len=41,my_as=65002,opt_param=[BGPOptParamCapabilityMultiprotocol(afi=1,cap_code=1,cap_length=4,length=6,reserved=0,safi=1,type=2), BGPOptParamCapabilityRouteRefresh(cap_code=2,cap_length=0,length=2,type=2)],opt_param_len=12,type=1,version=4),timestamp=1419720539.120414,type=3,version=3)

2014 Dec 28 08:54:48 | 192.168.0.101 | BMPRouteMonitoring(bgp_update=BGPUpdate(len=54,nlri=[BGPNLRI(addr='192.168.0.0',length=24)],path_attributes=[BGPPathAttributeNextHop(flags=64,length=4,type=3,value='192.168.201.101'), BGPPathAttributeOrigin(flags=64,length=1,type=1,value=2), BGPPathAttributeAsPath(flags=64,length=6,type=2,value=[[65002, 65001]]), BGPPathAttributeMultiExitDisc(flags=128,length=4,type=4,value=100)],total_path_attribute_len=27,type=2,withdrawn_routes=[],withdrawn_routes_len=0),is_post_policy=True,len=102,peer_address='192.168.201.1',peer_as=65001,peer_bgp_id='10.0.0.1',peer_distinguisher=0,peer_type=0,timestamp=1419720540.0,type=0,version=3)

2014 Dec 28 08:54:48 | 192.168.0.101 | BMPRouteMonitoring(bgp_update=BGPUpdate(len=55,nlri=[BGPNLRI(addr='10.0.0.1',length=32)],path_attributes=[BGPPathAttributeNextHop(flags=64,length=4,type=3,value='192.168.201.101'), BGPPathAttributeOrigin(flags=64,length=1,type=1,value=2), BGPPathAttributeAsPath(flags=64,length=6,type=2,value=[[65002, 65001]]), BGPPathAttributeMultiExitDisc(flags=128,length=4,type=4,value=100)],total_path_attribute_len=27,type=2,withdrawn_routes=[],withdrawn_routes_len=0),is_post_policy=True,len=103,peer_address='192.168.201.1',peer_as=65001,peer_bgp_id='10.0.0.1',peer_distinguisher=0,peer_type=0,timestamp=1419720540.0,type=0,version=3)

2014 Dec 28 08:54:48 | 192.168.0.101 | BMPRouteMonitoring(bgp_update=BGPUpdate(len=54,nlri=[BGPNLRI(addr='172.16.101.0',length=24)],path_attributes=[BGPPathAttributeNextHop(flags=64,length=4,type=3,value='192.168.201.101'), BGPPathAttributeOrigin(flags=64,length=1,type=1,value=2), BGPPathAttributeAsPath(flags=64,length=6,type=2,value=[[65002, 65001]]), BGPPathAttributeMultiExitDisc(flags=128,length=4,type=4,value=100)],total_path_attribute_len=27,type=2,withdrawn_routes=[],withdrawn_routes_len=0),is_post_policy=True,len=102,peer_address='192.168.201.1',peer_as=65001,peer_bgp_id='10.0.0.1',peer_distinguisher=0,peer_type=0,timestamp=1419720540.0,type=0,version=3)

... snip

◆自作サンプル"sample_bmpServer.py"を試してみる

本家、RyuプロジェクトのBMP Serverでは、詳細なログ保存としての活用シーンを想定しているみたいです。
手軽にBGP経路情報を確認してみたいという活用シーンでは、ちょっと、つらいところです。
そこで、自作サンプルを試してみます。vpnv4には未対応ですけど。
simpleRouter/sample_bmpServer.py at v0.4 · ttsubo/simpleRouter · GitHub

自分が知りたいBGP経路情報について、直感的に把握しやすいように、表示項目を絞ってみました。
ちなみに、表示項目のタイムスタンプは、BMP情報を受信した時刻ではなく、BGPメッセージ受信時のタイムスタンプを表示しております。

$ cd simpleRouter/other/
$ python sample_bmpServer.py
Start BMP session!! [192.168.0.101]
192.168.0.101 | 2014/12/28 07:48:59 65001 10.0.0.1 | BGP_PeerUp
192.168.0.101 | 2014/12/28 07:49:00 65001 10.0.0.1 | BGP_Update(add_prefix:192.168.0.0/24    , nexthop:192.168.201.101)
192.168.0.101 | 2014/12/28 07:49:00 65001 10.0.0.1 | BGP_Update(add_prefix:10.0.0.1/32       , nexthop:192.168.201.101)
192.168.0.101 | 2014/12/28 07:49:00 65001 10.0.0.1 | BGP_Update(add_prefix:172.16.101.0/24   , nexthop:192.168.201.101)
192.168.0.101 | 2014/12/28 07:49:00 65001 10.0.0.1 | BGP_Update(add_prefix:192.168.201.0/24  , nexthop:192.168.201.101)
192.168.0.101 | 2014/12/28 07:49:00 65001 10.0.0.1 | BGP_Update(add_prefix:172.16.104.0/24   , nexthop:192.168.201.101)
192.168.0.101 | 2014/12/28 07:49:00 65001 10.0.0.1 | BGP_Update(add_prefix:172.16.102.0/24   , nexthop:192.168.201.101)
192.168.0.101 | 2014/12/28 07:49:00 65001 10.0.0.1 | BGP_Update(add_prefix:192.168.202.0/24  , nexthop:192.168.201.101)
192.168.0.101 | 2014/12/28 07:49:00 65001 10.0.0.1 | BGP_Update(add_prefix:0.0.0.0/0         , nexthop:192.168.201.101)
192.168.0.101 | 2014/12/28 07:49:00 65001 10.0.0.1 | BGP_Update(add_prefix:172.16.103.0/24   , nexthop:192.168.201.101)
192.168.0.101 | 2014/12/28 07:49:00 65001 10.0.0.1 | BGP_Update(add_prefix:192.168.100.0/24  , nexthop:192.168.201.101)
192.168.0.101 | 2014/12/28 07:49:00 65001 10.0.0.1 | BGP_Update(add_prefix:10.0.0.2/32       , nexthop:192.168.201.101)
192.168.0.101 | 2014/12/28 07:49:04 65002 10.0.1.3 | BGP_PeerUp
192.168.0.101 | 2014/12/28 07:49:05 65002 10.0.1.3 | BGP_Update(add_prefix:192.168.0.0/24    , nexthop:172.16.201.101 )
192.168.0.101 | 2014/12/28 07:49:05 65002 10.0.1.3 | BGP_Update(add_prefix:172.16.202.0/24   , nexthop:172.16.201.101 )
192.168.0.101 | 2014/12/28 07:49:05 65002 10.0.1.3 | BGP_Update(add_prefix:10.0.1.3/32       , nexthop:172.16.201.101 )
192.168.0.101 | 2014/12/28 07:49:05 65002 10.0.1.3 | BGP_Update(add_prefix:172.16.201.0/24   , nexthop:172.16.201.101 )
192.168.0.101 | 2014/12/28 07:49:05 65002 10.0.1.3 | BGP_Update(add_prefix:192.168.101.0/24  , nexthop:172.16.201.101 )
192.168.0.101 | 2014/12/28 07:49:05 65002 10.0.1.3 | BGP_Update(add_prefix:172.16.205.0/24   , nexthop:172.16.201.101 )

[追記(2015.3.7)]
Ryu BMPクライアント側でのBGPモニタリング情報の通知内容として、誤ったUPDATEメッセージを送信してしまう場合が発覚しましたが、すでにbug-fix済みです。それに伴い、自作ツールも修正しました。さらにvpnv4にも対応しておりますよ!
simpleRouter/sample_bmpServer.py at master · ttsubo/simpleRouter · GitHub


◆おわりに

BMPを活用したBGPプロトコルモニタリング機能を試してみました。まず、障害原因特定などのネットワーク運用の視点での活用が注目されるところです。今後は、上位アプリ連携を想定した経路探索などの活用にも期待できそうです。

Ryu BGPSpeakerの実践活用へのチャレンジ 〜BGP/OpenFlow連携編〜

これまで、OpenFlow簡易ルータ作成を通じて、SDN/OpenFlow的な実装テクニックでも市販ルータ相当なIPルーティング制御が可能であることを確認してきました。しかしながら、これまでのOpenFlow簡易ルータでは、デフォルト・ルーティングしか対応していないため、市販ルータと比べてみるとルーティング機能面で、相当見劣りする現状だと思います。SDN/OpenFlow的な実装テクニックの学習素材と割り切る場合には、これで十分なんでしょうけど。
ところで、最近、Ryu SDN FrameworkにてBGPSpeaker機能が利用できるようになったようです。そこで、OpenFlow簡易ルータでも、BGP機能を取り込んだ上で、ルーティング機能拡充にチャレンジしてみます。

◆まずは、BGPSpeakerを試してみる

Ryu ドキュメントに記載されているBGP Speakerを動かしてみるところからはじめます。
BGP speaker library — Ryu 3.15 documentation

0. 目標感

「家庭LANとPC端末との間を、BGPSpeakerを介して接続した場合、PC端末〜インタネット回線までの途中経路区間でのルーティング情報の配布が正しく行えるかどうかを確認する。」という目標感で、動作環境を構築しました。

1. 動作環境

Ryu SDN FrameworkのBGPSpeaker機能を試してみるにあたり、BGPルータが必要となります。
市販のBGPルータを購入するほど、家計に余力がないので、極力安価に環境整備が実現できる方法として、OpenWRT化したBuffaloルータにQuaggaをインストールして対応しました。
f:id:ttsubo:20141129125434j:plain

Ryuコントローラは、以下のパッチ導入後のバージョンを配備する必要があります。必要に応じてアップデートを行ってください。
[bgp: bug fix of handling nexthop for eBGP peering · aa497ed · osrg/ryu · GitHub

2. BGPルータ(Quagga1)動作確認

以下のコンフィグ設定を行った上で、BGPテーブルを確認しておきます。

Quagga-1# sh run
Building configuration...

Current configuration:
!
!
password zebra
!
interface eth0
 ipv6 nd suppress-ra
!
interface eth0.1
 ip address 192.168.200.1/24
 ipv6 nd suppress-ra
!
interface eth0.2
 ip address 192.168.100.100/24
 ipv6 nd suppress-ra
!
interface eth0.3
 ip address 172.16.101.1/24
 ipv6 nd suppress-ra
!
interface eth0.4
 ip address 172.16.102.1/24
 ipv6 nd suppress-ra
!
interface eth0.5
 ipv6 nd suppress-ra
!
interface lo
 ip address 10.0.0.1/32
!
router bgp 65001
 bgp router-id 10.0.0.1
 redistribute connected
 redistribute static
 neighbor 192.168.200.100 remote-as 65002
!
ip route 0.0.0.0/0 192.168.100.1
!
access-list vty permit 127.0.0.0/8
access-list vty deny any
!
ip forwarding
ipv6 forwarding
!
line vty
 access-class vty
!
end

BGPルータ(Quagga1)では、複数のPrefix経路情報がBGPテーブルに保持されている様子が確認できます。

Quagga-1# sh ip bgp
BGP table version is 0, local router ID is 10.0.0.1
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale, R Removed
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*> 0.0.0.0          192.168.100.1            0         32768 ?
*> 10.0.0.1/32      0.0.0.0                  1         32768 ?
*> 172.16.101.0/24  0.0.0.0                  1         32768 ?
*> 172.16.102.0/24  0.0.0.0                  1         32768 ?
*> 192.168.0.0      0.0.0.0                  1         32768 ?
*> 192.168.100.0    0.0.0.0                  1         32768 ?
*> 192.168.200.0    0.0.0.0                  1         32768 ?

Total number of prefixes 7

3. BGPSpeakerサンプルコード

今回のサンプル(sampleBGP.py)は、こんな感じです。

import eventlet

# BGPSpeaker needs sockets patched
eventlet.monkey_patch()


from ryu.services.protocols.bgp.bgpspeaker import BGPSpeaker

def dump_remote_best_path_change(event):
    print 'the best path changed:', event.remote_as, event.prefix,\
        event.nexthop, event.is_withdraw

if __name__ == "__main__":
    speaker = BGPSpeaker(as_number=65002, router_id='10.0.0.2',
                         best_path_change_handler=dump_remote_best_path_change,
                         ssh_console=True)

    speaker.neighbor_add('192.168.200.1', 65001)
    prefix = '192.168.101.0/24'
    speaker.prefix_add(prefix='192.168.101.0/24', next_hop='192.168.201.1')
    eventlet.sleep(3000)

4. 動作確認結果

「sampleBGP.py」サンプルコードの実行は、ルート権限で行います。
BGPルータ(Quagga1)で保持しているPrefix情報を受信した様子が確認できました。

$ sudo python ./sampleBGP.py 
the best path changed: 65001 0.0.0.0/0 192.168.200.1 False
the best path changed: 65001 10.0.0.1/32 192.168.200.1 False
the best path changed: 65001 192.168.200.0/24 192.168.200.1 False
the best path changed: 65001 192.168.100.0/24 192.168.200.1 False
the best path changed: 65001 192.168.0.0/24 192.168.200.1 False
the best path changed: 65001 172.16.102.0/24 192.168.200.1 False
the best path changed: 65001 172.16.101.0/24 192.168.200.1 False

再度、BGPルータ(Quagga1)でBGPテーブルを参照してみると、「192.168.101.0」経路が追加されている様子が確認できました。

Quagga-1# sh ip bgp
BGP table version is 0, local router ID is 10.0.0.1
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale, R Removed
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*> 0.0.0.0          192.168.100.1            0         32768 ?
*> 10.0.0.1/32      0.0.0.0                  1         32768 ?
*> 172.16.101.0/24  0.0.0.0                  1         32768 ?
*> 172.16.102.0/24  0.0.0.0                  1         32768 ?
*> 192.168.0.0      0.0.0.0                  1         32768 ?
*> 192.168.100.0    0.0.0.0                  1         32768 ?
*> 192.168.101.0    192.168.200.100                        0 65002 i
*> 192.168.200.0    0.0.0.0                  1         32768 ?

Total number of prefixes 8

BGPSpeakerでは、豊富なAPIが提供されているので、BGP自体を動作されるのは、それほど難しいことではありません。
でも、BGPSpeakerが、やってくれることは、あくまでもBGP制御によるPrefix経路の配布管理です。
実際に、PC端末がインターネットと通信できるようなデータプレーン構築機能は有しておりません。
そこで、これまでのOpenFlow簡易ルータとのBGP連携により、データプレーン構築を含めた動作確認にチャレンジしてみます。

◆BGP版OpenFlow簡易ルータ構築

PC端末がインターネット通信できるようにするためには、途中経路のデータプレーンを適切に構築する必要があります。そこで、OpenFlow簡易ルータでのBGP/OpenFlow連携の機能拡充を行いました。これにより、BGPSpeakerが対向BGPルータからPrefix経路情報を取得した場合、OpenFlowスイッチ上にFlowエントリを設定できるようになります。
f:id:ttsubo:20141129135107j:plain

1. プログラムの入手

BGP版OpenFlow簡易ルータのプログラム一式を以下のサイトからダウンロードできます。
Release OpenFlow簡易ルータ(BGP統合版) · ttsubo/simpleRouter · GitHub

あくまでも、BGP/OpenFlow実装テクニックの学習素材なので、実用性を想定した実装は一切行っておりません... (^_^;)

2. 環境構築

f:id:ttsubo:20141129135822j:plain

実際の環境構築として、OpenFlowスイッチは、RB750GLを使用しました。実際の構築手順は、こちらのブログ記事を参考にしてください。

RouterBOARD (RB750GL)のOpenFlow化へのチャレンジ 〜OpenvSwitch構築手順メモ編〜 - SDN開発エンジニアを目指した活動ブログ

なお、実際のLANケーブル結線は、こんな感じです。
f:id:ttsubo:20141129140647j:plain

あと、RB750GL上にて、LANケーブル結線に応じたOVSポート追加を行います。

root@OpenWrt:~# ovs-vsctl add-port br0 eth0.4

OpenFlowスイッチでの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
 3(eth0.4): 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

つぎに、Ryuコントローラ側の設定です。
まずは、BGPルータとの隣接関係を構築するために、新たに、NIC追加を行い、IPアドレス"192.168.200.100"を付与します。
さらに、OpenFlow簡易ルータ構成に関わるOpenFlow.ini ファイルの初期設定を行います。
"Port1"のmacaddressとして設定する値は、さきほどのIPアドレス"192.168.200.100"として追加したNICに割り当てられているMACアドレスです。動作させる環境に応じて適切なMACアドレスを設定してください。

$ cd simpleRouter-0.2/rest-client/
$ vi OpenFlow.ini 
[Port1]
port = "1"
macaddress = "xx:xx:xx:xx:x:xx"
ipaddress = "192.168.200.100"
netmask = "255.255.255.0"
opposite_ipaddress = "192.168.200.1"
opposite_asnumber = "65001"
port_offload_bgp = "3"

[Port2]
port = "2"
macaddress = "00:00:00:00:00:02"
ipaddress = "192.168.201.100"
netmask = "255.255.255.0"
opposite_ipaddress = "192.168.201.1"
opposite_asnumber = ""
port_offload_bgp = ""

[Gateway]
ipaddress = "192.168.200.1"

3. 実行開始

BGP版OpenFlow簡易ルータをルート権限で起動します。

$ sudo 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 None of SimpleBGPSpeaker
creating context bgps
instantiating app openflowRouter.py of OpenflowRouter
instantiating app ryu.controller.ofp_handler of OFPHandler
API method core.start called with args: {'router_id': '10.0.0.2', 'label_range': (100, 100000), 'waiter': <ryu.lib.hub.Event object at 0x1058a6450>, 'local_as': 65002, 'bgp_server_port': 179, 'refresh_max_eor_time': 0, 'refresh_stalepath_time': 0}
(27034) wsgi starting up on http://0.0.0.0:8080/
starting ssh server at localhost:4990

さらに別ターミナルから、REST-IF経由で、構成情報の設定を行います。

$ cd simpleRouter-0.2/rest-client/
$ ./post_interface.sh 
======================================================================
create_interface
======================================================================
/openflow/0000000000000001/interface

{
"interface": {
"port": "1",
"macaddress": "40:6c:8f:59:31:af",
"ipaddress": "192.168.200.100",
"netmask": "255.255.255.0",
"opposite_ipaddress": "192.168.200.1",
"opposite_asnumber": "65001",
"port_offload_bgp": "3"
}
}
----------
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: application/json; charset=UTF-8
header: Content-Length: 243
header: Date: Sat, 29 Nov 2014 05:28:47 GMT
----------
{
    "interface": {
        "macaddress": "40:6c:8f:59:31:af", 
        "opposite_asnumber": "65001", 
        "port_offload_bgp": "3", 
        "netmask": "255.255.255.0", 
        "opposite_ipaddress": "192.168.200.1", 
        "ipaddress": "192.168.200.100", 
        "port": "1"
    }, 
    "id": "0000000000000001"
}

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

{
"interface": {
"port": "2",
"macaddress": "00:00:00:00:00:02",
"ipaddress": "192.168.201.100",
"netmask": "255.255.255.0",
"opposite_ipaddress": "192.168.201.1",
"opposite_asnumber": "",
"port_offload_bgp": ""
}
}
----------
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: application/json; charset=UTF-8
header: Content-Length: 237
header: Date: Sat, 29 Nov 2014 05:28:52 GMT
----------
{
    "interface": {
        "macaddress": "00:00:00:00:00:02", 
        "opposite_asnumber": "", 
        "port_offload_bgp": "", 
        "netmask": "255.255.255.0", 
        "opposite_ipaddress": "192.168.201.1", 
        "ipaddress": "192.168.201.100", 
        "port": "2"
    }, 
    "id": "0000000000000001"
}


最後に、PC端末を収容しているLANセグメントを対象に、スタティックルーティング設定を行います。

$ ./post_route.sh 192.168.101.0 255.255.255.0 192.168.201.1
======================================================================
create_route
======================================================================
/openflow/0000000000000001/route

{
"route": {
"destination": "192.168.101.0",
"netmask": "255.255.255.0",
"nexthop": "192.168.201.1"
}
}
----------
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: application/json; charset=UTF-8
header: Content-Length: 125
header: Date: Sat, 29 Nov 2014 05:29:52 GMT
----------
{
    "route": {
        "destination": "192.168.101.0", 
        "netmask": "255.255.255.0", 
        "nexthop": "192.168.201.1"
    }, 
    "id": "0000000000000001"
}

OpenFlow簡易ルータで保持しているルーティングテーブル情報を確認してみます。
さきほど設定したスタティックルーティングや、BGPルータから配布されたPrefix情報が確認できました。

$ ./get_route.sh 
======================================================================
get_route
======================================================================
/openflow/0000000000000001/route
----------
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: application/json; charset=UTF-8
header: Content-Length: 1275
header: Date: Sat, 29 Nov 2014 05:31:28 GMT
+++++++++++++++++++++++++++++++
2014/11/29 14:31:28 : RoutingTable 
+++++++++++++++++++++++++++++++
prefix             nexthop
------------------ ----------------
192.168.0.0/24     192.168.200.1  
192.168.200.0/24   192.168.200.1  
0.0.0.0/0          192.168.200.1  
10.0.0.1/32        192.168.200.1  
172.16.101.0/24    192.168.200.1  
192.168.101.0/24   192.168.201.1  
172.16.102.0/24    192.168.200.1  
192.168.201.1/32   0.0.0.0        
192.168.200.1/32   0.0.0.0        
192.168.100.0/24   192.168.200.1  

BGPルータ側でのBGPテーブルも確認しておきます。

Quagga-1# sh ip bgp
BGP table version is 0, local router ID is 10.0.0.1
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale, R Removed
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*> 0.0.0.0          192.168.100.1            0         32768 ?
*> 10.0.0.1/32      0.0.0.0                  1         32768 ?
*> 172.16.101.0/24  0.0.0.0                  1         32768 ?
*> 172.16.102.0/24  0.0.0.0                  1         32768 ?
*> 192.168.0.0      0.0.0.0                  1         32768 ?
*> 192.168.100.0    0.0.0.0                  1         32768 ?
*> 192.168.101.0    192.168.200.100                        0 65002 i
*> 192.168.200.0    0.0.0.0                  1         32768 ?

Total number of prefixes 8

OpenFlowスイッチ側でのFlowテーブルも確認しておきます。

root@OpenWrt:~# ovs-ofctl dump-flows br0 --protocols=OpenFlow13
OFPST_FLOW reply (OF1.3) (xid=0x2):
 cookie=0x0, duration=262.466s, table=0, n_packets=140, n_bytes=52980, priority=15,ip,nw_dst=192.168.101.0/24 actions=set_field:00:00:00:00:00:02->eth_src,set_field:16:23:ec:ab:8d:8d->eth_dst,output:2,dec_ttl
 cookie=0x0, duration=311.750s, table=0, n_packets=0, n_bytes=0, priority=15,ip,nw_dst=172.16.102.0/24 actions=set_field:40:6c:8f:59:31:af->eth_src,set_field:96:9a:9c:c5:74:70->eth_dst,output:1,dec_ttl
 cookie=0x0, duration=312.754s, table=0, n_packets=0, n_bytes=0, priority=15,ip,nw_dst=192.168.0.0/24 actions=set_field:40:6c:8f:59:31:af->eth_src,set_field:96:9a:9c:c5:74:70->eth_dst,output:1,dec_ttl
 cookie=0x0, duration=313.758s, table=0, n_packets=146, n_bytes=11754, priority=15,ip,nw_dst=192.168.100.0/24 actions=set_field:40:6c:8f:59:31:af->eth_src,set_field:96:9a:9c:c5:74:70->eth_dst,output:1,dec_ttl
 cookie=0x0, duration=310.746s, table=0, n_packets=0, n_bytes=0, priority=15,ip,nw_dst=172.16.101.0/24 actions=set_field:40:6c:8f:59:31:af->eth_src,set_field:96:9a:9c:c5:74:70->eth_dst,output:1,dec_ttl
 cookie=0x0, duration=314.763s, table=0, n_packets=25, n_bytes=3496, priority=15,ip,nw_dst=192.168.200.0/24 actions=set_field:40:6c:8f:59:31:af->eth_src,set_field:96:9a:9c:c5:74:70->eth_dst,output:1,dec_ttl
 cookie=0x0, duration=327.431s, table=0, n_packets=129, n_bytes=9677, priority=255,ip,in_port=3,nw_dst=192.168.200.1 actions=output:1
 cookie=0x0, duration=327.431s, table=0, n_packets=115, n_bytes=9157, priority=255,ip,in_port=1,nw_dst=192.168.200.100 actions=output:3
 cookie=0x0, duration=316.770s, table=0, n_packets=211, n_bytes=31030, priority=1,ip actions=set_field:40:6c:8f:59:31:af->eth_src,set_field:96:9a:9c:c5:74:70->eth_dst,output:1,dec_ttl
 cookie=0x0, duration=327.432s, table=0, n_packets=0, n_bytes=0, priority=16,ip,nw_dst=192.168.200.100 actions=CONTROLLER:65535
 cookie=0x0, duration=315.766s, table=0, n_packets=4, n_bytes=296, priority=15,ip,nw_dst=10.0.0.1 actions=set_field:40:6c:8f:59:31:af->eth_src,set_field:96:9a:9c:c5:74:70->eth_dst,output:1,dec_ttl
 cookie=0x0, duration=322.417s, table=0, n_packets=0, n_bytes=0, priority=16,ip,nw_dst=192.168.201.100 actions=CONTROLLER:65535
 cookie=0x0, duration=330.285s, table=0, n_packets=19, n_bytes=1525, priority=0 actions=CONTROLLER:65535
 cookie=0x0, duration=327.431s, table=0, n_packets=7, n_bytes=420, priority=255,arp,in_port=1 actions=output:3,CONTROLLER:65535
 cookie=0x0, duration=327.433s, table=0, n_packets=4, n_bytes=240, priority=255,arp,in_port=3 actions=output:1,CONTROLLER:65535
 cookie=0x0, duration=274.075s, table=0, n_packets=0, n_bytes=0, priority=2,ip,in_port=2,dl_src=16:23:ec:ab:8d:8d,dl_dst=00:00:00:00:00:02,nw_dst=192.168.200.1 actions=set_field:40:6c:8f:59:31:af->eth_src,set_field:96:9a:9c:c5:74:70->eth_dst,output:1,dec_ttl
 cookie=0x0, duration=274.075s, table=0, n_packets=0, n_bytes=0, priority=2,ip,in_port=1,dl_src=96:9a:9c:c5:74:70,dl_dst=40:6c:8f:59:31:af,nw_dst=192.168.201.1 actions=set_field:00:00:00:00:00:02->eth_src,set_field:16:23:ec:ab:8d:8d->eth_dst,output:2,dec_ttl

4. 動作確認

ひととおり、PC端末からインターネット通信できるような経路設定が完了したので、さっそく、インターネットにアクセスしてみます。想定どおり、YouTubeを快適にアクセスできました。(BabyMetalのベーシストの超絶テク、いいですよね。)

f:id:ttsubo:20141129144935p:plain

OpenFlow簡易ルータを通過したトラフィック流量を確認してみました。

$ ./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: 1158
header: Date: Sat, 29 Nov 2014 05:46:45 GMT
+++++++++++++++++++++++++++++++
2014/11/29 14:46:45 : FlowStats
+++++++++++++++++++++++++++++++
inPort   ethSrc             ethDst             ipv4Dst         packets  bytes
-------- ------------------ ------------------ --------------- -------- --------
       1  96:9a:9c:c5:74:70  40:6c:8f:59:31:af   192.168.201.1        0        0
       2  16:23:ec:ab:8d:8d  00:00:00:00:00:02   192.168.200.1        0        0
       *                  *                  *   192.168.101.0    49038 67791018
       *                  *                  *   192.168.100.0      363    28728
       *                  *                  *    172.16.102.0        0        0
       *                  *                  *       0.0.0.0/0    18161  2768420
       *                  *                  *   192.168.200.0       49     6952
       *                  *                  *        10.0.0.1        4      296
       *                  *                  *     192.168.0.0        0        0
       *                  *                  *    172.16.101.0        0        0

◆おわりに

SDN/OpenFlow実装テクニックにより、BGP/OpenFlow連携によるデータプレーン構築が可能であることが確認できました。
最近のSDNテクノロジでは、集中制御から分散制御に、話題がシフトしている気がします。
今後は、「SDN分散制御における中核技術としてのBGP拡張が、どこまで具現化していくのか?」を意識しながら、Ryu BGPSpeakerの活用をいろいろと考えていきたいです。

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でのパケット転送がリアルに体感できて面白いと思います。

RouterBOARD (RB750GL)のOpenFlow化へのチャレンジ 〜OpenvSwitch構築手順メモ編〜

今回は、RouterBOARD (RB750GL)をOpenFlow化して、OpenFlow基本動作を確認するというチャレンジになります。
こちらが、OpenFlow化したRouterBOARD (RB750GL)です。さらに、OpenWRT化に対応したOpenvSwitch 2.3.0版パッケージを搭載しているので、ユーザランドではなく、カーネルモジュールとして、datapathが動作する点が特徴となります。
f:id:ttsubo:20141102183626j:plain

◆これまでのOpenFlow化の経緯

以前、RouterBOARD (RB750GL)のOpenFlow動作の評価を実施しましたが、OpenFlow機能の実用化の視点では、期待はずれでした。


いっぽう、過去のブログ記事「家庭用BuffaloルータのOpenFlow化へのチャレンジ 〜OpenvSwitch構築手順メモ編〜」で紹介したとおり、Buffalo”BHR-4GRV"でもOpenvSwitch構築が可能でした。安価にOpenFlow化にチャレンジするには、よい素材だと思います。

最近になって、一部のオープンソースコミュニテイの間で、RouterBOARDのOpenWRT化が話題になってきました。
さらに、「OpenvSwitchも搭載してOpenFlow機器として安価に構築してみよう!」という活動報告を入手できましたので、今回、実際にOpenvSwitch構築にチャレンジしてみました。
前回のBuffaloルータとの違いは、RouterBOARDのOpenWRT化コミュニテイ有志の尽力により、OpenvSwitch/OpenWRTの構築に必要なソフトウェア資材が、インタネット上のリポジトリに公開されているため、実際の構築手順が、だいぶ簡潔になった点が挙げられます。

◆構築手順の流れ

まずは、RouterBOARD (RB750GL)を用いて、OpenFlowスイッチ台数を増やすことを想定して、OpenvSwitch構築手順をメモっておきます。おおまかな構築手順の流れは、こんな感じです。

(1) RB750GLのOpenWRT化
(2) OpenvSwitchパッケージのインストール
(3) OpenWRTのネットワーク設定
(4) OpenvSwitchの各種設定

◆RB750GLのOpenWRT化

本構築手順は、MacBookMac OS X)での作業を想定しております。
注) ここでの構築手順は、個人の構築メモとして掲載しております。
 (RouterBOARD”RB750GL"が文鎮化してしまうなどの不測な事態が発生しても、あくまでも、自己責任でお願いします。)

こちらの記事がOpenWRT構築の参考にさせて頂きました。

1. RB750GL構成イメージ

RB750GLのOpenWRT化には、NICポートへのLANケーブルの抜き差しが多数発生しますので、参考までに、最終的にOpenWRT構築するRB750GL構成イメージを掲載しておきます。

f:id:ttsubo:20141102195200j:plain

2. initramfsのダウンロード

公開リポジトリIndex of /openwrt/r43011-ovs/trunk/ar71xx.mikrotik/)より
"openwrt-ar71xx-mikrotik-vmlinux-initramfs-lzma.elf"をダウンロードし、MacBookのローカルディスクに置いておきます。

3. BOOTモード変更

RB750GLの2番ポートから、telnetログインして次回のBOOTモードを変更する。

> ssh admin@192.168.88.1

事前の設定内容を確認する。

[admin@MikroTik] /system routerboard settings> print
          boot-device: nand-if-fail-then-ethernet
        cpu-frequency: 400MHz
        boot-protocol: bootp
  force-backup-booter: no
          silent-boot: no

BOOTモードを変更する。

[admin@MikroTik] > /system routerboard settings set boot-device=try-ethernet-once-then-nand

変更後の設定内容を確認する。

[admin@MikroTik] /system routerboard settings> print 
          boot-device: try-ethernet-once-then-nand
        cpu-frequency: 400MHz
        boot-protocol: bootp
  force-backup-booter: no
          silent-boot: no

4. 作業PC側でのdnsmasq起動

作業PC(MacBook)のUSB-LAN Port設定(en2)のIPアドレスを設定する。

> sudo ifconfig en2 192.168.1.99

事前に、dnsmasqインストールを行った上で、dnsmasqを起動する。
なお、dnsmasqの引数パラメータとして指定する内容については、
user: tsubo
tftp-root: /Users/t_tsubo2000/openwrt
として作業を行った。

> sudo /usr/local/opt/dnsmasq/sbin/dnsmasq -i en2  --dhcp-range=192.168.1.100,192.168.1.200 --dhcp-boot=openwrt-ar71xx-mikrotik-vmlinux-initramfs-lzma.elf --enable-tftp --tftp-root=/Users/t_tsubo2000/openwrt -d -u tsubo -p0 -K --log-dhcp --bootp-dynamic

5. initramfsの転送開始

RB750GLの1番ポートに差し替えて、しばらく待つとinitramfsが転送されるので、しばらくしてから、RB再起動する。1番ポートのLED点滅が完了するまで、しばらく待つ。

6. RB750GLへの初回ログイン

RB750GLの2番ポートに差し替えて、RB750GLにログインする。

> telnet 192.168.1.1
Trying 192.168.1.1...
Connected to 192.168.1.1.
Escape character is '^]'.
 === IMPORTANT ============================
  Use 'passwd' to set your login password
  this will disable telnet and enable SSH
 ------------------------------------------


BusyBox v1.22.1 (2014-10-25 16:27:26 JST) built-in shell (ash)
Enter 'help' for a list of built-in commands.

  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
 -----------------------------------------------------
 CHAOS CALMER (Bleeding Edge, r43011)
 -----------------------------------------------------
  * 1 1/2 oz Gin            Shake with a glassful
  * 1/4 oz Triple Sec       of broken ice and pour
  * 3/4 oz Lime Juice       unstrained into a goblet.
  * 1 1/2 oz Orange Juice
  * 1 tsp. Grenadine Syrup
 -----------------------------------------------------
root@OpenWrt:/#

現在のNICポート情報を確認する。

root@OpenWrt:/# ifconfig
br-lan    Link encap:Ethernet  HWaddr D4:CA:6D:73:14:8B  
          inet addr:192.168.1.1  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fd51:9f97:adc0::1/60 Scope:Global
          inet6 addr: fe80::d6ca:6dff:fe73:148b/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:172 errors:0 dropped:0 overruns:0 frame:0
          TX packets:117 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:25189 (24.5 KiB)  TX bytes:13656 (13.3 KiB)

eth0      Link encap:Ethernet  HWaddr D4:CA:6D:73:14:8B  
          inet6 addr: fe80::d6ca:6dff:fe73:148b/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:314 errors:0 dropped:1 overruns:0 frame:0
          TX packets:137 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:70007 (68.3 KiB)  TX bytes:16790 (16.3 KiB)
          Interrupt:4 

eth0.1    Link encap:Ethernet  HWaddr D4:CA:6D:73:14:8B  
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:235 errors:0 dropped:0 overruns:0 frame:0
          TX packets:111 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:44285 (43.2 KiB)  TX bytes:13060 (12.7 KiB)

eth0.2    Link encap:Ethernet  HWaddr D4:CA:6D:73:14:8B  
          inet addr:192.168.1.134  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::d6ca:6dff:fe73:148b/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:74 errors:0 dropped:0 overruns:0 frame:0
          TX packets:22 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:19528 (19.0 KiB)  TX bytes:2750 (2.6 KiB)

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:529 errors:0 dropped:0 overruns:0 frame:0
          TX packets:529 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:36808 (35.9 KiB)  TX bytes:36808 (35.9 KiB)

7. OpenWRTファームウェア設定の事前準備

OpenWRTファームウェアを公開リポジトリからダウンロードできるよう、インタネット利用可能なネットワークセグメント(192.168.100.0/24)に、RB750GLの1番ポートを接続し、RB750GLの1番ポートの設定変更を行う。
なお、1番ポートのifconfig down/upを行っても、DHCPでの自動IPアドレス設定が行われなかったので、必要な諸設定を手作業で実施した。

root@OpenWrt:/# ifconfig eth0.2 192.168.100.134
  • 名前解決の設定
root@OpenWrt:/etc# vi /etc/resolv.conf 
search lan
nameserver 127.0.0.1
nameserver 192.168.100.1
  • デフォルトルート設定
root@OpenWrt:~# route add -net default dev eth0.2 gateway 192.168.100.1
root@OpenWrt:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.100.1   0.0.0.0         UG    0      0        0 eth0.2
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 br-lan
192.168.100.0   0.0.0.0         255.255.255.0   U     0      0        0 eth0.2

8. OpenWRTファームウェア有効化

古い設定ファイルの削除しておく。

root@OpenWrt:/# mtd erase kernel
Unlocking kernel ...
Erasing kernel ...
root@OpenWrt:/# mtd erase rootfs
Unlocking rootfs ...
Erasing rootfs ...

公開リポジトリIndex of /openwrt/r43011-ovs/trunk/ar71xx.mikrotik/)より、OpenWRTファームウェアの書き込みを行う。

root@OpenWrt:~# wget2nand http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik
Connecting to rb-openwrt-test.mydns.jp (157.7.235.137:80)
kernel               100% |*******************************|  1129k  0:00:00 ETA
Connecting to rb-openwrt-test.mydns.jp (157.7.235.137:80)
rootfs.tgz           100% |*******************************|  2406k  0:00:00 ETA
Erasing filesystem...
Mounting /dev/mtdblock2 as new root and /dev/mtdblock1 as kernel partition
Copying kernel...
Preparing filesystem...
./
./etc/
./etc/resolv.conf
./etc/hotplug-preinit.json
./etc/firewall.user
./etc/hosts
./etc/sysupgrade.conf

…(snip)

./sys/
./rom/
./rom/note
Cleaning up...
Image written, you can now reboot.  Remember to change the boot source to Boot from Nand

OpenWRTを再起動する。

root@OpenWrt:~# reboot

9. SSH疎通の設定

RB750GLの1番ポート(WANポート)でのSSHログインが可能なように、firewall設定を行う。
まずは、RB750GLの2番ポートからtelnetログインする。

> telnet 192.168.1.1
Trying 192.168.1.1...
Connected to 192.168.1.1.
Escape character is '^]'.
 === IMPORTANT ============================
  Use 'passwd' to set your login password
  this will disable telnet and enable SSH
 ------------------------------------------


BusyBox v1.22.1 (2014-10-25 16:27:26 JST) built-in shell (ash)
Enter 'help' for a list of built-in commands.

 ############ Routerboard User's Group JP ############
  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
 -----------------------------------------------------
 CHAOS CALMER (Bleeding Edge, r43011 with OVS)
 -----------------------------------------------------
  * 1 1/2 oz Gin            Shake with a glassful
  * 1/4 oz Triple Sec       of broken ice and pour
  * 3/4 oz Lime Juice       unstrained into a goblet.
  * 1 1/2 oz Orange Juice
  * 1 tsp. Grenadine Syrup
 -----------------------------------------------------

RB750GLの1番ポート(wan)は、eth0.2対応付けられている。よって、インタネット利用可能なネットワークセグメント側のDHCPから”192.168.100.9”が自動付与されていることを確認する。

root@OpenWrt:~# ifconfig
br-lan    Link encap:Ethernet  HWaddr D4:CA:6D:73:14:8B  
          inet addr:192.168.1.1  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fdaa:b9c8:e3b0::1/60 Scope:Global
          inet6 addr: fe80::d6ca:6dff:fe73:148b/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1166 errors:0 dropped:0 overruns:0 frame:0
          TX packets:579 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:174701 (170.6 KiB)  TX bytes:153478 (149.8 KiB)

eth0      Link encap:Ethernet  HWaddr D4:CA:6D:73:14:8B  
          inet6 addr: fe80::d6ca:6dff:fe73:148b/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:2267 errors:0 dropped:10 overruns:0 frame:0
          TX packets:1284 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:497542 (485.8 KiB)  TX bytes:286522 (279.8 KiB)
          Interrupt:4 

eth0.1    Link encap:Ethernet  HWaddr D4:CA:6D:73:14:8B  
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1259 errors:0 dropped:0 overruns:0 frame:0
          TX packets:567 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:200432 (195.7 KiB)  TX bytes:152262 (148.6 KiB)

eth0.2    Link encap:Ethernet  HWaddr D4:CA:6D:73:14:8B  
          inet addr:192.168.100.9  Bcast:192.168.100.255  Mask:255.255.255.0
          inet6 addr: fe80::d6ca:6dff:fe73:148b/64 Scope:Link
          inet6 addr: 240b:11:53a0:400:d6ca:6dff:fe73:148b/64 Scope:Global
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:985 errors:0 dropped:0 overruns:0 frame:0
          TX packets:712 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:251586 (245.6 KiB)  TX bytes:128654 (125.6 KiB)

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:1 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:76 (76.0 B)  TX bytes:76 (76.0 B)

rootパスワードを設定する。

root@OpenWrt:/# passwd
Changing password for root
New password: 

firewallについて、SSHに関わる設定を追加する。

# Allow SSH
config rule
	option name		Allow-ssh
	option src		wan
	option proto		tcp
	option dest_port	22
	option target		ACCEPT

firewall設定変更を有効にする。
以降、RB750GLの2番ポートと作業PC間のLANケーブリングは不要となる。

root@OpenWrt:/etc# /etc/init.d/firewall restart
Warning: Unable to locate ipset utility, disabling ipset support
 * Flushing IPv4 filter table
 * Flushing IPv4 nat table
 * Flushing IPv4 mangle table
 * Flushing IPv4 raw table
 * Flushing IPv6 filter table
 * Flushing IPv6 mangle table
 * Flushing IPv6 raw table
 * Flushing conntrack table ...
 * Populating IPv4 filter table
   * Zone 'lan'
   * Zone 'wan'
   * Rule 'Allow-DHCP-Renew'
   * Rule 'Allow-Ping'
   * Rule 'Allow-ssh'
   * Forward 'lan' -> 'wan'
 * Populating IPv4 nat table
   * Zone 'lan'
   * Zone 'wan'
 * Populating IPv4 mangle table
   * Zone 'lan'
   * Zone 'wan'
 * Populating IPv4 raw table
   * Zone 'lan'
   * Zone 'wan'
 * Populating IPv6 filter table
   * Zone 'lan'
   * Zone 'wan'
   * Rule 'Allow-DHCPv6'
   * Rule 'Allow-ICMPv6-Input'
   * Rule 'Allow-ICMPv6-Forward'
   * Rule 'Allow-ssh'
   * Forward 'lan' -> 'wan'
 * Populating IPv6 mangle table
   * Zone 'lan'
   * Zone 'wan'
 * Populating IPv6 raw table
   * Zone 'lan'
   * Zone 'wan'
 * Set tcp_ecn to off
 * Set tcp_syncookies to on
 * Set tcp_window_scaling to on
 * Running script '/etc/firewall.user'

RB750GLの1番ポート(wan)から、SSHログインする。

> ssh root@192.168.100.9
The authenticity of host '192.168.100.9 (192.168.100.9)' can't be established.
RSA key fingerprint is f4:ca:b7:fe:19:6e:a0:60:5c:0e:26:76:3f:bf:32:fe.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.100.9' (RSA) to the list of known hosts.
root@192.168.100.9's password: 


BusyBox v1.22.1 (2014-10-25 16:27:26 JST) built-in shell (ash)
Enter 'help' for a list of built-in commands.

 ############ Routerboard User's Group JP ############
  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
 -----------------------------------------------------
 CHAOS CALMER (Bleeding Edge, r43011 with OVS)
 -----------------------------------------------------
  * 1 1/2 oz Gin            Shake with a glassful
  * 1/4 oz Triple Sec       of broken ice and pour
  * 3/4 oz Lime Juice       unstrained into a goblet.
  * 1 1/2 oz Orange Juice
  * 1 tsp. Grenadine Syrup
 -----------------------------------------------------

◆OpenvSwitchパッケージのインストール

現在のopkg設定内容を確認する。

root@OpenWrt:~# cat /etc/opkg.conf
dest root /
dest ram /tmp
lists_dir ext /var/opkg-lists
option overlay_root /overlay
src/gz chaos_calmer_base http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/base
src/gz chaos_calmer_luci http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/luci
src/gz chaos_calmer_management http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/management
src/gz chaos_calmer_packages http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/packages
src/gz chaos_calmer_routing http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/routing
src/gz chaos_calmer_telephony http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/telephony
src/gz chaos_calmer_openvswitch http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/openvswitch

opkgをアップデート。

root@OpenWrt:~# opkg update
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/base/Packages.gz.
Updated list of available packages in /var/opkg-lists/chaos_calmer_base.
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/luci/Packages.gz.
Updated list of available packages in /var/opkg-lists/chaos_calmer_luci.
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/management/Packages.gz.
Updated list of available packages in /var/opkg-lists/chaos_calmer_management.
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/packages/Packages.gz.
Updated list of available packages in /var/opkg-lists/chaos_calmer_packages.
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/routing/Packages.gz.
Updated list of available packages in /var/opkg-lists/chaos_calmer_routing.
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/telephony/Packages.gz.
Updated list of available packages in /var/opkg-lists/chaos_calmer_telephony.
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/openvswitch/Packages.gz.
Updated list of available packages in /var/opkg-lists/chaos_calmer_openvswitch.

OpenvSwitchパッケージをインストールする。

root@OpenWrt:~# opkg install openvswitch-common openvswitch-ipsec openvswitch-switch
Installing openvswitch-common (2.3.0-1) to root...
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/openvswitch/openvswitch-common_2.3.0-1_ar71xx.ipk.
Installing libpcap (1.5.3-1) to root...
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/base/libpcap_1.5.3-1_ar71xx.ipk.
Installing libopenssl (1.0.1j-1) to root...
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/base/libopenssl_1.0.1j-1_ar71xx.ipk.
Installing zlib (1.2.8-1) to root...
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/base/zlib_1.2.8-1_ar71xx.ipk.
Installing librt (0.9.33.2-1) to root...
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/base/librt_0.9.33.2-1_ar71xx.ipk.
Installing libpthread (0.9.33.2-1) to root...
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/base/libpthread_0.9.33.2-1_ar71xx.ipk.
Installing kmod-openvswitch (3.10.49+2.3.0-1) to root...
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/openvswitch/kmod-openvswitch_3.10.49+2.3.0-1_ar71xx.ipk.
Installing kmod-stp (3.10.49-1) to root...
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/base/kmod-stp_3.10.49-1_ar71xx.ipk.
Installing kmod-llc (3.10.49-1) to root...
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/base/kmod-llc_3.10.49-1_ar71xx.ipk.
Installing kmod-gre (3.10.49-1) to root...
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/base/kmod-gre_3.10.49-1_ar71xx.ipk.
Installing kmod-iptunnel (3.10.49-1) to root...
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/base/kmod-iptunnel_3.10.49-1_ar71xx.ipk.
Installing kmod-lib-crc32c (3.10.49-1) to root...
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/base/kmod-lib-crc32c_3.10.49-1_ar71xx.ipk.
Installing kmod-crypto-crc32c (3.10.49-1) to root...
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/base/kmod-crypto-crc32c_3.10.49-1_ar71xx.ipk.
Installing kmod-crypto-hash (3.10.49-1) to root...
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/base/kmod-crypto-hash_3.10.49-1_ar71xx.ipk.
Installing openvswitch-ipsec (2.3.0-1) to root...
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/openvswitch/openvswitch-ipsec_2.3.0-1_ar71xx.ipk.
Installing openvswitch-switch (2.3.0-1) to root...
Downloading http://rb-openwrt-test.mydns.jp/openwrt/r43011-ovs/trunk/ar71xx.mikrotik/packages/openvswitch/openvswitch-switch_2.3.0-1_ar71xx.ipk.
Configuring kmod-llc.
Configuring kmod-stp.
Configuring libpthread.
Configuring kmod-crypto-hash.
Configuring kmod-iptunnel.
Configuring kmod-gre.
Configuring libpcap.
Configuring zlib.
Configuring libopenssl.
Configuring librt.
Configuring kmod-crypto-crc32c.
Configuring kmod-lib-crc32c.
Configuring kmod-openvswitch.
Configuring openvswitch-common.
2014-11-02T05:58:18Z|00001|vlog|INFO|opened log file /var/log/ovsdb-server.log
2014-11-02T05:58:22Z|00001|vlog|INFO|opened log file /var/log/ovs-vswitchd.log
2014-11-02T05:58:22Z|00002|reconnect|INFO|unix:/var/run/db.sock: connecting...
2014-11-02T05:58:22Z|00003|reconnect|INFO|unix:/var/run/db.sock: connected
Configuring openvswitch-ipsec.
Configuring openvswitch-switch.

OpenWRT起動時、OpenvSwitch自動起動を有効にする。

root@OpenWrt:~# /etc/init.d/openvswitch enable

OpenWRTを再起動する。

root@OpenWrt:/# reboot

OpenvSwitch環境を確認する。

root@OpenWrt:~# lsmod|grep openvswitch
libcrc32c                599  1 openvswitch
openvswitch            64208  0 

root@OpenWrt:~# ovs-vsctl -V
ovs-vsctl (Open vSwitch) 2.3.0
Compiled Oct 25 2014 16:42:21
DB Schema 7.6.0

◆OpenWRTのネットワーク設定

現在のNICポート情報を確認する。

root@OpenWrt:~# ifconfig
br-lan    Link encap:Ethernet  HWaddr D4:CA:6D:73:14:8B  
          inet addr:192.168.1.1  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fd81:eb66:ce8d::1/60 Scope:Global
          inet6 addr: fe80::d6ca:6dff:fe73:148b/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:797 errors:0 dropped:0 overruns:0 frame:0
          TX packets:315 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:142753 (139.4 KiB)  TX bytes:57490 (56.1 KiB)

eth0      Link encap:Ethernet  HWaddr D4:CA:6D:73:14:8B  
          inet6 addr: fe80::d6ca:6dff:fe73:148b/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1936 errors:0 dropped:17 overruns:0 frame:0
          TX packets:1322 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:396757 (387.4 KiB)  TX bytes:190786 (186.3 KiB)
          Interrupt:4 

eth0.1    Link encap:Ethernet  HWaddr D4:CA:6D:73:14:8B  
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:889 errors:0 dropped:0 overruns:0 frame:0
          TX packets:308 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:169810 (165.8 KiB)  TX bytes:56768 (55.4 KiB)

eth0.2    Link encap:Ethernet  HWaddr D4:CA:6D:73:14:8B  
          inet addr:192.168.100.9  Bcast:192.168.100.255  Mask:255.255.255.0
          inet6 addr: fe80::d6ca:6dff:fe73:148b/64 Scope:Link
          inet6 addr: 240b:11:53a0:400:d6ca:6dff:fe73:148b/64 Scope:Global
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:976 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1008 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:178785 (174.5 KiB)  TX bytes:128222 (125.2 KiB)

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:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

OpenWRTネットワーク設定内容を確認する。

root@OpenWrt:~# cat /etc/config/network

config interface 'loopback'
	option ifname 'lo'
	option proto 'static'
	option ipaddr '127.0.0.1'
	option netmask '255.0.0.0'

config globals 'globals'
	option ula_prefix 'fd81:eb66:ce8d::/48'

config interface 'lan'
	option ifname 'eth0.1'
	option force_link '1'
	option type 'bridge'
	option proto 'static'
	option ipaddr '192.168.1.1'
	option netmask '255.255.255.0'
	option ip6assign '60'

config interface 'wan'
	option ifname 'eth0.2'
	option proto 'dhcp'

config interface 'wan6'
	option ifname 'eth0.2'
	option proto 'dhcpv6'

config switch
	option name 'switch0'
	option reset '1'
	option enable_vlan '1'

config switch_vlan
	option device 'switch0'
	option vlan '1'
	option ports '0t 2 3 4 5'

config switch_vlan
	option device 'switch0'
	option vlan '2'
	option ports '0t 1'

OpenWRTネットワーク設定変更として、WAN側ポートには、以下のIPアドレスを設定する。

root@OpenWrt:~# vi /etc/config/network
――――

config interface 'loopback'
	option ifname 'lo'
	option proto 'static'
	option ipaddr '127.0.0.1'
	option netmask '255.0.0.0'

config switch
	option name 'switch0'
	option reset '1'
	option enable_vlan '1'

#### Port:1 ####
config switch_vlan
	option device 'switch0'
	option vlan '1'
	option ports '0t 1'

config interface 'wan'
	option ifname 'eth0.1'
	option proto 'static'
	option ipaddr '192.168.0.1'
	option netmask '255.255.255.0'

#### Port:2 ####
config switch_vlan
	option device 'switch0'
	option vlan '2'
	option ports '0t 2'
	
config interface 'lan1'
	option ifname 'eth0.2'
	option proto 'static'


#### Port:3 ####
config switch_vlan
	option device 'switch0'
	option vlan '3'
	option ports '0t 3'
	
config interface 'lan2'
	option ifname 'eth0.3'
	option proto 'static'


#### Port:4 ####
config switch_vlan
	option device 'switch0'
	option vlan '4'
	option ports '0t 4'
	
config interface 'lan3'
	option ifname 'eth0.4'
	option proto 'static'


#### Port:5 ####
config switch_vlan
	option device 'switch0'
	option vlan '5'
	option ports '0t 5'
	
config interface 'lan4'
	option ifname 'eth0.5'
	option proto 'static'

――――

OpenWRTを再起動する。

root@OpenWrt:/# reboot

OpenWRTネットワーク設定後、現在のNICポート情報を確認する。

root@OpenWrt:~# ifconfig
eth0      Link encap:Ethernet  HWaddr D4:CA:6D:73:14:8B  
          inet6 addr: fe80::d6ca:6dff:fe73:148b/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:590 errors:0 dropped:6 overruns:0 frame:0
          TX packets:191 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:122929 (120.0 KiB)  TX bytes:28084 (27.4 KiB)
          Interrupt:4 

eth0.1    Link encap:Ethernet  HWaddr D4:CA:6D:73:14:8B  
          inet addr:192.168.0.1  Bcast:192.168.0.255  Mask:255.255.255.0
          inet6 addr: fe80::d6ca:6dff:fe73:148b/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:508 errors:0 dropped:0 overruns:0 frame:0
          TX packets:169 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:91250 (89.1 KiB)  TX bytes:25180 (24.5 KiB)

eth0.2    Link encap:Ethernet  HWaddr D4:CA:6D:73:14:8B  
          inet6 addr: fe80::d6ca:6dff:fe73:148b/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:44 errors:0 dropped:0 overruns:0 frame:0
          TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:15710 (15.3 KiB)  TX bytes:408 (408.0 B)

eth0.3    Link encap:Ethernet  HWaddr D4:CA:6D:73:14:8B  
          inet6 addr: fe80::d6ca:6dff:fe73:148b/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:408 (408.0 B)

eth0.4    Link encap:Ethernet  HWaddr D4:CA:6D:73:14:8B  
          inet6 addr: fe80::d6ca:6dff:fe73:148b/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:408 (408.0 B)

eth0.5    Link encap:Ethernet  HWaddr D4:CA:6D:73:14:8B  
          inet6 addr: fe80::d6ca:6dff:fe73:148b/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:408 (408.0 B)

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:1296 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1296 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:88128 (86.0 KiB)  TX bytes:88128 (86.0 KiB)

◆OpenvSwitchの各種設定

OpenFlowコントローラとの接続を想定したOpenvSwitch設定を行う。

root@OpenWrt:~# ovs-vsctl add-br br0
root@OpenWrt:~# ovs-vsctl add-port br0 eth0.2
root@OpenWrt:~# ovs-vsctl add-port br0 eth0.3
root@OpenWrt:~# ovs-vsctl set-controller br0 tcp:192.168.0.100:6633
root@OpenWrt:~# ovs-vsctl set bridge br0 other-config:datapath-id=0000000000000001
root@OpenWrt:~# ovs-vsctl set bridge br0 protocols=OpenFlow13

設定結果を確認しておく。

root@OpenWrt:~# ovs-vsctl show
ee6fb013-ddce-4af7-a3b5-c0bd4bef0d0e
    Bridge "br0"
        Controller "tcp:192.168.0.100:6633"
        Port "br0"
            Interface "br0"
                type: internal
        Port "eth0.2"
            Interface "eth0.2"
        Port "eth0.3"
            Interface "eth0.3"

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

以上で、OpenWRT上でのOpenvSwitch環境が構築できました。

留意事項

万一、OpenWRT化の作業中に、不測の事態に陥った場合には、必要に応じた切り戻しを実施しなければなりません。
1. initramfsの再転送によるOpenWRT再構築
もし、tftpサーバからのinitramfsダウンロードにより復旧できる見込みがある場合には、

  • RB750GLの1番ポートに差し替える
  • リセットボタンの長押ししながら、RB750GLを再起動する
  • initramfs転送開始される

2. NetInstallによるRouterOS再構築
initramfsの再転送によるOpenWRT再構築では復旧見込みがない場合、こちらが参考になると思います。←実際。試してませんが...

◆終わりに

Buffalo版と比べると、OpenWRTファームとOpenvSwitchパッケージの導入手順について、相当、簡略化が図られていると思います。
RouterBOARD他機種でのOpenFlow化の実績は不明です。現時点では、RB750GLのOpenFlow化は、いちばん魅力があると思います。

Ryu SDN FrameworkのBGP機能を試してみた(4) 〜Ryu BGPSpeaker再検証〜

前回は、Ryu BGPSpeakerを活用したInterAS MPLS-VPN環境において、BGP基本動作を確認しました。

当時の動作確認では、i-BGPまわりの基本パラメータ未対応など、実用面での課題が判明しました。

◆最近のRyu BGPSpeaker機能改善

最近のSDN的な仮想ネットワークでは、マルチテナント対応を前提とした柔軟なトラフィックフロー制御技術を活用したServiceChainingに注目があつまっております。
Ryu BGPSpeakerでは、もともと、VRFを活用したMPLS-VPN構築機能が備わっておりますが、最近の機能改善としては、mp-BGPまわりの基本パラメータ対応に加えて、LocalPrefereceに対応したそうです。

f:id:ttsubo:20141020210048j:plain

そこで、Ryu BGPSpeaker機能改善を実際に確認しました。
f:id:ttsubo:20141020205703j:plain
Ryu BGPSpeakerの動作確認にあたっては、前回同様に、GNS3を活用しました。

◆Ryu BGPSpaker動作確認で使用したサンプルコード

1. Ryu BGP1のサンプルコード

対向ASからのトラフィックフローは、すべて、Ryu BGP1を経由するようにLocalPreferenceによるポリシー・ルーティングを設定しました。

import eventlet
import time

eventlet.monkey_patch()

import logging
logging.basicConfig(level=logging.INFO)

from ryu.services.protocols.bgp.bgpspeaker import BGPSpeaker
from ryu.services.protocols.bgp.info_base.base import ASPathFilter
from ryu.services.protocols.bgp.info_base.base import AttributeMap

def dump_remote_best_path_change(event):
    print 'the best path changed:', event.remote_as, event.prefix,\
        event.nexthop, event.is_withdraw

if __name__ == "__main__":
    speaker = BGPSpeaker(as_number=65011, router_id='10.0.1.1',
                         best_path_change_handler=dump_remote_best_path_change, ssh_console=True,
                         label_range=(1000,1999))

    speaker.neighbor_add('192.168.101.101', 65010, enable_ipv4=True, enable_vpnv4=True, multi_exit_disc=100)
    speaker.neighbor_add('10.0.1.2', 65011, enable_ipv4=True, enable_vpnv4=True, is_next_hop_self=True, local_address='10.0.1.1', local_port=50001)
    speaker.neighbor_add('10.0.1.3', 65011, enable_ipv4=True, enable_vpnv4=True, is_next_hop_self=True, local_address='10.0.1.1', local_port=50002)
    speaker.vrf_add('65010:101', ['65010:101'], ['65010:101'])
    speaker.prefix_add('192.168.4.0/30', next_hop='0.0.0.0', route_dist='65010:101')
    speaker.prefix_add('10.10.10.4/32', next_hop='192.168.4.2', route_dist='65010:101')
    speaker.prefix_add('192.168.204.0/30', next_hop='192.168.4.2', route_dist='65010:101')
    as_path_filter = ASPathFilter(65010,policy=ASPathFilter.POLICY_TOP)
    attribute_map = AttributeMap([as_path_filter], AttributeMap.ATTR_LOCAL_PREF, 200)
    speaker.attribute_map_set('10.0.1.3', [attribute_map], route_dist='65010:101', route_family='ipv4')
    eventlet.sleep(5)

    while True:
        eventlet.sleep(5)

2. Ryu BGP2のサンプルコード

import eventlet
import time

eventlet.monkey_patch()

import logging
import sys
logging.basicConfig(level=logging.INFO)

from ryu.services.protocols.bgp.bgpspeaker import BGPSpeaker

def dump_remote_best_path_change(event):
    print 'the best path changed:', event.remote_as, event.prefix,\
        event.nexthop, event.is_withdraw

if __name__ == "__main__":
    speaker = BGPSpeaker(as_number=65011, router_id='10.0.1.2',
                         best_path_change_handler=dump_remote_best_path_change, ssh_console=True,
                         label_range=(2000,2999))

    speaker.neighbor_add('192.168.102.101', 65010, enable_ipv4=True, enable_vpnv4=True, multi_exit_disc=200)
    speaker.neighbor_add('10.0.1.1', 65011, enable_ipv4=True, enable_vpnv4=True, is_next_hop_self=True, local_address='10.0.1.2', local_port=60001)
    speaker.neighbor_add('10.0.1.3', 65011, enable_ipv4=True, enable_vpnv4=True, is_next_hop_self=True, local_address='10.0.1.2', local_port=60002)
    speaker.vrf_add('65010:101', ['65010:101'], ['65010:101'])
    eventlet.sleep(5)
    speaker.prefix_add('192.168.5.0/30', next_hop='0.0.0.0', route_dist='65010:101')
    speaker.prefix_add('10.10.10.5/32', next_hop='192.168.5.2', route_dist='65010:101')
    speaker.prefix_add('192.168.205.0/30', next_hop='192.168.5.2', route_dist='65010:101')

    while True:
        eventlet.sleep(5)

◆Ryu BGPSpaker動作結果

Ryu BGPSpeaker間では、i-BGP Peeringを構築するにあたり、ループバックInterfaceを指定することができるようになりました。通常のRouterの場合には、ループバックInterface間でルーティングが可能となるようにOSPFに参加させる必要があります。しかしながら、Ryu BGPSpeakerにはOSPF制御機能が備わっていませんので、別途、対応が必要となります。
(今回の動作確認では、ループバックInterface間でルーティングは、Staticで対応しました。)

(1) 通常時のPE3でのBGPテーブル内容

RyuBGP1経由で受信したBGP経路については、LocalPreference値が"200"と設定されており、RyuBGP2経由で受信したBGP経路については、LocalPreference値がデフォルト"100"と設定されています。よって、PE3では、BGP最適パス計算によって、RyuBGP1経由のルーティング経路が選択される様子が確認できました。

PE3#sh bgp vpnv4 unicast all
BGP table version is 151, local router ID is 10.0.1.3
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale, m multipath, b backup-path, f RT-Filter,
              x best-external, a additional-path, c RIB-compressed,
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

     Network          Next Hop            Metric LocPrf Weight Path
Route Distinguisher: 65010:101 (default for vrf customerA)
 * i 10.10.10.1/32    10.0.1.2                      100      0 65010 65001 ?
 *>i                  10.0.1.1                      200      0 65010 65001 ?
 * i 10.10.10.2/32    10.0.1.2                      100      0 65010 65002 ?
 *>i                  10.0.1.1                      200      0 65010 65002 ?
 *>  10.10.10.3/32    192.168.3.2              0         32768 ?
 *>i 10.10.10.4/32    10.0.1.1                      100      0 ?
 *>i 10.10.10.5/32    10.0.1.2                      100      0 ?
 * i 192.168.1.0/30   10.0.1.2                      100      0 65010 ?
 *>i                  10.0.1.1                      200      0 65010 ?
 * i 192.168.2.0/30   10.0.1.2                      100      0 65010 ?
 *>i                  10.0.1.1                      200      0 65010 ?
 *>  192.168.3.0/30   0.0.0.0                  0         32768 ?
 *>i 192.168.4.0/30   10.0.1.1                      100      0 ?
 *>i 192.168.5.0/30   10.0.1.2                      100      0 ?
 * i 192.168.201.0    10.0.1.2                      100      0 65010 65001 i
 *>i                  10.0.1.1                      200      0 65010 65001 i
 * i 192.168.202.0    10.0.1.2                      100      0 65010 65002 i
 *>i                  10.0.1.1                      200      0 65010 65002 i
 *>  192.168.203.0    192.168.3.2              0         32768 ?
 *>i 192.168.204.0/30 10.0.1.1                      100      0 ?
 *>i 192.168.205.0/30 10.0.1.2                      100      0 ?

(2) Ryu BGP1障害時の迂回ルート時のPE3でのBGPテーブル内容

Ryu BGP1とのi-BGPピア断に伴い、BGP最適パス再計算が行われて、Ryu BGP2経由へのルーティング経路が選択される様子が確認できました。
f:id:ttsubo:20141020205629j:plain

◆おわりに

Ryu BGPSpeakerを活用することにより、InterAS MPLS-VPN構成を作成できることが確認できました。
また、前回の技術課題は、ひととおり改修対応が行われていることも確認できました。
これからのNFV的な仮想ネットワーク環境には、柔軟なトラフィック制御を可能とするポリシー・ルーティングに注目が集まっていくものと推測されます。Ryu SDN Framework活用によるOpenFlow/BGP連携機能は、NFV実現に直結可能な技術だと考えておりますので、今後も、いろいろなユースケースを考案していきたいと思います。

Ryu SDN FrameworkのBGP機能を試してみた(3) 〜InterAS接続編 その2〜

前回は、既存のBGP/MPLS VPN網とのInterAS接続によりBGP情報の共有を図ることができました。
ただし、ネットワーク拡張性を想定すると、前回モデルでは、スケール性に課題があります。

今回は、InterAS MPLS VPNにおけるボーダールータとしてRyu BGPを配備したモデルを検証してみました。

なお、現段階のRyu BGPには、いろいろ制約条件が存在するようです。
> i-BGPピアに関わる機能配備には適用が困難そう。
> BGPピアの終端点への配備を 前提とした機能具備がなされている。
> BGPピアの中継点に配備する場合には、BGPパラメータ の伝搬に関わる留意点を想定する必要がある。
> OSPFルーティングドメイン等との連携については、 使い手が自前で準備する必要がある。
-> NextHopへの到達性への対応も別途必要
-> データプレーン連携に関わる対応も別途必要

ただし、Ryu SDN Frameworkの開発スコープとして、本当に従来ルーティングエンジンの焼き直し機能が必要でしょうか?
SDNならではの集中制御/分散制御のハイブリッド的なトラフィックエンジニアリングなアプローチを目指すのであれば、さきほどの制約条件も、これから乗り越えていけばよい技術課題だと思います。