[[TOC(Tutorials/c0WiFi*)]] == Wifi Tutorial: Access point with multiple clients == This tutorial shows how an experiment script configures an access point (AP) and multiple clients for performance testing with iperf. In this experiment script we'll use an OMF feature to define an application header for iperf and run this application on the AP and access points. === Experiment Script === The experiment script is shown below. Near the top of the script we define an application header for iperf. After which we define two groups - the first group (AP) consists of a single node to be configured as an access point. The second group (client) can be single or multiple node(s) to be configured as wifi clients. Both groups add the iperf application and configure the wireless interfaces accordingly. At the bottom of the script, the nodes in the all the groups are brought up and the applications are executed. {{{ 1 # 2 # Tutorial experiment 3 # 4 defProperty('master', 'node15-1', "node ID for access point") 5 defProperty('client', 'node16-1,node17-1', "node ID for client nodes") 6 defProperty('duration', 60, "Seconds to run the application.") 7 8 defApplication('oml:app:iperf', 'iperf') do |app| 9 10 app.version(2, 10, 0) 11 app.shortDescription = 'Iperf traffic generator and bandwidth measurement tool' 12 app.description = %{Iperf is a traffic generator and bandwidth measurement 13 tool. It provides generators producing various forms of packet streams and port 14 for sending these packets via various transports, such as TCP and UDP. 15 } 16 app.path = "/usr/bin/iperf-oml2" 17 18 app.defProperty('interval', 'pause n seconds between periodic bandwidth reports', '-i', 19 :type => :double, :unit => "seconds", :default => '1.') 20 app.defProperty('len', 'set length read/write buffer to n (default 8 KB)', '-l', 21 :type => :integer, :unit => "KiBytes") 22 app.defProperty('print_mss', 'print TCP maximum segment size (MTU - TCP/IP header)', '-m', 23 :type => :boolean) 24 app.defProperty('output', 'output the report or error message to this specified file', '-o', 25 :type => :string) 26 app.defProperty('port', 'set server port to listen on/connect to to n (default 5001)', '-p', 27 :type => :integer) 28 app.defProperty('udp', 'use UDP rather than TCP', '-u', 29 :type => :boolean, 30 :order => 2) 31 app.defProperty('window', 'TCP window size (socket buffer size)', '-w', 32 :type => :integer, :unit => "Bytes") 33 app.defProperty('bind', 'bind to , an interface or multicast address', '-B', 34 :type => :string) 35 app.defProperty('compatibility', 'for use with older versions does not sent extra msgs', '-C', 36 :type => :boolean) 37 app.defProperty('mss', 'set TCP maximum segment size (MTU - 40 bytes)', '-M', 38 :type => :integer, :unit => "Bytes") 39 app.defProperty('nodelay', 'set TCP no delay, disabling Nagle\'s Algorithm', '-N', 40 :type => :boolean) 41 app.defProperty('IPv6Version', 'set the domain to IPv6', '-V', 42 :type => :boolean) 43 app.defProperty('reportexclude', 'exclude C(connection) D(data) M(multicast) S(settings) V(server) reports', '-x', 44 :type => :string, :unit => "[CDMSV]") 45 app.defProperty('reportstyle', 'C or c for CSV report, O or o for OML', '-y', 46 :type => :string, :unit => "[CcOo]", :default => "o") # Use OML reporting by default 47 48 app.defProperty('oml-server', 'OML server for collecting data','--oml-server') 49 app.defProperty('oml-id', 'ID for this oml client','--oml-id') 50 app.defProperty('oml-exp-id', 'ID for this experiment','--oml-exp-id') 51 52 app.defProperty('server', 'run in server mode', '-s', 53 :type => :boolean) 54 55 app.defProperty('bandwidth', 'set target bandwidth to n bits/sec (default 1 Mbit/sec)', '-b', 56 :type => :string, :unit => "Mbps") 57 app.defProperty('client', 'run in client mode, connecting to ', '-c', 58 :type => :string, 59 :order => 1) 60 app.defProperty('dualtest', 'do a bidirectional test simultaneously', '-d', 61 :type => :boolean) 62 app.defProperty('num', 'number of bytes to transmit (instead of -t)', '-n', 63 :type => :integer, :unit => "Bytes") 64 app.defProperty('tradeoff', 'do a bidirectional test individually', '-r', 65 :type => :boolean) 66 app.defProperty('time', 'time in seconds to transmit for (default 10 secs)', '-t', 67 :type => :integer, :unit => "seconds") 68 app.defProperty('fileinput', 'input the data to be transmitted from a file', '-F', 69 :type => :string) 70 app.defProperty('stdin', 'input the data to be transmitted from stdin', '-I', 71 :type => :boolean) 72 app.defProperty('listenport', 'port to recieve bidirectional tests back on', '-L', 73 :type => :integer) 74 app.defProperty('parallel', 'number of parallel client threads to run', '-P', 75 :type => :integer) 76 app.defProperty('ttl', 'time-to-live, for multicast (default 1)', '-T', 77 :type => :integer, 78 :default => 1) 79 app.defProperty('linux-congestion', 'set TCP congestion control algorithm (Linux only)', '-Z', 80 :type => :boolean) 81 82 app.defMeasurement("application"){ |m| 83 m.defMetric('pid', :integer, 'Main process identifier') 84 m.defMetric('version', :string, 'Iperf version') 85 m.defMetric('cmdline', :string, 'Iperf invocation command line') 86 m.defMetric('starttime_s', :integer, 'Time the application was received (s)') 87 m.defMetric('starttime_us', :integer, 'Time the application was received (us)') 88 } 89 90 app.defMeasurement("settings"){ |m| 91 m.defMetric('pid', :integer, 'Main process identifier') 92 m.defMetric('server_mode', :integer, '1 if in server mode, 0 otherwise') 93 m.defMetric('bind_address', :string, 'Address to bind') 94 m.defMetric('multicast', :integer, '1 if listening to a Multicast group') 95 m.defMetric('multicast_ttl', :integer, 'Multicast TTL if relevant') 96 m.defMetric('transport_protocol', :integer, 'Transport protocol (IANA number)') 97 m.defMetric('window_size', :integer, 'TCP window size') 98 m.defMetric('buffer_size', :integer, 'UDP buffer size') 99 } 100 101 app.defMeasurement("connection"){ |m| 102 m.defMetric('pid', :integer, 'Main process identifier') 103 m.defMetric('connection_id', :integer, 'Connection identifier (socket)') 104 m.defMetric('local_address', :string, 'Local network address') 105 m.defMetric('local_port', :integer, 'Local port') 106 m.defMetric('remote_address', :string, 'Remote network address') 107 m.defMetric('remote_port', :integer, 'Remote port') 108 } 109 110 app.defMeasurement("transfer"){ |m| 111 m.defMetric('pid', :integer, 'Main process identifier') 112 m.defMetric('connection_id', :integer, 'Connection identifier (socket)') 113 m.defMetric('begin_interval', :double, 'Start of the averaging interval (Iperf timestamp)') 114 m.defMetric('end_interval', :double, 'End of the averaging interval (Iperf timestamp)') 115 m.defMetric('size', :uint64, 'Amount of transmitted data [Bytes]') 116 } 117 118 app.defMeasurement("losses"){ |m| 119 m.defMetric('pid', :integer, 'Main process identifier') 120 m.defMetric('connection_id', :integer, 'Connection identifier (socket)') 121 m.defMetric('begin_interval', :double, 'Start of the averaging interval (Iperf timestamp)') 122 m.defMetric('end_interval', :double, 'End of the averaging interval (Iperf timestamp)') 123 m.defMetric('total_datagrams', :integer, 'Total number of datagrams') 124 m.defMetric('lost_datagrams', :integer, 'Number of lost datagrams') 125 } 126 127 app.defMeasurement("jitter"){ |m| 128 m.defMetric('pid', :integer, 'Main process identifier') 129 m.defMetric('connection_id', :integer, 'Connection identifier (socket)') 130 m.defMetric('begin_interval', :double, 'Start of the averaging interval (Iperf timestamp)') 131 m.defMetric('end_interval', :double, 'End of the averaging interval (Iperf timestamp)') 132 m.defMetric('jitter', :double, 'Average jitter [ms]') 133 } 134 135 app.defMeasurement("packets"){ |m| 136 m.defMetric('pid', :integer, 'Main process identifier') 137 m.defMetric('connection_id', :integer, 'Connection identifier (socket)') 138 m.defMetric('packet_id', :integer, 'Packet sequence number for datagram-oriented protocols') 139 m.defMetric('packet_size', :integer, 'Packet size') 140 m.defMetric('packet_time_s', :integer, 'Time the packet was processed (s)') 141 m.defMetric('packet_time_us', :integer, 'Time the packet was processed (us)') 142 m.defMetric('packet_sent_time_s', :integer, 'Time the packet was sent (s) for datagram-oriented protocols') 143 m.defMetric('packet_sent_time_us', :integer, 'Time the packet was sent (us) for datagram-oriented protocols') 144 } 145 146 end 147 148 149 150 defGroup('AP', property.master) do |node| 151 node.addApplication("oml:app:iperf") do |app| 152 app.setProperty('server', true) 153 end 154 node.net.w0.mode = "master" 155 node.net.w0.type = 'g' 156 node.net.w0.channel = "6" 157 node.net.w0.essid = "TEST1234" 158 node.net.w0.ip = "192.168.0.254" 159 end 160 161 defGroup('client', property.client) do |node| 162 node.addApplication("oml:app:iperf") do |app| 163 app.setProperty('client', "192.168.0.254") 164 app.setProperty('time', 20) 165 app.setProperty('interval', 5) 166 #app.setProperty('reportstyle','O') 167 #app.setProperty('oml-server', "oml:3003") 168 #app.setProperty('oml-id', "#{Experiment.ID}") 169 #app.setProperty('oml-exp-id', "#{Experiment.ID}") 170 end 171 node.net.w0.mode = "managed" 172 node.net.w0.type = 'g' 173 node.net.w0.channel = "6" 174 node.net.w0.essid = "TEST1234" 175 node.net.w0.ip = "192.168.0.%index%" 176 end 177 178 onEvent(:ALL_UP_AND_INSTALLED) do |event| 179 info "Wifi Multi Client Iperf Experiment" 180 wait 10 181 allGroups.startApplications 182 info "All my Applications are started now..." 183 wait property.duration 184 allGroups.stopApplications 185 info "All my Applications are stopped now." 186 Experiment.done 187 end }}} Here's brief run down with some details from top to bottom. In Lines 4-6 we use ''defProperty'' to define a few experiment properties along with default values which allows the script to be executed with arguments passed from the command line. From Lines 8 - 146 we use ''defApplication'' to define the application header for iperf.