Basic Tutorial - "Hello World"

This section of the OMF Users' Guide provides a basic tutorial to help you get started with OMF. This tutorial is intended for first-time users of OMF. The tutorial also provides basic information on writing and executing experiments for the testbed.

If you are new to OMF, review the OMF architecture before you proceed. Once you are familiar with this document, you can go through this tutorial to get started.

In this tutorial, you will:

  • learn the basics of developing a script for a simple experiment
  • understand the resulting "Hello World" script
  • run this experiment and understand its outputs
  • be directed to the next step, i.e. accessing and analyzing the result of your experiment

Developing an Experiment Script

As explained in the Overview page, to run an experiment on the testbed you need to first develop a script, which describea this experiment. This experiment script is then passed on to an Experiment Controller, which will run the experiment and control its execution. This process is illustrated in the following figure.

A script includes the following sections:

  • a description of the required resources for this experiment. For example, a given type of node on the testbed, a particular required application, etc...
  • a description of their initialisation and optional associations. For example, resource X is connected to resource Y, and all resources use channel 6 of 802.11g, etc...
  • a description of the actions to perform on or with the resources throughout the duration of the experiment. For example, application X starts at T0 and runs for 60 seconds, resource Y switches wireless configuration after 100 seconds, etc...

OMF experiment scripts are written using a Domain-specific Language based on the Ruby scripting language. However, you do not necessarily need to be familiar with Ruby to be able to write and run simple experiments. The only prerequisite skills are some prior basic knowledge of any other scripting and/or programming languages (for example, Python, Perl, C, Java, and so on). Thus, you do not need to master Ruby to develop simple experiments, although basic knowledge of Ruby commands would be desirable.

To be able to develop more complex experiments, you will need to learn the basics of Ruby and read about OMF-specific Ruby methods.

The Hello World Experiment

In this basic experiment, we first define two groups of resources: a source group and a sink group. Although a group can contain several resources, in this simple case, there is only one resource (i.e. a node) in each group.

Also, we associate a traffic generator application to the source group, and a traffic receiver application to the sink group.

Then, we specify the configuration of the wireless interfaces on the nodes in the two groups.

Finally, we describe the actions to perform in order to realize the experiment. In this simple example, the experiment will consist of the source group sending constant bit rate (CBR) traffic to the sink group for a given duration.

(Note: In general, a node refers to a PC-based resource only.)

You can view the full Hello World experiment script here.

Understanding Hello World

As you would have noticed the Hello World script is quite human-readable. It is fairly easy to understand for computer-literate readers. As stated earlier, knowledge or Ruby is not a prerequisite for running experiments on the OMF testbed.

The code in the Hello World experiment can be divided into four distinct parts:

  1. Defining the source group
  2. Defining the sink group
  3. Configuring the interfaces
  4. Defining the actions to perform

Defining the source group

The first part of this script uses the OMF method defGroup to define a group of resources. The name source is assigned to this group. This group includes a node that is identified by a unique node identifier [1,1].

Next, we describe some specific configurations to be carried out on the node(s) in the source group. These configurations are described in a block (a block is delimited by curly braces) that directly follows the defGroup call.

Within this block, a specific application is assigned to the node(s) within the source group. This application is a UDP constant bit rate (CBR) traffic generator and is accessed through a prototype called test:proto:udp_sender. Prototypes are wrappers around existing applications. They allow OMF experiment scripts to access and configure these applications. A prototype provides a pre-defined configuration of the application, that can be reused as is or be modified easily for use. A prototype is akin to a template that can can be applied to a node for configuring it, or can be customized through a set of parameters. For example, in the Hello World script, the prototype parameters can be used to set the packet rate or size to use for the generated traffic. Prototypes are normally defined in separate files.

OMF provides a set of predefined prototypes for some basic applications. For example, the prototype test:proto:udp_sender is a wrapper around the existing simple Traffic Generator(OTG) application. It is pre-configured with some default parameters and measurement to collect. Refer to the Advanced tutorials for information on how to write your own prototypes.

Finally, the last line in this block configures the first wireless interface w0 on the source node(s) into 'master' mode (i.e. access-point mode).

 1 #
 2 # A)  Define the 'source' group, which has the unique node [1,1]
 3 #
 4 defGroup('source', [1,1]) {|node|        
 5 
 6   # Assign the prototype "test:proto:udp_sender" to the node(s) in this group
 7   node.prototype("test:proto:udp_sender", {
 8 
 9     # Configure the properties for this prototype, i.e. the parameters for the wrapped application
10     'destinationHost' => '192.168.0.2',
11     'localHost' => '192.168.0.1',
12     'packetSize' => 256, # in Bytes
13     'rate' => 8192 # in bits per second
14    })
15 
16   # Configure the wireless interface "w0" of the node(s) in this group
17   # Put the interface into "Ad-Hoc" mode. 
18   # Other modes can be 'managed' or 'master'
19   node.net.w0.mode = "master" 
20 }

Defining the sink group

The second part of the experiment script is very similar to the first one. Here, we define a sink group, which includes a unique node (identified by [1,2]).

Again, the block following the defGroup call contains some specific configuration for the node(s) in the sink group. In this case, a traffic receiver application is associated with the node(s) through the test:proto:udp_receiver prototype.

The w0 wireless interface of the node(s) is configured into 'managed' mode (i.e. wireless station mode).

 1 #
 2 # B)  Define the 'sink' group, which has the unique node [1,2]
 3 #
 4 defGroup('sink', [1,2]) {|node|
 5 
 6   # Assign the prototype "test:proto:receiver2" to the node(s) in this group
 7   node.prototype("test:proto:udp_receiver" , {
 8     'localHost' => '192.168.0.2'
 9   })
10 
11   # Configure the wireless interface "w0" of the node(s) in this group to 'Ad-Hoc' mode
12   # Other modes can be 'managed' or 'master'
13   node.net.w0.mode = "managed" 
14 }

Configuring the interface

The third part of the script contains the code to configure network interfaces on all nodes in all the defined groups. In this example, the configuration for all the nodes are described in this a single place. This allows a certain consistency in the node configuration.

  • The command allGroups indicates that the following actions or descriptions will apply to all the groups defined in this experiment.
  • Following the allGroups command is a Resource Path net.w0, which refers to the first wireless network interface of a node. Thus the combination allGroups.net.w0 refers to all the first wireless network interfaces of all the nodes in all the groups. More information on Resource Paths can be found on here
  • The code in the following block within curly braces configures various parameters of these interfaces. In this example, the interface is configured as an 802.11g type, the essid is set to a common string, and a parameter is used to set the IP address of the nodes. As a different IP address is required per interfaces, any string beginning with a '%' is personalized for each node by replacing any characters prefixed by a '%' with a local node-specific attribut. In this specific example, '%y' is replaced by the 'y' coordinate of the node. For this specific experiment setup, the IP address of node [1,1] is 192.168.0.1, while node [1,2] has 192.168.0.2 assigned.
# 
# C)  Configure the wireless interfaces of All the Nodes in this experiment
#
allGroups.net.w0 { |w|
  w.type = 'g'
  w.channel = "6" 
  w.essid = "helloworld" 
  w.ip = "%192.168.0.%y" 
}

Note: The declaration for the parameters in the above code snippet uses a short form. The following code can also be used instead:

allGroups.net.w0.type = 'g'
allGroups.net.w0.channel = "6" 
allGroups.net.w0.essid = "helloworld" 
allGroups.net.w0.ip = "%192.168.%x.%y" 

Note: Also in this example, the network interface configuration is described for all the groups in a single allGroup block. Alternatively, this configuration could have been specified for each individual group as some extra lines in its defGroup block. For example:

defGroup('sink', [1,2]) {|node|

  node.prototype("test:proto:udp_receiver" , {
    'localHost' => '192.168.0.2'
  })

  node.net.w0.mode = "managed" 
  node.net.w0.type = 'g'
  node.net.w0.channel = "6" 
  node.net.w0.essid = "helloworld" 
  node.net.w0.ip = "192.168.0.2" 
}

Defining the actions to perform

The last part of the script describes the operations to perform in order to realize the experiment. Basically, this last part defines the sequence of actions (commands) to be performed when an experiment enters a particular state (thus it can be viewed as a 'state machine' description).

This simple example only uses one state, which will trigger the execution of some actions on the nodes. This state is the whenAllInstalled state. This state is reached when all the resources (i.e. nodes in this example) of all the defined groups are:

  • are turned on,
  • have received their configuration settings (but they might still not have reached the desired configuration yet),
  • have all the requested applications installed on them.

The sequence of commands to perform is given in a block following the whenAllInstalled call. Here is a description of this block of code:

  • The first command wait 30 suspends the execution for 30 seconds. This will ensure that the nodes have reached the desired configuration (i.e. it takes some seconds for wireless stations to authenticate and associate to a base station, etc...).
  • The call to allGroups.startApplications sends the 'startApplication' command to all the resources in all the defined groups. This command starts the applications assigned to the resources (through the use of prototypes as described earlier). In this example, this command will start a traffic generator on node [1,1] and a corresponding sink on node [1,2]. The different parameters for these applications are taken from the above definition as well.
  • The next line wait 20 suspends the control of the experiment for 20 seconds during which the applications on the nodes will run and exchange traffic.
  • The experiment ends with a call to Experiment.done.
 1 #
 2 # D)  When all the nodes are turned On and the all the applications
 3 #     are installed and ready, we can start to perform the experiment
 4 #
 5 whenAllInstalled() {|node|
 6 
 7   # Wait 30sec
 8   wait 30 
 9 
10   # Start all the Applications on all the nodes
11   allGroups.startApplications
12 
13   # Wait for 20sec
14   wait 20
15 
16   # Stop the experiment execution
17   Experiment.done
18 }

Note: Click here to view a detailed description of all the OMF-specific scripting commands in the Experiment Controller.

Running the Hello World Experiment

Before you run an experiment, ensure that:

  • you have an account. If not, register for an account.
  • you make a reservation for a time slot to use the testbed.
  • log on to the console machine corresponding to this testbed.

To invoke the Experiment Controller and control your experiment and the resources on the testbed, use the generic omf command and its options, which is described in the Developing Experiments page.

IMPORTANT -- Prior to running the 'Hello World' script, you might have to install a fresh disk image on the nodes. We provide a updated baseline.ndz disk image for our testbeds. Please refer to the 'Install a disk image' page for details instruction on how to install the latest baseline image. If the nodes on the testbed already have that image installed, you can skip this step.

Once the nodes have been imaged, you can run the Hello World experiment using one of the following ways:

  • option 1 - copy the above script code into a new file and run it with the omf command
  • option 2 - Run the tutorial using a copy of the above script, which is bundled with the omf command

Option 1

This is most likely how you will run your own experiments when using OMF.

You save your experiment script in a file on the console machine of the testbed. In this example, you may copy the contents of the Hello World experiment into a file named 'hello.rb' and save it on the console machine. Then to run the experiment, you use the omf exec command with the file name 'hello.rb' as a parameter:

omf exec hello.rb

Note: the '.rb' on the command line is optional, when called with only the parameter 'hello', the omf exec command will automatically try to find a file named 'hello.rb'.

Option 2

For your convenience, the 'Hello World' experiment script is bundled with the omf command. More precisely, the Experiment Controller (which is invoked by omf exec) has a bundled repository of useful scripts to perform various tasks and tutorials. One of these bundled scripts is the 'Hello World' tutorial.

To run the experiment using the bundled 'Hello World' script, you can use one of the two following commands:

omf exec --tutorial

omf exec test:exp:tutorial

In this last command, a different notation with a colon (:) is used for representing a directory path. At runtime, the Experiment Controller interprets the colon as a slash(/). By default, it looks for experiments in the paths under its bundled repository (i.e. in this case it will look for '<repository>/test/exp/tutorial.rb'). If the script is not found there, it then looks in the current directory.

Please be aware that this bundled 'Hello World' experiment is exactly the same as the one described above. Therefore the nodes used are exactly [1,1] and [1,2]. If for some hardware or any other issues these two nodes are not available in your testbed (e.g. disk failure, etc...). Then this bundled experiment will fail. In such case, you will have to revert to option 1 above and modify your script to use some alternate nodes. In a following tutorial, we will introduce 'experiment properties' and how we can use them to give input parameters to experiments.

Experiment output

After executing one of the above commands, your experiment should be running and your console output should look like this:

  • the first line shows the Experiment Controller's version (Note: as mentioned earlier the software still shows our old naming scheme, where NodeHandler = Experiment Controller)
  • the second line gives you the ID of your experiment, in this example: 'npc_2009_01_28_16_07_04'
  • the following 4 lines provides some experiment configuration information
  • the next line 'INFO whenAll (...)' indicates that the experiment reached the state 'whenAllInstalled'. From that point, the commands, which you described in the corresponding block in the script, will be executed.
  • the next lines provides information about the execution of the experiment. Here you can see that the node in your experiment first were not assigned to any wireless cell, but then joined the same wireless cell identified by '00:0B:6B:84:3D:04'. (Note that this screenshot was taken when using node [1,3] and [1,4] instead of [1,1] and [1,2]).
  • in your subsequent other uses of OMF to run experiments, any information or error messages will be similarly displayed after the above 'whenAll' message.

When you run an experiment, the Experiment Controller displays different types of messages. Click here to read about these messages.

Congratulations! You just ran your first experiment script on a testbed using the OMF framework.

Notes:

- in case you run into some problem while executing an experiment, please refer to our Troubleshooting page.

- Only for Winlab's testbed: with the current interaction between the Chassis Manager Controller of the nodes and the Experiment Controller, make sure that you turn OFF your nodes before the next experiment, by using the omf tools as described here.

Accessing and Analyzing the resulting measurements.

As mentioned in the previous pages, the OMF software suite provides an independent and complementary measurement collection framework, named OML.

To ease the learning curve, this simple tutorial does not show you how to use the full features of OML to collect experiment measurements. Please refer to our OML tutorial pages to learn more about OML usage.

However, the simple traffic generator and sink applications that we used in this 'Hello World' have some default measurement points enabled. Thus some measurements were made and collected by the OML framework while you were running the 'Hello World' experiment.

Continue reading on the next page 'Analysing Results' to learn how to access and analyze the results of this simple tutorial experiment.

Next...


OMFHelp.PNG (10.5 kB) Vidya Sunder, 29/01/2009 08:26 am

ExperimentExecution.png (18.3 kB) Vidya Sunder, 29/01/2009 03:05 pm

HelloOutput.PNG (36.2 kB) Vidya Sunder, 02/02/2009 08:30 am

ExperimentExecution.png (14.4 kB) Vidya Sunder, 02/02/2009 08:42 am