OpenFlowの本を買ったので環境を作って試してみたいと思います。そう「Trema」です。
TremaはOpenFlowコントローラを開発するためのRubyおよびC用のプログラミングフレームワークです。
Tremaのサイトでサポートプラットフォームが掲載されています。
https://github.com/trema/tremaSupported Platforms
Ruby 1.9.3 or higher
RubyGems 1.8.25 or higher
Ubuntu 13.04, 12.10, 12.04, 11.10, and 10.04 (i386/amd64, Desktop Edition)
Debian GNU/Linux 7.0 and 6.0 (i386/amd64)
Fedora 16-19 (i386/x86_64)
AWSのCommunityAMIから「ubuntu-raring-13.04-amd64-server-20130615」を選択してインストールすることにします。Ubuntu 13.04 がサポート外になったため、パッケージのファイルの置き場所がold-releases.ubuntu.com に変わったとのこと。
下記のファイルを修正します。
# sed -i -e 's|//.*ubuntu.com/|//old-releases.ubuntu.com/|' /etc/apt/sources.list # apt-get update :情報を更新します。
Rubyをインストールします。
# apt-get install gcc make git ruby rubygems ruby-dev libpcap-dev libsqlite3-dev libglib2.0-dev
rubygemsをUpdateします。
# gem install rubygems-update -v 1.8.25 # sudo update_rubygems
バージョンを確認します。
# ruby -v ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux] # gem -v 1.8.25
Tremaを設置しバージョンを確認します。
# gem install trema # trema version trema version 0.4.7
下記のブログが大変参考になりました。
http://ranosgrant.cocolog-nifty.com/blog/2014/06/openflow-trema-.html
■動作確認 – dumper
デフォルトで様々なサンプルが設置されるので試してみたいと思います。まずはdumper。
OpenFlowコントローラーに通知される様々なイベントを標準出力に表示します。
# trema run /usr/lib/ruby/gems/1.9.1/gems/trema-0.4.7/src/examples/dumper/dumper.rb -c /usr/lib/ruby/gems/1.9.1/gems/trema-0.4.7/src/examples/dumper/dumper.conf
別コンソールを開いて「trema send_packets」でパケットを投げてみると様々な情報が出力されます。
trema send_packets --source host1 --dest host2 --n_pkts 100
■動作確認 – switch-monitor
スイッチの起動、切断を捕捉するサンプルです。
イベントハンドラを記述しています。
# run /usr/lib/ruby/gems/1.9.1/gems/trema-0.4.7/src/examples/switch_monitor/switch-monitor.rb -c /usr/lib/ruby/gems/1.9.1/gems/trema-0.4.7/src/examples/switch_monitor/switch-monitor.conf
※switch-monitor.rb class SwitchMonitor < Controller periodic_timer_event :show_switches, 10 def start @switches = [] end def switch_ready(datapath_id) @switches << datapath_id.to_hex info "Switch #{ datapath_id.to_hex } is UP" end def switch_disconnected(datapath_id) @switches -= [datapath_id.to_hex] info "Switch #{ datapath_id.to_hex } is DOWN" end private def show_switches info 'All switches = ' + @switches.sort.join(', ') end end
コントローラが起動するとすぐに出力が出ます。
Switch 0x1 is UP Switch 0x2 is UP Switch 0x3 is UP All switches = 0x1, 0x2, 0x3 All switches = 0x1, 0x2, 0x3
別コンソールからtrema killで0x3スイッチをダウンさせてみます。
# trema kill 0x3
すると下記のようにコントローラーが補足します。
Switch 0x3 is DOWN Send queue is already deleted or not created yet ( service_name = switch.0x3 ). All switches = 0x1, 0x2 All switches = 0x1, 0x2 All switches = 0x1, 0x2 All switches = 0x1, 0x2 All switches = 0x1, 0x2
別コンソールからtrema killで0x3スイッチをアップさせてみます。
# trema up 0x3 Switch 0x3 is UP All switches = 0x1, 0x2, 0x3
■動作確認 – repeater_hub
フローに無いパケットを受け取ったらpacket_inが呼び出されフローエントリをスイッチへ書き込みます。その後、packet_inを引き起こしたパケットを明示的にpacket_outします。
# trema run /usr/lib/ruby/gems/1.9.1/gems/trema-0.4.7/src/examples/repeater_hub/repeater-hub.rb -c /usr/lib/ruby/gems/1.9.1/gems/trema-0.4.7/src/examples/repeater_hub/repeater_hub.conf
host1からhost2へパケットを送ってみます。
# trema send_packets --source host1 --dest host2 --n_pkts 1
フローテーブルを見ます。
# trema dump_flows repeater_hub NXST_FLOW reply (xid=0x4): cookie=0x1, duration=6.068s, table=0, n_packets=1, n_bytes=64, priority=65535,udp,in_port=3,vlan_tci=0x0000, dl_src=00:00:00:01:00:01,dl_dst=00:00:00:01:00:02,nw_src=192.168.0.1,nw_dst=192.168.0.2, nw_tos=0,tp_src=1,tp_dst=1 actions=FLOOD
※repeater-hub.rb class RepeaterHub < Controller def packet_in(datapath_id, message) send_flow_mod_add( datapath_id, :match => ExactMatch.from(message), :マッチングルールが定義する 12 個の条件がすべてまったく同じ :actions => ActionOutput.new(OFPP_FLOOD) ) send_packet_out( datapath_id, :packet_in => message, :actions => ActionOutput.new(OFPP_FLOOD) :パケット出力+フラッディング ) end end