Features Request でスイッチから情報を取得する (その2)

前回、Ruby でコントローラを書きましたが、もちろん C 言語でも同様なことができます。

#include <stdio.h>
#include "trema.h"


static void
handle_switch_ready( uint64_t dpid, void *user_data )
{
  UNUSED( user_data );

  buffer *features_request = create_features_request( get_transaction_id() );

  send_openflow_message( dpid, features_request );
  free_buffer( features_request );
}


static void
handle_features_reply( uint64_t dpid, uint32_t txid, uint32_t n_buffers, uint8_t n_tables, uint32_t capabilities, uint32_t actions, const list_element *phy_ports, void *user_data )
{
  UNUSED( user_data );
  UNUSED( n_buffers );
  UNUSED( n_tables );
  UNUSED( actions );
  UNUSED( txid );

  printf( "Datapath ID: %#" PRIx64 "\n", dpid );

  const list_element *p;  
  for ( p = phy_ports; p != NULL; p = p->next ) {
    struct ofp_phy_port *port = p->data;
    printf( "Port no: %u\n", port->port_no );
    printf( "  Hardware address: %02x:%02x:%02x:%02x:%02x:%02x\n", 
            port->hw_addr[0], port->hw_addr[1], port->hw_addr[2],
            port->hw_addr[3], port->hw_addr[4], port->hw_addr[5] );
    printf( "  Port name: %s\n", port->name );
  }
}


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;
}

上記のファイルを show_features.c として保存し、以下のようにコンパイル、実行をします。

$ gcc `trema-config --cflag` -c show_features.c
$ gcc show_features.o `trema-config --libs` -o show_features
$ sudo trema run ./show_features -c ./network.conf 
Datapath ID: 0xabc
Port no: 2
  Hardware address: f6:1d:1b:91:e6:ae
  Port name: trema0-1
Port no: 65534
  Hardware address: 8e:14:20:6f:54:15
  Port name: vsw_0xabc
Port no: 1
  Hardware address: b2:69:85:cf:91:aa
  Port name: trema1-1
^C
terminated

Ruby と比べると、コードが長くなりますが、同じ実行結果を得ることができるはずです。

次回、OpenFlow の仕様を参考に、Features Request でどのような情報が表示できるかを見ていきましょう。