前回のlearning_switchはわかったでしょうか?
learning_switchがわかっていれば、今回のtraffic_monitorもわかると思います。
ではさっそくtraffic_monitorのソースを見て行きましょう。
(traffic-monitor.rb)
1 require "counter" 2 require "fdb" 3 4 class TrafficMonitor < Controller 5 periodic_timer_event :show_counter, 10 6 7 def start 8 @counter = Counter.new 9 @fdb = FDB.new 10 end 11 12 def packet_in datapath_id, message 13 macsa = message.macsa 14 macda = message.macda 15 16 @fdb.learn macsa, message.in_port 17 @counter.add macsa, 1, message.total_len 18 out_port = @fdb.lookup( macda ) 19 if out_port 20 packet_out datapath_id, message, out_port 21 flow_mod datapath_id, macsa, macda, out_port 22 else 23 flood datapath_id, message 24 end 25 end 26 27 def flow_removed datapath_id, message 28 @counter.add message.match.dl_src, message.packet_count, message.byte_count 29 end 30 31 private 32 33 def show_counter 34 puts Time.now 35 @counter.each_pair do | mac, counter | 36 puts "#{ mac } #{ counter[ :packet_count ] } packets (#{ counter[ :byte_count ] } bytes)" 37 end 38 end 39 40 def flow_mod datapath_id, macsa, macda, out_port 41 send_flow_mod_add( 42 datapath_id, 43 :hard_timeout => 10, 44 :match => Match.new( :dl_src => macsa, :dl_dst => macda ), 45 :actions => ActionOutput.new( out_port ) 46 ) 47 end 48 49 def packet_out datapath_id, message, out_port 50 send_packet_out( 51 datapath_id, 52 :packet_in => message, 53 :actions => ActionOutput.new( out_port ) 54 ) 55 end 56 57 def flood datapath_id, message 58 packet_out datapath_id, message, OFPP_FLOOD 59 end
このプログラムではlearning switchをベースに以下のような変更をしています。
・パケットの送信回数、送信バイト数を集計し、定期的に画面に表示します
・フローエントリの有効期限を10秒に設定し、フローエントリを削除します
・フローエントリが削除されるタイミングでスイッチから送信回数と送信バイト数を取得します
1~2行目
requireではCounterクラスとFDBクラスを読み込んでいます。
FDBクラスは前回のlearning_switchに出てきたものよりもだいぶシンプルな内容になっています。
Counterクラスはパケットの送信回数と送信バイト数を管理するクラスです。
これらのクラスの説明は後ほど行います。
FDBクラスは前回のlearning_switchに出てきたものよりもだいぶシンプルな内容になっています。
Counterクラスはパケットの送信回数と送信バイト数を管理するクラスです。
これらのクラスの説明は後ほど行います。
4行目
TrafficMonitorクラスを定義しています。
5行目
periodic_timer_eventはタイマーでメソッドを実行します。
「show_counter」メソッドを10秒おきに実行します。
「show_counter」メソッドを10秒おきに実行します。
6~10行目
startメソッドでCounterクラスのオブジェクトとFDBクラスのオブジェクトを作成しています。
@counterと@fdbはTrafficMonitorクラスの内で参照できます。
@counterと@fdbはTrafficMonitorクラスの内で参照できます。
12~14行目
packet_inイベントハンドラです。
スイッチのフローテーブルにマッチしないパケットを受け取った時に実行されます。
引数のmessageから送信元のmacアドレスと送信先のmacアドレスを取得し、変数にセットしています。
スイッチのフローテーブルにマッチしないパケットを受け取った時に実行されます。
引数のmessageから送信元のmacアドレスと送信先のmacアドレスを取得し、変数にセットしています。
16行目
@fdb.learnはFDBクラスのメソッドです。
このメソッドはmessageオブジェクトから取得した送信元macアドレスをハッシュキーにして物理ポート番号を@fdbオブジェクトに追加します。
learnメソッドについては後ほど見ます。
このメソッドはmessageオブジェクトから取得した送信元macアドレスをハッシュキーにして物理ポート番号を@fdbオブジェクトに追加します。
learnメソッドについては後ほど見ます。
17行目
@counter.addはCounterクラスのメソッドです。
このメソッドはmessageオブジェクトから取得した送信元のmacアドレスをハッシュキーにして、パケットの送信回数と送信バイト数を@counterオブジェクトに追加します。
addメソッドについては後ほど見ます。
このメソッドはmessageオブジェクトから取得した送信元のmacアドレスをハッシュキーにして、パケットの送信回数と送信バイト数を@counterオブジェクトに追加します。
addメソッドについては後ほど見ます。
18行目
@fdb.lookupはFDBクラスのメソッドで、送信先のmacアドレスに対応した物理ポート番号を@fdbオブジェクトから取得するメソッドです。
lookupメソッドについては後ほど見ます。
lookupメソッドについては後ほど見ます。
19~24行目
lookupメソッドで物理ポート番号が取得できた場合は以下の処理を行います。
@fdbオブジェクトから物理ポート番号が取得できた場合、以下の処理を行います。
49行目にあるpacket_outメソッドを実行し、送信先の物理ポート宛てにパケットを送ります。
40行目にあるflow_modメソッドを実行し、フローテーブルにフローエントリを追加します。
lookupメソッドで物理ポート番号が取得できなかった場合、以下の処理を行います。
57行目にあるfloodメソッドを実行し、送信元の物理ポート以外の全てのポートにパケットを流します。
@fdbオブジェクトから物理ポート番号が取得できた場合、以下の処理を行います。
49行目にあるpacket_outメソッドを実行し、送信先の物理ポート宛てにパケットを送ります。
40行目にあるflow_modメソッドを実行し、フローテーブルにフローエントリを追加します。
lookupメソッドで物理ポート番号が取得できなかった場合、以下の処理を行います。
57行目にあるfloodメソッドを実行し、送信元の物理ポート以外の全てのポートにパケットを流します。
27~29行目
flow_removedイベントハンドラです。フローテーブルからフローエントリが削除される時に実行されます。
messageはFlowRemovedクラスのオブジェクトで、ここから削除するフローエントリの情報が取得できます。
@counter.addメソッドでフローテーブルに保持されてていた統計情報を@counterオブジェクトに加算します。
messageはFlowRemovedクラスのオブジェクトで、ここから削除するフローエントリの情報が取得できます。
@counter.addメソッドでフローテーブルに保持されてていた統計情報を@counterオブジェクトに加算します。
31行目
priveateからは下に書かれたメソッドは外部から参照することはできません
33~38行目
5行目に記述のあったタイマーで実行されるメソッドです
まず、現在時刻を画面に出力します。
35行目から37行目はCounterクラスのeach_pairメソッドを実行しています。
ここではブロック引数という書き方をしていて、doからendまでの処理を@counterクラスのeach_pairメソッドに渡して実行します。
each_pairの処理については後ほど見ます。
まず、現在時刻を画面に出力します。
35行目から37行目はCounterクラスのeach_pairメソッドを実行しています。
ここではブロック引数という書き方をしていて、doからendまでの処理を@counterクラスのeach_pairメソッドに渡して実行します。
each_pairの処理については後ほど見ます。
40~47行目
flow_modメソッドでは、send_flow_mod_addというフローエントリの追加・変更をするメソッドを実行します。
:hard_timeoutはフローエントリの有効期限を定義しています。ここでは10をセットしているので10秒間フローテーブルに保持されます。
「条件」にあたる「:match」にはMatchオブジェクトを作成して、送信元と送信元のmacアドレスを条件に指定しています。
「処理」にあたる「:actions」には、指定した物理ポート番号に対しパケットを送るようにします。
:hard_timeoutはフローエントリの有効期限を定義しています。ここでは10をセットしているので10秒間フローテーブルに保持されます。
「条件」にあたる「:match」にはMatchオブジェクトを作成して、送信元と送信元のmacアドレスを条件に指定しています。
「処理」にあたる「:actions」には、指定した物理ポート番号に対しパケットを送るようにします。
49~55行目
packet_outメソッドではsend_packet_outメソッドを実行してパケットを送ります。
「:pacekt_in」で送るパケットやパケットの送信元物理ポート等をセットしています。
「:actions」では指定した物理ポート番号にパケットを送るようにします。
floodメソッドは49行目にかかれたpacket_outメソッドを実行し、送信元以外の全ての物理ポートにパケットを送ります。
「:pacekt_in」で送るパケットやパケットの送信元物理ポート等をセットしています。
「:actions」では指定した物理ポート番号にパケットを送るようにします。
floodメソッドは49行目にかかれたpacket_outメソッドを実行し、送信元以外の全ての物理ポートにパケットを送ります。
今回はここまで。
次回につづく。。。
0 件のコメント:
コメントを投稿