その前にRubyのブロック引数について少し説明をしておきます。
ブロックとは、{ } や do ~ end で囲まれた処理を言います。
このブロックをメソッドの引数として渡す事が出来ます。
簡単な例を書きました。
(test.rb)
def zandaka &block bank = { "taro" => 10000, "jiro" => 5000, "sabro" => 20000 } bank.each &block end zandaka { | k, v | puts "#{k}氏の残高は#{v}円ナリ" } zandaka do | k ,v | puts "#{k}君は貯金が#{v}円もあるらしい" end
$ ruby test.rb
sabro氏の残高は20000円ナリ jiro氏の残高は5000円ナリ taro氏の残高は10000円ナリ sabro君は貯金が20000円もあるらしい jiro君は貯金が5000円もあるらしい taro君は貯金が10000円もあるらしい
今回はtraffic_monitorのソースコードの内容に近い形の説明だけしておきます。
簡単な例ではありますが、zandakaメソッドを実行すると { } や do ~ end の間に書かれた処理が実行されているのが分かると思います。
ではfdbのソースを見てみましょう。
examplesの中のtraffic_monitor配下にあるfdb.rbファイルを見てください。
(fdb.rb)
1 class FDB 2 def initialize 3 @db = {} 4 end 5 6 def lookup mac 7 @db[ mac ] 8 end 9 10 def learn mac, port_number 11 @db[ mac ] = port_number 12 end 13 end
2~4行目
initializeでは、@dbというインスタンス変数に空のハッシュ(連想配列)を定義しています。
この@dbには11行目の処理でmacアドレスをハッシュキーにして物理ポート番号を代入している事がわかります。
この@dbには11行目の処理でmacアドレスをハッシュキーにして物理ポート番号を代入している事がわかります。
6~8行目
lookupメソッドは引数のmacアドレスをハッシュキーにして物理ポートの番号を返すメソッドです。
@dbからハッシュ値が取得できない場合はnilを返します。
@dbからハッシュ値が取得できない場合はnilを返します。
10~12行目
learnメソッドは引数のmacアドレスをハッシュキーにして物理ポート番号を@dbに代入しています。
@dbにハッシュキーがあれば物理ポート番号を更新、無ければ新たにハッシュ要素を追加します。
@dbにハッシュキーがあれば物理ポート番号を更新、無ければ新たにハッシュ要素を追加します。
続いてCounterのソースコードを見ていきます。
examplesの中のtraffic_monitor配下にあるcounter.rbファイルを見てください。
(counter.rb)
1 class Counter 2 def initialize 3 @db = {} 4 end 5 6 def add mac, packet_count, byte_count 7 @db[ mac ] ||= { :packet_count => 0, :byte_count => 0 } 8 @db[ mac ][ :packet_count ] += packet_count 9 @db[ mac ][ :byte_count ] += byte_count 10 end 11 12 def each_pair &block 13 @db.each_pair &block 14 end 15 end
2~4行目
initializeでは@dbというインスタンス変数に空のハッシュ(連想配列)を定義しています。
この@dbには、8~9行目の処理でmacアドレスをハッシュキーにし、さらにパケットの送信回数とバイト数のハッシュを作っています。
この@dbには、8~9行目の処理でmacアドレスをハッシュキーにし、さらにパケットの送信回数とバイト数のハッシュを作っています。
6行目
addメソッドでは引数のmacアドレスをハッシュ値にしてパケットの送信回数とバイト数を管理します。
7行目
||=は左辺がnilだった場合に右辺の代入を行います。
@dbのハッシュ値に指定したmacアドレスが無い場合、パケットの送信回数とバイト数に0が代入されます。
@dbのハッシュ値に指定したmacアドレスが無い場合、パケットの送信回数とバイト数に0が代入されます。
8~9行目
@dbからmacアドレスをハッシュキーにしてハッシュ値にパケット送信回数とバイト数を加算しています。
12~14行目
eache_pairメソッドは&blockというブロック引数の内容を実行します。
実行するブロックの内容はtraffic-monitor.rbでメソッドを実行する時に指定しています。
@dbオブジェクトが保持しているmacアドレスをハッシュキーにして@dbオブジェクトのパケット送信回数とバイト数を画面に出力します。
実行するブロックの内容はtraffic-monitor.rbでメソッドを実行する時に指定しています。
@dbオブジェクトが保持しているmacアドレスをハッシュキーにして@dbオブジェクトのパケット送信回数とバイト数を画面に出力します。
次に、traffic_monitor.confの仮想環境の構成です。
(traffic_monitor.conf)
1 vswitch { 2 datapath_id "0xabc" 3 } 4 5 vhost ("host1") { 6 ip "192.168.0.1" 7 mac "00:00:00:00:00:01" 8 } 9 10 vhost ("host2") { 11 ip "192.168.0.2" 12 mac "00:00:00:00:00:02" 13 } 14 15 link "0xabc", "host1" 16 link "0xabc", "host2"
1~13行目
スイッチ1台、ホスト2台の構成になっています。
15~16行目
スイッチとホスト1、スイッチとホスト2を接続する構成にしています。
では、以下のコマンドでtraffic_monitorを実行してみましょう。
trema run ./traffic-monitor.rb -c ./traffic_monitor.conf
$ trema run ./traffic-monitor.rb -c ./traffic_monitor.conf
traffic_monitorを起動した端末を端末1とします。
プログラムを実行して10秒後すると時間が表示されます。
まだホスト1とホスト2でパケットの送受信をしていないため、パケットの送信回数と送信バイト数は表示されません。
$ trema run ./traffic-monitor.rb -c ./traffic_monitor.conf Wed Oct 02 00:40:02 +0900 2013 Wed Oct 02 00:40:12 +0900 2013 Wed Oct 02 00:40:22 +0900 2013 …
Ctl-Cで停止します。
ではこれから以下の事を確認していきます。
・端末2でホスト1とホスト2でパケットの送受信をすると、端末1に表示されるパケットの送信回数と送信バイト数が増える事
・所定の時間が経過するとフローエントリが削除される事
・フローエントリが削除されたタイミングでパケットの送信回数と送信バイト数が計上される事
確認しやすいようにtraffic-monitor.rbのソースコードを少し修正します。
画面表示が多すぎて見づらいため、パケットの送信回数と送信バイト数の表示間隔を20秒にします。
periodic_timer_eventの引数を20に変更
(変更前)periodic_timer_event :show_counter, 10
(変更後)periodic_timer_event :show_counter, 20
フローエントリが10秒で削除されてしまい確認しづらいため、フローエントリの有効期限を60秒にします。
send_flow_mod_addメソッドの:hard_timeoutを600に変更
(変更前) :hard_timeout => 10
(変更後) :hard_timeout => 60
動作確認をするにあたり、traffic-monitor.rbを実行した端末とは別に、もう一つ端末を起動して操作します。
こちらの端末を端末2とします。
まずは端末1で先ほどと同じコマンドを実行し、traffic_monitorを起動します。
trema run ./traffic-monitor.rb -c ./traffic_monitor.conf
では端末2から以下のコマンドで、ホスト1からホスト2、ホスト2からホスト1へパケットを送ります。
コマンドを実行して20秒したら、もう一度ホスト1からホスト2、ホスト2からホスト1へパケットを送ります。
trema send_packets --source host1 --dest host2 trema send_packets --source host2 --dest host1 (20秒後) trema send_packets --source host1 --dest host2 trema send_packets --source host2 --dest host1 trema show_stats host1 trema show_stats host2
<端末2>
$ trema send_packets --source host1 --dest host2$ trema send_packets --source host2 --dest host1 $ trema show_stats host1 Sent packets: ip_dst,tp_dst,ip_src,tp_src,n_pkts,n_octets 192.168.0.2,1,192.168.0.1,1,2,100 Received packets: ip_dst,tp_dst,ip_src,tp_src,n_pkts,n_octets 192.168.0.1,1,192.168.0.2,1,2,100 $ trema show_stats host2 Sent packets: ip_dst,tp_dst,ip_src,tp_src,n_pkts,n_octets 192.168.0.1,1,192.168.0.2,1,2,100 Received packets: ip_dst,tp_dst,ip_src,tp_src,n_pkts,n_octets 192.168.0.2,1,192.168.0.1,1,2,100この時、端末1にはホスト1とホスト2のmacアドレスとパケットの送信回数と送信バイト数が表示されます。
パケットを送るたびに送信回数と送信バイト数が増えていく事が確認出来ます。
<端末1>
$ trema run ./traffic-monitor.rb -c ./traffic_monitor.conf Wed Oct 02 00:48:57 +0900 2013 Wed Oct 02 00:49:17 +0900 2013 00:00:00:00:00:01 1 packets (64 bytes) 00:00:00:00:00:02 1 packets (64 bytes) Wed Oct 02 00:49:37 +0900 2013 00:00:00:00:00:01 2 packets (128 bytes) 00:00:00:00:00:02 1 packets (64 bytes)
次は、以下のコマンドで端末2にフローテーブルの内容を表示します。
1分後にもう一度フローテーブルの内容を表示します。
trema dump_flows 0xabc (1分後) trema dump_flows 0xabc
<端末2>
$ trema dump_flows 0xabc NXST_FLOW reply (xid=0x4): cookie=0x2, duration=40.845s, table=0, n_packets=0, n_bytes=0, hard_timeout=60,priority=65535,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02 actions=output:1 cookie=0x1, duration=52.259s, table=0, n_packets=1, n_bytes=64, hard_timeout=60,priority=65535,dl_src=00:00:00:00:00:02,dl_dst=00:00:00:00:00:01 actions=output:2 $ trema dump_flows 0xabc NXST_FLOW reply (xid=0x4):
1分後にはフローテーブルからフローエントリーが削除された事が確認出来ます。
1つ目のコマンドでフローテーブルが表示されなかった場合は、もう一度ホスト1からホスト2、ホスト2からホスト1へパケットを送ってからすぐにフローテーブルの内容を表示してください。
次は、以下のコマンドでホスト2からホスト1へパケットを送った後、ホスト1からホスト2へパケットを3回送ります。
trema send_packets --source host2 --dest host1 trema send_packets --source host1 --dest host2 (20秒後) trema send_packets --source host1 --dest host2 trema send_packets --source host1 --dest host2 trema send_packets --source host1 --dest host2 trema dump_flows 0xabc (1分後) trema dump_flows 0xabc
<端末2>
$ trema send_packets --source host2 --dest host1 $ trema send_packets --source host1 --dest host2 $ $ trema send_packets --source host1 --dest host2 $ trema send_packets --source host1 --dest host2 $ trema send_packets --source host1 --dest host2 $ trema dump_flows 0xabc NXST_FLOW reply (xid=0x4): cookie=0x1, duration=36.986s, table=0, n_packets=3, n_bytes=192, hard_timeout=60,priority=65535,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02 actions=output:1 $ $ trema dump_flows 0xabc NXST_FLOW reply (xid=0x4):
端末1の表示を見ると、ホスト1からホスト2にパケットを送っても2回目以降はすぐには送信回数と送信バイト数は増えません。
パケットを送ってから60秒するとフローエントリが削除され、そのタイミングで送信回数と送信バイト数が計上されます。
<端末1>
$ trema run ./traffic-monitor.rb -c ./traffic_monitor.conf Wed Oct 02 01:01:22 +0900 2013 00:00:00:00:00:01 1 packets (64 bytes) 00:00:00:00:00:02 1 packets (64 bytes) Wed Oct 02 01:01:42 +0900 2013 00:00:00:00:00:01 1 packets (64 bytes) 00:00:00:00:00:02 1 packets (64 bytes) Wed Oct 02 01:02:02 +0900 2013 00:00:00:00:00:01 1 packets (64 bytes) 00:00:00:00:00:02 1 packets (64 bytes) Wed Oct 02 01:02:22 +0900 2013 00:00:00:00:00:01 4 packets (256 bytes) 00:00:00:00:00:02 1 packets (64 bytes) …
以上になります。
0 件のコメント:
コメントを投稿