Flow Mod はスイッチのフローテーブルを変更する OpenFlow メッセージの総称で、次の 3 種類があります。
- Add フローエントリを追加する
- Delete フローエントリを削除する
- Modify フローエントリを変更する
Trema の Flow Mod API はそれぞれ
というメソッドで定義されています。今回は、この中でもとくによく使う send_flow_mod_add メソッドの API 定義を見ていきましょう。
API 定義
send_flow_mod_add メソッドは次の 2 つの引数を取ります。
send_flow_mod_add( datapath_id, options )
それぞれの引数の意味は次の通りです。
- datapath_id Flow Mod の届け先となるスイッチの Datapath ID です。
- options Flow Mod メッセージの中身を決めるためのオプションで、フローの構成要素であるマッチングルールとアクションに加え、フローの寿命や優先度といった属性を指定します。これは Hash で定義されていて、必要なオプションのみを指定すればいいことになっています。
具体的な利用例は次のとおりです。
フローエントリを追加する
フローエントリを追加するには、フローを作るのに必要な要素であるマッチングルールとアクションを次のように指定します。
def packet_in datapath_id, message # .. send_flow_mod_add( datapath_id, :match => Match.new( :dl_src => message.macsa, :dl_dst => message.macda ), :actions => ActionOutput.new( port_no ) )
マッチングルール (:match オプション) は Match クラスのインスタンスとして指定します。ここでは、送信元と宛先の MAC アドレスが Packet In メッセージと同じ、というマッチングルールを指定しています。アクション (:actions) ではポート番号 port_no 番のスイッチポートへ出力というアクションを指定しています。
このほか、send_flow_mod_add では次のオプションを指定できます。
- :idle_timeout フローが一定時間参照されなかった場合に破棄されるまでの秒数を指定します。デフォルトは 0 秒で、この場合フローは破棄されません。
- :hard_timeout フローの寿命を秒数で指定します。デフォルトは 0 秒で、この場合フローは破棄されません。
- :priority フローエントリの優先度 (符号なし 16 ビット、大きいほど優先度高) です。Packet In メッセージはこの優先度順にフローのマッチングルールと照らし合わされます。デフォルトでは 0xffff (最高優先度) です。
- :send_flow_rem タイムアウトでフローが消されるときに Flow Removed メッセージをコントローラに送るかどうかを指定します。デフォルトで true です。
- :check_overlap true にセットすると、フローテーブルの中に同じ優先度で競合するものがあった場合フローを追加せずにエラーを起こします。デフォルトは false です。
- :emerg この値を true にセットすると、フローを緊急エントリとして追加します。緊急エントリはスイッチがコントローラと切断されたときにのみ有効となります。デフォルトは false です。
- :cookie 任意の用途に使える 64 ビットの整数です。使い道としては、同じクッキー値を持つフロー同士をまとめて管理するなどといった用途に使えます。
初心者が陥りやすい罠として、packet_in ハンドラの中で Packet Out をし忘れるということがあります。Packet In を起こしたパケットは何もしないと捨てられてしまうので、次のように Flow Mod の前または後で明示的に Packet Out を打つ必要があります。
def packet_in datapath_id, message # .. send_flow_mod_add( datapath_id, :match => Match.new( :dl_src => message.macsa, :dl_dst => message.macda ), :actions => ActionOutput.new( port_no ) ) # Packet Out することで message を届ける send_packet_out( datapath_id, ... )
同時に Packet Out も行う
Packet In を起こしたメッセージがスイッチのバッファに乗っている場合に限り、:buffer_id オプションを指定することでフローを適用した後のメッセージを Flow Mod と同時に Packet Out できます。この場合、明示的な send_packet_out メソッドの呼び出しは必要ありません。もちろん、バッファが使えなかった場合にはエラーが起こります。
def packet_in datapath_id, message # .. send_flow_mod_add( datapath_id, :buffer_id => message.buffer_id, :match => Match.new( :dl_src => message.macsa, :dl_dst => message.macda ), :actions => ActionOutput.new( port_no ) )
まとめ
Trema の Flow Mod API のうち、send_flow_mod_add メソッドを解説しました。Flow Mod にはたくさんのパラメータがありますので、必要なときにこの記事を読み直してみてください。