こんな夜中にOpenFlowでネットワークをプログラミング!

第10回Trema編】Tremaプロジェクトの深層に迫る!

はじめに

「合言葉を」異口同音にささやく。⁠デンマーク」

アルトゥル・シュニッツラー
「夢奇譚」

平穏と思える日常生活にも、思わぬところに「闇」が潜んでいるものです。アメリカの最古の秘密結社の1つ、トライステロをご存じでしょうか。トライステロは裏社会の地下郵便組織で、その流通ネットワークはなんと全米に広がっています。恐ろしいことに、トライステロは重要な社会インフラの1つである郵便事業を通じて、あらゆる歴史的事件に社会の裏側から関与し続けていると言われています。

ところで、アメリカの街中で図1のような小さなラッパの落書きに気づいたことはありませんか? これはトライステロのマークで、メンバーどうしが秘密裡に連絡を取り合うのに使うと言われています。このマークがある場所にはアジトがある可能性が高く危険なため、賢明な読者のみなさまはどうか近づかないでください[1]⁠。

図1 秘密結社トライステロのマーク
図1 秘密結社トライステロのマーク

この連載で紹介しているTremaも、その実体はトレマと呼ばれる秘密結社によって作られたフリーソフトウェアです。トレマは闇プログラマや闇エンジニアを抱える地下組織であり、OpenFlowフレームワークTremaを通じてネットワーク界の大変革をもくろんでいます。

トライステロと同じく、トレマも図2のような秘密のマークを使って連絡を取り合っています。ぱっと見、どこにでもある道路標識のようにカムフラージュされているところに注目してください。まさに、思わぬ日常に闇は潜んでいるのです。

図2 道路標識としてカムフラージュされた、秘密結社トレマのマーク
図2 道路標識としてカムフラージュされた、秘密結社トレマのマーク

今回は、我々「トレマ探検隊」が知られざる秘密結社トレマの秘密に迫ります。謎のソフトウェアTremaの全貌は? 闇組織トレマに入るには?実に丸1年の歳月を費やし、命がけで調査した結果をここに公開します。もちろん、世界初公開です!

調査報告:Tremaの全貌

いきなりTremaのソースコードに飛び込むのもよいですが、すぐに迷ってしまうのが関の山です。我々トレマ探検隊が道案内をしましょう。まずは、大まかなファイル構成をつかんでおくとソースコード探検に便利です。

ファイル構成

Tremaをダウンロードすると、いくつかのファイルとディレクトリがあることがわかります。次に主要なものを挙げましょう。

  • build.rb:ビルドスクリプト
  • cruise.rb:すべてのテストコードを実行するテストスイート。開発者向け
  • features/:受け入れテスト一式。開発者向け
  • ruby/:Rubyライブラリのソースコード
  • spec/:Rubyのユニットテスト一式。開発者向け
  • src/examples/:サンプルアプリ(後述)
  • src/lib/:Cライブラリのソースコード
  • trema:tremaコマンド本体
  • unittests/:Cのユニットテスト一式。開発者向け

この中でもTremaで何か作りたい人が真っ先に読むべきは、サンプルアプリ(src/examples/)です。

サンプルアプリ

サンプルアプリは簡単なアプリケーションをたくさん含んでおり、実際のAPIの使い方を調べるのに便利です。基本的にはCとRubyの両方で書かれているため、両者のAPI対応を調べるのにも使えます。

表1におもなサンプルアプリをまとめておきます。この表では、簡単な順に上から並べていますので、順に読んでいくことをお勧めします。

TremaにはたくさんのAPIがあり、表1に掲載したサンプルではまだまだすべてを紹介しきれていません。新しいサンプルアプリを作成した人は、ぜひGitHubでPullリクエストを送ってください。あなたの名前が作者リスト(README.md)に載るかもしれません!

表1 Tremaのおもなサンプルアプリ
アプリ説明
hello_tremaすべての基本、Helloと表示するだけのサンプル連載第7回に掲載⁠⁠。これをtrema runに渡せば、手っ取り早くTremaを試すことができる。Tremaを始めたばかりの初心者向け
packet_inOpenFlowメッセージの中でも重要なpacket_inメッセージをハンドルするサンプル。ハンドラの定義方法やpacket_inメッセージの基本が学べる
switch_monitorスイッチの起動、切断を捕捉するサンプル連載第7回に掲載⁠⁠。ハンドラを複数使ったコントローラの実装が学べる
dumper受け取ったすべてのOpenFlowメッセージを文字列としてダンプするサンプル。OpenFlowメッセージのハンドル方法が学べる
switch_infofeatures_requestメッセージをスイッチに送信し、スイッチから受信したスイッチ情報を出力するサンプル。コントローラからスイッチへOpenFlowメッセージを送る方法が学べる
repeater_hub受け取ったパケットを、入ってきたポート以外に出力する、いわゆるリピータハブをOpenFlowで実装したサンプル連載第9回に掲載⁠⁠。重要なメッセージであるflow_modとpacket_outの基本が学べる
learning_switchいわゆるL2スイッチをエミュレートするサンプル。普通のスイッチの基本構成(FDBなど)を学ぶことができる。これは1台のOpenFlowスイッチのみで動作するが、複数スイッチ向けにはmulti_learning_switchを参照すること
traffic_monitorlearning_switchを拡張し、ユーザごとのトラフィックを測れるようにしたサンプル連載第8回に掲載⁠⁠。スイッチのフローが消えたときに送信されるflow_removed メッセージの応用例としておもしろい
multi_learning_switchlearning_switchの複数スイッチ対応版。learning_switchとの違い、とくにスイッチごとにFDBを管理している部分に注目

Trema Apps

Trema Appsは、Tremaを使った実用的/実験的なアプリケーションを集めたリポジトリです。Tremaと同様にGitHub上で公開されており、次の手順で取得できます。

$ git clone https://github.com/trema/apps.git

それでは、Trema Appsの中でもとくに実用的なアプリを中心に解説していきましょう。

Routing Switch

Routing Switchは、複数のOpenFlowスイッチで構成されるネットワークを1つのL2スイッチに仮想化します図3⁠。サンプルプログラムのlearning_switchと異なり、ループのあるネットワークトポロジにも対応しています。

図3 Routing Switchによる物理スイッチの仮想化
図3 Routing Switchによる物理スイッチの仮想化

また、multi_learning_switchとは異なり、routing_switchはパケットの送信元と宛先のホストが異なるスイッチに接続している場合にも対応しています。スイッチにパケットが届くと図3に示すように、パケットを受信したスイッチから宛先ホストに送出するスイッチまでの最短パスを計算します。そして、計算されたパス上の各スイッチに「同一の特徴を持つパケットを、最短パス上の次のスイッチへと転送せよ」というfl ow_modメッセージを送ります。

Sliceable Routing Switch

Sliceable Routing Switchは、OpenFlowネットワーク全体をスライスに分割し、複数のL2スイッチに仮想化します。ちょうど、L2スイッチを複数のVLANに分けて使うイメージです。

スライスを2つ設定した例を図4に示します。同一のスライスに接続されたホストどうしはパケットをやりとりできますが、異なるスライスに接続されたホストどうしではできません。このようにうまくスライスを設定することで、アプリケーションやグループ別など用途に応じて独立したネットワークを作ることができます。

図4 Sliceable Routing Switchによるスライスの作成
図4 Sliceable Routing Switchによるスライスの作成

Topology

Topologyは、複数のOpenFlowスイッチ間の接続関係(ネットワークトポロジ)を取得するためのユーティリティ的なアプリケーションです。前述のRouting SwitchやSliceable RoutingSwitchで最短パスを決める際に利用されます。

ネットワークトポロジの検出には、OpenFlowで標準的なLink Layer Discovery Protocol(LLDP)注2を用います図5⁠。Topologyからpacket_outにより送信されたLLDPパケットは、LLDPが到達した隣のスイッチからpacket_inでTopologyへと戻ります。LLDPパケット中には、それが経由したスイッチとポート情報などが含まれています。そのため、これを繰り返すことでネットワーク中のすべてのスイッチ間の接続関係を知ることができます。

図5 LLDPを用いたネットワークトポロジ検出のしくみ
図5 LLDPを用いたネットワークトポロジ検出のしくみ

Redirectable Routing Switch

Routing Switchのもう1つの亜種で、ユーザ認証とパケットのリダイレクト機能を付け加えたものです。認証されていないホストのパケットは、ほかのサーバに強制的にリダイレクトされます。このしくみを使えば、たとえば認証していないユーザのHTTPセッションを強制的にあるサイトへ飛ばすといったことが簡単にできます。

Learning switch with memcached

サンプルプログラムのlearning_switchと同じ機能を持ちますが、FDB部分にmemcached[3]を用いています。Rubyのmemcachedライブラリを使うことで、オリジナルのlearning_switchにほとんど変更を加えずにmemcached対応しています。

Multi learning switch with memcached

サンプルプログラムのmulti_learning_switchをmemcached対応したものです。

Flow dumper

OpenFlowスイッチのフローテーブルを取得するためのユーティリティです。デバッグツールとしてとても便利です。

Packetin dispatcher

packet_in メッセージを複数のTrema アプリケーションに振り分けるためのサンプルです。物理アドレスから、ユニキャストかブロードキャストかを判断します。

Broadcast helper

ブロードキャストやマルチキャストなど、コントローラに負荷の大きいトラフィックを分けるためのアプリです。

Flow manager

フローエントリとパス情報を管理するアプリケーションおよびAPIを提供します。実験的な実装なので、APIは変更される可能性があります。

実録・秘密結社トレマに潜入!

検索エンジンの海をさまよった結果、ついに我々はトレマとの接触に成功した。指定された場所は関東某所。こんな場所でソフトウェアの開発を? というほど意外な場所にトレマ本部はあった。

Tremaメンバーと接触

我々を案内してくれたのは、キーボードで顔を隠した謎の男。我々をTremaプロジェクトの闇プログラマや闇エンジニアたち写真1と引き合わせてくれると言う。

写真1 Tremaプロジェクトのメンバーたち。緊張で写真がブレてしまった……
写真1 Tremaプロジェクトのメンバーたち。緊張で写真がブレてしまった……

キーボード男「まずはみんなの紹介だ。本名は明かせないが、GitHubのアカウント名とTwitterのアカウント名を教えよう。」

yasuhito(@yasuhito)

高性能計算(HPC)を専門とし、ネットワークのことは専門外。世界中どこでも便所サンダルで現れる。Tremaの設計や実装方針を割と勝手に決めてしまう自称リーダー。

sugyo

別の秘密結社K○M△プロジェクトから参加。IPv6のプロトコルスタックの開発に長年従事してきたネットワーク界のスーパーハッカー。Tremaの各種デーモンを担当。

kazuyas(@countone)

自称インターネット屋、ルータ屋さん。L2よりL3、とくに経路制御が大好きで、OpenFlowはL3っぽくないなどとボヤきつつTremaのパケットパーサー部分を書いた。

chibacchie

経験豊富なネットワークエンジニア兼プログラマ。TremaのOpenFlowプロトコルスタックやデバッグツールTremashark、および数多くのTremaアプリを開発している。

eff(@effy55)

ギークハウス武蔵小杉管理人。Tremaプロセス間のメッセージング機構を開発。現在はTremaで何やら小難しいものを作ろうとしているらしいが、その全容は誰も知らない。

Tremaの掟

キーボード男「TremaはGPL2だし、GitHubに置いてあるから、OpenFlowプログラミングに興味があれば誰でも参加できるんだ。でも、そのためにはちょっとした掟があるんだ。それを紹介しよう。」

使いたいものしか作らない

キーボード男「俺たちは自分たちの使いたいものしか作らないんだ。⁠必要だから作った』ってのが一番品質が良いからね。だから、使ってもない人間の『ここはこうしたほうがよい』⁠こんなのダメ』という意見はきっぱり無視するんだ。」

シンプルに保つ

キーボード男「全部入りの重量級ソフトウェアはみっともないし、使いにくいもんだ。⁠お客さんに言われたんで、さっそくこういう機能を付けてみました!』とかアホだろ? 俺たちが目指しているのはバカでかい空母なんかじゃなくて、自由に乗り回せる自転車。たとえ『こういう機能ほしいかも?』と思っても、まずは却下しよう。それが本当に必要と確信できるまで実装しないことが大事だ。」

性能は二の次

キーボード男「さっきの話と似てるけど、必要のない高速化はしないことにしてるんだ。アルゴリズムも変に凝ったものは使わない。ポインタの小細工で米粒みたいな高速化をしてもバグるだけで無意味だよ。そんなことよりコードをいかにきれいに読みやすくできるか─⁠─コーディング規則の統一はもちろんだが、極端な話、行末の無駄なスペースにまで目を光らせてるよ。」

テスト中毒

キーボード男「よく言われることだけど、テストされていない機能は存在しないのと一緒だ。Trema にコミットしたい人は、まずはテストコードを書いてほしい。そしてテストコードをまた書いて、最後に実装だ。そう、テスト中毒みたいな奴に来てほしいんだ。」


なんか外タレのインタビューみたいですね。キーボード男さん、ありがとうございました。

まとめ

今回はいつもと趣向を変え、Tremaプロジェクトの深い部分を紹介しました。今回学んだことは次の2つです。

  • Tremaでアプリケーションを書きたい人は、まずsrc/examples/以下のサンプルアプリを読みましょう。より高度なサンプルはTremaAppsリポジトリで発見できます。
  • Tremaの開発に参加したい人は、⁠掟」を読んで設計思想を知ろう。簡単なサンプルアプリを書いてコミットしてみよう。そして、秘密結社トレマの一員になろう!

次回は、いよいよTremaを使って自宅や職場のネットワークをOpenFlowに置き換える方法を紹介します。我々の成功例や問題が起こったときの解決方法など、実践テクニックが満載です!

おすすめ記事

記事・ニュース一覧