Version 2 (modified by 9 years ago) (diff) | ,
---|
Module E Design and Setup
1 Write Application for OpenFlow Statistics Measurement
1.1 Get Flow Statistics you want to measure
Define stats_reply in /root/learning-switch-copy.rb as follows. This file is the Trema controller script which we ran in ModuleC. For the purpose of this tutorial, the modified script has been downloaded into switch1 prior to this tutorial.
You can find this file in the node called switch1. If you need help with logging in to your nodes, please refer How To Login.
def stats_reply (dpid, message) puts "[flow stats_reply #{@my_switch}]---------------------------------" byte_count = 0 packet_count = 0 flow_count = 0 throughput = 0 inst_throughput =0 total_flow_count = message.stats.length if(total_flow_count != 0) message.stats.each do | flow_msg | # WARNING: This only works for the EXACT case of two actions. If we add more than two actions the flow monitoring # will break. flow_ip = flow_msg.match puts "This is the message #{flow_ip.nw_src}" flow_count = flow_count + 1 byte_count += flow_msg.byte_count packet_count += flow_msg.packet_count if flow_msg.duration_sec + flow_msg.duration_nsec/1000000000 != 0 throughput += flow_msg.byte_count/(flow_msg.duration_sec + flow_msg.duration_nsec/1000000000) file = File.open("/tmp/flowstats.out", "a") file.puts "#{flow_ip.nw_src} #{flow_count.to_s} #{byte_count} #{packet_count} #{throughput} Bps" file.close end end end @prev_byte_count = byte_count end
1.2 Define Flow Statistics measurement points
We now proceed to write the application which collects the measurement points defined in the controller code above.
The complete script is already pre-loaded into the node switch1 at /usr/local/bin/learn_ofcollect.rb. The steps provided here are for your reference.
class MPThroughput < OML4R::MPBase name :ofthroughput param :srcaddr, :type => :string param :numflows, :type => :int64 param :numbytes, :type => :int64 param :numpacket, :type => :int64 param :throughput, :type => :int64 param :units, :type => :string end
1.3 Parse Measurement Fields
def processOutput(output) column = output.split(" ") puts "Each line process" # Inject the measurements into OML MPThroughput.inject("#{column[0]}", column[1], column[2], column[3], column[4], "#{column[5]}") end
1.4 Write application Script
!/usr/bin/env ruby require 'rubygems' require 'oml4r' require 'file-tail' APPNAME = "ofstats" class MPThroughput < OML4R::MPBase name :ofthroughput param :srcaddr, :type => :string param :numflows, :type => :int64 param :numbytes, :type => :int64 param :numpacket, :type => :int64 param :throughput, :type => :int64 param :units, :type => :string end class OFStatsWrapper def initialize(args) @addr = nil @if_num = ' ' @trema_port = ' ' @trema_path = ' ' @verbose = true @numeric = ' ' OML4R::init(args, :appName => "#{APPNAME}_wrapper", :domain => 'foo', :collect => 'file:-') { |argParser| argParser.banner = "Reports OpenFlow stat measurements via OML\n\n" argParser.on("-f" , "--file_path ADDRESS", "Path where output is saved"){ |address| @addr = address } argParser.on("-i","--interface IFNUM","Interface number"){ |if_num| @if_num ="#{if_num.to_i()}" } argParser.on("-q", "--no-quiet ","Don't show of stats 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' } } unless @addr !=nil raise "You did not specify path of file (-p option)" end end class MyFile < File include File::Tail end def start() log = MyFile.new("#{@addr}") log.interval = @if_num log.backward(3) puts "#{@if_num}" log.tail { |line| print line processOutput(line) } end def processOutput(output) column = output.split(" ") puts "Each line process" # Inject the measurements into OML MPThroughput.inject("#{column[0]}", column[1], column[2], column[3], column[4], "#{column[5]}") end end begin app = OFStatsWrapper.new(ARGV) app.start() rescue SystemExit rescue SignalException puts "OFWrapper stopped." rescue Exception => ex puts "Error - When executing the wrapper application!" puts "Error - Type: #{ex.class}" puts "Error - Message: #{ex}\n\n" # Uncomment the next line to get more info on errors # puts "Trace - #{ex.backtrace.join("\n\t")}" end OML4R::close() # Local Variables: # mode:ruby # End: # vim: ft=ruby:sw=2
2. Write OEDL Script to run in LabWiki
This script is used to orchestrate the OML application we just wrote. It is pre-loaded into your LabWiki directory as GEC20_flowstatistics.oedl.
The steps provided here are for your reference.
2.1 Define Resource name
Here you will identify the nodes you used for the tutorial as a combination of the <node-slicename>
defProperty('source1', "switch1-rspecforMax", "ID of a resource") defProperty('source2', "switch2-rspecforMax", "ID of a resource") defProperty('source3', "switch1-rspecforMax", "ID of a resource") defProperty('theSender1', "nodeb-rspecforMax", "ID of a resource") defProperty('theSender2', "nodec-rspecforMax", "ID of a resource") defProperty('theSender3', "noded-rspecforMax", "ID of a resource") defProperty('theSender4', "nodec-rspecforMax", "ID of a resource") defProperty('theSender5', "nodee-rspecforMax", "ID of a resource") defProperty('theReceiver', "nodef-rspecforMax", "ID of a resource")
2.2 Specify the location where Flow Statistics will be stored
defProperty('pathfile', "/tmp/flowstats.out", "Path to file")
2.3 Define the Application created in Step 1) in OEDL
defApplication('ofstats') do |app| app.description = 'Simple Definition for the of-collect application' # Define the path to the binary executable for this application app.binary_path = '/usr/local/bin/learn_ofcollect.rb' app.defProperty('target', 'Address to output file', '-f', {:type => :string}) app.defProperty("interval","Interval",'-i', {:type => :string}) app.defMeasurement('wrapper_ofthroughput') do |m| m.defMetric(':srcaddr', :string) m.defMetric('throughput',:int64) end end
2.4 Create Node Group with Application
defGroup('Source3', property.source1) do |node| node.addApplication("ofstats") do |app| app.setProperty('target', property.pathfile) app.setProperty('interval', property.intervalcol) app.measure('wrapper_ofthroughput', :samples => 1) end end
2.5 Define parameters for graphs
defGraph 'Throughput' do |g| g.ms('wrapper_ofthroughput').select(:oml_ts_client, :throughput, :srcaddr) g.caption "Throughput of Flows" g.type 'line_chart3' g.mapping :x_axis => :oml_ts_client, :y_axis => :throughput, :group_by => :srcaddr g.xaxis :legend => 'oml_ts' g.yaxis :legend => 'Throughput', :ticks => {:format => 's'} end