• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2017 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import logging
6import time
7
8from autotest_lib.client.common_lib import error
9from autotest_lib.client.common_lib.cros.network import tcpdump_analyzer
10from autotest_lib.server.cros.network import hostap_config
11from autotest_lib.server.cros.network import wifi_cell_test_base
12
13class RandomMACAddressTestBase(wifi_cell_test_base.WiFiCellTestBase):
14    """An abstract base class for MAC address randomization tests in WiFi cells.
15
16       MAC address randomization tests will test the ability of the DUT to
17       successfully randomize the MAC address it sends in probe requests when
18       such a feature is supported and configured, and that it does not do so
19       otherwise.
20    """
21
22    # Approximate number of seconds to perform a full scan.
23    REQUEST_SCAN_DELAY = 5
24
25    # Default number of shill scans to run.
26    DEFAULT_NUM_SCANS = 5
27
28    def initialize(self, host):
29        """Generate the HostapConfig used by the AP."""
30        self._ap_config = hostap_config.HostapConfig(channel=1)
31
32
33    def warmup(self, host, raw_cmdline_args, additional_params=None):
34        super(RandomMACAddressTestBase, self).warmup(
35                host, raw_cmdline_args, additional_params)
36
37        self.context.configure(self._ap_config)
38
39
40    def start_capture(self):
41        """
42        Start packet capture.
43        """
44        logging.debug('Starting packet capture')
45        self.context.capture_host.start_capture(
46                self._ap_config.frequency,
47                width_type=self._ap_config.packet_capture_mode)
48
49
50    def request_scans(self, num_scans=DEFAULT_NUM_SCANS):
51        """
52        Helper to request a few scans with the configured randomization.
53
54        @param num_scans: The number of scans to perform.
55        """
56        for _ in range(num_scans):
57            # Request scan through shill rather than iw because iw won't
58            # set the random MAC flag in the scan request netlink packet.
59            self.context.client.shill.request_scan()
60            time.sleep(self.REQUEST_SCAN_DELAY)
61
62
63    def _frame_matches_ssid(self, frame):
64        # Empty string is a wildcard SSID.
65        return frame.ssid == '' or frame.ssid == self.context.router.get_ssid()
66
67
68    def stop_capture_and_get_probe_requests(self):
69        """
70        Stop packet capture and return probe requests from the DUT.
71        have the hardware MAC address.
72        """
73        logging.debug('Stopping packet capture')
74        results = self.context.capture_host.stop_capture()
75        if len(results) != 1:
76            raise error.TestError('Expected to generate one packet '
77                                  'capture but got %d captures instead.',
78                                  len(results))
79
80        logging.debug('Analyzing packet capture...')
81        # Get all the frames in chronological order.
82        frames = tcpdump_analyzer.get_frames(
83                results[0].local_pcap_path,
84                tcpdump_analyzer.WLAN_PROBE_REQ_ACCEPTOR, reject_bad_fcs=True,
85                reject_low_signal=True)
86
87        return [frame for frame in frames if self._frame_matches_ssid(frame)]
88