◆ ポートベース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"
図にすると:
※注意!!
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でネットワーク機器プログラミング」カテゴリの記事
- ◆単純なブリッジに仮想インターフェースを追加【OpenFlow1.0をTremaの土管として使う】(2014.08.02)
- ◆ 単純なブリッジの実装その4~Open vSwitch対策~【OpenFlow1.0をTremaの土管として使う】(2014.07.13)
- ◆ ポートベースVLANの作成【OpenFlow1.0をTremaの土管として使う】(2014.07.05)
- ◆ 単純なブリッジの実装その3~より完璧な土管化~【OpenFlow1.0をTremaの土管として使う】(2014.06.29)
- ◆ 単純なブリッジの実装その2~複数ポート対応~【OpenFlow1.0をTremaの土管として使う】(2013.11.02)
この記事へのコメントは終了しました。
« ◆ 単純なブリッジの実装その3~より完璧な土管化~【OpenFlow1.0をTremaの土管として使う】 | トップページ | ◆ 単純なブリッジの実装その4~Open vSwitch対策~【OpenFlow1.0をTremaの土管として使う】 »
コメント