Version 13 (modified by 10 years ago) (diff) | ,
---|
How to use OML4R to write your OML application
1. Setup your Application
1.1 Download and build the tar file of your application
sudo su wget http://www.gpolab.bbn.com/experiment-support/gec17/pingPlus/pingPlus_v3.tar.gz tar xvzf pingPlus_v3.tar.gz cd pingPlus_v3 make
1.2 Test connectivity
On the receiver
chmod +x pingPlusListener ping -c 5 10.10.10.1 ifconfig eth1 0.0.0.0 ping -c 5 10.10.10.1 ./pingPlusListener 10002
The format for the pingPlusListener is sudo ./pingPlusListener <EtherType>
On the sender
ping -c 5 10.10.10.2 ifconfig eth1 0.0.0.0 ping -c 5 10.10.10.2 chmod +x pingPlus ./pingPlus 02:26:ae:0e:9b:3e eth1 10002
The format for the sender is
./pingPlus <server mac> <client i/f name> <EtherType> <count>
1. Observe your Output
root@sender:/users/dbhat/pingPlus_v3# ./pingPlus 02:26:ae:0e:9b:3e eth1 10002 5 RQ:'9641+4173' to 2:26:ae:e:9b:3e. RL:9641+4173=13814 from 2:26:ae:e:9b:3e. RTT = 0.920166 RQ:'2271+7533' to 2:26:ae:e:9b:3e. RL:2271+7533=9804 from 2:26:ae:e:9b:3e. RTT = 0.654053 RQ:'8858+353' to 2:26:ae:e:9b:3e. RL:8858+353=9211 from 2:26:ae:e:9b:3e. RTT = 0.489014 RQ:'447+5696' to 2:26:ae:e:9b:3e. RL:447+5696=6143 from 2:26:ae:e:9b:3e. RTT = 0.290039 RQ:'7238+5082' to 2:26:ae:e:9b:3e. RL:7238+5082=12320 from 2:26:ae:e:9b:3e. RTT = 0.252930
2. Write your OML Application
2.1 Write your OML Parser
def process_output(row) if not (parse= /RQ:'(?<pktsnt1>\d*)\+(?<pktsnt2>\d*)' to (?<host>[a-f0-9:]*)/.match(row)).nil? puts "ReturnQual #{parse[:pktsnt1]}\n" MPrt.inject(parse[:pktsnt1], parse[:pktsnt2],parse[:host]) elsif not (parse= /RL:(?<numofpkt1>\d*)\+(?<numofpkt2>\d*)=(?<totpktrec>\d*) from (?<dest_hw_addr>[a-f0-9:]*)/.match(row)).nil? puts "ReturnLength\n" p parse p MPrl.inject(parse[:numofpkt1],parse[:numofpkt2],parse[:totpktrec],parse[:dest_hw_addr]) elsif not (parse = /RTT = (?<rtt>[0-9.]*)/.match(row)).nil? puts "RoundTripTime #{parse[:rtt]}\n" p parse p MPrtt.inject(parse[:rtt]) end end
2.2 Write your OML Application
Define all varying parameters as properties that can be set within your Application.
Save the following code to any location on your node. E.g /usr/local/bin/pingl2.rb
#!/usr/bin/ruby1.9.1 require 'rubygems' require 'oml4r' class MPrt < OML4R::MPBase name :pingrt param :pktsnt1, :type => :uint64 param :pktsnt2, :type => :uint64 param :host, :type => :string end class MPrl < OML4R::MPBase name :pingrl param :totpktrec, :type => :uint64 param :numofpkt1, :type => :uint64 param :numofpkt2, :type => :uint64 param :dest_hw_addr, :type => :string end class MPrtt < OML4R::MPBase name :pingrtt param :rtt, :type => :double end class Pingl2Wrapper def initialize(args) @addr = nil @if_num = '' @eth = nil @verbose = true @numeric = '' leftover = OML4R::init(args, :appName => 'pingl2') do |argParser| argParser.banner = "Runs layer 2 ping and reports measurements via OML\n\n" argParser.on("-a" , "--dest_hw_addr ADDRESS", "Hardware address to ping (the -a switch is optional)"){ |address| @addr = address.to_s() } argParser.on("-i","--interface IFNUM","Interface number"){ |if_num| @if_num ="#{if_num.to_i()}" } argParser.on("-e", "--eth ETHTYPE","Ethernet Type") { |ethtype| @eth = ethtype.to_s() } argParser.on("-c","--count NUMBER","Number of pings (default: infinite)"){ |count| @count = "#{count.to_i()}"} argParser.on("-q", "--no-quiet ","Don't show layer 2 ping output on console"){ @verbose = false } argParser.on("-n", "--[no]-numeric ", "No attempt twill be made to look up symbolic names for host addresses"){ @numeric ='-n' } end if @addr.nil? if leftover.length > 0 @addr = leftover [0] else raise "You did not specify an address to ping!" end end end def process_output(row) if not (parse= /RQ:'(?<pktsnt1>\d*)\+(?<pktsnt2>\d*)' to (?<host>[a-f0-9:]*)/.match(row)).nil? puts "ReturnQual #{parse[:pktsnt1]}\n" MPrt.inject(parse[:pktsnt1], parse[:pktsnt2],parse[:host]) elsif not (parse= /RL:(?<numofpkt1>\d*)\+(?<numofpkt2>\d*)=(?<totpktrec>\d*) from (?<dest_hw_addr>[a-f0-9:]*)/.match(row)).nil? puts "ReturnLength\n" p parse p MPrl.inject(parse[:numofpkt1],parse[:numofpkt2],parse[:totpktrec],parse[:dest_hw_addr]) elsif not (parse = /RTT = (?<rtt>[0-9.]*)/.match(row)).nil? puts "RoundTripTime #{parse[:rtt]}\n" p parse p MPrtt.inject(parse[:rtt]) end end def pingl2() @pingio = IO.popen("/bin/pingPlus #{@addr} #{@eth} #{@if_num} #{@count}") while true row = @pingio.readline puts row if @verbose process_output(row) end end def start() return if not @pingio.nil? # handle for OMF's exit command a = Thread.new do $stdin.each do |line| if /^exit/ =~ line Process.kill("INT",0) end end end # Handle Ctrl+C and OMF's SIGTERM Signal.trap("INT", stop) Signal.trap("TERM", stop) begin pingl2 rescue EOFError end end def stop() return if @pingio.nil? # Kill the ping process, which will result in EOFError from ping() Process.kill("INT", @pingio.pid) end end begin $stderr.puts "INFO\tpingl2 2.11.0\n" app = Pingl2Wrapper.new(ARGV) app.start() sleep 1 rescue Interrupt rescue Exception => ex $stderr.puts "Error\t#{ex}\n" end # Local Variables: # mode:ruby # End: # vim: ft=ruby:sw=2
3. Instrument your Application using LabWiki
3.1 Copy binaries and set permissions
cp pingPlusListener /bin cp ping2.rb /usr/local/bin chmod +x /bin/pingPluListener chmod +x /usr/local/bin/pingl2.rb
3.2 Write your LabWiki Application
3.2.1 Edit a new OEDL Script in the Prepare Window
3.2.2 Copy the following script into the Prepare Window
defProperty('source1', "sender-gimiinsta", "ID of a resource") defProperty('sinkaddr11', '02:ee:1a:a2:51:11', "Ping destination address") defProperty('eth11','eth1',"Output Eth interface") defApplication('pingl2') do |app| app.description = 'Simple Definition for the pingl2 application' # Define the path to the binary executable for this application app.binary_path = '/usr/local/bin/pingl2.rb' # 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 macaddress -c 2 app.defProperty('target', 'Address to ping', '-a', {:type => :string}) app.defProperty('count', 'Number of times to ping', '-c', {:type => :integer}) app.defProperty('if_num', 'interface number', '-i', {:type => :integer}) app.defProperty('eth', 'Ethernet Type', '-e', {:type => :string}) # Define the OML2 measurement point that this application provides. app.defMeasurement('pingrl') do |m| m.defMetric('dest_hw_addr',:string) end app.defMeasurement('pingrtt') do |m| m.defMetric('rtt',:double) end end defGroup('Source1', property.source1) do |node| node.addApplication("pingl2") do |app| app.setProperty('target', property.sinkaddr11) app.setProperty('count', 30) app.setProperty('if_num', 10002) app.setProperty('eth',property.eth11) app.measure('pingrl', :samples => 1) app.measure('pingrtt', :samples => 1) end end onEvent(:ALL_UP_AND_INSTALLED) do |event| info "Starting the ping" after 5 do allGroups.startApplications end after 70 do info "Stopping the ping" allGroups.stopApplications Experiment.done end end defGraph 'RTT' do |g| g.ms('pingrtt').select(:rtt__oml_seq, :rtt__rtt, :rl__dest_hw_addr)\ .from(:pingl2_pingrtt___rtt, :pingl2_pingrl___rl)\ .where(:rtt__oml_seq => :rl__oml_seq) g.caption "RTT of received packets." g.type 'line_chart3' g.mapping :x_axis => :oml_seq, :y_axis => :rtt, :group_by => :dest_hw_addr g.xaxis :legend => 'oml_seq' g.yaxis :legend => 'rtt', :ticks => {:format => 's'} end defGraph 'RTT2' do |g| g.ms('pingrtt').select(:rtt__oml_seq, :rtt__rtt, :rl__dest_hw_addr)\ .from(:pingl2_pingrtt___rtt, :pingl2_pingrl___rl)\ .where(:rtt__oml_seq => :rl__oml_seq) g.caption "RTT of received packets." g.type 'histogram2' g.mapping :value => :rtt, :group_by => :dest_hw_addr g.xaxis :legend => 'RTT [ms]' g.yaxis :legend => 'Density [%]' end
3.2.3 Start your application from LabWiki
Attachments (4)
- markdown.png (337.9 KB) - added by 10 years ago.
- graphresults.png (430.0 KB) - added by 10 years ago.
- editscriptLW.png (286.3 KB) - added by 10 years ago.
- pingedit.png (289.4 KB) - added by 10 years ago.
Download all attachments as: .zip