def verify_traffic_between_dut_and_ap(self, iperf_server_on_ap, iperf_client_on_dut, ip_version=IPV4): """Runs IPerf traffic from the iperf client (dut) and the iperf server (and vice versa) and verifies traffic was able to pass successfully. Args: iperf_server_on_ap: IPerfServer object, linked to AP iperf_client_on_dut: IPerfClient object, linked to DUT ip_version: string, the ip version (ipv4 or ipv6) Raises: ValueError, if invalid ip_version is passed. ConnectionError, if traffic is not passed successfully in both directions. """ dut_ip_addresses = self.dut.get_interface_ip_addresses( iperf_client_on_dut.test_interface) iperf_server_ip_address = self.get_iperf_server_address( iperf_server_on_ap, ip_version) self.log.info( 'Attempting to pass traffic from DUT to IPerf server (%s).' % iperf_server_ip_address) tx_file = iperf_client_on_dut.start(iperf_server_ip_address, '-i 1 -t 3 -J', 'reboot_tx') tx_results = iperf_server.IPerfResult(tx_file) if not tx_results.avg_receive_rate or tx_results.avg_receive_rate == 0: raise ConnectionError( 'Failed to pass IPerf traffic from DUT to server (%s). TX ' 'Average Receive Rate: %s' % (iperf_server_ip_address, tx_results.avg_receive_rate)) else: self.log.info( 'Success: Traffic passed from DUT to IPerf server (%s).' % iperf_server_ip_address) self.log.info( 'Attempting to pass traffic from IPerf server (%s) to DUT.' % iperf_server_ip_address) rx_file = iperf_client_on_dut.start(iperf_server_ip_address, '-i 1 -t 3 -R -J', 'reboot_rx') rx_results = iperf_server.IPerfResult(rx_file) if not rx_results.avg_receive_rate or rx_results.avg_receive_rate == 0: raise ConnectionError( 'Failed to pass IPerf traffic from server (%s) to DUT. RX ' 'Average Receive Rate: %s' % (iperf_server_ip_address, rx_results.avg_receive_rate)) else: self.log.info( 'Success: Traffic passed from IPerf server (%s) to DUT.' % iperf_server_ip_address)
def run_iperf_traffic(self, ip_client, server_address, server_port=5201): """Runs traffic between client and ap an verifies throughput. Args: ip_client: iperf client to use server_address: ipv4 address of the iperf server to use server_port: port of the iperf server Raises: TestFailure, if no traffic passes in either direction """ ip_client_identifier = self.get_iperf_client_identifier(ip_client) self.log.info( 'Running traffic from iperf client %s to iperf server %s.' % (ip_client_identifier, server_address)) client_to_ap_path = ip_client.start( server_address, '-i 1 -t 10 -J -p %s' % server_port, 'client_to_soft_ap') self.log.info( 'Running traffic from iperf server %s to iperf client %s.' % (server_address, ip_client_identifier)) ap_to_client_path = ip_client.start( server_address, '-i 1 -t 10 -R -J -p %s' % server_port, 'soft_ap_to_client') self.log.info('Getting iperf results') client_to_ap_result = iperf_server.IPerfResult(client_to_ap_path) ap_to_client_result = iperf_server.IPerfResult(ap_to_client_path) if (not client_to_ap_result.avg_receive_rate): asserts.fail( 'Failed to pass traffic from iperf client %s to iperf server %s.' % (ip_client_identifier, server_address)) self.log.info( 'Passed traffic from iperf client %s to iperf server %s with avg ' 'rate of %s MB/s.' % (ip_client_identifier, server_address, client_to_ap_result.avg_receive_rate)) if (not ap_to_client_result.avg_receive_rate): asserts.fail( 'Failed to pass traffic from iperf server %s to iperf client %s.' % (server_address, ip_client_identifier)) self.log.info( 'Passed traffic from iperf server %s to iperf client %s with avg ' 'rate of %s MB/s.' % (server_address, ip_client_identifier, ap_to_client_result.avg_receive_rate))
def process_iperf_results(self): """Get the iperf results and process. Returns: throughput: the average throughput during tests. """ # Get IPERF results and add this to the plot title RESULTS_DESTINATION = os.path.join( self.iperf_server.log_path, 'iperf_client_output_{}.log'.format(self.current_test_name)) PULL_FILE = '{} {}'.format(TEMP_FILE, RESULTS_DESTINATION) self.dut.adb.pull(PULL_FILE) # Calculate the average throughput if self.use_client_output: iperf_file = RESULTS_DESTINATION else: iperf_file = self.iperf_server.log_files[-1] try: iperf_result = ipf.IPerfResult(iperf_file) throughput = (math.fsum(iperf_result.instantaneous_rates[:-1]) / len(iperf_result.instantaneous_rates[:-1])) * 8 self.log.info('The average throughput is {}'.format(throughput)) except ValueError: self.log.warning('Cannot get iperf result. Setting to 0') throughput = 0 return throughput
def get_iperf_result(self): """Pulls the iperf json output from device. Returns: An IPerfResult object based on the iperf run output. """ dest = os.path.join(self.iperf_server.log_path, "iperf.txt") self.dut.adb.pull(pmc_iperf_json_file, " ", dest) result = ip_server.IPerfResult(dest) self.dut.adb.shell("rm %s" % pmc_iperf_json_file) return result
def run_throughput_stability_test(self, testcase_params): """Main function to test throughput stability. The function sets up the AP in the correct channel and mode configuration and runs an iperf test to measure throughput. Args: testcase_params: dict containing test specific parameters Returns: test_result: dict containing test result and meta data """ # Run test and log result # Start iperf session self.log.info('Starting iperf test.') llstats_obj = wputils.LinkLayerStats(self.dut) llstats_obj.update_stats() self.iperf_server.start(tag=str(testcase_params['atten_level'])) current_rssi = wputils.get_connected_rssi_nb( dut=self.dut, num_measurements=self.testclass_params['iperf_duration'] - 1, polling_frequency=1, first_measurement_delay=1, disconnect_warning=1, ignore_samples=1) client_output_path = self.iperf_client.start( testcase_params['iperf_server_address'], testcase_params['iperf_args'], str(testcase_params['atten_level']), self.testclass_params['iperf_duration'] + TEST_TIMEOUT) current_rssi = current_rssi.result() server_output_path = self.iperf_server.stop() # Set attenuator to 0 dB for attenuator in self.attenuators: attenuator.set_atten(0) # Parse and log result if testcase_params['use_client_output']: iperf_file = client_output_path else: iperf_file = server_output_path try: iperf_result = ipf.IPerfResult(iperf_file) except: asserts.fail('Cannot get iperf result.') llstats_obj.update_stats() curr_llstats = llstats_obj.llstats_incremental.copy() test_result = collections.OrderedDict() test_result['testcase_params'] = testcase_params.copy() test_result['ap_settings'] = self.access_point.ap_settings.copy() test_result['attenuation'] = testcase_params['atten_level'] test_result['iperf_result'] = iperf_result test_result['rssi_result'] = current_rssi test_result['llstats'] = curr_llstats self.testclass_results.append(test_result) return test_result
def run_iperf_server(self, network): """Run iperf RX throughput after connection. Args: params: Dictionary with network info. Returns: rvr_result: Dict containing rvr_results """ rvr_result = [] self.iperf_server.start(tag="RX_client_{}_angle{}_{}dB".format( self.ssid, self.angle[self.ag], self.DB)) wait_time = 5 SSID = network[WifiEnums.SSID_KEY] self.log.info("Starting iperf traffic RX through {}".format(SSID)) time.sleep(wait_time) port_arg = "-p {} -J -R {}".format( self.iperf_server.port, self.rvr_test_params["iperf_port_arg"]) success, data = self.dut.run_iperf_client( self.rvr_test_params["iperf_server_address"], port_arg, timeout=self.rvr_test_params["iperf_duration"] + self.TEST_TIMEOUT) # Parse and log result client_output_path = os.path.join( self.iperf_server.log_path, "IperfDUT,{},RX_server_{}_angle{}_{}dB".format( self.iperf_server.port, self.ssid, self.angle[self.ag], self.DB)) with open(client_output_path, 'w') as out_file: out_file.write("\n".join(data)) self.iperf_server.stop() iperf_file = client_output_path try: iperf_result = ipf.IPerfResult(iperf_file) curr_throughput = (math.fsum(iperf_result.instantaneous_rates[ self.rvr_test_params["iperf_ignored_interval"]:-1]) / len( iperf_result.instantaneous_rates[ self.rvr_test_params["iperf_ignored_interval"]:-1]) ) * 8 * (1.024**2) except: self.log.warning( "ValueError: Cannot get iperf result. Setting to 0") curr_throughput = 0 rvr_result.append(curr_throughput) self.log.info("RX Throughput at {0:.2f} dB is {1:.2f} Mbps".format( self.DB, curr_throughput)) self.log.debug(pprint.pformat(data)) asserts.assert_true(success, "Error occurred in iPerf traffic.") return rvr_result
def process_iperf_results(self, dut, log, iperf_servers, test_name): """Gets the iperf results from the phone and computes the average rate Returns: throughput: the average throughput (Mbit/s). """ # Stopping the server (as safety to get the result file) iperf_servers[self.server_idx].stop() time.sleep(1) # Get IPERF results and add this to the plot title RESULTS_DESTINATION = os.path.join( iperf_servers[self.server_idx].log_path, 'iperf_client_output_{}.log'.format(test_name)) PULL_FILE = '{} {}'.format(self.results_filename_phone, RESULTS_DESTINATION) dut.adb.pull(PULL_FILE) # Calculate the average throughput if self.use_client_output: iperf_file = RESULTS_DESTINATION else: iperf_file = iperf_servers[self.server_idx].log_files[-1] try: iperf_result = ipf.IPerfResult(iperf_file) # Get instantaneous rates after measuring starts samples = iperf_result.instantaneous_rates[self.start_meas_time:-1] # Convert values to Mbit/s samples = [rate * 8 * (1.024**2) for rate in samples] # compute mean, var and max_dev mean = statistics.mean(samples) var = statistics.variance(samples) max_dev = 0 for rate in samples: if abs(rate - mean) > max_dev: max_dev = abs(rate - mean) log.info('The average throughput is {}. Variance is {} and max ' 'deviation is {}.'.format( round(mean, 2), round(var, 2), round(max_dev, 2))) except: log.warning('Cannot get iperf result.') mean = 0 return mean
def run_iperf_server(self, network): """Run iperf RX throughput after connection. Args: params: Dictionary with network info. Returns: iot_result: dict containing iot_results """ if "iperf_server_address" in self.user_params: # Add iot_result iot_result = [] self.iperf_server.start( tag="RX_client_{}".format(self.current_test_name)) wait_time = 5 SSID = network[WifiEnums.SSID_KEY] self.log.info("Starting iperf traffic RX through {}".format(SSID)) time.sleep(wait_time) port_arg = "-p {} -J -R {}".format(self.iperf_server.port, self.iperf_port_arg) success, data = self.dut.run_iperf_client( self.iperf_server_address, port_arg) client_output_path = os.path.join( self.iperf_server.log_path, "IperfDUT,{},RX_server_{}".format(self.iperf_server.port, self.current_test_name)) with open(client_output_path, 'w') as out_file: out_file.write("\n".join(data)) self.iperf_server.stop() iperf_file = client_output_path try: iperf_result = ipf.IPerfResult(iperf_file) curr_throughput = math.fsum(iperf_result.instantaneous_rates) except: self.log.warning( "ValueError: Cannot get iperf result. Setting to 0") curr_throughput = 0 iot_result.append(curr_throughput) self.log.info("Throughput is {0:.2f} Mbps".format(curr_throughput)) self.log.debug(pprint.pformat(data)) asserts.assert_true(success, "Error occurred in iPerf traffic.") return iot_result
def run_iperf_test(self, testcase_params): """Main function for iperf roaming tests. Args: testcase_params: dict including all test params encoded in test name Returns: result: dict containing all test results and meta data """ self.log.info('Starting iperf test.') self.iperf_server.start(extra_args='-i {}'.format(IPERF_INTERVAL)) self.dut_ip = self.dut.droid.connectivityGetIPv4Addresses('wlan0')[0] if isinstance(self.iperf_server, ipf.IPerfServerOverAdb): iperf_server_address = self.dut_ip else: iperf_server_address = wputils.get_server_address( self.remote_server, self.dut_ip, '255.255.255.0') iperf_args = '-i {} -t {} -J'.format( IPERF_INTERVAL, testcase_params['atten_waveforms']['length']) if not isinstance(self.iperf_server, ipf.IPerfServerOverAdb): iperf_args = iperf_args + ' -R' iperf_future = wputils.start_iperf_client_nb( self.iperf_client, iperf_server_address, iperf_args, 0, testcase_params['atten_waveforms']['length'] + MED_SLEEP) rssi_future = wputils.get_connected_rssi_nb( self.dut, int(testcase_params['atten_waveforms']['length'] / testcase_params['rssi_polling_frequency']), testcase_params['rssi_polling_frequency']) self.run_attenuation_waveform(testcase_params) client_output_path = iperf_future.result() server_output_path = self.iperf_server.stop() if isinstance(self.iperf_server, ipf.IPerfServerOverAdb): iperf_file = server_output_path else: iperf_file = client_output_path iperf_result = ipf.IPerfResult(iperf_file) instantaneous_rates = [ rate * 8 * (1.024**2) for rate in iperf_result.instantaneous_rates ] return { 'throughput': instantaneous_rates, 'rssi_result': rssi_future.result(), 'ap_settings': self.access_point.ap_settings, }
def measure_throughput_and_power(self, direction): # Start iperf locally self.log.info("Starting iperf server.") self.iperf_server.start() self.log.info("Starting iperf client on the phone.") iperf_args = '-i 1 -t %d' % self.iperf_duration if direction == DIRECTION_DOWNLINK: iperf_args = iperf_args + ' -R' iperf_args = iperf_args + ' > /dev/null' wputils.run_iperf_client_nonblocking(self.ad, self.ip, iperf_args) # Collect power data self.log.info("Starting sampling with monsoon.") file_path, current = wputils.monsoon_data_collect_save( self.ad, self.mon_info, self.current_test_name, bug_report=0) # Collect iperf data # Give some time for iperf to finish time.sleep(self.iperf_offset) self.iperf_server.stop() throughput = 0 try: iperf_result = ipf.IPerfResult(self.iperf_server.log_files[-1]) if direction == DIRECTION_DOWNLINK: if iperf_result.avg_send_rate is not None: throughput = iperf_result.avg_send_rate * 8 elif direction == DIRECTION_UPLINK: if iperf_result.avg_receive_rate is not None: throughput = iperf_result.avg_receive_rate * 8 except: pass self.log.info("Average receive rate: %sMbps", throughput) return [throughput, current]
def get_iperf_results(iperf_server_obj): """Get the iperf results and process. Args: iperf_server_obj: the IperfServer object Returns: throughput: the average throughput during tests. """ # Get IPERF results and add this to the plot title iperf_file = iperf_server_obj.log_files[-1] try: iperf_result = ipf.IPerfResult(iperf_file) # Compute the throughput in Mbit/s if iperf_result.error == IPERF_CLIENT_ERROR: rates = [] for item in iperf_result.result['intervals']: rates.append(item['sum']['bits_per_second'] / 8 / 1024 / 1024) throughput = ((math.fsum(rates) / len(rates))) * 8 * (1.024**2) else: throughput = (math.fsum(iperf_result.instantaneous_rates) / len( iperf_result.instantaneous_rates)) * 8 * (1.024**2) except (ValueError, TypeError): throughput = 0 return throughput
def run_rvr_test(self, testcase_params): """Test function to run RvR. The function runs an RvR test in the current device/AP configuration. Function is called from another wrapper function that sets up the testbed for the RvR test Args: testcase_params: dict containing test-specific parameters Returns: rvr_result: dict containing rvr_results and meta data """ self.log.info('Start running RvR') # Refresh link layer stats before test llstats_obj = wputils.LinkLayerStats(self.dut) zero_counter = 0 throughput = [] llstats = [] rssi = [] for atten in testcase_params['atten_range']: for dev in self.android_devices: if not wputils.health_check(dev, 5, 50): asserts.skip('DUT health check failed. Skipping test.') # Set Attenuation for attenuator in self.attenuators: attenuator.set_atten(atten, strict=False) # Refresh link layer stats llstats_obj.update_stats() # Setup sniffer if self.testbed_params['sniffer_enable']: self.sniffer.start_capture( network=testcase_params['test_network'], chan=int(testcase_params['channel']), bw=int(testcase_params['mode'][3:]), duration=self.testclass_params['iperf_duration'] / 5) # Start iperf session self.iperf_server.start(tag=str(atten)) rssi_future = wputils.get_connected_rssi_nb( self.dut, self.testclass_params['iperf_duration'] - 1, 1, 1) client_output_path = self.iperf_client.start( testcase_params['iperf_server_address'], testcase_params['iperf_args'], str(atten), self.testclass_params['iperf_duration'] + self.TEST_TIMEOUT) server_output_path = self.iperf_server.stop() rssi_result = rssi_future.result() current_rssi = { 'signal_poll_rssi': rssi_result['signal_poll_rssi']['mean'], 'chain_0_rssi': rssi_result['chain_0_rssi']['mean'], 'chain_1_rssi': rssi_result['chain_1_rssi']['mean'] } rssi.append(current_rssi) # Stop sniffer if self.testbed_params['sniffer_enable']: self.sniffer.stop_capture(tag=str(atten)) # Parse and log result if testcase_params['use_client_output']: iperf_file = client_output_path else: iperf_file = server_output_path try: iperf_result = ipf.IPerfResult(iperf_file) curr_throughput = numpy.mean(iperf_result.instantaneous_rates[ self.testclass_params['iperf_ignored_interval']:-1] ) * 8 * (1.024**2) except: self.log.warning( 'ValueError: Cannot get iperf result. Setting to 0') curr_throughput = 0 throughput.append(curr_throughput) llstats_obj.update_stats() curr_llstats = llstats_obj.llstats_incremental.copy() llstats.append(curr_llstats) self.log.info( ('Throughput at {0:.2f} dB is {1:.2f} Mbps. ' 'RSSI = {2:.2f} [{3:.2f}, {4:.2f}].').format( atten, curr_throughput, current_rssi['signal_poll_rssi'], current_rssi['chain_0_rssi'], current_rssi['chain_1_rssi'])) if curr_throughput == 0 and ( current_rssi['signal_poll_rssi'] < -80 or numpy.isnan(current_rssi['signal_poll_rssi'])): zero_counter = zero_counter + 1 else: zero_counter = 0 if zero_counter == self.MAX_CONSECUTIVE_ZEROS: self.log.info( 'Throughput stable at 0 Mbps. Stopping test now.') throughput.extend( [0] * (len(testcase_params['atten_range']) - len(throughput))) break for attenuator in self.attenuators: attenuator.set_atten(0, strict=False) # Compile test result and meta data rvr_result = collections.OrderedDict() rvr_result['test_name'] = self.current_test_name rvr_result['testcase_params'] = testcase_params.copy() rvr_result['ap_settings'] = self.access_point.ap_settings.copy() rvr_result['fixed_attenuation'] = self.testbed_params[ 'fixed_attenuation'][str(testcase_params['channel'])] rvr_result['attenuation'] = list(testcase_params['atten_range']) rvr_result['total_attenuation'] = [ att + rvr_result['fixed_attenuation'] for att in rvr_result['attenuation'] ] rvr_result['rssi'] = rssi rvr_result['throughput_receive'] = throughput rvr_result['llstats'] = llstats return rvr_result
def throughput_stability_test_func(self, channel, mode): """Main function to test throughput stability. The function sets up the AP in the correct channel and mode configuration and runs an iperf test to measure throughput. Args: channel: Specifies AP's channel mode: Specifies AP's bandwidth/mode (11g, VHT20, VHT40, VHT80) Returns: test_result: dict containing test result and meta data """ #Initialize RvR test parameters test_result = {} # Configure AP band = self.access_point.band_lookup_by_channel(channel) self.access_point.set_channel(band, channel) self.access_point.set_bandwidth(band, mode) self.log.info("Access Point Configuration: {}".format( self.access_point.ap_settings)) # Set attenuator to test level self.log.info("Setting attenuation to {} dB".format(self.atten_level)) [ self.attenuators[i].set_atten(self.atten_level) for i in range(self.num_atten) ] # Connect DUT to Network self.main_network[band]["channel"] = channel wutils.reset_wifi(self.dut) wutils.wifi_connect(self.dut, self.main_network[band], num_of_tries=5) time.sleep(5) # Run test and log result # Start iperf session self.log.info("Starting iperf test.") self.iperf_server.start(tag=str(self.atten_level)) try: client_output = "" client_status, client_output = self.dut.run_iperf_client( self.testbed_params["iperf_server_address"], self.iperf_args, timeout=self.test_params["iperf_duration"] + TEST_TIMEOUT) except: self.log.warning("TimeoutError: Iperf measurement timed out.") client_output_path = os.path.join( self.iperf_server.log_path, "iperf_client_output_{}".format(self.current_test_name)) with open(client_output_path, 'w') as out_file: out_file.write("\n".join(client_output)) self.iperf_server.stop() # Set attenuator to 0 dB [self.attenuators[i].set_atten(0) for i in range(self.num_atten)] # Parse and log result if self.use_client_output: iperf_file = client_output_path else: iperf_file = self.iperf_server.log_files[-1] try: iperf_result = ipf.IPerfResult(iperf_file) except: self.log.warning("ValueError: Cannot get iperf result.") iperf_result = None test_result["ap_settings"] = self.access_point.ap_settings.copy() test_result["attenuation"] = self.atten_level test_result["iperf_result"] = iperf_result return test_result
def _run_traffic(self, uuid, client, server_ip, server_port, active_streams, stream_results, access_category=None, bandwidth=None, stream_time=DEFAULT_STREAM_TIME, start_time=None): """Runs an iperf3 stream. 1. Adds stream UUID to active_streams 2. Runs stream 3. Saves results to stream_results 4. Removes stream UUID from active_streams Args: uuid: UUID object, identifier for stream client: IPerfClient object on device server_ip: string, ip address of IPerfServer for stream server_port: int, port of the IPerfServer for stream active_streams: multiprocessing.Manager.dict, which holds stream UUIDs of active streams on the device stream_results: multiprocessing.Manager.dict, which maps stream UUIDs of streams to IPerfResult objects access_category: string, WMM access category to use with iperf (AC_BK, AC_BE, AC_VI, AC_VO). Unset if None. bandwidth: int, bandwidth in mbps to use with iperf. Implies UDP. Unlimited if None. stream_time: int, time in seconds, to run iperf stream start_time: float, time, seconds since epoch, at which to start the stream (for better synchronicity). If None, start immediately. """ active_streams[uuid] = True # SSH sessions must be started within the process that is going to # use it. if type(client) == iperf_client.IPerfClientOverSsh: with utils.SuppressLogOutput(): client.start_ssh() ac_flag = '' bandwidth_flag = '' time_flag = '-t %s' % stream_time if access_category: ac_flag = ' -S %s' % DEFAULT_AC_TO_TOS_TAG_MAP[access_category] if bandwidth: bandwidth_flag = ' -u -b %sM' % bandwidth iperf_flags = '-p %s -i 1 %s%s%s -J' % (server_port, time_flag, ac_flag, bandwidth_flag) if not start_time: start_time = time.time() time_str = datetime.fromtimestamp(start_time).strftime('%H:%M:%S.%f') self.log.info( 'At %s, starting %s second stream to %s:%s with (AC: %s, Bandwidth: %s)' % (time_str, stream_time, server_ip, server_port, access_category, bandwidth if bandwidth else 'Unlimited')) # If present, wait for stream start time if start_time: current_time = time.time() while current_time < start_time: current_time = time.time() path = client.start(server_ip, iperf_flags, '%s' % uuid) stream_results[uuid] = iperf_server.IPerfResult( path, reporting_speed_units='mbps') if type(client) == iperf_client.IPerfClientOverSsh: client.close_ssh() active_streams.pop(uuid)