Skip to content
chibacchie edited this page Sep 7, 2011 · 24 revisions

Hello Trema!

Let us get started with the first Trema application "Hello trema". The message "Hello trema" is printed out, and the related source code is as follows:

#include "trema.h"

int main( int argc, char *argv[] ) {
  init_trema( &argc, &argv );
  info( "Hello trema!" );
  start_trema();
  return 0;
}

"Hello trema!" is the simplest Trema program, and it also contains the mandatory part for a Trema application. It is a program with only eight lines of source code.

Let us give a brief explanation on it.

Including Trema header file

First, all of the Trema applications begin with the line of #include.

#include "trema.h"

It includes all necessary header files for Trema applications.

Initialization

init_trema() is invoked to initialize Trema framework.

  init_trema( &argc, &argv );

Please note that the arguments argc and argv of main() are passed as pointers. They are used to parse the runtime option from the command-line. Since the command-line option is not used in this program, we will explain how Trema handles command-line options later.

Printing out messages

info() is one of the functions of Trema for printing out messages. It is used as follows.

  info( "Hello trema!" );

In the above example, "Hello trema!" is passed as an argument. It will be printed out to stdout or the log file in a specific format.

According to their severity levels, the functions of Trema can be divided into six categories as follows. We will explain how to set the severity level of a message and how to set the output location in Trema later.

  • critical()
  • error()
  • warn()
  • notice()
  • info()
  • debug()

Main loop

start_trema() is the start point of Trema main loop.

  start_trema();

Trema programs are event-driven, the same as Gtk and other general GUI libraries. In the main loop, function waits for timer events or OpenFlow messages, and invokes corresponding handler functions when they arrive.

Building and execution

You can type the following command to build it, and the executable program hello_trema is generated.

% gcc -o hello_trema hello_trema.c `./trema-config --cflags --libs`

If the executable program is generated successfully, try to run it by trema run. It is noted that trema run can be used to run any Trema applications.

% ./trema run ./hello_trema
Hello trema!  # It can be terminated by Ctrl-c.

How do you like Trema now? Hope you can enjoy developing your Trema applications in this way.

Connecting it to a switch

We have shown the basic format of a Trema program. In the following part, we try to develop another Trema application, connect it to a OpenFlow switch, and print out the unique ID of the OpenFlow switch ( it is also called Datapath unique ID, datapath_id ). If you know the unique ID of the OpenFlow switch, you may further control it.

Virtual OpenFlow switch

Wait a minute. Is it OK even I do not have an OpenFlow switch?

Don't worry about it. Supporting virtual network is one of the powerful features provided by Trema. Trema virtual network consists of virtual OpenFlow switches and virtual hosts. You can run your programs directly on the Trema virtual network. It means that you can develop, test and run your Trema programs without real OpenFlow switches. Moreover, your Trema programs can be used on the real hardware platform without any modification further. It sounds cool, right? OK, let us create a virtual switch first.

Defining a virtual switch

To launch a virtual switch, you should add the following lines to the configure file trema.conf, which lies in the same directory as command trema. Then the defined virtual switch launches automatically when trema run is executed.

vswitch {
  datapath_id "0xabc"
}

datapath_id is a 64-bit number in hexadecimal format, you can assign any proper value to it as you like.

Capturing switch connection events

Once a Trema program connects to an OpenFlow switch, the switch_ready event is emitted; so that you can confirm the connection by setting the event handler for switch_ready event. In Trema, the function set_switch_ready_handler() is used to set its event handler. Please invoke it between init_trema() and start_trema() as follows.

#include "trema.h"

// event handler definition
static void handle_switch_ready( uint64_t datapath_id, void *user_data ) {
  info( "Hello %#llx from %s!", datapath_id, user_data );
}

int main( int argc, char *argv[] ) {
  init_trema( &argc, &argv );
  set_switch_ready_handler( handle_switch_ready, argv[ 0 ] ); // set event handler
  start_trema();
  return 0;
}

The first argument passed to handle_switch_ready is set_switch_ready_handler(), it is a function pointer of the event handler. The second argument is reserved for passing user data. In the above example, the name of the execution file ("hello_trema") is passed.

The function info() prints out the datapath_id in the event handler handle_switch_ready.

Building and execution

The building method is the same as explained before. OK, let us build and run it.

% gcc -o hello_trema hello_trema.c `./trema-config --cflags --libs`

Please make sure the configure file named trema.conf and command trema lie in the same directory before running the program.

% ./trema run -c ./trema.conf ./hello_trema
Hello 0xabc from hello_trema!  # You can terminate by Ctrl-c

You can see the datapath_id of the virtual switch is printed out correctly. We show how to use the datapath_id to control a real OpenFlow switch later.

Summary

In this tutorial, we have developed a program named "Hello trema!". It contains mandatory parts for all Trema applications. We have also created another program, and it prints out the datapath_id correctly. What we learned is summarized as follows.

  • trema.h contains all necessary header files for Trema applications.
  • init_trema( &argc, &argv ) is in charge of the initialization of Trema.
  • info() is used to print out messages.
  • start_trema() is the start point of a Trema application.
  • How to use vswitch to define a virtual switch in the Trema configure file trema.conf.
  • How to define a event handler for switch_ready event by invoking set_switch_ready_handler() function.