[[TOC(Tutorials/c0WiFi*)]] == !WiFi Tutorial: Access point with multiple clients == === Prerequisites === This tutorial series assumes you have an [http://www.orbit-lab.org/userManagement/register ORBIT account], have [https://www.orbit-lab.org/schedule/ scheduled a session] on the ORBIT testbed, are familiar with [http://en.wikipedia.org/wiki/Secure_Shell SSH]'ing [http://www.orbit-lab.org/wiki/Tutorial/HelloWorld#a4.RunningtheHelloWorldexperiment into the testbed itself, and are familiar with the basics of running ORBIT experiments]. If you have not done these things yet, you may wish to do so before taking a look at this slightly more advanced experiment. If you are unfamiliar with or are entirely new to ORBIT, you may wish to start [http://www.orbit-lab.org/ here]. === About This Experiment === This tutorial shows how an experiment script configures multiple nodes to work as an access point (AP) and multiple clients for performance testing with [http://en.wikipedia.org/wiki/Iperf 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 available below for reference. It is already accessible from the console of the domain you will be working on, so there is no need download it there. * [attachment:wifi-ap-iperf.rb Experiment Script] === Dissecting the Experiment === Below you will find a step by step explanation of how the experiment script is structured and what each section does. '''1. Define experiment properties:''' [http://www.orbit-lab.org/attachment/wiki/Tutorials/c0WiFi/Tutorial3/wifi-ap-iperf.rb#L4 Lines 4 - 6] We use ''defProperty'' to define a few experiment properties along with their default values which allows the script to be executed with arguments passed from the command line. {{{ defProperty('accesspoint', 'node1-1', "node ID for access point") defProperty('client', 'node1-2', "node ID for client nodes") defProperty('duration', 60, "Seconds to run the application.") }}} '''2. Define application that will run on nodes:''' [http://www.orbit-lab.org/attachment/wiki/Tutorials/c0WiFi/Tutorial3/wifi-ap-iperf.rb#L8 Lines 8 - 81] We use ''defApplication'' to define the application header for iperf. This creates a reference name ''iperf'' that can be used later in the script. {{{ defApplication('iperf', 'iperf-oml2') do |app| }}} The actual path to the iperf application in the node is defined as follows. {{{ app.path = "/usr/bin/iperf-oml2" }}} The numerous ''defProperty'' that follow define references to the various arguments for the application. For example, in the following definition, the reference name ''interval'' is mapped to the application argument specified with the ''-i'' flag. The default value and the other properties can also be specified. {{{ app.defProperty('interval', 'pause n seconds between periodic bandwidth reports', '-i', :type => :double, :unit => "seconds", :default => '1.') }}} '''3. Define properties for group of nodes that will act as !WiFi APs:''' [http://www.orbit-lab.org/attachment/wiki/Tutorials/c0WiFi/Tutorial3/wifi-ap-iperf.rb#L83 Lines 83 - 92] The first group (AP) consists of a single node to be configured as an access point. In practice, these property definitions can be applied to multiple nodes (as we will see in the next section). However, for the purposes of this tutorial we will write this particular set of properties assuming it will apply to a single node. We first define a group name ''AP'' using ''defGroup'' which will apply the subsequent properties to the node specified inthe ''property.accesspoint'' reference. {{{ defGroup('AP', property.accesspoint) do |node| }}} Now we define various properties that will be applied to the AP node. First, ''node.addApplication'' connects the previously defined ''iperf'' application to this node with the specified arguments and values using ''setProperty''. On the AP node, the iperf application will be configured as a server. {{{ node.addApplication("iperf") do |app| app.setProperty('server', true) end }}} Next, The wireless card properties are set with the ''node.net.w0'' parameters. Here we set ''node.net.w0.mode'' to ''master'' to configure the 1st wireless card in the node as an access point. Other relevant parameters are also set here as well, such as channel and SSID. {{{ node.net.w0.mode = "master" node.net.w0.type = 'g' node.net.w0.channel = "6" node.net.w0.essid = "TEST1234" node.net.w0.ip = "192.168.0.254" }}} '''4. Define properties for group of nodes that will act as !WiFi clients:''' [http://www.orbit-lab.org/attachment/wiki/Tutorials/c0WiFi/Tutorial3/wifi-ap-iperf.rb#L94 Lines 94 - 105] The second group (client) consists of a single or multiple node(s) that will be configured as !WiFi clients. Like the AP group, we use ''defGroup'' again to define a reference name ''client'' for the client node(s) specified in ''property.client'' reference. {{{ defGroup('client', property.client) do |node| }}} Now we configure iperf for the client node(s), but this time iperf will be running as a client connecting to the previously defined iperf server with the appropriate properties set accordingly. {{{ node.addApplication("iperf") do |app| app.setProperty('client', "192.168.0.254") app.setProperty('time', 20) app.setProperty('interval', 5) end }}} The wireless card properties are then set with the ''node.net.w0'' parameters. Note that we set ''node.net.w0.mode'' to ''managed'' to configure the wireless card as a client. Other relevant parameters are also set here as well. Since we can have multiple nodes in a group we specify ''node.net.w0.ip'' with the last byte of the IP address as ''%index%''. This way, each node will automatically be assigned a unique address. {{{ node.net.w0.mode = "managed" node.net.w0.type = 'g' node.net.w0.channel = "6" node.net.w0.essid = "TEST1234" node.net.w0.ip = "192.168.0.%index%" }}} '''5. Define event that will occur once all nodes are setup and ready:''' [http://www.orbit-lab.org/attachment/wiki/Tutorials/c0WiFi/Tutorial3/wifi-ap-iperf.rb#L107 Lines 107 - 116] At the end of the script, once all the nodes are at the same point and all applications have been initialized, an event is triggered to continue and execute the remaining steps. {{{ onEvent(:ALL_UP_AND_INSTALLED) do |event| }}} The remaining commands execute the actual experiment. The 10 second delay before the call to ''startApplications'' allows time for the clients to establish a !WiFi connection with the access point before continuing. Then iperf is started on all the nodes (AP and clients). Execution of the experiment script is once delayed again, this time for a period defined by ''property.duration'', giving time to collect experiment data. Finally all applications are stopped and the experiment exits out. {{{ info "Wifi Multi Client Iperf Experiment" wait 10 allGroups.startApplications info "All my Applications are started now..." wait property.duration allGroups.stopApplications info "All my Applications are stopped now." Experiment.done }}} === Executing the Experiment Script === An overview on running experiment scripts on the ORBIT testbed can be found on the [wiki:Documentation/CGettingStarted Getting Started Page]. In order to run this experiment script, connect to the console of the domain for which you have an active and approved reservation for and load the ''baseline.ndz'' image onto nodes with !WiFi cards. Check the ''Status Page'' in the [https://www.orbit-lab.org/cPanel/controlPanel/start Control Panel] to find nodes with a compatible !WiFi card (either ath9k or ath5k). {{{ user@console:~$ omf load -i baseline.ndz -t node1-1,node1-2,node1-3 }}} After the nodes have finished imaging, turn the nodes on. The topology used here is ''system:topo:imaged'' which selects the prior set of nodes that were successfully imaged. {{{ user@console:~$ omf tell -a on -t system:topo:imaged }}} Wait about 1 minute before proceeding to allow the nodes time to boot up. To run this experiment with 2 clients nodes (assuming the domain you are using has more than 2 compatible nodes): {{{ user@console:~$ omf exec test:exp:tutorial:wifi-ap-iperf.rb -- --accesspoint node1-1 --client node1-2,node1-3 --duration 60 }}} The output of this script should be similar to the following: {{{ INFO NodeHandler: OMF Experiment Controller 5.4 (git a7fbf12) INFO NodeHandler: Reading configuration file /etc/omf-expctl-5.4/services.yaml INFO NodeHandler: Add domain http - http://internal2dmz.orbit-lab.org:5054/ INFO NodeHandler: Add domain http - http://internal1.orbit-lab.org:5054/ INFO NodeHandler: Add domain http - http://repository1.orbit-lab.org:5054/ INFO NodeHandler: Add domain http - http://external1.orbit-lab.org:5054/ INFO NodeHandler: Slice ID: default_slice (default) INFO NodeHandler: Experiment ID: default_slice-2016-05-26t10.05.35.243-04.00 INFO NodeHandler: Message authentication is disabled INFO Experiment: load system:exp:stdlib INFO property.resetDelay: resetDelay = 230 (Fixnum) INFO property.resetTries: resetTries = 1 (Fixnum) INFO Experiment: load system:exp:eventlib INFO Experiment: load system:exp:winlib INFO Experiment: load test:exp:tutorial:wifi-ap-iperf.rb INFO property.accesspoint: accesspoint = "node1-1" (String) INFO property.client: client = "node1-2,node1-3" (String) INFO property.duration: duration = 60 (Fixnum) INFO ALL_UP_AND_INSTALLED: Event triggered. Starting the associated tasks. INFO exp: Wifi Multi Client Iperf Experiment INFO exp: Request from Experiment Script: Wait for 10s.... INFO BRING_UP: Event triggered. Starting the associated tasks. INFO Experiment: Bringing up resources INFO exp: All my Applications are started now... INFO exp: Request from Experiment Script: Wait for 60s.... INFO exp: All my Applications are stopped now. INFO EXPERIMENT_DONE: Event triggered. Starting the associated tasks. INFO NodeHandler: INFO NodeHandler: Shutting down experiment, please wait... INFO NodeHandler: INFO run: Experiment default_slice-2016-05-26t10.05.35.243-04.00 finished after 1:35 }}} === Retrieving Results === Data is collected during the experiment and pushed to an OML server running on the domain's console and is identified using the '''' indicated during the initiation and conclusion of each experiment. This ID is important, as it is used to recover experiment results and even view them in real-time. (Server names vary with test beds. This server name is specific to ORBIT.) To recover experiment data to the local machine, and using the experiment ID: {{{ wget "http://oml:5054/result/dumpDatabase?expID=" -O myDatabase }}} * If the experiment ID contains non-alphanumeric ASCII characters, it is necessary to escape each of them using "%" followed by the ASCII code. You're almost done. In order to get SQLite to recognize the database, it first must be told that the information '''is''' a database. {{{ sqlite3 -init myDatabase myDatabase.sq3 }}} You can also view the results in a web browser by visiting the following URL: {{{ http://console.sb4.orbit-lab.org:5054/result/dumpDatabase?expID= }}} TODO The experiment script generates a lot of data that contains not only results, but also information useful for debugging. This detailed output of the experiment along with iperf's output are aggregated on the console in a log file: /tmp/''''.log For this example, the file would be: /tmp/default_slice-2016-05-26t10.05.35.243-04.00.log Partial contents of this file (specifically iperf results) are shown below: {{{ 2016-05-26 10:06:06 INFO nodeHandler::exp: All my Applications are started now... 2016-05-26 10:06:06 INFO nodeHandler::exp: Request from Experiment Script: Wait for 60s.... 2016-05-26 10:06:06 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#1' (node1-1.grid.orbit-lab.org) - msg: '------------------------------------------------------------' 2016-05-26 10:06:06 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#1' (node1-1.grid.orbit-lab.org) - msg: 'Server listening on TCP port 5001' 2016-05-26 10:06:06 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#1' (node1-1.grid.orbit-lab.org) - msg: 'TCP window size: 85.3 KiByte (default)' 2016-05-26 10:06:06 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#1' (node1-1.grid.orbit-lab.org) - msg: '------------------------------------------------------------' 2016-05-26 10:06:12 DEBUG nodeHandler::AgentCommands: OK from: 'node1-2.grid.orbit-lab.org' - cmd: 'BRINGUP' - msg: 'net/w0 Connect sucessfull, params configured were mode,type,essid,ip,freq,rate' 2016-05-26 10:06:12 DEBUG nodeHandler::AgentCommands: APP_EVENT STARTED from: 'iperf#2' (node1-2.grid.orbit-lab.org) - msg: '' 2016-05-26 10:06:12 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#1' (node1-1.grid.orbit-lab.org) - msg: '[ 4] local 192.168.0.254 port 5001 connected with 192.168.0.2 port 32816' 2016-05-26 10:06:12 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-2.grid.orbit-lab.org) - msg: '------------------------------------------------------------' 2016-05-26 10:06:12 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-2.grid.orbit-lab.org) - msg: 'Client connecting to 192.168.0.254, TCP port 5001' 2016-05-26 10:06:12 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-2.grid.orbit-lab.org) - msg: 'TCP window size: 85.0 KiByte (default)' 2016-05-26 10:06:12 DEBUG nodeHandler::AgentCommands: OK from: 'node1-3.grid.orbit-lab.org' - cmd: 'BRINGUP' - msg: 'net/w0 Connect sucessfull, params configured were mode,type,essid,ip,freq,rate' 2016-05-26 10:06:12 DEBUG nodeHandler::AgentCommands: APP_EVENT STARTED from: 'iperf#2' (node1-3.grid.orbit-lab.org) - msg: '' 2016-05-26 10:06:12 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-2.grid.orbit-lab.org) - msg: '------------------------------------------------------------' 2016-05-26 10:06:12 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-2.grid.orbit-lab.org) - msg: '[ 3] local 192.168.0.2 port 32816 connected with 192.168.0.254 port 5001' 2016-05-26 10:06:12 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-3.grid.orbit-lab.org) - msg: '------------------------------------------------------------' 2016-05-26 10:06:12 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-3.grid.orbit-lab.org) - msg: 'Client connecting to 192.168.0.254, TCP port 5001' 2016-05-26 10:06:12 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-3.grid.orbit-lab.org) - msg: 'TCP window size: 85.0 KiByte (default)' 2016-05-26 10:06:12 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#1' (node1-1.grid.orbit-lab.org) - msg: '[ 6] local 192.168.0.254 port 5001 connected with 192.168.0.3 port 54237' 2016-05-26 10:06:12 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-3.grid.orbit-lab.org) - msg: '------------------------------------------------------------' 2016-05-26 10:06:12 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-3.grid.orbit-lab.org) - msg: '[ 3] local 192.168.0.3 port 54237 connected with 192.168.0.254 port 5001' 2016-05-26 10:06:17 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-2.grid.orbit-lab.org) - msg: '[ ID] Interval Transfer Bandwidth' 2016-05-26 10:06:17 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-2.grid.orbit-lab.org) - msg: '[ 3] 0.0- 5.0 sec 2.50 MiBytes 4.19 Mbits/sec' 2016-05-26 10:06:17 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-3.grid.orbit-lab.org) - msg: '[ ID] Interval Transfer Bandwidth' 2016-05-26 10:06:17 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-3.grid.orbit-lab.org) - msg: '[ 3] 0.0- 5.0 sec 640 KiBytes 1.05 Mbits/sec' 2016-05-26 10:06:22 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-2.grid.orbit-lab.org) - msg: '[ 3] 5.0-10.0 sec 2.38 MiBytes 3.98 Mbits/sec' 2016-05-26 10:06:23 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-3.grid.orbit-lab.org) - msg: '[ 3] 5.0-10.0 sec 768 KiBytes 1.26 Mbits/sec' 2016-05-26 10:06:27 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-2.grid.orbit-lab.org) - msg: '[ 3] 10.0-15.0 sec 2.50 MiBytes 4.19 Mbits/sec' 2016-05-26 10:06:27 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-3.grid.orbit-lab.org) - msg: '[ 3] 10.0-15.0 sec 640 KiBytes 1.05 Mbits/sec' 2016-05-26 10:06:32 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-2.grid.orbit-lab.org) - msg: '[ 3] 15.0-20.0 sec 2.50 MiBytes 4.19 Mbits/sec' 2016-05-26 10:06:32 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-2.grid.orbit-lab.org) - msg: '[ 3] 0.0-20.1 sec 10.0 MiBytes 4.17 Mbits/sec' 2016-05-26 10:06:32 DEBUG nodeHandler::AgentCommands: APP_EVENT DONE.OK from: 'iperf#2' (node1-2.grid.orbit-lab.org) - msg: 'status: pid 1698 exit 0' 2016-05-26 10:06:32 DEBUG nodeHandler::NodeApp: Application 'iperf#2' on 'node1-2.grid.orbit-lab.org' finished successfully (returned: 'status: pid 1698 exit 0') 2016-05-26 10:06:32 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#1' (node1-1.grid.orbit-lab.org) - msg: '[ ID] Interval Transfer Bandwidth' 2016-05-26 10:06:32 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#1' (node1-1.grid.orbit-lab.org) - msg: '[ 4] 0.0-20.4 sec 10.0 MiBytes 4.11 Mbits/sec' 2016-05-26 10:06:32 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-3.grid.orbit-lab.org) - msg: '[ 3] 15.0-20.0 sec 640 KiBytes 1.05 Mbits/sec' 2016-05-26 10:06:32 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#2' (node1-3.grid.orbit-lab.org) - msg: '[ 3] 0.0-20.1 sec 2.75 MiBytes 1.15 Mbits/sec' 2016-05-26 10:06:32 DEBUG nodeHandler::AgentCommands: APP_EVENT DONE.OK from: 'iperf#2' (node1-3.grid.orbit-lab.org) - msg: 'status: pid 1570 exit 0' 2016-05-26 10:06:32 DEBUG nodeHandler::NodeApp: Application 'iperf#2' on 'node1-3.grid.orbit-lab.org' finished successfully (returned: 'status: pid 1570 exit 0') 2016-05-26 10:06:33 DEBUG nodeHandler::AgentCommands: APP_EVENT STDOUT from: 'iperf#1' (node1-1.grid.orbit-lab.org) - msg: '[ 6] 0.0-20.2 sec 2.75 MiBytes 1.14 Mbits/sec' 2016-05-26 10:07:06 DEBUG nodeHandler::nodeSetPath: Stop all applications }}} === Troubleshooting === * When you login to the domain's console at the start of your approved time slot, do not assume the nodes you will be using have a working image on them. Load the appropriate image onto the nodes you will be using before attempting your experiment. * Make sure the nodes that you are trying to run the experiment on are ''actually'' powered on. You can use the `omf stat` command or view the Status page in the Control Panel to check this. Please note that the Status page is only periodically refreshed and may not show immediate changes in node power state. * Make sure the nodes (and domain) you are using for this experiment have compatible !WiFi cards. Refer to the Status page in the Control Panel to find nodes that have compatible !Wifi cards (either ath9k or ath5k). * If you are attempting this tutorial with more than 1 client node, please make a reservation on Grid or SB4. All other compatible domains only have 2 nodes, which will only allow for 1 AP and 1 client node. * It is not recommended to attempt this tutorial on SB4 unless you have completed the tutorial on configuring the attenuator matrix. The experiment will fail or produce errors if the attenuators are set beyond certain values. * If you are trying this tutorial on SB9, you are going to have a bad time because that sandbox does not have ANY wireless devices. === Final Observations === You have now, hopefully, succeeded in executing the experiment script in this tutorial. Try to run this experiment again but with more client nodes or using nodes in different locations to see those effects on performance.