« PLANEX MZK-WNH および MZK-W300NH2 で動く OpenWrt with OpenFlow 1.0 のイメージをアップロードしました(Ver.2)」 | トップページ | Trema のコントローラと仮想ネットワークをそれぞれ別々に動かす »

2013年4月 7日 (日)

Trema を改造して仮想ネットワーク機能にポート番号指定を追加

[ 2013/04/07 21:00 追記: すみません。公開後にバグを見つけたのでパッチファイル trema.diff を差し替えました。詳細は本記事の最後を見てください ]

OpenFlow フレームワーク Trema (0.3.19)を改造してみました。
改造内容は、仮想ネットワーク機能において仮想スイッチで使われるポート番号を指定できる機能の追加です。実装を楽にするため制約をつけてはいますが、それでも十分使えると思います。

ちなみに、GitHub 上の Trema の Issue リストには、ポート番号指定について以下があがっていて現時点ではまだクローズしていない状態です:
https://github.com/trema/trema/issues/52
https://github.com/trema/trema/issues/286
ここで議論されているポート番号の表記方法をパクりました(^^;

動作確認は、Lubuntu 12.04 Desktop (i386) で確認しています。

■ポート番号を指定できると何が嬉しいか?

当たり前のことですが、どのポートに何がつながっているかの構成が決まっていて、その構成に依存してなにかしたいときにポート番号指定が必要です。
たとえば、ロードバランサをOpenFlow で作ることを考えると、どのポートにサーバがつながっているのか分かっていないと振り分け先を決めるのに困ります。

また、書籍『OpenFlow実践入門』「第7章 インテリジェントなパッチパネル」(初版 P.105)はポート番号を利用した例ですがテストには実機を必要としています。ポート番号指定ができれば仮想ネットワーク機能だけで試すことができます。

書籍『OpenFlow実践入門』(初版)の出版後にサポートされた機能でポート番号を指定して port_up, port_down する機能を使うにも仮想ネットワーク設定ファイルでポート番号が指定できれば便利です。
以下が port_up/port_down についての Trema プロジェクトの Issue:
https://github.com/trema/trema/issues/253

■使い方

仮想ネットワーク設定ファイルにて link 文でスイッチ名を指定するときに名前の後ろに「コロン+OpenFlowでのポート番号」を追加します。
以下に使用例を示します。赤字がポート番号指定箇所です:

例:

  vswitch("sw1") {
    datapath_id "1"
  }
  vhost("host1") {
    ip "192.168.0.1"
    netmask "255.255.255.0"
  }
  vhost("host2") {
    ip "192.168.0.2"
    netmask "255.255.255.0"
  }
  link "sw1:1","host1"
  link "sw1:2","host2"

制約:
  1) 仮想スイッチ名、仮想ホスト名、ネットワークネームスペース名にコロンを使わないこと。
  2) 指定するポートの番号は各スイッチごとに以下を守ること:
   a) 指定するポート番号のうち一番小さい番号は 1 であること。
   b) 指定するポート番号に抜けがないこと。

  NG: ポート番号 2を飛ばして 3 を使っているのでダメ
    link "sw1:1", "host1"
    link "sw1:3", "host2"
  NG: 一番小さいポート番号が 1 ではないのでダメ
    link "sw1:2", "host1"
    link "sw1:3", "host2"
  OK: ポート番号は 1,2, 3, ... と昇順で出現する必要はありません。
    link "sw1:2", "host1"
    link "sw1:1", "host2"
  OK: ポート番号指定の有り無しが混在しても構いません。
    link "sw1:1", "host1"
    link "sw1", "host2"

■改造版 Trema の作り方

Trema でソースからビルドする方法についての説明は省きます。書籍『OpenFlow実践入門』(初版  P.70)などを参照ください。

今回改造した箇所のパッチファイルは下記においておきます:
 http://ranosgrant.cocolog-nifty.com/trema-port/trema.diff

改造版を作る上での手順の違いは、ソースからビルドする手順において、./build.rb を実行する前にこのパッチをあてる手順を追加で実施するだけです。

wget http://ranosgrant.cocolog-nifty.com/trema-port/trema.diff
patch -p0 < trema.diff
./build.rb

パッチ作成に使った Trema は 2013年4月5日頃のものです。
バージョンは、trema version 0.3.19

本改造版 Trema が既存機能に悪さしていないことは Trema が提供する cruise.rb を実行し全テストケースがパスしたことで確認してあります(ただし、spec を一部修正してあります)。
[ 2013/04/07 追記: パスしたのですがバグありました。過信は禁物ですね ]

■改造版 Trema の起動方法

ソースからビルドした Trema はビルド環境に置いたまま使います。

例: ソースのありかが /home/ranosgrant/TREMA-git/trema/ の時にバージョン表示

 /home/ranosgrant/TREMA-git/trema/trema --version

または、

 cd /home/ranosgrant/TREMA-git/trema/
 ./trema --version

Ubuntu や Lubuntu のログインシェルのデフォルトである bash であればコマンドのエイリアスが使えるのでこれを使うと便利です。

例: bash で、改造版 Trema を mtrema というコマンド名で扱うための設定例
  alias mtrema=/home/ranosgrant/TREMA-git/trema/trema

これでパス名ではなく、
  mtrema --version
と呼び出せます。
.bashrc などを使って自動で alias を設定するようにしておくとよいでしょう。

■ソース改造箇所について少し説明

(1) Open vSwtich 側
vendor/openvswitch-1.2.2.trema1/tests/test-openflowd.c

  Trema が仮想スイッチとして利用している Open vSwitch (ovs-openflowd プロセス)の改造をしています。

  OpenFlow ポートとして使用する Linux のネットワークインターフェース名は、起動時のコマンドラインで --ports オプションを使ってコンマで区切って指定します。
こんな感じです: --ports=trema1-0,trema2-0,trema0-0
(trema が動いている時に ifconfig コマンドでみれば分かるように trema が使うネットワークインタフェース名は trema#-0, trema#-1 の形式です。ソースファイル ruby/trema/link.rb の initialize メソッドで名前を作っています。)
  --ports で指定された値を解析する parse_ports 関数では1つ1つ取り出したインターフェース名をハッシュに格納しています。引数で指定されたインターフェース名に対して処理をする箇所ではこのハッシュから取り出しながら処理をしています。ハッシュを使っているので取り出し順は登録順とは異なった順番になります。

  そこで、ハッシュを使わない方式に変更して --ports で指定した順に登録処理が行われるように変更しました。これで、--ports に書いた順にポート番号が1から順にふられるようになりました。

test-openflowd.c への変更分だけ抜き出した修正パッチはこちら:
http://ranosgrant.cocolog-nifty.com/trema-port/openvswitch-1.2.2-test-openflowd.diff

Trema では Open  vSwitch のソースファイルを tar.gz で固めた形で提供しているので tar.gz を展開した後にこのパッチが適用されるように Rakefile に変更を入れました。

(2) Trema 本体側

ruby/trema/dsl/parser.rb

  仮想ネットワーク設定ファイル内の link 指定にもとづいて生成した Linux のネットワークインターフェースの名前を仮想スイッチのオブジェクトに登録する処理をポート番号指定に対応するように変更しています。

ruby/trema/open-vswitch.rb

  ovs-openflowd プロセスの起動時オプションの1つ --ports に指定する文字列を生成する処理を変更しています。
  指定されたポート番号の順で、対応する Linux のインターフェース名を並べるようにしています。

(3) テストケース

spec/trema/packet-in_spec.rb
spec/trema/packet-out_spec.rb

  ポート番号を指定する機能がないのにポート番号を仮定したテストケースがあったので、今回のポート番号指定機能を使うように修正しました。

p.s.

動けば良いを優先したので、修正ソースはイマイチな感じがします...
誰かが本改造に刺激を受けてきれいに実装しなおして Trema プロジェクトに提供してくれたら嬉しいな。


■公開後のバグ修正情報

2013/04/07 21:00頃
最初に公開したパッチ trema.diff は、ruby/trema/dsl/parser.rb にバグを作りこんでいたので修正済みのものに置き換えました。
仮想ネットワーク設定ファイルで link 文に trema の仮想ネットワーク機能で作ったものではないすでに Linux にあるネットワークインタフェースを指定したときにエラーになります。具体例としては、書籍『OpenFlow実践入門』「リスト13-2 逆流防止フィルタ(OneWayBridge コントローラ)の設定ファイル」(初版 P.219)の eth0, eth1 が該当します。
すでにダウンロードしてビルドしている場合は行を1つ追加してください(赤字箇所)。
      def configure_switch(config, peer_str, ifname)
        return until peer_str
        pa = peer_str.split(PORT_DELIMITER_CHAR)

« PLANEX MZK-WNH および MZK-W300NH2 で動く OpenWrt with OpenFlow 1.0 のイメージをアップロードしました(Ver.2)」 | トップページ | Trema のコントローラと仮想ネットワークをそれぞれ別々に動かす »

OpenFlow」カテゴリの記事

Trema」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.f.cocolog-nifty.com/t/trackback/1776113/51117824

この記事へのトラックバック一覧です: Trema を改造して仮想ネットワーク機能にポート番号指定を追加:

« PLANEX MZK-WNH および MZK-W300NH2 で動く OpenWrt with OpenFlow 1.0 のイメージをアップロードしました(Ver.2)」 | トップページ | Trema のコントローラと仮想ネットワークをそれぞれ別々に動かす »

最近のトラックバック

無料ブログはココログ