Changes between Version 34 and Version 35 of Tutorials/a0Basic/Tutorial2


Ignore:
Timestamp:
Feb 13, 2013, 6:03:46 AM (11 years ago)
Author:
ssugrim
Comment:

Legend:

Unmodified
Added
Removed
Modified
  • Tutorials/a0Basic/Tutorial2

    v34 v35  
    8585As you noticed the "Hello World" script is almost ''human-readable'', and is quite understandable to any computer-literate reader. As already mentioned above, deep Ruby knowledge is '''not''' a prerequisite to running experiments on the ORBIT testbed.
    8686
    87  * The first part of this script uses the ORBIT method ''defGroup'' to define a group of nodes called ''sender'', which contains a unique node ''[1,1]''. Next, we perform some specific configurations on the node(s) within the group ''sender''. These specific configurations are described in a ''block'' (e.g. curly braces) that directly follows the ''defGroup'' call. Within this ''block'', we first assign a particular application to the ''sender'' node(s). This application is a traffic generator and is accessed via a ''prototype'' which is called ''test:proto:sender'' in this example. A prototype can be viewed as a wrapper around an existing application. It defines some set of properties (i.e. "parameters"), which allows us to customize the wrapped application for the specific need of an experiment. For example in this case, through the prototype we can set the address of the sender, and various parameters of the traffic generator itself, such as packet size, rate, and the protocol over which to send the traffic. Prototypes are normally defined in separate files, and the ORBIT platform has a set of predefined prototypes for some basic applications. For example, the prototype "test:proto:sender" is a wrapper around the application "otg" (orbit traffic generator). Other tutorials (see [wiki:Tutorials main page]) describe how to write your own prototypes for your own or existing applications. The last line on this ''sender'' block configures the first wireless interface ''w0'' on the node(s) in this block into ''managed'' mode.
    88 
    89 {{{
    90 #
    91 # A)  Define the 'sender' group, which has the unique node [1,1]
    92 #
    93 defGroup('sender', [1,1]) {|node|       
    94            
    95   # Assign the prototype "test:proto:sender" to the node(s) in this group
    96   node.prototype("test:proto:sender", {
    97 
    98     # Configure the properties for this prototype, i.e. the parameters for the wrapped application
    99     'destinationHost' => '192.168.1.2',
    100     'packetSize' => 1024,
    101     'rate' => 300,
    102     'protocol' => 'udp'
    103   })
    104 
    105   # Configure the wireless interface "w0" of the node(s) in this group
    106   # Put the interface into "Managed" mode.
    107   node.net.w0.mode = "managed"
    108 }
    109 }}}
    110 
    111  * The second part of the script is very similar to the previous one. Here we define a 'receiver' group with a unique node, this time node [1,2]. Again we define some specific configuration for the 'receiver' nodes in a block following the ''defGroup'' call. In this case, we assign a traffic sink application to the node(s) via a prototype called "test:proto:receiver", we also set the 'protocol' property of this prototype. Finally, we configure the "w0" wireless interface of the node(s) into "master" mode.
    112 
    113 {{{
    114 #
    115 # B)  Define the 'receiver' group, which has the unique node [1,2]
    116 #
    117 defGroup('receiver', [1,2]) {|node|
    118 
    119   # Assign the prototype "test:proto:receiver" to the node(s) in this group
    120   node.prototype("test:proto:receiver" , {
    121     'protocol' => 'udp'
    122   })
    123 
    124   # Configure the wireless interface "w0" of the node(s) in this group
    125   node.net.w0.mode = "master"
    126 }
    127 }}}
    128 
    129 
    130  * The third part of the script presents an example on how to configure interfaces on all nodes in one place to ensure consistency. The command ''allGroups.net.w0'' describes the first wireless interface on all nodes in the experiment. The code inside the following ''block'' (e.g. curly braces) configures various parameters of these interfaces. In this specific example, we configure the interface as an 802.11b type, set the ''essid'' to a common string, and set it's IP address. We obviously do not want to set all the interfaces to the same IP address, thus any string beginning with a '%' is ''personalized'' for each node by replacing characters prefixed by a '%' with a local string. 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] will be 192.168.1.1, while node [1,2] will have 192.168.1.2 assigned. This part concludes the configuration phase of the experiment.
    131 
    132 {{{
    133 #
    134 # C)  Configure the wireless interfaces of All the Nodes in this experiment
    135 #
    136 allGroups.net.w0 { |w|
    137   w.type = 'b'
    138   w.channel = "6"
    139   w.essid = "helloworld"
    140   w.ip = "%192.168.%x.%y"
    141 }
    142 }}}
    143 
    144  * This final part of the script describes the operation to execute in order to perform the experiment. An ORBIT experiment script basically defines a state machine, or more precisely, what sequence of commands should be executed if the experiments enters a particular state. The only state we will use in this experiment is ''whenAllInstalled''. This state is reached when all the nodes are configured and all the requested applications are installed and ready to go. The sequence of commands to perform are given in a ''block'' following the ''whenAllInstalled'' call. The first command 'wait 30' will suspend the execution for 30 seconds to ensure that indeed everything has settled. The ''allGroups.startApplications'' will then send a command to all nodes to start the applications assigned to them (via the use of ''prototypes'') in the previous script parts. Thus 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. Finally, the next line 'wait 40' will suspend the control of the experiment for 40 seconds (during which the applications on the nodes '''will run''' and exchange traffic), before concluding the experiment with a call to ''Experiment.done''.
    145 
    146 {{{
    147 #
    148 # D)  When all the nodes are turned On and the all the applications
    149 #     are installed and ready, we can start to perform the experiment
    150 #
    151 whenAllInstalled() {|node|
    152  
    153   # Wait 30sec
    154   wait 30
    155 
    156   # Start all the Applications on all the nodes
     87{{{
     88defProperty('duration', 60, "Duration of the experiment")
     89
     90baseTopo = Topology['system:topo:imaged']
     91
     92st = defTopology("sender") do |t|
     93  t.addNode(baseTopo.getNodeByIndex(0))
     94end
     95
     96rt = defTopology("receiver") do |t|
     97  t.addNode(baseTopo.getNodeByIndex(1))
     98end
     99}}}
     100
     101This portion of the script establishes a few parameters to control the experiment behavior. In particular the ''defProperty'' function call establishes a '''duration''' property for the experiment. The baseTopo variable is set to a Topology object which has collected names of nodes from the 'system:topo:imaged' set, which was established during your last imaging (omf load) operation. Using the defTopology function we define two topolgies names "sender" and "receiver". The baseTopo object's getNodeByIndex will return a node name from the 'system:topo:imaged' set.
     102
     103{{{
     104defGroup('Sender', "sender") do |node|
     105  node.addApplication("test:app:otg2") do |app|
     106    app.setProperty('udp:local_host', '192.168.0.2')
     107    app.setProperty('udp:dst_host', '192.168.0.3')
     108    app.setProperty('udp:dst_port', 3000)
     109    app.measure('udp_out', :samples => 1)
     110  end
     111  node.net.w1.mode = "adhoc"
     112  node.net.w1.type = 'g'
     113  node.net.w1.channel = "6"
     114  node.net.w1.essid = "helloworld"
     115  node.net.w1.ip = "192.168.0.2"
     116end
     117
     118defGroup('Receiver', "receiver") do |node|
     119  node.addApplication("test:app:otr2") do |app|
     120    app.setProperty('udp:local_host', '192.168.0.3')
     121    app.setProperty('udp:local_port', 3000)
     122    app.measure('udp_in', :samples => 1)
     123  end
     124  node.net.w1.mode = "adhoc"
     125  node.net.w1.type = 'g'
     126  node.net.w1.channel = "6"
     127  node.net.w1.essid = "helloworld"
     128  node.net.w1.ip = "192.168.0.3"
     129end
     130}}}
     131
     132Using the ''defGroup'' function we define "Sender" and "Receiver" groups. We associate two existing applications to each group,  test:app:otg2 to the  "Sender" group and test:app:otr2 to the "Receiver" group. These associations were made with the node.addApplication method. These applications would be installed and run on each node of this group. In this tutorial however, these applications are already installed on the baseline disk image, which you previously loaded on the node. These applications are a simple traffic generator and receiver respectively. By default these applications generate fixed-sized UDP packets at a constant bitrate. We set a bunch of application parameters via the app.setProperty method for each application. We also set some properties of the node using the node.net.w1.* attributes within each group. These attributes will be shared by all nodes in the group (in this case just one per group).
     133
     134{{{
     135onEvent(:ALL_UP_AND_INSTALLED) do |event|
     136  info "This is my first OMF experiment"
     137  wait 15
    157138  allGroups.startApplications
    158 
    159   # Wait for 40sec
    160   wait 40
    161 
    162   # Stop the experiment execution
     139  info "All my Applications are started now..."
     140  wait property.duration
     141  allGroups.stopApplications
     142  info "All my Applications are stopped now."
    163143  Experiment.done
    164 }
    165 }}}
    166 
    167  * You can find detailed description of all the various experiment-specific scripting commands (such as ''defGroup'', ''allGroups'', ''whenAllInstalled'', etc...) in the '''Node Handler''' document page '''[wiki:Old/NodeHandler/Commands/defNodes here]'''
    168 
    169 [[BR]]
    170 [[BR]]
     144end
     145}}}
     146
     147Finally the last block sets up the onEvent(:ALL_UP_AND_INSTALLED) trigger. When the
     148
    171149== 4. Running the "Hello World" experiment ==
    172150
     
    243221
    244222As mentioned previously, ORBIT experiment scripts are written in Ruby, an easily understood, extensible, dynamic, object-oriented scripting language.  Ruby has been extended into the testbed user's domain with a number of methods.  Besides its extensibility and object-orientation, Ruby is concise and consistent. An ORBIT script therefore is written in Ruby primarily using ORBIT-specific methods. Users are encouraged to take look at following resources:
    245 
    246   * [wiki:Tutorial/HowtoWriteScripts/RubyResources Ruby Resources]
    247   * [wiki:Tutorial/HowtoWriteScripts/OrbitRuby ORBIT Specific Ruby Methods]
    248 
    249 === 5.2. More Tutorials ===
    250 
    251 Once you are done with the remaining parts of this basic tutorial (i.e. [wiki:Tutorials/CollectMeasurements collecting] and [wiki:Tutorials/AnalyzeResults interpreting] experiment measurements and results), you might want to have a look at the other tutorials on the [wiki:Tutorials main page] to further learn about the other ORBIT functions that can help you develop your own complex experiments.
    252 
    253 === 5.3. Definitions of the Prototypes and Application used in the "Hello World" script ===
    254 
    255  * Orbit Traffic Generator (OTG) [[BR]] [wiki:Documentation/OTG/ScriptsRepository/ProtoDefSender sender.rb] is the file that contains the "test:proto:sender" prototype, which wraps around the [wiki:Documentation/OTG/ScriptsRepository/OtgAppDef otg.rb] application.
    256  * Orbit Traffic Receiver (OTR) [[BR]] [wiki:Documentation/OTG/ScriptsRepository/ProtoDefReceiver receiver.rb] is the file that contains the "test:proto:receiver" prototype, which wraps around the [wiki:Documentation/OTG/ScriptsRepository/OtrAppdef otr.rb] application.