Upload
hiroshi-oshiba
View
2.836
Download
0
Embed Size (px)
DESCRIPTION
Document for develop OFC App by Trema-Edge.
Citation preview
意外に違う Trema と Trema-Edge
oshiba
自己紹介
Python と Ruby が好きで、 色々遊んでます!
フレームワークをあれこれ触って楽しんでます。
会社で OpenFlow スイッチ扱ってます。
今日お話しする内容TremaEdge を使ってみて分かった、Trema との違いどころを色々と書きます。
Pio 試したり、 Sinatra 試したりすると中々手ごわいこと( ズバリ書くと不具合 ) があったため、その辺りを重点的
に。※ 今後修正されると思うので、そのときにはこの資料
は意味をなさないね!(2014 年 2 月 17 日で作りました )
What is TremaEdge ?
要するに Trema の OF1.3用
フレームワークです
Trema TremaEdge
OF v1.0 対応
OF v1.3 対応
ちなみに。。。
OF v1.3 になったことによる変更点は、あんまり解説しません。
マスタリング TCP/IP の OpenFlow とか読んでね!
解説しない理由: めんどくさいから ( 変更点多すぎ )※ 混乱しそうな場所だけほんのちょっと触れるかも
※ あと、 Ruby2.0 になったことによる違いも触れないです
まず、起動するだけ
class TestController < Controller
def start
puts “ Hello Trema! ”
end
end
何も変化無し。
ハンドラ定義
def packet_in dpid, messageenddef port_status dpid, messageenddef port_desc_multipart_reply dpid, messageenddef packet_in dpid, messageend
ハンドラ名はものによって変わってる
※ OpenFlow メッセージが変わったので
今まで通りメソッドを定義。
ポート情報一覧の取得用※FeaturesRequest/Reply で受け取れなくなった情報
タイマ定義とかメッセージ送信とか
# タイマ定義add_timer_event :discover_neighbor, 5, :periodic
# フロー追加send_flow_mod_add( dpid, options)
# メッセージ送信send_message dpid, PortMultipartRequest.new
基本、今まで通り。
※ フロー追加は option について変更有 (instruction とか )
ここから変更点とか問題点とか
・ PacketIn のときのパケット情報取得・ PortStatus のポート情報受け取り・ PacketOut でデータのみのパケット出
力・ 色々な便利メソッドの有無・ Sinatra と連携・ Trema::Pio と連携
PacketIn のときのパケット情報取得 マッチ条件の名前がベース
eth_dst 、 eth_src 、 ipv4_dst とか
https://github.com/trema/trema-edge/blob/develop/ruby/trema/match.rb
をチェック!
PortStatus のポート情報受け取り
Tremadef port_status dpid, message message.phy_port.port_noend TremaEdgedef port_status dpid, message message.port_noend
理由: TremaEdge では、PortStatus が Port クラスを継承する形で作られている
phy_portがない
PacketOut でデータのみのパケット出力
# PacketIn ベースのリアクティブな処理 send_packet_out( dpid, :packet_in => packet_in, :actions => SendOutPort.new( OFPP_ALL )
)# バイナリデータを渡す形の処理 send_packet_out( dpid, :data => packet, :buffer_id => OFP_NO_BUFFER, :actions => SendOutPort.new( OFPP_ALL )
) An Ethernet frame must be provided if buffer_id is equal to 0xffffffff データを渡しても NG…
PacketOut でデータのみのパケット出力VALUE r_opt_message = HASH_REF( options, packet_in );~中略~if ( buffer_id == OFP_NO_BUFFER && !NIL_P( r_opt_message ) ) {~中略~else {
packet_out = create_packet_out(
get_transaction_id(),
buffer_id,
in_port,
actions,
NULL
);
}
一部改変が必要
:packet_in オプションが指定されていないと、ちゃんと動くようになっていない。
PacketOut でデータのみのパケット出力~改変例~
VALUE r_opt_message = HASH_REF( options, packet_in );VALUE r_opt_data = HASH_REF( options, data ); // データオプション追
加~中略~if ( !NIL_P( r_opt_message ) ) {
~中略~else if( !NIL_P(r_opt_data) ){ // データオプション追加 data = r_array_to_buffer( r_opt_data );
}
~中略~if ( buffer_id == OFP_NO_BUFFER && // 条件を1つ追加 ( !NIL_P( r_opt_message ) || !NIL_P(r_opt_data) )) {
~中略~else {
~中略~:data のオプション指定があった場合を想定
data に対する free 自体は既に処理があるため、追記はしない
これだけでは NG!
PacketOut でデータのみのパケット出力
send_packet_out( dpid,# :data => packet, :data => packet.unpack(“C*”), :buffer_id => OFP_NO_BUFFER, :actions => SendOutPort.new( OFPP_ALL ) )
Array で渡さないといけないので、 unpack をする必要がある
Sinatra と連携普通に使うと以下のようなメッセージが出てしまい、 Sinatra が動かない。。。
「 Logger 」に問題がありそう?クラスじゃないというメッセージが出てる。
Sinatra と連携Sinatra の Logger クラスとTrema の Logger モジュールがバッティングしてる。
Sinatra
Loggerクラス
Trema-Edge
Loggerモジュー
ル競合
Trema だと、「 DefaultLogger 」だったので OK だった。。。
# logger.c について (145 行目 )
mLogger = rb_define_module_under( mTrema, "TremaLogger" );
# logger.rb について (20 行目 )
module TremaLogger
# controller.rb について (33 行目 )
include TremaLogger
Sinatra と連携 ( 回避策 )
Logger モジュールの名前を変えてあげる。
Sinatra と連携 ( 変更後 )
エラーは出ない。ルートを書けば問題なく動作
少なくとも、 GET 、 POST 、 DELETE は動作
Trema::Pio と連携require "pio"
class TestPacket < Controller
def start
puts "start"
end
end
error: field '[:octets, {:type=>:uint8, :initial_length=>6}]' is an illegal fieldname in Pio::Type::MacAddress
require しただけでエラー動かない。。。
Trema::Pio と連携どうやら、 Trema-Edge の問題。。。
Objecttruetrue
# Trema-Edge で動かした場合class Fuga
end
p Fuga.superclass
p Fuga.superclass.respond_to? "string"
p Fuga.superclass.respond_to? “array"
Object クラスに対して、 string や array がクラスメソッドとして存在してしまっている。
Trema::Pio と連携この” string” や” array” が、 bindata を使った Pio のソースにおける、 array や string の宣言的な箇所で問題を起こしている。
こういう箇所で問題になる
class PioString < Bindata::String
end
class PioArray < Bindata::Array
end
Trema::Pio と連携(回避策)array とか string が使えないので、とりあえず Pio 側を書き換え。pio_array とか pio_string にする。
こんな感じの宣言箇所をarray から、 pio_array に変更 string から、 pio_string に変更
sugyo さんからもっとよさそうな回避策も出てました。でも試してないからここでは書くのをやめました。
色々な便利メソッドの有無message-helper に今後は纏められる?(sugyo さんが issue あげてた )
でも、今はまだ、ほとんどない。。。
send_flow_mod_add 、send_group_mod_add ぐらいしかない。。。
色々な便利メソッドの有無残念ながら以下みたいなのは自分で定義する必要あり・ send_flow_mod_delete
・ Port クラスの port.up? もしくは port.down?
def up?
if(self.state | 1 == 0)
return true
end
return false
end
def down?
return (not self.up?)
end
def send_flow_mod_delete datapath_id, options
options[ :command ] = OFPFC_DELETE
options[ :table_id ] = OFPTT_ALL if options[ :table_id ].nil?
options[ :match ] = Match.new if options[ :match ].nil?
options[ :cookie ] = 0 if options[ :cookie ].nil?
options[ :cookie_mask ] = 0 if options[ :cookie_mask ].nil?
options[ :out_port ] = OFPP_ANY if options[ :out_port ].nil?
options[ :out_group ] = OFPG_ANY if options[ :out_group ].nil?
send_flow_mod datapath_id, options
end
message-helper に追加するなどPort クラスに追加する
Stats メッセージについてMultipart メッセージになったことにより、名前が変わっているので注意。
# PortStats を取る場合send_message dpid, PortMultipartRequest.new
# GroupStats を取る場合send_message dpid, GroupDescMultipartRequest.new
# FlowStats を取る場合send_message dpid, FlowMultipartRequest.new( cookie: 0x0 )
def flow_multipart_reply dpid, message # FlowStats のハンドラend
def group_desc_multipart_reply dpid, message # GroupStats のハンドラend
def port_multipart_reply dpid, message # PortStats のハンドラend
最後に注意事項( OF 1.3 関連)
FeaturesReply にはポート情報は入ってない( PortMultipartRequest/Reply が必要になります)
フローエントリには Instructions というものが増えてる フローの削除でクッキー番号の指定と out_group の指定を考えてあげ
る必要がある PacketIn 用のフローを入れないと、 PacketIn しない ポート番号以外に、物理ポート番号とかあるから気をつけて OFPP_NONE とかなくなった アクションについて set_field とか push/pop tag とか色々細かくなっ
たから気をつけて アクションは即時実行( APPLY_ACTION )とパイプライン終了後に
実行する WRITE_ACTION がある WRITE_ACTION には実行順序が決められている APPLY_ACTION は、今まで通りセットした順番どおりに実行される
以上です!有難うございました。oshiba