« ◆ 単純なブリッジの実装その3~より完璧な土管化~【OpenFlow1.0をTremaの土管として使う】 | トップページ | ◆ 単純なブリッジの実装その4~Open vSwitch対策~【OpenFlow1.0をTremaの土管として使う】 »

2014年7月 5日 (土)

◆ ポートベースVLANの作成【OpenFlow1.0をTremaの土管として使う】

[注意: 本記事は、OpenFlow の適切な使い方ではありません。単にパケットの出し入れの道具として利用しています。]

前回のブリッジのコードをもとにしてポートベースVLAN を実装し、動かしてみました。

■確認環境
  OS: Lubuntu 13.04 Desktop (i386)
  Trema: 0.4.7

■構成
  スイッチは、4ポート。
  ポート1,2で VLAN1 を構成。
  ポート3、4で VLAN2 を構成。

  各ポートにはホストを接続。

  Trema の仮想ネットワーク構成ファイル(h4s1.conf)は以下の通り:

vswitch ( "vswitch1" ) {
  datapath_id 0x01
}

vhost ( "vhost1" ) {
  mac "02:00:00:00:00:01"
  ip "192.168.1.1"
  netmask "255.255.255.0"
}

vhost ( "vhost2" ) {
  mac "02:00:00:00:00:02"
  ip "192.168.1.2"
  netmask "255.255.255.0"
}

vhost ( "vhost3" ) {
  mac "02:00:00:00:00:03"
  ip "192.168.1.3"
  netmask "255.255.255.0"
}

vhost ( "vhost4" ) {
  mac "02:00:00:00:00:04"
  ip "192.168.1.4"
  netmask "255.255.255.0"
}

link "vswitch1", "vhost1"
link "vswitch1", "vhost2"
link "vswitch1", "vhost3"
link "vswitch1", "vhost4"

図にすると:
Photo_2
※注意!!
Trema の仮想ネットワークではスイッチのポート番号と仮想ホストの対応を指定できません。上記の図における仮想ホストが接続されるポートのポート番号は今回テストした時にたまたまこうだったというだけで、必ずこうなるわけではありません。

■Trema のコード(PortBasedVLAN1.rb)
基本となるコードは前回のブリッジのコードです。

class PortBasedVLAN1 < Controller

  def start
    @port_list = [ 1, 2, 3, 4 ]    # all port numbers

    @port_list_of_vlan = {
      1 => [ 1, 2 ],
      2 => [ 3, 4 ]
    }

    @vlan_id_of_port = { }
    @port_list_of_vlan.each do | vlan_id, vlan_port_list |
      vlan_port_list.each do | port |
        @vlan_id_of_port[ port ] = vlan_id
      end
    end

    @port_of_mac = { }
  end

  def switch_ready( datapath_id )
    info "Switch[0x%016x] is up." % datapath_id

    send_flow_mod_add( datapath_id, :priority => 100 )

    @port_list.each do | port |
      send_flow_mod_add( datapath_id,
        :match => Match.new( :in_port => port ),
        :actions => SendOutPort.new( OFPP_CONTROLLER ) )
    end
  end

  def switch_disconnected( datapath_id )
    info "Switch[0x%016x] is disconnected." % datapath_id
  end

  def packet_in( datapath_id, message )
    return unless message.reason == Trema::PacketIn::OFPR_ACTION

    learned_port = @port_of_mac[ message.macsa.to_i ]
    if learned_port == nil or learned_port != message.in_port
      info "MAC[%s] is found at Port #{ message.in_port }." % message.macsa.to_s
      @port_of_mac[ message.macsa.to_i ] = message.in_port
    end

    vlan_id = @vlan_id_of_port[ message.in_port ]
    vlan_port_list = @port_list_of_vlan[ vlan_id ]

    actions = [ ]
    vlan_port_list.each do | port |
      if ( message.in_port != port )
        actions.push( SendOutPort.new( port ) )
      end
    end

    send_packet_out( datapath_id,
      :in_port => message.in_port,
      :data => message.data,
      :actions => actions )
  end

end

緑のところ:
ポート数を4つに増やしています。

青いところ:
仮想ホストがどのポートにつながっているか分かるようにメッセージ出力するためのコードです。MACアドレスをキーにしたハッシュにポート番号を格納しています。受け取ったパケットが、まだ記録がないMAC から届いた場合か記録があってもポート番号に変更があった時にメッセージ出力するようにしています。

赤いところ:
start メソッド
VLAN ごとに含まれるポート番号の配列を @port_list_of_mac 変数にあらかじめ指定しています。VLAN ID をキーとしたハッシュです。
ポート番号から VLAN ID を求めるため @vlan_id_of_port のハッシュをあらかじめ計算しています。

packet_in メソッド
ポート番号から VLAN ID を求めて、その VLAN のポート番号の配列を求めています。
以前は、すべてのポートに対してパケットを送信していた箇所を、入力ポート番号が属する VLAN の各ポートにパケットを送信するように変更しています。

■テスト

trema を起動します。

$ trema run PortBasedVLAN1.rb -c h4s1.conf
Switch[0x0000000000000001] is up.

Lubuntu の network-monitor サービスを停止していないと、勝手にパケットが飛ぶので仮想ホスト以外のMACが検出されてメッセージが出力されますがこれらは無視してください。

別のターミナルウィンドウを開き、各仮想ホストからパケットを送ります:

$ trema send_packet -s vhost1 -d vhost2
$ trema send_packet -s vhost2 -d vhost3
$ trema send_packet -s vhost3 -d vhost4
$ trema send_packet -s vhost4 -d vhost1

そうすると trema を起動した画面に以下のように各仮想ホストのMACが検出されてどのポートにつながっているか確認できます:

MAC[02:00:00:00:00:01] is found at Port 3.
MAC[02:00:00:00:00:02] is found at Port 1.
MAC[02:00:00:00:00:03] is found at Port 2.
MAC[02:00:00:00:00:04] is found at Port 4.

上記のポートと仮想ホストの接続関係を前提に通信のテストを行います。

まず、テストの前に以下のコマンドで統計情報をクリアしておきます:

$ trema reset_stats

(1) テスト1: VLAN をまたがった通信
ポート3の vhost1 からポート1 の vhost2 へパケットを送り vhost2 側の受信パケットを確認してみます。

$ trema send_packet -s vhost1 -d vhost2
$ trema show_stats -r vhost2

ポート3 は VLAN2, ポート1 は VLAN1 に属し異なる VLAN なのでパケットが届かず vhost2 では何もパケットを受信していないので空行が表示されます。

(2) テスト2: VLAN 内の通信
ポート2 の vhost3 からポート1 の vhost2 へパケットを送り vhost2 側の受信パケットを確認してみます。

$ trema send_packet -s vhost3 -d vhost2
$ trema show_stats -r vhost2
ip_dst,tp_dst,ip_src,tp_src,n_pkts,n_octets
192.168.1.2,1,192.168.1.3,1,1,50

VLAN1 内の通信なので受信パケットが vhost2 に届いています。

(3) その他のポートの組み合わせも試してみます

$ trema send_packet -s vhost3 -d vhost4
$ trema show_stats -r vhost4

$ trema send_packet -s vhost1 -d vhost4
$ trema show_stats -r vhost4
ip_dst,tp_dst,ip_src,tp_src,n_pkts,n_octets
192.168.1.4,1,192.168.1.1,1,1,50

こちらも、VLAN内の通信となる場合だけパケットが受信できています。

以上です。

« ◆ 単純なブリッジの実装その3~より完璧な土管化~【OpenFlow1.0をTremaの土管として使う】 | トップページ | ◆ 単純なブリッジの実装その4~Open vSwitch対策~【OpenFlow1.0をTremaの土管として使う】 »

Tremaでネットワーク機器プログラミング」カテゴリの記事

コメント

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

トラックバック


この記事へのトラックバック一覧です: ◆ ポートベースVLANの作成【OpenFlow1.0をTremaの土管として使う】:

« ◆ 単純なブリッジの実装その3~より完璧な土管化~【OpenFlow1.0をTremaの土管として使う】 | トップページ | ◆ 単純なブリッジの実装その4~Open vSwitch対策~【OpenFlow1.0をTremaの土管として使う】 »

最近のトラックバック

無料ブログはココログ