C 言語で packet_in ハンドラを書く (その1)

C 言語を使った Trema 上でのコントローラプログラミングに関する話です。今回は packet_in を扱う方法について解説します。
packet_in は、OpenFlow スイッチがフローエントリにマッチしなかったパケットをコントローラに送るためのメッセージです。このメッセージは、スイッチ側から送られるので、コントローラ側からみるといつ送られてくるかわかりません。そのため、packet_in メッセージが送られてきたとき呼び出す関数(packet_in ハンドラ)を用意し、それを set_packet_in_handler() 関数で登録しておきます。

set_packet_in_handler( my_packet_in_handler, my_user_data );

上記の my_packet_in_handler の部分が、用意した packet_in ハンドラです。このハンドラに渡したいデータがある場合は、my_user_data のところに指定します。
それでは、どのような引数をとる packet_in ハンドラを用意すればよいでしょうか?openflow_application_interface.h には以下のように定義されています。

typedef void ( simple_packet_in_handler )( uint64_t datapath_id, packet_in message );
typedef void ( packet_in_handler )(
  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
);

simple_packet_in_handler と packet_in_handler の二つが typedef されていますが、set_packet_in_handler() ではどちらの型を使ってもよいように定義されています。simple_packet_in_handler() の引数の 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;

つまり、どちらの型でハンドラを書いてもわたってくる情報は同じです。

次回、具体的に packet_in ハンドラを書く際のポイントについて解説します。