= Part 0 Design and Setup = == 1. Choose Application == In this example, we will use the [https://mytestbed.net/projects/omlapp/repository/iperf/entry/oml/iperf.rb.in?rev=oml%2Fmaster Iperf Application] and [https://github.com/mytestbed/oml4r/blob/master/omf/ping-oml2.app.rb 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 Application == 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 applications it is advised to open and editor of your choice and define your experiment scripts similar to the procedure described here. === 2.1 Define Property === An experiment property maybe described as any variable entity you wish to define for your experiment. 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 === The entire application definition for OML-Iperf is given [http://mytestbed.net/projects/omlapp/repository/iperf/entry/oml/iperf.rb.in?rev=oml%2Fmaster here] Select the definition you will use in your experiment. The Application definition includes the experiment properties and measurement parameters. 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. {{{ 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 ', '-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 [https://github.com/mytestbed/oml4r/blob/master/omf/ping-oml2.app.rb here] === 2.3 Define Group and add Applications === A Group is a set of resources on which you want to run your experiment. Here, we see a group definition with just one resource but we can run the same set of applications on a set of resources. For example, change defGroup('theReceiver', property.thelistener) to defGroup('theReceiver', property.thelistener1, property.listener2) if you have more than one resource on which you want to run an Iperf server. [[BR]] a) Server Group [[BR]] {{{ 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 [[BR]] {{{ 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 Define Experiment Event === The experiment event will include the exact order of 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. {{{ 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 ==== Some events are time-based. For examble, 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', "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") 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 ', '-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_ts [s]' g.yaxis :legend => 'size [Bytes]', :ticks => {:format => 's'} end }}} = [wiki:GENIFIRE/Labwiki/Part0/Introduction Part 0 Introduction] = = [wiki:GENIFIRE/Labwiki/Part0/Execute Next: Run Experiment] =