はじめに
今回も、前回に引き続き、オープンソースで提供されているNOX(OpenFlowコントローラ)上で動作するNOXモジュールの実装方法を説明します。
オープンクラウドキャンパス
先に、8月2日に開催された「オープンクラウドキャンパス」という勉強会で、OpenFlowについて説明してきましたので、そのときの様子を紹介します。OpenFlowに取り組むNTTデータ、NEC、Citrix、Fusionの4社がそれぞれの視点で話をしています。他にMidonetやVyattaの紹介もありました。質疑応答の時間が十分にあったとは言えない状況でしたが、OpenFlowの本質は「プログラマブルである」など、深い指摘があったのが印象的でした。
最近は雑誌などでOpenFlowが取り上げられる機会が増えています。OpenFlowへの注目も高まっており、SDN(Software-Defi ned Network)技術を推進するONF(Open Networking Foundation)に参加する企業は、新たにIntel、Extream Networks、富士通、OpenFlowベンチャーなどが加わり、43社まで増えています(2011年8月12日現在)。また、OpenFlowを用いて複数のデータセンターを仮想的に1つのデータセンターとして見る、データセンター間でライブマイグレーションを行う、といった取り組みも行われています。
今回の開発で使用する構成
今回開発するNOXモジュールは、図1に示す構成で動作させます。これは第4回で構築した環境と同じですが、サーバ2のIPアドレスが異なっているので注意してください。
開発するNOXモジュールの仕様
今回開発するNOXモジュールの仕様を以下に示します。OpenFlowらしく、一般的なネットワーク装置では実現できない仕様にします。
- OpenFlowコントローラがOpenFlowスイッチを検出したとき、スイッチに接続されているサーバ1とサーバ2のMACアドレスを取得するため、スイッチからサーバに対してARP要求パケットを送信する
- OpenFlowスイッチがサーバからARP応答パケットを受信した場合、ARP応答パケットからサーバのMACアドレスを取得し、スイッチの物理ポートの先に接続されているサーバのMACアドレスを取得する
- NOXが制御するOpenFlowスイッチは1台とする。2台以上検知した場合は、エラーをコンソールに表示する。新しく検知されたスイッチは一切管理せず、存在しないものとして扱う
- OpenFlowスイッチは、サーバからOpenFlowルータ宛のARP要求パケットを受信した場合、OpenFlowコントローラ内でARP応答パケットを生成し、サーバに返送する。OpenFlowルータ宛でない場合は、受信したARP要求パケットを破棄する
- IPv4パケットを受信したとき、サーバ1とサーバ2のMACアドレスを取得できていない場合は受信したパケットを破棄する
- IPv4パケットを受信し、かつサーバ1とサーバ2のMACアドレスが既知の場合、OpenFlowコントローラ内でパケットがOpenFlowルータを通過したのと同じようにMACアドレスを書き換え、コントローラからスイッチ経由でパケットを送出する
- ARPでもIPv4パケットでもない場合は、パケットを破棄する
OpenFlowプロトコルとパケットアウトの関係
前回は、OpenFlowスイッチに制御ルールを書き込むことでパケットの転送を実現しました。今回は、OpenFlowコントローラ内で書き換えたパケットをスイッチ経由でサーバに対して送出する方法でパケットを転送します(パケットアウトとも呼びます)。パケットアウトを行うときに利用するOpenFlowプロトコルのメッセージやイベントの関係を図2に示します。
パケットアウトを行う場合はOpenFlowスイッチに制御ルールを書き込まないため、同じパケットを受信した場合は再びOpenFlowコントローラにPacketInメッセージが送信されることに注意してください。
- ① サーバ1はサーバ2に対してPingパケットを送信する
- ② 未知のパケットを受信したOpenFlowSwitchは、受信したパケットを自身のバッファに格納する。そして、PacketInメッセージをNOXに対して送信し、パケットの制御方法を問い合わせる
- ③ NOXはPacketInイベントを発行し、OpenFlowSwitchが新しいパケットを受信したことをNOXモジュールに通知する
- ④ NOXモジュールは、OpenFlowスイッチが受信したパケットを必要に応じて書き換える(OpenFlowスイッチが受信したパケットは、PacketInメッセージやPacketInイベントを通してNOXモジュールまで届けられる)
- ⑤ NOXモジュールは、書き換えたパケットを送信するようにNOXに対して指示する
- ⑥ NOXは、コントローラから送信されたパケットをサーバ2に送信するようにOpenFlowSwitchに対して指示する
- ⑦ OpenFlowSwitchは、コントローラから受信した書き換え済みのPingパケットをサーバ2に送信する
NOXモジュールの実装
それでは、NOXモジュールを作成しましょう。前回と同様にpyswitch.pyの中身を書き換えます。サーバ3にユーザhogehogeでログインし、次のコマンドでpyswitch.pyのバックアップをしましょう。
バックアップが終わったら、エディタでpyswitch.pyを開き、リスト1のソースコードを上書きで書き込みます。その後、以下のコマンドでNOXを起動してください(すでにNOXが起動中の場合は、停止してから起動します)。
NOXが正しく動作しているか、Pingコマンドで確認してみます。サーバ1、サーバ2から次のコマンドを実行してください。
Pingに対して応答があれば、成功です。
ソースコードの説明
以降、リスト1のソースコードについて説明していきますが、前回と重複する部分の説明は省略します。
pyswitchクラスのcreate_arp_request関数(リスト1-①)は、ARP要求パケットを生成する関数です。引数のsrcmac、srcip、dstipには、それぞれARPの送信元MACアドレス、送信元IPアドレス、送信先IPアドレスを指定する必要があります。本関数の戻り値は、生成されたARP要求パケットです。
reply_arp_packet関数(②)は、サーバが送信したARP要求パケットからARP応答パケットを生成し、サーバにARP応答を送り返す関数です。response_macには、ARP要求に応答するノードが保持しているMACアドレスを指定します。
datapath_join_event関数(③)は、OpenFlowスイッチを検出したときに呼ばれる関数です。OpenFlowの重複を検出した場合は、エラーをコンソールに表示し処理を終えます。1つ目のスイッチの検出である場合は、create_arp_request関数でARP要求パケットを生成し、生成したパケットをsend_openfl ow_packet関数でサーバに送信します。サーバにARP要求パケットを送信すると、サーバからARP応答パケットを受け取ることができるので、結果としてサーバのMACアドレスを取得できます。本関数は引数にopenfl ow.OFPP_ALLを指定しているため、スイッチのすべての物理ポートからパケットが送出されます。また、arp_for_host1.tostring()により生成したパケットを文字列に変換しています。文字列に変換されたパケットは、さらに本関数の中でバイナリに変換されNOXに渡されます。
packet_in_event関数(④)は、OpenFlowスイッチが未知のパケットを受信したときに呼ばれる関数です。etherframe.nextは、ethernetフレームから上位のプロトコルを取得する処理です。
etherframe.nextにより取得したプロトコルがARPだった場合は、さらにARP要求か、ARP応答かにより実行する処理が変わります。ARP要求を受信した場合は、reply_arp_packet関数を呼び出し、サーバにARP応答を返却します。ARP応答を受信した場合は、ethernetフレームの送信元MACアドレスの値を取得し、サーバのMACアドレスを取得します。
プロトコルがIPv4の場合は、以下のいずれかの動作になります。OpenFlowコントローラがサーバのMACアドレス取得に失敗している場合は、受信したパケットを破棄します。MACアドレスの取得に成功している場合は、サーバ1からのパケットはサーバ2へ、サーバ2からのパケットはサーバ1へ転送します。もちろん、OpenFlowルータを経由しているので、パケットの発信元MACアドレスと送信先MACアドレスは書き変わります。
まとめ
今回は、前回に引き続きNOXモジュールの実装方法について説明しました。今回の例で物足りない方は、ルータのIPアドレス(192.168.0.10や192.168.1.10)宛にPingパケットを送信した場合に応答が返るように追加実装してみてください。
現在、OpenFlowはデータセンターへの適用を中心に検討されています。将来的には、データセンター間の連携やWANへの適用が期待されています。OpenFlowによりネットワーク機器を自由にコントロールできるようになりましたが、同時に限界を感じることもあります。OpenFlowを利用して従来のネットワークと真に異なる世界を実現するには、サーバ側のプロトコルスタックもプログラムで制御可能にするべきでしょう。「サーバからARPパケットが送信される」「デフォルトゲートウェイという概念が存在する」ことが、OpenFlowのプログラマビリティを損ねていると感じることもあります。
今回で筆者の執筆は終わりになります。お付き合いいただきありがとうございました。次回からは、オープンソースのOpenFlowコントローラ「Trema」を開発している方が継続して執筆する予定です。ご期待ください。