wiki:GENIFIRE/Labwiki/Part0/DesignSetup

Version 22 (modified by divyashri.bhat@gmail.com, 10 years ago) (diff)

--

Part 0 Design and Setup

1. Choose Application

In this example, we will use the Iperf Application and Ping Application

However, for your own topology outside this tutorial, choose an application that best suits your purpose.

A list of available applications is given here:

http://mytestbed.net/projects/omlapp/wiki/OML-instrumented_Applications

2. Write OEDL/LabWiki Script

.

For this tutorial, Sec 2.1 - Sec 2.3 are for understanding the OEDL script that we have preloaded into LabWiki for you. When you write your own scripts it is advised to open an editor of your choice or use the Prepare window of LabWiki and define your experiment scripts similar to the procedure described here.

2.1 Define Property

Any property of your experiment maybe described as a variable entity. Generally this would be the name of your resources (hostname-slicename) that you will use but it can also include IP addresses, Port numbers and so on. Properties defined within quotes are treated as strings.

defProperty('source1', "client-lwtest6", "ID of a resource")
defProperty('thelistener', "server-lwtest6", "ID of a resource")
defProperty('thesender', "client-lwtest6", "ID of a resource")
defProperty('thesender2', "client-lwtest6", "ID of a resource")
defProperty('interfaceServer', "eth3", 'server interface to modify')
defProperty('capacity', 10000000, 'in bits per second')

defProperty('sinkaddr11', '10.0.5.102', "Ping destination address")
defProperty('sinkaddr12', '10.0.5.101', "Ping destination address")

2.2 Define Application for OEDL Script

In your OEDL scripts, you are required to define applications that you would like to run. The Application definition includes the experiment properties and measurement parameters.

In this example, we show how to use an Iperf.
For an Iperf, the properties would be similar to what you run on the command line, i.e, select whether server or client, TCP or UDP and so on. The measurement parameters would be throughput, packet loss, jitter and so on.
All possible parameters for running an Iperf in OEDL, are described in the complete application definition given here.

We are only required to select the properties and applications we will run. For example, here we only measure TCP throughput and therefore, do not include UDP related properties and measurement parameters in our script.

defApplication('iperf') do |app| 
  app.description = 'Iperf traffic generator and bandwidth measurement tool'
  app.binary_path = "/usr/bin/iperf-oml2"

  app.defProperty('server', 'run in server mode', '-s',
		  :type => :boolean)

  app.defProperty('client', 'run in client mode, connecting to <host>', '-c',
		  :type => :string,
		  :order => 1)

  app.defMeasurement("transfer"){ |m|
    m.defMetric('pid', :integer, 'Main process identifier')
    m.defMetric('connection_id', :integer, 'Connection identifier (socket)')
    m.defMetric('begin_interval', :double, 'Start of the averaging interval (Iperf timestamp)')
    m.defMetric('end_interval', :double, 'End of the averaging interval (Iperf timestamp)')
    m.defMetric('size', :uint64, 'Amount of transmitted data [Bytes]')
  }
   app.defMeasurement("connection"){ |m|
    m.defMetric('pid', :integer, 'Main process identifier')
    m.defMetric('connection_id', :integer, 'Connection identifier (socket)')
    m.defMetric('local_address', :string, 'Local network address')
    m.defMetric('local_port', :integer, 'Local port')
    m.defMetric('remote_address', :string, 'Remote network address')
    m.defMetric('remote_port', :integer, 'Remote port')
  }

end

We follow the same for the ping application. The entire definition is given here. Please find the entire OEDL script definition here

2.3 Define Group and add Applications on nodes

A 'Group' is a set of nodes on which you want to run your experiment. Here, we see a group definition with just one node but we can run the same set of applications on a set of nodes. For example, change defGroup('theReceiver', property.thelistener) to defGroup('theReceiver', property.thelistener1, property.listener2) if you have more than one node on which you want to run an Iperf server.

a) Server Group

defGroup('theReceiver', property.thelistener) do |node|
  node.addApplication("iperf") do |app|
    app.setProperty('server', true)
    app.measure('transfer', :samples => 1)
    app.measure('connection', :samples => 1)
  end
end

b) Client Group

defGroup('theSender', property.thesender) do |node|
  node.addApplication("iperf") do |app|
    app.setProperty('client', property.sinkaddr12)
    #app.measure('transfer', :samples => 1)
  end
end

c) Ping Group

defGroup('Source1', property.source1) do |node|
  node.addApplication("ping") do |app|
    app.setProperty('target', property.sinkaddr12)
    app.setProperty('count', 40)
    #app.setProperty('interval', 1)
    app.measure('ping', :samples => 1)
  end
end

2.3 Start your experiment and Define experiment events

The experiment event will include the exact order of the applications you wish to run.

2.3.1 Traffic Control

The Traffic control code limits traffic from server to client, so that you will see throughput reducing as time passes.

During the course of the experiment, if you would like to execute commands on your nodes, you can do so by referencing the group of nodes followed by a simple 'exec' command as shown below. Here we configure a traffic controller using modprobe and tc qdisc commands to limit traffic at the ingress points

group("theReceiver").exec("/sbin/modprobe sch_netem")
  group("theReceiver").exec("/sbin/modprobe ifb numifbs=10")
  group("theReceiver").exec("/sbin/sysctl -w net.core.rmem_max=8388608") 
  group("theReceiver").exec("/sbin/sysctl -w net.core.wmem_max=8388608") 
  group("theReceiver").exec("/sbin/sysctl -w net.core.netdev_max_backlog=2048") 
  #group("theReceiver").exec("/sbin/ifconfig #{prop.interfaceServer} txqueuelen") 
  group("theReceiver").exec("/sbin/tc qdisc del dev #{prop.interfaceServer} root") 
  group("theReceiver").exec("/sbin/tc qdisc del dev #{prop.interfaceServer} ingress") 
  group("theReceiver").exec("/sbin/tc qdisc add dev #{prop.interfaceServer} handle 130 root htb default 1") 
  group("theReceiver").exec("/sbin/tc class add dev #{prop.interfaceServer} classid 130:1 parent 130 htb rate #{prop.capacity.to_s} ceil #{prop.capacity.to_s}") 
  group("theReceiver").exec("/sbin/tc qdisc add dev #{prop.interfaceServer} handle 120 parent 130:1 netem drop 0 delay 0us")

2.3.2 Define Events

In OEDL, events are time-based. For example, you want to start the Iperf server before the client starts. To ensure this, you can select the Iperf server group to run applications as soon as the resources are configured. We can wait for about 3 seconds before we run the client. Below, we start one Iperf stream from client to server. After 10 seconds, we start a second stream from client to server.

after 2 do 
    group('theReceiver').startApplications
  end
  after 5 do
    group('theSender').startApplications
     info "Starting the ping"
    group('Source1').startApplications
  end
  after 15 do 
    group('theSender2').startApplications
  end
  after 70 do
    info "Stopping the ping"
    group('theSender').stopApplications
  end
  after 72 do
    allGroups.stopApplications
    Experiment.done
  end

2.4 Complete OEDL script

defProperty('source1', "nodeb-divpart0", "ID of a resource")
defProperty('thelistener', "nodea-divpart0", "ID of a resource")
defProperty('thesender', "nodeb-divpart0", "ID of a resource")
defProperty('thesender2', "nodeb-divpart0", "ID of a resource")
defProperty('interfaceServer', "wlan0", 'server interface to modify')
defProperty('capacity', 10000000, 'in bits per second')

defProperty('sinkaddr11', '192.168.1.7', "Ping destination address")
defProperty('sinkaddr12', '192.168.1.6', "Ping destination address")

defApplication('iperf') do |app| 
  app.description = 'Iperf traffic generator and bandwidth measurement tool'
  app.binary_path = "/usr/bin/iperf-oml2"

  app.defProperty('server', 'run in server mode', '-s',
		  :type => :boolean)

  app.defProperty('client', 'run in client mode, connecting to <host>', '-c',
		  :type => :string,
		  :order => 1)

  app.defMeasurement("transfer"){ |m|
    m.defMetric('pid', :integer, 'Main process identifier')
    m.defMetric('connection_id', :integer, 'Connection identifier (socket)')
    m.defMetric('begin_interval', :double, 'Start of the averaging interval (Iperf timestamp)')
    m.defMetric('end_interval', :double, 'End of the averaging interval (Iperf timestamp)')
    m.defMetric('size', :uint64, 'Amount of transmitted data [Bytes]')
  }
   app.defMeasurement("connection"){ |m|
    m.defMetric('pid', :integer, 'Main process identifier')
    m.defMetric('connection_id', :integer, 'Connection identifier (socket)')
    m.defMetric('local_address', :string, 'Local network address')
    m.defMetric('local_port', :integer, 'Local port')
    m.defMetric('remote_address', :string, 'Remote network address')
    m.defMetric('remote_port', :integer, 'Remote port')
  }

end


defApplication('ping') do |app|
  app.description = 'Simple Definition for the ping-oml2 application'
  # Define the path to the binary executable for this application
  app.binary_path = '/usr/local/bin/ping-oml2'
  # Define the configurable parameters for this application
  # For example if target is set to foo.com and count is set to 2, then the 
  # application will be started with the command line:
  # /usr/bin/ping-oml2 -a foo.com -c 2
  app.defProperty('target', 'Address to ping', '-a', {:type => :string})
  app.defProperty('count', 'Number of times to ping', '-c', {:type => :integer})
  # Define the OML2 measurement point that this application provides.
  # Here we have only one measurement point (MP) named 'ping'. Each measurement
  # sample from this MP will be composed of a 4-tuples (addr,ttl,rtt,rtt_unit)
  app.defMeasurement('ping') do |m|
    m.defMetric('dest_addr',:string)
    m.defMetric('ttl',:uint32)
    m.defMetric('rtt',:double)
    m.defMetric('rtt_unit',:string)
  end
end
defGroup('Source1', property.source1) do |node|
  node.addApplication("ping") do |app|
    app.setProperty('target', property.sinkaddr12)
    app.setProperty('count', 40)
    #app.setProperty('interval', 1)
    app.measure('ping', :samples => 1)
  end
end
defGroup('theReceiver', property.thelistener) do |node|
  node.addApplication("iperf") do |app|
    app.setProperty('server', true)
    app.measure('transfer', :samples => 1)
   # app.measure('connection', :samples => 1)
  end
end

defGroup('theSender', property.thesender) do |node|
  node.addApplication("iperf") do |app|
    app.setProperty('client', property.sinkaddr12)
    #app.measure('transfer', :samples => 1)   
  end
end
defGroup('theSender2', property.thesender2) do |node|
  node.addApplication("iperf") do |app|
    app.setProperty('client', property.sinkaddr12)
    #app.measure('transfer', :samples => 1)
  end
end



onEvent(:ALL_UP_AND_INSTALLED) do |event|
  info(" ------ Setup Traffic Shaping")
  group("theReceiver").exec("/sbin/modprobe sch_netem")
  group("theReceiver").exec("/sbin/modprobe ifb numifbs=10")
  group("theReceiver").exec("/sbin/sysctl -w net.core.rmem_max=8388608") 
  group("theReceiver").exec("/sbin/sysctl -w net.core.wmem_max=8388608") 
  group("theReceiver").exec("/sbin/sysctl -w net.core.netdev_max_backlog=2048") 
  #group("theReceiver").exec("/sbin/ifconfig #{prop.interfaceServer} txqueuelen") 
  group("theReceiver").exec("/sbin/tc qdisc del dev #{prop.interfaceServer} root") 
  group("theReceiver").exec("/sbin/tc qdisc del dev #{prop.interfaceServer} ingress") 
  group("theReceiver").exec("/sbin/tc qdisc add dev #{prop.interfaceServer} handle 130 root htb default 1") 
  group("theReceiver").exec("/sbin/tc class add dev #{prop.interfaceServer} classid 130:1 parent 130 htb rate #{prop.capacity.to_s} ceil #{prop.capacity.to_s}") 
  group("theReceiver").exec("/sbin/tc qdisc add dev #{prop.interfaceServer} handle 120 parent 130:1 netem drop 0 delay 0us")
  after 2 do 
    group('theReceiver').startApplications
  end
  after 5 do
    group('theSender').startApplications
     info "Starting the ping"
    group('Source1').startApplications
  end
  after 15 do 
    group('theSender2').startApplications
  end
  after 70 do
    info "Stopping the ping"
    group('theSender').stopApplications
  end
  after 72 do
    allGroups.stopApplications
    Experiment.done
  end
end

defGraph 'RTT' do |g|
  g.ms('ping').select(:oml_seq, :dest_addr, :rtt) 
  g.caption "RTT of received packets."
  g.type 'line_chart3'
  g.mapping :x_axis => :oml_seq, :y_axis => :rtt, :group_by => :dest_addr
  g.xaxis :legend => 'oml_seq'
  g.yaxis :legend => 'rtt', :ticks => {:format => 's'}
end
defGraph 'Iperf' do |g|
  g.ms('transfer').select(:oml_seq, :size, :connection_id) 
  g.caption "Size of received packets."
  g.type 'line_chart3'
  g.mapping :x_axis => :oml_seq, :y_axis => :size, :group_by => :connection_id
  g.xaxis :legend => 'oml_seq [s]'
  g.yaxis :legend => 'size [Bytes]', :ticks => {:format => 's'}
end


Part 0 Introduction

Next: Run Experiment