-
Notifications
You must be signed in to change notification settings - Fork 0
スイッチの情報を調べる
このチュートリアルではスイッチの詳しい情報を調べる Trema アプリケーションを書きます。スイッチから取得できる情報は次のとおりで、OpenFlow のスペックで詳しく定義されています。
- datapath ID
- バッファリングしておけるパケットの数
- フローテーブルの数
- ケイパビリティ
- サポートしているオープンフローのアクション
- 物理ポートの一覧
スイッチの情報を取るためには、スイッチに features request というメッセージを投げます。
// features request メッセージを作る
buffer *message = create_features_request( get_transaction_id() );
// 作ったメッセージを送る
send_openflow_message( datapath_id, message );
// メモリの開放
free_buffer( message );
このメッセージはいつスイッチに送ればいいのでしょうか? 答えはスイッチが準備 OK になったときです。前回のチュートリアルで作った switch_ready ハンドラの中で呼べばよいですね。
static void
handle_switch_ready( uint64_t datapath_id, void *user_data ) {
// features request メッセージを作る
buffer *message = create_features_request( get_transaction_id() );
// 作ったメッセージを送る
send_openflow_message( datapath_id, message );
// メモリの開放
free_buffer( message );
}
features request の返事を受けとるには、features_reply ハンドラを書きます。たとえば各種情報を表示するハンドラは info() 関数を使って次のように書けます。
static void
handle_features_reply (
uint64_t datapath_id,
uint32_t transaction_id,
uint32_t n_buffers,
uint8_t n_tables,
uint32_t capabilities,
uint32_t actions,
const list_element *phy_ports,
void *user_data
) {
info( "datapath_id: %#llx", datapath_id );
info( "transaction_id: %#lx", transaction_id );
info( "n_buffers: %lu", n_buffers );
info( "n_tables: %u", n_tables );
info( "capabilities: %lu", capabilities );
info( "actions: %lu", actions );
info( "#ports: %d", list_length_of( phy_ports ) );
}
物理ポートの数を表示する部分で使っている list_length_of は Trema 標準関数で、物理ポート一覧 (phy_ports) の要素数を返します。
最終的なコードはこうなります。
#include "trema.h"
static void
handle_switch_ready( uint64_t datapath_id, void *user_data ) {
buffer *message = create_features_request( get_transaction_id() );
send_openflow_message( datapath_id, message );
free_buffer( message );
}
static void
handle_features_reply (
uint64_t datapath_id,
uint32_t transaction_id,
uint32_t n_buffers,
uint8_t n_tables,
uint32_t capabilities,
uint32_t actions,
const list_element *phy_ports,
void *user_data
) {
info( "datapath_id: %#llx", datapath_id );
info( "transaction_id: %#lx", transaction_id );
info( "n_buffers: %lu", n_buffers );
info( "n_tables: %u", n_tables );
info( "capabilities: %lu", capabilities );
info( "actions: %lu", actions );
info( "#ports: %d", list_length_of( phy_ports ) );
}
int
main( int argc, char *argv[] ) {
init_trema( &argc, &argv );
set_switch_ready_handler( handle_switch_ready, NULL );
set_features_reply_handler( handle_features_reply, NULL );
start_trema();
return 0;
}
さっそくコンパイルして実行してみましょう。
% gcc -o features_request features_request.c `./trema-config --cflags --libs`
% ./trema
trema> vswitch { datapath_id "0xabc" }
trema> app { path "./features_request" }
trema> run
datapath_id: 0xabc
transaction_id: 0x27aa0001
n_buffers: 256
n_tables: 2
capabilities: 135
actions: 2047
#ports: 1
うまく仮想スイッチの情報を表示できました。ここでは、datapath_id が 0xabc になっていることと、ポートの数はスイッチのコントロールポート 1 つだけであることに注目してください。
もうちょっと遊んでみましょう。スイッチのポートを増やし、表示されるスイッチ情報に反映されることを確認します。スイッチにポートを増やすには、次のようにあたらしくスイッチ 0xdef を追加し、スイッチ間にリンクを張ります。リンクを張るには、次の link ディレクティブを使います。
trema> link スイッチ名1, スイッチ名2
さきほどのセッションに続けて、次のように入力します。
trema> vswitch { datapath_id "0xdef" }
trema> link "0xabc", "0xdef" # スイッチ 0xabc と 0xdef にポートがひとつ追加される
実行すると、スイッチが 2 つになりポートの数もそれぞれ 2 つずつ (コントロールポート + スイッチ間接続のポート) になります。
trema> run
datapath_id: 0xdef
transaction_id: 0x7200002
n_buffers: 256
n_tables: 2
capabilities: 135
actions: 2047
#ports: 2 # ポートが 2 つになった
datapath_id: 0xabc
transaction_id: 0x7200001
n_buffers: 256
n_tables: 2
capabilities: 135
actions: 2047
#ports: 2 # ポートが 2 つになった
このチュートリアルではスイッチの情報を取得する Trema アプリケーションを書きました。学んだことは次の 5 つです。
- スイッチに features request メッセージを送るとスイッチの情報を取得できる
- create_features_request() で features reqeust メッセージを作る
- send_openflow_message() で作ったメッセージを送る
- set_features_reply_handler() で features reply メッセージのハンドラを登録
- link でスイッチ間にリンクを作ることができる