今回はTremaを使ってOpenFlowスイッチの統計情報を表示するサンプルプログラム作りに挑戦します。
作成し終わってから、似たようなサンプルがあることに気づきましたが、スルーします。
環境準備
下記サイトを参考にinstallします。https://github.com/trema/trema/blob/develop/README.md
下記のサンプルコードも同時に、src/examples/にinstallされます。
https://github.com/trema/trema/tree/develop/src/examples
install完了したら、上述のlink先のtutorialや下記のTrema編の情報をみながら、実際にサンプルコードを触りながら、動作を確認していきます。Tremaはイベント駆動型で、最初は少し戸惑いました。
http://gihyo.jp/dev/serial/01/openflow_sd
サンプル
今回はOpenFlowスイッチの統計情報を収集するサンプルを作成します。ネットワーク機器を運用していると、何かと統計情報を参照することが多いので、Tremaで、どのような情報を収集できるのか気になります。
tremaに付属しているサンプル「traffic_monitor」を元に、機能追加する形で実装します。
Trema APIはこちらにreferenceがありますが多すぎるので、まずは、こちらに記載のものから少しずつ試すのがいいと思います。
今回は、下記の2つのrequest messageをOpenFlowコントローラからOpenFlowスイッチに送出し、その結果を対応するevent handlerで待ち受けます。
<メッセージ>
Trema::FeaturesRequest
Trema::PortStatsRequest
<Event Handler>
features_reply(datapath_id, message)
stats_reply(datapath_id, message)
下記はコード抜粋です。
class TrafficMonitor < Controller
---snip---
def switch_ready datapath_id
@datapath_id = datapath_id
send_message datapath_id, FeaturesRequest.new
send_message datapath_id, PortStatsRequest.new
end
def features_reply datapath_id, message
puts "---------"
p message.datapath_id
p message.transaction_id
p message.n_buffers
p message.n_tables
p message.capabilities
p message.actions
puts "==="
p message.ports
end
def stats_reply datapath_id, message
p message.flags
p message.transaction_id
p message.type
puts message.stats
end
---snip---
OpenFlowスイッチと接続時(switch_ready)、OpenFlowコントローラからOpenFlowスイッチに対して、FeaturesRequestとPortStatsRequestメッセージを送出しています。その後、OpenFlowスイッチからのそれぞれの応答(FeaturesReplyとPortStatsReply)を受け取ります。それぞれの応答を受け取るためのEvent Handler、はfeature_replyとstats_replyです。
出力結果は下記の通りです。
とりあえず、featuresとportstatsのreply messageを取得できていることがわかります。
サンプルプログラム全体はgithubに置いてあります。
https://github.com/snumano/trema_stats
出力結果は下記の通りです。
とりあえず、featuresとportstatsのreply messageを取得できていることがわかります。
$ cd trema/src/examples/test/
$ ls
fdb.rb readme traffic-monitor.rb traffic_monitor.conf
$ ~/trema/trema run traffic-monitor.rb -c traffic_monitor.conf
##### features_reply結果 #####
---------
2748
174194689
256
1
135
4095
===
[#<Trema::Port:0xb734bc5c @peer=0, @name="trema0-0", @state=0, @supported=0, @config=0, @hw_addr=#<Trema::Mac:0xb734bc84 @string="3a:91:53:f7:8e:b7", @value=64395853401783>, @advertised=0, @number=2, @curr=192>, #<Trema::Port:0xb734b7e8 @peer=0, @name="vsw_0xabc", @state=1, @supported=0, @config=1, @hw_addr=#<Trema::Mac:0xb734b84c @string="e2:4d:c0:65:dc:2a", @value=248823568260138>, @advertised=0, @number=65534, @curr=130>, #<Trema::Port:0xb734b16c @peer=0, @name="trema1-0", @state=0, @supported=0, @config=0, @hw_addr=#<Trema::Mac:0xb734b310 @string="8a:75:10:17:c2:1c", @value=152235385799196>, @advertised=0, @number=1, @curr=192>]
###### stats_reply(PortsStatsReply)結果 #####
0
174194690
4
#<Trema::PortStatsReply:0xb73499e8>
collisions: 0
port_no: 2
rx_bytes: 0
rx_crc_err: 0
rx_dropped: 0
rx_errors: 0
rx_frame_err: 0
rx_over_err: 0
rx_packets: 0
tx_bytes: 0
tx_dropped: 0
tx_errors: 0
tx_packets: 0
#<Trema::PortStatsReply:0xb734922c>
collisions: 0
port_no: 65534
rx_bytes: 0
rx_crc_err: 0
rx_dropped: 0
rx_errors: 0
rx_frame_err: 0
rx_over_err: 0
rx_packets: 0
tx_bytes: 0
tx_dropped: 0
tx_errors: 0
tx_packets: 0
#<Trema::PortStatsReply:0xb734850c>
collisions: 0
port_no: 1
rx_bytes: 0
rx_crc_err: 0
rx_dropped: 0
rx_errors: 0
rx_frame_err: 0
rx_over_err: 0
rx_packets: 0
tx_bytes: 0
tx_dropped: 0
tx_errors: 0
tx_packets: 0
サンプルプログラム全体はgithubに置いてあります。
https://github.com/snumano/trema_stats
ハマりポイント
- Trema情報少ない
v0.2.5なので、現状では仕方ないですね。上述のサイトのtutorialやサンプルを参考に、必要なAPI documentを読んでいきます。 - どのEvent Handlerを使えばいいか分かりづらい。
上記のサンプルでは2種類のメッセージに対応するEvent Handlerを使っていますが、stats_replyで複数のメッセージ(*StatsRequets)に対応するReplyのEventを待ち受けするようです。
ここのmessageのOb jectの説明をみてやっと理解できました。 - バグや実装漏れ、ドキュメント間違い
上述のstats_replyの動作について、実際の動作とDocumentに差異があり、悩んでいたのですが、結局古いTremaバージョンの不具合だったようで、最新バージョンにすることで解消しました。(常に最新バージョンにするようにしたほうがいいですね)
また、ドキュメントにも小さな記載間違いなどがあるので、都度、確認するようにしています。間違いなど見つけたら、Issue Trackerに記載するようにしています。
引き続き、Tremaのサンプル作りに挑戦したいと思います。次はFlow情報系かな。。。
<追記>
・2012/9/10 出力結果追記
<追記>
・2012/9/10 出力結果追記