Esempio n. 1
0
 def run_once(self):
     """Test body."""
     wpa_config = xmlrpc_security_types.WPAConfig(
             psk='chromeos',
             wpa_mode=xmlrpc_security_types.WPAConfig.MODE_MIXED_WPA,
             wpa_ciphers=[xmlrpc_security_types.WPAConfig.CIPHER_TKIP,
                          xmlrpc_security_types.WPAConfig.CIPHER_CCMP],
             wpa2_ciphers=[xmlrpc_security_types.WPAConfig.CIPHER_CCMP],
             wpa_ptk_rekey_period=self.REKEY_PERIOD)
     ap_config = hostap_config.HostapConfig(
                 frequency=2412,
                 mode=hostap_config.HostapConfig.MODE_11N_PURE,
                 security_config=wpa_config)
     # TODO(wiley) This is just until we find the source of these
     #             test failures.
     self.context.router.start_capture(ap_config.frequency)
     self.context.configure(ap_config)
     assoc_params = xmlrpc_datatypes.AssociationParameters(
             ssid=self.context.router.get_ssid(),
             security_config=wpa_config)
     self.context.assert_connect_wifi(assoc_params)
     ping_config = ping_runner.PingConfig(self.context.get_wifi_addr(),
                                          count=self.PING_COUNT,
                                          interval=self.PING_INTERVAL)
     logging.info('Pinging DUT for %d seconds and rekeying '
                  'every %d seconds.',
                  self.PING_COUNT * self.PING_INTERVAL,
                  self.REKEY_PERIOD)
     self.context.assert_ping_from_dut(ping_config=ping_config)
     self.context.client.shill.disconnect(assoc_params.ssid)
     self.context.router.deconfig()
Esempio n. 2
0
    def run_once(self):
        """Test body.

        When fragthreshold is set, packets larger than the threshold are
        broken up by the AP and sent in fragments. The DUT needs to reassemble
        these fragments to reconstruct the original packets before processing
        them.

        """
        configuration = hostap_config.HostapConfig(
            frequency=2437,
            mode=hostap_config.HostapConfig.MODE_11G,
            frag_threshold=256)
        self.context.configure(configuration)
        self.context.router.start_capture(configuration.frequency)
        assoc_params = xmlrpc_datatypes.AssociationParameters()
        assoc_params.ssid = self.context.router.get_ssid()
        self.context.assert_connect_wifi(assoc_params)
        build_config = lambda size: ping_runner.PingConfig(
            self.context.client.wifi_ip, size=size)
        self.context.assert_ping_from_server(ping_config=build_config(256))
        self.context.assert_ping_from_server(ping_config=build_config(512))
        self.context.assert_ping_from_server(ping_config=build_config(1024))
        self.context.assert_ping_from_server(ping_config=build_config(1500))
        self.context.client.shill.disconnect(assoc_params.ssid)
        self.context.router.deconfig()
 def is_up_fast(self):
     """Return True if the host can be pinged."""
     ping_config = ping_runner.PingConfig(self.hostname,
                                          count=3,
                                          ignore_result=True,
                                          ignore_status=True)
     return ping_runner.PingRunner().ping(ping_config).received > 0
Esempio n. 4
0
    def run(self, client):
        """
        Create a NetperfRunner, run netperf between DUT and work_client.

        @param client: WiFiClient object representing the DUT

        """
        with netperf_runner.NetperfRunner(
                client, self.work_client, self._config) as netperf:
            ping_config = ping_runner.PingConfig(
                    self.work_client.wifi_ip, count=10)
            # pinging work client to ensure we have a connection
            logging.info('work client ip: %s', self.work_client.wifi_ip)
            ping_result = client.ping(ping_config)

            result = netperf.run(self._config)
            logging.info('Netperf Result: %s', result)

        if result is None:
            raise error.TestError('Failed to create NetperfResult')

        if result.duration_seconds < self._config.test_time:
            raise error.TestFail(
                    'Netperf duration too short: %0.2f < %0.2f' %
                    (result.duration_seconds, self._config.test_time))

        # TODO: Convert this limit to a perf metric crbug.com/348780
        if result.throughput <self.NETPERF_MIN_THROUGHPUT:
            raise error.TestFail(
                    'Netperf throughput too low: %0.2f < %0.2f' %
                    (result.throughput, self.NETPERF_MIN_THROUGHPUT))
Esempio n. 5
0
    def run_once(self):
        """Body of the test."""

        get_assoc_params = lambda conf: xmlrpc_datatypes.AssociationParameters(
            ssid=self.context.router.get_ssid(instance=0), bgscan_config=conf)
        get_ping_config = lambda period: ping_runner.PingConfig(
            self.context.get_wifi_addr(),
            interval=self.PING_INTERVAL_SECONDS,
            count=int(period / self.PING_INTERVAL_SECONDS))
        self.context.configure(self._config_first_ap)
        bgscan_config = xmlrpc_datatypes.BgscanConfiguration(
            short_interval=self.CONFIGURED_BGSCAN_INTERVAL_SECONDS,
            long_interval=self.CONFIGURED_BGSCAN_INTERVAL_SECONDS,
            method=xmlrpc_datatypes.BgscanConfiguration.SCAN_METHOD_SIMPLE)
        self.context.assert_connect_wifi(get_assoc_params(bgscan_config))
        logging.info('Pinging router with background scans for %d seconds.',
                     self.BGSCAN_SAMPLE_PERIOD_SECONDS)
        result_bgscan = self.context.client.ping(
            get_ping_config(self.BGSCAN_SAMPLE_PERIOD_SECONDS))
        logging.info('Ping statistics with bgscan: %r', result_bgscan)
        # Bring up a second AP, make sure that it shows up in bgscans.
        self._config_second_ap.ssid = self.context.router.get_ssid()
        self.context.configure(self._config_second_ap, multi_interface=True)
        logging.info('Without a ping running, ensure that bgscans succeed.')
        ap_mac = self.context.router.get_hostapd_mac(ap_num=1)
        logging.debug('Looking for BSS %s', ap_mac)
        iw = iw_runner.IwRunner(remote_host=self.context.client.host)

        utils.poll_for_condition(
            condition=lambda: self._find_bss_matching_mac_addr(iw, ap_mac),
            exception=error.TestFail(
                'Background scans should detect new BSSes '
                'within an associated ESS.'),
            timeout=self.BGSCAN_SAMPLE_PERIOD_SECONDS,
            sleep_interval=1)

        self.context.router.deconfig_aps(instance=1)
        self.context.client.shill.disconnect(
            self.context.router.get_ssid(instance=0))
        # Reconfigure AP, so the new bgscan setting can be correctly applied.
        self.context.configure(self._config_first_ap)
        # Gather some statistics about ping latencies without scanning going on.
        self.context.assert_connect_wifi(get_assoc_params(None))
        logging.info('Pinging router without background scans for %d seconds.',
                     self.NO_BGSCAN_SAMPLE_PERIOD_SECONDS)
        result_no_bgscan = self.context.client.ping(
            get_ping_config(self.NO_BGSCAN_SAMPLE_PERIOD_SECONDS))
        logging.info('Ping statistics without bgscan: %r', result_no_bgscan)
        if result_no_bgscan.max_latency > self.THRESHOLD_BASELINE_LATENCY_MS:
            raise error.TestFail('RTT latency is too high even without '
                                 'background scans: %f' %
                                 result_no_bgscan.max_latency)

        if (result_bgscan.max_latency >
                self.LATENCY_MARGIN_MS + result_no_bgscan.avg_latency):
            raise error.TestFail(
                'Significant difference in rtt due to bgscan: '
                '%.1f > %.1f + %d' %
                (result_bgscan.max_latency, result_no_bgscan.avg_latency,
                 self.LATENCY_MARGIN_MS))
Esempio n. 6
0
    def run_once(self):
        """Test body.

        When fragthreshold is set, packets larger than the threshold are
        broken up by the AP and sent in fragments. The DUT needs to reassemble
        these fragments to reconstruct the original packets before processing
        them.

        """

        # Whirlwind routers don't support fragmentation, and older builds
        # (up to 7849.0.2016_01_20_2103) don't know that they don't, so check
        # here using board name.
        if self.context.router.board == "whirlwind":
            raise error.TestNAError(
                'Whirlwind AP does not support frag threshold')

        configuration = hostap_config.HostapConfig(
            frequency=2437,
            mode=hostap_config.HostapConfig.MODE_11G,
            frag_threshold=256)
        self.context.configure(configuration)
        self.context.capture_host.start_capture(configuration.frequency)
        assoc_params = xmlrpc_datatypes.AssociationParameters()
        assoc_params.ssid = self.context.router.get_ssid()
        self.context.assert_connect_wifi(assoc_params)
        build_config = lambda size: ping_runner.PingConfig(
            self.context.client.wifi_ip, size=size)
        self.context.assert_ping_from_server(ping_config=build_config(256))
        self.context.assert_ping_from_server(ping_config=build_config(512))
        self.context.assert_ping_from_server(ping_config=build_config(1024))
        self.context.assert_ping_from_server(ping_config=build_config(1500))
        self.context.client.shill.disconnect(assoc_params.ssid)
        self.context.router.deconfig()
        self.context.capture_host.stop_capture()
Esempio n. 7
0
    def test_one(self, session, config, ap_config_tag, bt_tag):
        """Run one iteration of wifi testing.

        @param session NetperfSession session
        @param config NetperfConfig config
        @param ap_config_tag string for AP configuration
        @param bt_tag string for BT operation

        """
        get_ping_config = lambda period: ping_runner.PingConfig(
            self.context.get_wifi_addr(), interval=1, count=period)

        logging.info('testing config %s, ap_config %s, BT:%s', config.tag,
                     ap_config_tag, bt_tag)
        test_str = '_'.join([ap_config_tag, bt_tag])
        time.sleep(1)

        # Record the signal level.
        signal_level = self.context.client.wifi_signal_level
        signal_description = '_'.join(['signal', test_str])
        self.write_perf_keyval({signal_description: signal_level})

        # Run netperf and log the results.
        results = session.run(config)
        if not results:
            logging.error('Failed to take measurement for %s', config.tag)
            return
        values = [result.throughput for result in results]
        self.output_perf_value(config.tag + '_' + bt_tag,
                               values,
                               units='Mbps',
                               higher_is_better=True,
                               graph=ap_config_tag)
        result = netperf_runner.NetperfResult.from_samples(results)
        self.write_perf_keyval(
            result.get_keyval(prefix='_'.join([config.tag, test_str])))

        # Log the drop in throughput compared with the 'BT_disconnected'
        # baseline.  Only positive values are valid.  Report the drop as a
        # whole integer percentage of (base_through-through)/base_through.
        if bt_tag == 'BT_disconnected':
            self.base_through = result.throughput
        elif self.base_through > 0:
            drop = int((self.base_through - result.throughput) * 100 /
                       self.base_through)
            self.output_perf_value(config.tag + '_' + bt_tag + '_drop',
                                   drop,
                                   units='percent_drop',
                                   higher_is_better=False,
                                   graph=ap_config_tag + '_drop')
            self.write_perf_keyval(
                {'_'.join([config.tag, test_str, 'drop']): drop})
            logging.info('logging drop value as %d%%', drop)

        # Test latency with ping.
        result_ping = self.context.client.ping(get_ping_config(3))
        self.write_perf_keyval(
            {'_'.join(['ping', test_str]): result_ping.avg_latency})
        logging.info('Ping statistics with %s: %r', bt_tag, result_ping)
Esempio n. 8
0
    def run_once(self):
        """Body of the test."""
        get_assoc_params = lambda: xmlrpc_datatypes.AssociationParameters(
            ssid=self.context.router.get_ssid())
        get_ping_config = lambda period: ping_runner.PingConfig(
            self.context.get_wifi_addr(),
            interval=self.PING_INTERVAL_SECONDS,
            count=int(period / self.PING_INTERVAL_SECONDS))
        # Gather some statistics about ping latencies without scanning going on.
        self.context.configure(self.get_ap_config('obss_disabled', False))
        self.context.assert_connect_wifi(get_assoc_params())
        logging.info('Pinging router without OBSS scans for %d seconds.',
                     self.NO_OBSS_SCAN_SAMPLE_PERIOD_SECONDS)
        result_no_obss_scan = self.context.client.ping(
            get_ping_config(self.NO_OBSS_SCAN_SAMPLE_PERIOD_SECONDS))
        logging.info('Ping statistics without OBSS scans: %r',
                     result_no_obss_scan)
        if result_no_obss_scan.max_latency > self.THRESHOLD_BASELINE_LATENCY_MS:
            raise error.TestFail('RTT latency is too high even without '
                                 'OBSS scans: %f' %
                                 result_no_obss_scan.max_latency)

        self.context.client.shill.disconnect(self.context.router.get_ssid())

        # Re-configure the AP for OBSS and repeat the ping test.
        self.context.configure(self.get_ap_config('obss_enabled', True))
        self.context.router.start_capture(self.WIFI_FREQUENCY,
                                          filename='obss_enabled.pcap')

        self.context.assert_connect_wifi(get_assoc_params())
        logging.info('Pinging router with OBSS scans for %d seconds.',
                     self.OBSS_SCAN_SAMPLE_PERIOD_SECONDS)
        result_obss_scan = self.context.client.ping(
            get_ping_config(self.OBSS_SCAN_SAMPLE_PERIOD_SECONDS))
        logging.info('Ping statistics with OBSS scans: %r', result_obss_scan)
        self.context.router.stop_capture()

        if not self.context.router.detect_client_coexistence_report(
                self.context.client.wifi_mac):
            raise error.TestFail('No coexistence action frames detected '
                                 'from the client.')

        self.context.client.shill.disconnect(self.context.router.get_ssid())
        self.context.router.deconfig()
        # Dwell time for scanning is usually configured to be around 100 ms,
        # since this is also the standard beacon interval.  Tolerate spikes in
        # latency up to 200 ms as a way of asking that our PHY be servicing
        # foreground traffic regularly during background scans.
        if (result_obss_scan.max_latency >
                self.LATENCY_MARGIN_MS + result_no_obss_scan.avg_latency):
            raise error.TestFail(
                'Significant difference in rtt due to OBSS: '
                '%.1f > %.1f + %d' %
                (result_obss_scan.max_latency, result_no_obss_scan.avg_latency,
                 self.LATENCY_MARGIN_MS))
Esempio n. 9
0
    def run_once(self):
        """Sets up a router, connects to it, then tests a channel switch."""
        for router_conf, alternate_channel in self._configurations:
            self.context.router.require_capabilities([
                site_linux_system.LinuxSystem.CAPABILITY_SEND_MANAGEMENT_FRAME
            ])
            self.context.configure(router_conf)
            self.context.capture_host.start_capture(router_conf.frequency,
                                                    filename='chan%d.pcap' %
                                                    router_conf.channel)
            assoc_params = xmlrpc_datatypes.AssociationParameters()
            assoc_params.ssid = self.context.router.get_ssid()
            self.context.assert_connect_wifi(assoc_params)
            ping_config = ping_runner.PingConfig(
                self.context.get_wifi_addr(ap_num=0))
            client_mac = self.context.client.wifi_mac
            for _ in range(10):
                # Since the client might be in power-save, we are not
                # guaranteed it will hear this message the first time around.
                self.context.router.send_management_frame_on_ap(
                    'channel_switch', alternate_channel)

                # Test to see if the router received a deauth message from
                # the client.
                if self.context.router.detect_client_deauth(client_mac):
                    break

                # Otherwise detect the client leaving indirectly by measuring
                # client pings.  This should fail at some point.
                ping_config = ping_runner.PingConfig(
                    self.context.get_wifi_addr(ap_num=0),
                    count=3,
                    ignore_status=True,
                    ignore_result=True)
                result = self.context.client.ping(ping_config)
                if result.loss > 60:
                    break
            else:
                raise error.TestFail('Client never lost connectivity')
            self.context.client.shill.disconnect(assoc_params.ssid)
            self.context.router.deconfig()
            self.context.capture_host.stop_capture()
    def wait_for_connection(self, ssid, timeout_seconds=30, freq=None,
                            ping_ip=None, desired_subnet=None):
        """Verifies a connection to network ssid, optionally verifying
        frequency, ping connectivity and subnet.

        @param ssid string ssid of the network to check.
        @param timeout_seconds int number of seconds to wait for
                connection on the given frequency.
        @param freq int frequency of network to check.
        @param ping_ip string ip address to ping for verification.
        @param desired_subnet string expected subnet in which client
                ip address should reside.

        @returns a named tuple of (state, time)
        """
        POLLING_INTERVAL_SECONDS = 1.0
        start_time = time.time()
        duration = lambda: time.time() - start_time
        success = False
        while duration() < timeout_seconds:
            success, state, conn_time  = self.wait_for_service_states(
                    ssid, self.CONNECTED_STATES,
                    int(math.ceil(timeout_seconds - duration())))
            if not success:
                time.sleep(POLLING_INTERVAL_SECONDS)
                continue

            if freq:
                actual_freq = self.get_iw_link_value(
                        iw_runner.IW_LINK_KEY_FREQUENCY)
                if str(freq) != actual_freq:
                    logging.debug('Waiting for desired frequency %s (got %s).',
                                  freq, actual_freq)
                    time.sleep(POLLING_INTERVAL_SECONDS)
                    continue

            if desired_subnet:
                actual_subnet = self.wifi_ip_subnet
                if actual_subnet != desired_subnet:
                    logging.debug('Waiting for desired subnet %s (got %s).',
                                  desired_subnet, actual_subnet)
                    time.sleep(POLLING_INTERVAL_SECONDS)
                    continue

            if ping_ip:
                ping_config = ping_runner.PingConfig(ping_ip)
                self.ping(ping_config)

            return ConnectTime(state, conn_time)

        freq_error_str = (' on frequency %d Mhz' % freq) if freq else ''
        raise error.TestFail(
                'Failed to connect to "%s"%s in %f seconds (state=%s)' %
                (ssid, freq_error_str, duration(), state))
Esempio n. 11
0
 def run_once(self):
     """Body of the test."""
     configuration = hostap_config.HostapConfig(
         frequency=2437,
         mode=hostap_config.HostapConfig.MODE_11G,
         force_wmm=True)
     self.context.configure(configuration)
     assoc_params = xmlrpc_datatypes.AssociationParameters()
     assoc_params.ssid = self.context.router.get_ssid()
     self.context.assert_connect_wifi(assoc_params)
     for qos in ('BE', 'BK', 'VI', 'VO'):
         client_ping_config = ping_runner.PingConfig(
             self.context.get_wifi_addr(), qos=qos)
         server_ping_config = ping_runner.PingConfig(
             self.context.client.wifi_ip, qos=qos)
         self.context.assert_ping_from_dut(ping_config=client_ping_config)
         self.context.assert_ping_from_server(
             ping_config=server_ping_config)
     self.context.client.shill.disconnect(assoc_params.ssid)
     self.context.router.deconfig()
Esempio n. 12
0
    def run(self, client):
        """Periodically pings work client to check liveliness of the connection

        @param client: WiFiClient object representing the DUT

        """
        ping_config = ping_runner.PingConfig(self.work_client.wifi_ip, count=10)
        logging.info('Pinging work client ip: %s', self.work_client.wifi_ip)
        start_time = time.time()
        while time.time() - start_time < self.duration_sec:
            time.sleep(10)
            ping_result = client.ping(ping_config)
            logging.info('Connection liveness %r', ping_result)
Esempio n. 13
0
 def check_pdu_status(self):
     """Check if the PDU is up before making any request."""
     ping_options = ping_runner.PingConfig(self.pdu,
                                           count=2,
                                           ignore_status=True,
                                           ignore_result=True)
     runner = ping_runner.PingRunner()
     logging.info('Pinging rpm %s', self.pdu)
     ping_result = runner.ping(ping_options)
     logging.info('ping result = %s', str(ping_result))
     # If all ping packets failed then mark PDU down.
     if ping_result.loss == 100:
         self.configuration_success = ap_constants.PDU_FAIL
         raise PduNotResponding(self.pdu)
Esempio n. 14
0
    def assert_ping_from_server(self, ping_config=None):
        """Ping the DUT across the WiFi network from the server.

        Check that the ping is mostly successful and fail the test if it
        is not.

        @param ping_config optional PingConfig object to override defaults.

        """
        logging.info('Pinging from server.')
        if ping_config is None:
            ping_ip = self.client.wifi_ip
            ping_config = ping_runner.PingConfig(ping_ip)
        self.router.ping(ping_config)
def servo_host_is_up(servo_hostname):
    """Given a servo host name, return if it's up or not.

    @param servo_hostname: hostname of the servo host.

    @return True if it's up, False otherwise
    """
    # Technically, this duplicates the SSH ping done early in the servo
    # proxy initialization code.  However, this ping ends in a couple
    # seconds when if fails, rather than the 60 seconds it takes to decide
    # that an SSH ping has timed out.  Specifically, that timeout happens
    # when our servo DNS name resolves, but there is no host at that IP.
    logging.info('Pinging servo host at %s', servo_hostname)
    ping_config = ping_runner.PingConfig(servo_hostname,
                                         count=3,
                                         ignore_result=True,
                                         ignore_status=True)
    return ping_runner.PingRunner().ping(ping_config).received > 0
Esempio n. 16
0
    def get_signal_to_noise(self, frequency):
        """Gets both the signal and the noise on the current connection.

        @param frequency: noise needs to be read for a frequency.
        @returns: signal and noise in dBm

        """
        ping_ip = self.context.get_wifi_addr(ap_num=0)
        ping_config = ping_runner.PingConfig(target_ip=ping_ip, count=1,
                                             ignore_status=True,
                                             ignore_result=True)
        self.context.client.ping(ping_config)  # Just to provide traffic.
        signal_dbm = self.context.client.wifi_signal_level
        noise_dbm = self.context.client.wifi_noise_level(frequency)
        print '. signal: %r, noise: %r' % (signal_dbm, noise_dbm)
        if noise_dbm is None:
            return None
        return signal_dbm - noise_dbm
Esempio n. 17
0
    def assert_ping_from_dut(self, ping_config=None, ap_num=None):
        """Ping a host on the WiFi network from the DUT.

        Ping a host reachable on the WiFi network from the DUT, and
        check that the ping is successful.  The host we ping depends
        on the test setup, sometimes that host may be the server and
        sometimes it will be the router itself.  Ping-ability may be
        used to confirm that a WiFi network is operating correctly.

        @param ping_config optional PingConfig object to override defaults.
        @param ap_num int which AP to ping if more than one is configured.

        """
        if ap_num is None:
            ap_num = 0
        if ping_config is None:
            ping_ip = self.router.get_wifi_ip(ap_num=ap_num)
            ping_config = ping_runner.PingConfig(ping_ip)
        self.client.ping(ping_config)
Esempio n. 18
0
    def run(self, client):
        """
        Check the liveliness of the connection to the AP by pinging the work
        client before and after a suspend resume.

        @param client: WiFiClient object representing the DUT

        """
        ping_config = ping_runner.PingConfig(self.work_client.wifi_ip, count=10)
        # pinging work client to ensure we have a connection
        logging.info('work client ip: %s', self.work_client.wifi_ip)
        ping_result = client.ping(ping_config)
        logging.info('before suspend:%r', ping_result)
        client.do_suspend(self._suspend_sec)
        # When going to suspend, DUTs using ath9k devices do not disassociate
        # from the AP. On resume, DUTs would re-use the association from prior
        # to suspend. However, this leads to some confused state for some APs
        # (see crbug.com/346417) where the AP responds to actions frames like
        # NullFunc but not to any data frames like DHCP/ARP packets from the
        # DUT.  Let us sleep for:
        #       + 2 seconds for linkmonitor to detect failure if any
        #       + 10 seconds for ReconnectTimer timeout
        #       + 5 seconds to reconnect to the AP
        #       + 3 seconds let us not have a very strict timeline.
        # 20 seconds before we start to query shill about the connection state.
        # TODO (krisr): add board detection code in wifi_client and adjust the
        # sleep time here based on the wireless chipset
        time.sleep(20)

        # Wait for WAIT_FOR_CONNECTION time before trying to ping.
        success, state, elapsed_time = client.wait_for_service_states(
                self.ssid, ('ready', 'portal', 'online'), WAIT_FOR_CONNECTION)
        if not success:
            raise error.TestFail('DUT failed to connect to AP (%s state) after'
                                 'resume in %d seconds' %
                                 (state, WAIT_FOR_CONNECTION))
        else:
            logging.info('DUT entered %s state after %s seconds',
                         state, elapsed_time)
            # ping work client to ensure we have connection after resume.
            ping_result = client.ping(ping_config)
            logging.info('after resume:%r', ping_result)
 def run_once(self):
     """Test body."""
     wpa_config = xmlrpc_security_types.WPAConfig(
         psk='chromeos',
         wpa_mode=xmlrpc_security_types.WPAConfig.MODE_MIXED_WPA,
         wpa_ciphers=[
             xmlrpc_security_types.WPAConfig.CIPHER_TKIP,
             xmlrpc_security_types.WPAConfig.CIPHER_CCMP
         ],
         wpa2_ciphers=[xmlrpc_security_types.WPAConfig.CIPHER_CCMP],
         wpa_ptk_rekey_period=self.REKEY_PERIOD)
     ap_config = hostap_config.HostapConfig(
         frequency=2412,
         mode=hostap_config.HostapConfig.MODE_11N_PURE,
         security_config=wpa_config)
     # TODO(wiley) This is just until we find the source of these
     #             test failures.
     self.context.capture_host.start_capture(ap_config.frequency)
     self.context.configure(ap_config)
     assoc_params = xmlrpc_datatypes.AssociationParameters(
         ssid=self.context.router.get_ssid(), security_config=wpa_config)
     self.context.assert_connect_wifi(assoc_params)
     ping_config = ping_runner.PingConfig(self.context.get_wifi_addr(),
                                          count=self.PING_COUNT,
                                          interval=self.PING_INTERVAL,
                                          ignore_result=True)
     logging.info(
         'Pinging DUT for %d seconds and rekeying '
         'every %d seconds.', self.PING_COUNT * self.PING_INTERVAL,
         self.REKEY_PERIOD)
     ping_result = self.context.client.ping(ping_config=ping_config)
     logging.info('Ping loss percentage: %d.', ping_result.loss)
     self.output_perf_value(description='Network_wifi_PTK_PingLoss',
                            value=ping_result.loss,
                            units='percent',
                            higher_is_better=False)
     if ping_result.loss > self.PING_LOSS_THRESHOLD:
         raise error.TestNAError('Lost ping packets %r percentage.' %
                                 ping_result.loss)
     self.context.client.shill.disconnect(assoc_params.ssid)
     self.context.router.deconfig()
     self.context.capture_host.stop_capture()
Esempio n. 20
0
    def test_one(self, session, config, ap_config_tag, bt_tag):
        """Run one iteration of wifi testing.

        @param session NetperfSession session
        @param config NetperfConfig config
        @param ap_config_tag string for AP configuration
        @param bt_tag string for BT operation

        """
        get_ping_config = lambda period: ping_runner.PingConfig(
            self.context.get_wifi_addr(), interval=1, count=period)

        logging.info('testing config %s, ap_config %s, BT:%s', config.tag,
                     ap_config_tag, bt_tag)
        test_str = '_'.join([ap_config_tag, bt_tag])
        time.sleep(1)

        signal_level = self.context.client.wifi_signal_level
        signal_description = '_'.join(['signal', test_str])
        self.write_perf_keyval({signal_description: signal_level})

        results = session.run(config)
        if not results:
            logging.error('Failed to take measurement for %s', config.tag)
            return
        values = [result.throughput for result in results]
        self.output_perf_value(config.tag + ' ' + bt_tag,
                               values,
                               units='Mbps',
                               higher_is_better=True,
                               graph=ap_config_tag)
        result = netperf_runner.NetperfResult.from_samples(results)
        self.write_perf_keyval(
            result.get_keyval(prefix='_'.join([config.tag, test_str])))

        # Test latency with ping.
        result_ping = self.context.client.ping(get_ping_config(3))
        self.write_perf_keyval(
            {'_'.join(['ping', test_str]): result_ping.avg_latency})
        logging.info('Ping statistics with %s: %r', bt_tag, result_ping)
Esempio n. 21
0
    def ping_and_check_for_tdls(self, frequency, expected):
        """
        Use an over-the-air packet capture to check whether we see
        ICMP packets from the DUT that indicate it is using a TDLS
        link to transmit its requests.  Raise an exception if this
        was not what was |expected|.

        @param frequency: int frequency on which to perform the packet capture.
        @param expected: bool set to true if we expect the sender to use TDLS.

        """
        self.context.capture_host.start_capture(frequency)

        # Since we don't wait for the TDLS link to come up, it's possible
        # that we'll have some fairly drastic packet loss as the link is
        # being established.  We don't care about that in this test, except
        # that we should see at least a few packets by the end of the ping
        # we can use to test for TDLS.  Therefore we ignore the statistical
        # result of the ping.
        ping_config = ping_runner.PingConfig(
            self.context.router.local_peer_ip_address(0), ignore_result=True)
        self.context.assert_ping_from_dut(ping_config=ping_config)

        results = self.context.capture_host.stop_capture()
        if len(results) != 1:
            raise error.TestError('Expected to generate one packet '
                                  'capture but got %d captures instead.' %
                                  len(results))
        pcap_result = results[0]

        logging.info('Analyzing packet capture...')

        # Filter for packets from the DUT.
        client_mac_filter = 'wlan.sa==%s' % self.context.client.wifi_mac

        # In this test we only care that the outgoing ICMP requests are
        # sent over IBSS, so we filter for ICMP echo requests explicitly.
        icmp_filter = 'icmp.type==0x08'

        # This filter requires a little explaining. DS status is the second byte
        # of the frame control field. This field contains the "tods" and
        # "fromds" bits in bit 0 and 1 respsectively. These bits have the
        # following interpretation:
        #
        #   ToDS  FromDS
        #     0     0      Ad-Hoc (IBSS)
        #     0     1      Traffic from client to the AP
        #     1     0      Traffic from AP to the client
        #     1     1      4-address mode for wireless distribution system
        #
        # TDLS co-opts the ToDS=0, FromDS=0 (IBSS) mode when transferring
        # data directly between peers. Therefore, to detect TDLS, we compare it
        # with 0.
        tdls_filter = 'wlan.fc.ds==0x00'

        dut_icmp_display_filter = ' and '.join(
            [client_mac_filter, icmp_filter, tdls_filter])
        frames = tcpdump_analyzer.get_frames(pcap_result.local_pcap_path,
                                             dut_icmp_display_filter,
                                             bad_fcs='include')
        if expected and not frames:
            raise error.TestFail('Packet capture did not contain any IBSS '
                                 'frames from the DUT!')
        elif not expected and frames:
            raise error.TestFail('Packet capture contains an IBSS frame '
                                 'from the DUT, but we did not expect them!')
Esempio n. 22
0
    def run_once(self):
        """Body of the test."""
        get_assoc_params = lambda conf: xmlrpc_datatypes.AssociationParameters(
            ssid=self.context.router.get_ssid(instance=0), bgscan_config=conf)
        get_ping_config = lambda period: ping_runner.PingConfig(
            self.context.get_wifi_addr(),
            interval=self.PING_INTERVAL_SECONDS,
            count=int(period / self.PING_INTERVAL_SECONDS))
        self.context.configure(hostap_config.HostapConfig(channel=1))
        bgscan_config = xmlrpc_datatypes.BgscanConfiguration(
            short_interval=self.CONFIGURED_BGSCAN_INTERVAL_SECONDS,
            long_interval=self.CONFIGURED_BGSCAN_INTERVAL_SECONDS,
            method=xmlrpc_datatypes.BgscanConfiguration.SCAN_METHOD_SIMPLE)
        self.context.assert_connect_wifi(get_assoc_params(bgscan_config))
        logging.info('Pinging router with background scans for %d seconds.',
                     self.BGSCAN_SAMPLE_PERIOD_SECONDS)
        result_bgscan = self.context.client.ping(
            get_ping_config(self.BGSCAN_SAMPLE_PERIOD_SECONDS))
        logging.info('Ping statistics with bgscan: %r', result_bgscan)
        # Bring up a second AP, make sure that it shows up in bgscans.
        self.context.configure(hostap_config.HostapConfig(
            channel=11, min_streams=1, ssid=self.context.router.get_ssid()),
                               multi_interface=True)
        logging.info('Without a ping running, ensure that bgscans succeed.')
        ap_mac = self.context.router.get_hostapd_mac(ap_num=1)
        logging.debug('Looking for BSS %s', ap_mac)
        iw = iw_runner.IwRunner(remote_host=self.context.client.host)
        start_time = time.time()
        while time.time() - start_time < self.BGSCAN_SAMPLE_PERIOD_SECONDS:
            bsses = iw.scan_dump(self.context.client.wifi_if)
            logging.debug('Found BSSes: %r', bsses)
            if filter(lambda bss: bss.bss == ap_mac, bsses):
                break

            time.sleep(1)
        else:
            raise error.TestFail('Background scans should detect new BSSes '
                                 'within an associated ESS.')

        self.context.router.deconfig_aps(instance=1)
        self.context.client.shill.disconnect(
            self.context.router.get_ssid(instance=0))
        # Reconfigure AP, so the new bgscan setting can be correctly applied.
        self.context.configure(hostap_config.HostapConfig(channel=1))
        # Gather some statistics about ping latencies without scanning going on.
        self.context.assert_connect_wifi(get_assoc_params(None))
        logging.info('Pinging router without background scans for %d seconds.',
                     self.NO_BGSCAN_SAMPLE_PERIOD_SECONDS)
        result_no_bgscan = self.context.client.ping(
            get_ping_config(self.NO_BGSCAN_SAMPLE_PERIOD_SECONDS))
        logging.info('Ping statistics without bgscan: %r', result_no_bgscan)
        if result_no_bgscan.max_latency > self.THRESHOLD_BASELINE_LATENCY_MS:
            raise error.TestFail('RTT latency is too high even without '
                                 'background scans: %f' %
                                 result_no_bgscan.max_latency)

        # Dwell time for scanning is usually configured to be around 100 ms,
        # since this is also the standard beacon interval.  Tolerate spikes in
        # latency up to 200 ms as a way of asking that our PHY be servicing
        # foreground traffic regularly during background scans.
        if (result_bgscan.max_latency >
                self.LATENCY_MARGIN_MS + result_no_bgscan.avg_latency):
            raise error.TestFail(
                'Significant difference in rtt due to bgscan: '
                '%.1f > %.1f + %d' %
                (result_bgscan.max_latency, result_no_bgscan.avg_latency,
                 self.LATENCY_MARGIN_MS))
Esempio n. 23
0
    def run_once(self, host):
        helper = privet_helper.PrivetHelper(host=host)
        logging.info('Looking for privet bootstrapping network from DUT.')
        scan_interface = self._router.get_wlanif(2437, 'managed')
        self._router.host.run('%s link set %s up' %
                              (self._router.cmd_ip, scan_interface))
        start_time = time.time()
        privet_bss = None
        while time.time() - start_time < PRIVET_AP_STARTUP_TIMEOUT_SECONDS:
            bss_list = self._router.iw_runner.scan(scan_interface)
            for bss in bss_list or []:
                if helper.is_softap_ssid(bss.ssid):
                    privet_bss = bss
        if privet_bss is None:
            raise error.TestFail('Device did not start soft AP in time.')
        self._router.release_interface(scan_interface)

        # Get the netblock of the interface running the AP.
        dut_iw_runner = iw_runner.IwRunner(remote_host=host)
        devs = dut_iw_runner.list_interfaces(desired_if_type='AP')
        if not devs:
            raise error.TestFail('No AP devices on DUT?')
        ap_interface = interface.Interface(devs[0].if_name, host=host)
        ap_netblock = netblock.from_addr(ap_interface.ipv4_address_and_prefix)

        # Set up an AP on the router in the 5Ghz range with WPA2 security.
        wpa_config = xmlrpc_security_types.WPAConfig(
                psk=PASSPHRASE,
                wpa_mode=xmlrpc_security_types.WPAConfig.MODE_PURE_WPA2,
                wpa2_ciphers=[xmlrpc_security_types.WPAConfig.CIPHER_CCMP])
        router_conf = hostap_config.HostapConfig(
                frequency=5240, security_config=wpa_config,
                mode=hostap_config.HostapConfig.MODE_11N_PURE)
        self._router.hostap_configure(router_conf)

        # Connect the other interface on the router to the AP on the client
        # at a hardcoded IP address.
        self._router.configure_managed_station(
                privet_bss.ssid, privet_bss.frequency,
                ap_netblock.get_addr_in_block(200))
        station_interface = self._router.get_station_interface(instance=0)
        logging.debug('Set up station on %s', station_interface)
        self._router.ping(ping_runner.PingConfig(ap_netblock.addr, count=3))

        logging.info('Looking for privet webserver in mDNS records.')
        start_time = time.time()
        while time.time() - start_time < PRIVET_MDNS_RECORD_TIMEOUT_SECONDS:
            all_records = avahi_utils.avahi_browse(host=self._router.host)
            records = [record for record in all_records
                       if (record.interface == station_interface and
                           record.record_type == '_privet._tcp')]
            if records:
                break
            time.sleep(POLLING_PERIOD)
        if not records:
            raise error.TestFail('Did not find privet mDNS records in time.')
        if len(records) > 1:
            raise error.TestFail('Should not see multiple privet records.')
        privet_record = records[0]
        # TODO(wiley) pull the HTTPs port number out of the /info API.
        helper = privet_helper.PrivetdHelper(
                host=self._router.host,
                hostname=privet_record.address,
                http_port=int(privet_record.port))
        helper.ping_server()

        # Now configure the client with WiFi credentials.
        auth_token = helper.privet_auth()
        ssid = self._router.get_ssid()
        data = helper.setup_add_wifi_credentials(ssid, PASSPHRASE)
        helper.setup_start(data, auth_token)

        logging.info('Waiting for DUT to connect to router network.')
        start_time = time.time()
        # Wait for the DUT to take down the AP.
        while time.time() - start_time < PRIVET_CONNECT_TIMEOUT_SECONDS:
            if not dut_iw_runner.list_interfaces(desired_if_type='AP'):
                break
            time.sleep(POLLING_PERIOD)
        else:
            raise error.TestFail('Timeout waiting for DUT to take down AP.')

        # But we should be able to ping the client from the router's AP.
        while time.time() - start_time < PRIVET_CONNECT_TIMEOUT_SECONDS:
            if dut_iw_runner.list_interfaces(desired_if_type='managed'):
                break
            time.sleep(POLLING_PERIOD)
        else:
            raise error.TestFail('Timeout waiting for DUT managerd interface.')

        while time.time() - start_time < PRIVET_CONNECT_TIMEOUT_SECONDS:
            devs = dut_iw_runner.list_interfaces(desired_if_type='managed')
            if devs:
                managed_interface = interface.Interface(devs[0].if_name,
                                                        host=host)
                # Check if we have an IP yet.
                if managed_interface.ipv4_address_and_prefix:
                    break
            time.sleep(POLLING_PERIOD)
        else:
            raise error.TestFail('Timeout waiting for DUT managerd interface.')

        managed_netblock = netblock.from_addr(
                managed_interface.ipv4_address_and_prefix)
        while time.time() - start_time < PRIVET_CONNECT_TIMEOUT_SECONDS:
            PING_COUNT = 3
            result = self._router.ping(
                    ping_runner.PingConfig(managed_netblock.addr,
                                           ignore_result=True,
                                           count=PING_COUNT))
            if result.received == PING_COUNT:
                break
            time.sleep(POLLING_PERIOD)
        else:
            raise error.TestFail('Timeout before ping was successful.')

        # And buffet should think it is online as well.
        helper = privet_helper.PrivetdHelper(
                host=host, hostname=managed_netblock.addr,
                http_port=int(privet_record.port))
        helper.ping_server()
        if not helper.wifi_setup_was_successful(ssid, auth_token):
            raise error.TestFail('Device claims to be offline, but is online.')