« 【TremaでOpenFlowプログラミング】リピーターハブを5行で作る | トップページ | Trema の仮想ネットワーク機能には『OpenFlow実践入門』に書いてない強力な機能がありました。 »

2013年2月 2日 (土)

Trema の仮想ネットワークの落とし穴。ARPなしで通信してしまう

 

[ 2013年2月3日 追記。 回避策がありました。新しい OS を必要としますが、こちらに書いたネットワークネームスペース機能を使うことでARPも含んだテストが仮想ネットワーク機能でもできます。 ]


OpenFlow フレームワークの Trema 用に書いた5行のリピーターハブを改造して、UDPのポート番号で通信を制限するファイアウォールのようなものを作ろうとして落とし穴にはまりました。失敗事例紹介です。

■教訓

   Trema の仮想ネットワーク機能で仮想ホスト同士の通信ができても現実のネットワークで通信できるとは限らない。
   ARP が通るフローを定義しているか確認せよ。

  目的によっては ARP だけでなく、例えば ICMP Echo を通すべきかなども考慮しないといけないかもしれません。

■失敗コード

やろうとしたことは宛先がUDPポート60000のパケットだけを通すというものです。

class Test1 < Controller
  def switch_ready( datapath_id )
    send_flow_mod_add(
      datapath_id,
      :match => Match.new(
        :dl_type => 0x0800, # IP
        :nw_proto => 17, # UDP
        :tp_dst => 60000 # UDP Port
      ),
      :actions => SendOutPort.new( OFPP_FLOOD )
    )
  end
end

マッチングルールを書くにあたって、書籍『OpenFlow ネットワーク入門』(初版、コロナ社)のP.136 に記載の「表6.10 Matchクラスのインスタンス化オプションのキー」を参考にしました。:dl_type も書かないとダメだということはこの本のおかげで気がつきました。

■仮想ネットワークでのテスト

きちんと通信できました。

仮想ネットワーク定義:

vswitch("vsw1") {
  datapath_id "0x1"
}
vhost("host2") {
  ip "192.168.0.2"
}
vhost("host1") {
  ip "192.168.0.1"
}
link "vsw1", "host2"
link "vsw1", "host1"

実行結果:

$ trema dump_flow vsw1 
NXST_FLOW reply (xid=0x4):
 cookie=0x1, duration=227.119s, table=0, n_packets=1, n_bytes=64, priority=65535,
udp,tp_dst=60000 actions=FLOOD
$ trema show_stats host2
Sent packets:

Received packets:

$ trema send_packets --source host1 --dest host2 --tp_dst 50000
$ trema show_stats host2Sent packets:

Received packets:

$ trema send_packets --source host1 --dest host2 --tp_dst 60000
$ trema show_stats host2Sent packets:

Received packets:
ip_dst,tp_dst,ip_src,tp_src,n_pkts,n_octets
192.168.0.2,60000,192.168.0.1,1,1,50

host2 めがけてUDPポート50000で通信した時には host2 の統計情報は空ですがUDPポート60000だとパケットが受信されています。

■リアルの世界では

2台のLinuxで nc コマンドで通信を試しました。

・構成:

     [Linux(IP: 10.0.0.3)] --- [OpenFlowスイッチ] --- [Linux(IP: 10.0.0.4)]

・1台目(IPアドレス 10.0.0.4): udp 60000 で待ち受け

 実行コマンド:

$ nc -u -l 60000

これでUDPポート60000でデータが来るのを待ちデータが来たら表示するようにしておきます。

・2台目(IPアドレス 10.0.0.3): udp 60000 めがけて送信

  実行コマンド:

$ nc -u 10.0.0.4 60000
aaaa  --- 入力して改行
bbbb  --- 入力して改行

 2台目にて、nc コマンドを実行すると標準入力からの入力待ちになるので、文字を入力して改行するとその行が1台目側で表示されるはずですが、何もでません。

 2台目側で arp -a コマンドで確認してみると...解決できていない

$ arp -a
? (10.0.0.4) at <incomplete> on eth0

本当なら <imcomplete> のところは MAC アドレスがでるべきです。

■修正後のコード

  ARP が通るようにフローエントリを追加しました。

class Test1 < Controller
  def switch_ready( datapath_id )
    send_flow_mod_add(
      datapath_id,
      :match => Match.new(
        :dl_type => 0x0806 # ARP
      ),
      :actions => SendOutPort.new( OFPP_FLOOD )
    )
    send_flow_mod_add(
      datapath_id,
      :match => Match.new(
        :dl_type => 0x0800, # IP
        :nw_proto => 17, # UDP
        :tp_dst => 60000 # UDP Port
      ),
      :actions => SendOutPort.new( OFPP_FLOOD )
    )
  end
end

このコードに変更して、2台で再度ncコマンドを起動し直したらうまく動きました。

« 【TremaでOpenFlowプログラミング】リピーターハブを5行で作る | トップページ | Trema の仮想ネットワーク機能には『OpenFlow実践入門』に書いてない強力な機能がありました。 »

OpenFlow」カテゴリの記事

Trema」カテゴリの記事

TremaでOpenFlowプログラミング」カテゴリの記事

コメント

この記事へのコメントは終了しました。

トラックバック


この記事へのトラックバック一覧です: Trema の仮想ネットワークの落とし穴。ARPなしで通信してしまう:

« 【TremaでOpenFlowプログラミング】リピーターハブを5行で作る | トップページ | Trema の仮想ネットワーク機能には『OpenFlow実践入門』に書いてない強力な機能がありました。 »

最近のトラックバック

無料ブログはココログ