今日も秋田で IoT

旧 Trema 日記

オープンルータ・コンペティション

Interop 2012 の併催イベントとして、オープンルータ・コンペティションが開催されました。6/13 に最終審査会が開かれたので、見学してきました。

最終審査会では、一次審査を通過した10チームのプレゼンが行われました。
FPGA 付きの NIC を使ってワイヤーレートの L3 ルーティングを実現したチームまるたかが、グランプリ(さくらインターネット賞)を受賞しました。
また準グランプリ(NEC賞)には、このブログでも以前に紹介した@SRCHACKさんのプロジェクトが選ばれました。

最終審査会参加の10チームのうち、OpenFlow 関連の4チームすべてで Trema を使っていただいたようです。オープンソースのよいところですね。
OpenFlow 以外にも多くの素晴らしい成果の発表がありました。コンペティションの名前にもあるように、"オープン" な成果が、今後の新しいアイデアの礎になっていくといいな思います。

そんな願いも込めて、まとめサイトを作りました。公開されている情報をまとめていますので、ご参考に。

Openvswitch を userspace で動かす

今回は Openvswitch (ovs-vswitchd) を userspace で動作させる方法を試してみたので紹介します。

以前にも openvswitch の userspace での動作について紹介しましたが、その時用いていたのは ovs-openflowd でした。こちらの方は 1.4.0 にはすでに同梱されていないので、今回は ovs-vswitchd を使う方法を紹介します。

設定

基本的には、以前紹介した kernel-module を使う方法とほとんど同じです。違う点は以下の二点だけです。

今回は kernel-module を使用しないので、lsmod で確認し、openvswitch_mod をアンロードしておきます。

$ rmmod openvswitch_mod

あとは ovs-vsctl で以下のような設定を入れればいいだけです。

$ ovs-vsctl set bridge ofs0 datapath_type=netdev

ただし、userspace での動作では、前回 紹介した openvswitch 組み込みの gre 機能は使えないようです。

試してみる

あるホスト上で動作する二つの VM 間を openvswitch でつなぎ、その ovs を Trema/routing_switch で OpenFlow 動作をさせます。kernel module を使った場合と userspace のみで動作させた場合の、二つの VM 間のスループットの違いについて netperf を使って調べてみました。kernel module を使った場合は 1465Mbps, userspace で動作させた場合は 248Mbps となり、だいたい 6 倍くらいの差が出るようです。(ざっくりと測定した結果なので、条件によっては異なる結果がでるかもしれません。その辺はご了承を。)

GRE を使って OpenFlow ネットワークを作る

前回は etherip を使ってトンネルを組む方法について紹介しましたが、今回は GRE を使う方法について紹介します。
Linux には kernel module として動作する GRE ドライバが存在しますが、今回は Openvswitch に組み込まれている GRE 機能を使用します。そのため lsmod で Kernel module (ip_gre) を確認し、組み込まれていれば rmmod しておいてください。
今回の構成は、以下のとおりです。
f:id:kazuya_ax:20120415152028p:image:w360

Openvswitch の設定

openvswitch は以下のように設定を行います。

ovs-vsctl add-bridge ofs0
ovs-vsctl add-port ofs0 vnet0
ovs-vsctl add-port ofs0 gre0
ovs-vsctl set interface gre0 type=gre options:remote_ip=192.168.1.2 options:pmtud=false

対向側も remote_ip のアドレス以外は同様に設定します。
gre0 は、openvswitch 内部のみで作られ、使用されるインターフェイス名なので、ifconfig 等では表示されません。

設定は以上で終わりです。後は、前回と同様に Trema/routing_switch を動作させ、VM 間の疎通確認を行ってみてください。

MTU の話

EtherIP や GRE を使うとカプセル化を行わなければならない分、パケットのサイズが大きくなります。そのためネットワークの MTU についての考慮が必要になります。

一般的な Ethernet ではフレームの最大長は FCS を除くと 1514 ですが、トンネルを使った場合以下のようになります。

  • EtherIP : 1478 = 1514 - 14(Ethernet header) - 20(IP header) - 2(EtherIP header)
  • GRE : 1476 = 1514 - 14(Ethernet header) - 20(IP header) - 4(GRE header)

例えば GRE トンネルで IP ネットワークを作った場合の MTU は、1462 となります。これらを図示すると以下のようになります。
f:id:kazuya_ax:20120418170048p:image:w360

今回のようにトンネルを使う構成では、以下のいずれかを選択する必要があります。

  • VM が接続する 192.168.2.0 のネットワークの MTU を小さくする(今回の場合 1462 にする)。
  • VM が接続するネットワークの MTU は 1500 のままとし、GRE のパケットのフラグメントを許容する。

今回はフラグメントを行うこととし、そのために openvswitch の pmtud の機能を使わないよう設定しています。

フラグメントが発生した場合、トンネルの終端側でリアセンブルを行う必要があるため、その分パフォーマンスが低下します。Nicira が提案している STT では、ハードウェアへのオフロード機能を活用して、この問題に対処しているようです。STT に関しては、internet-draft が出ているので、そのうち内容紹介を行いたいと思います。

追記(2012/4/24)

gre の設定方法に誤りがありましたので、以下のように訂正しました。

誤 : ovs-vsctl set interface gre0 type=gre options:remote_ip=192.168.1.2,pmtud=false
正 : ovs-vsctl set interface gre0 type=gre options:remote_ip=192.168.1.2 options:pmtud=false

EtherIP を使って OpenFlow ネットワークを作る

今回は EtherIP を使って、openvswitch 同士を接続してみたいと思います。ハードウェア OpenFlow スイッチを持っていなくても、トンネルを使うことで、オーバーレイで OpenFlow ネットワークを作ることが出来ます。今回は、以下のような構成を作ることが目標です。
f:id:kazuya_ax:20120415152029p:image:w360

etherip のインストール

EtherIP の Kernel module 実装である EtherIP for Linux を使用します。kernel module は kernel のバージョンが違うと build 出来ないことがあるので、最新版を利用しましょう。ここ から取ってきます。

$ git clone git://git.8bytes.org/scm/etherip.git
$ cd etherip
$ make 
$ make driver
$ sudo make install
$ sudo make driver-install

kernel module のロードと tunnel endpoint の設定

対向の IP アドレスを 192.168.1.2 としたトンネルインターフェス ethip0 を、以下のように作ります。

$ sudo insmod /lib/modules/`uname -r`/misc/etherip.ko
$ sudo /usr/sbin/ethiptunnel -a -d 192.168.1.2 -n ethip0
$ sudo ifconfig ethip0 up

192.168.1.2 側の PC も同様に設定を行ってください。こちら側からのトンネルの対向のアドレスは 192.168.1.1 になります。

openvswitch の設定

openvswitch のインストールと初期設定は、こちら を参考にしてください。

$ sudo ovs-vsctl add-br ofs0
$ sudo ovs-vsctl add-port ethip0 
$ sudo ovs-vsctl add-port vnet0
$ sudo ovs-vsctl set-controller ofs0 tcp:192.168.1.1:6633

二台とも同様な設定を行って下さい。

trema/routing_switch の起動

Trema は 192.168.1.1 側のマシンで動作させます。

$ cd trema/
$ ./trema run -c ../apps/routing_switch/routing_switch_null.conf -d
$ TREMA_HOME=. ../apps/show_description/show_description
Manufacturer description: Nicira Networks, Inc.
Hardware description: Open vSwitch
... 省略

show_description コマンドにより、openvswitch 二台分の情報が表示されるはずです。次にトポロジーが正しく認識できているかを次のコマンドで確認します。

$ TREMA_HOME=. ../apps/topology/show_topology

二台の openvswitch の datapath_id と、それらの間のリンクに関する情報が表示されるはずです。
ここまで出来ていれば、VM 間の通信が出来るはずです。一方の VM 上から対向の VM に対して、ping を打ってみましょう。

次回は、EtherIP の代わりに GRE を使う方法について紹介したと思います。

C 言語で Match を書く (その1)

今回は、C 言語で Match を書いてみましょう。

送信元 IP アドレス 192.168.1.0/24、宛先 IP アドレス 192.168.2.0/24 とマッチさせる Flow_mod を設定するコントローラは、以下のようになります。

ポイントは二点です。

  • 宛先 IP アドレスをマッチ条件に用いる場合には、dl_type = 0x0800 もマッチ条件として用いる必要があります(詳しくはここ)。
  • 以前説明したように、今回のケースでは wildcard は 11,0010,0000,1000,1110,1111b = 0x3208ef である必要があります。nw_src, nw_dst の mask は 24 ビットなので、wildcard として扱うのは下位 8 ビットとなり、それぞれ 001000b = 8 を設定しています。

build した後、network.conf を使って、起動してみましょう。

$ ./trema run ./matchtest -c ./network.conf -d
$ ./trema dump_flows 0x1
NXST_FLOW reply (xid=0x4):
 cookie=0x1, duration=3.536s, table=0, n_packets=0, n_bytes=0, priority=65535,ip,nw_src=192.168.1.0/24,nw_dst=192.168.2.0/24 actions=drop

想定したとおりのフローエントリができたでしょうか?