C 言語で packet_in ハンドラを書く (その3)
今回は packet_in ハンドラにどのような情報が渡ってくるかについて解説します。
packet_in ハンドラに引数として渡ってくる packet_in 構造体は、以下のように定義されています。
typedef struct { uint64_t datapath_id; uint32_t transaction_id; uint32_t buffer_id; uint16_t total_len; uint16_t in_port; uint8_t reason; const buffer *data; void *user_data; } packet_in;
datapath_id と in_port は、packet_in の契機となったスイッチの datapath_id と受信ポート番号です。その他の各フィールドは、OpenFlow 1.0 Spec 中の ofp_packet_in 中にある書くフィールドの値が、ホストバイトオーダーで格納されています。user_data には、set_packet_in_handler() で登録された値が格納されています。
packet_in で送られてくるパケット本体は、packet_in 構造体の data のフィールドに格納されています。data の型である buffer 構造体は、buffer.h 内で以下のように定義されています。
typedef struct buffer { void *data; size_t length; void *user_data; void ( *user_data_free_function )( struct buffer *buffer ); } buffer;
この中の data にパケットの本体が、length にその長さが格納されています。再び data が出てきてややこしいですが、パケット本体を覗きたい場合には、buffer 構造体のメンバー data を参照すればよいということになります。
Trema ではパケットの中身をユーザが覗かなくてもよいよう、予め parse した結果を buffer 構造体中の user_data
に格納しています。user_data の中身は packet_info 型ですので、キャストして参照してください。ここに格納されている値は、すべてホストバイトオーダーに変換してあるので、オーダーを気にせずに使用することができます。
typedef struct { uint32_t format; uint8_t eth_macda[ ETH_ADDRLEN ]; uint8_t eth_macsa[ ETH_ADDRLEN ]; uint16_t eth_type; ... } packet_info;
packet_info 構造体の定義は、packet_info.h にありますので、詳しくはそちらをご参照ください。
次回は、packet_info 中の値を使った packet_in ハンドラの作り方について紹介します。