Beispiel #1
0
    def check_bitrates_in_capture(self, pcap_result):
        """
        Check that bitrates look like we expect in a packet capture.

        The DUT should not send packets at high bitrates until after DHCP
        negotiation is complete.  If this is detected, fail the test.

        @param pcap_result: RemoteCaptureResult tuple.

        """
        logging.info('Analyzing packet capture...')
        dut_src_display_filter = ('wlan.sa==%s' %
                               self.context.client.wifi_mac)
        # Some chips use self-addressed frames to tune channel
        # performance. They don't carry host-generated traffic, so
        # filter them out.
        dut_dst_display_filter = ('wlan.da==%s' %
                               self.context.client.wifi_mac)
        # Get all the frames in chronological order.
        frames = tcpdump_analyzer.get_frames(
                pcap_result.local_pcap_path,
                ('%s and not %s' % (
                    dut_src_display_filter, dut_dst_display_filter)),
                bad_fcs='include')
        # Get just the DHCP related packets.
        dhcp_frames = tcpdump_analyzer.get_frames(
                pcap_result.local_pcap_path,
                '%s and bootp' % dut_src_display_filter,
                bad_fcs='include')
        if not dhcp_frames:
            raise error.TestFail('Packet capture did not contain a DHCP '
                                 'negotiation!')

        for frame in frames:
            if frame.time_datetime > dhcp_frames[-1].time_datetime:
                # We're past the last DHCP packet, so higher bitrates are
                # permissable and expected.
                break

            if frame.mcs_index is not None:
                if frame.mcs_index > 1:
                    # wpa_supplicant should ask that all but the 2 lowest rates
                    # be disabled.
                    raise error.TestFail(
                        'Frame at %s was sent with MCS index %d.' %
                        (frame.time_string, frame.mcs_index))

            elif frame.bit_rate >= 12:
                raise error.TestFail(
                    'Frame at %s was sent at %f Mbps.' %
                    (frame.time_string, frame.bit_rate))
    def stop_capture_and_check_for_probe_requests(self, mac):
        """
        Stop packet capture and check that no probe requests launched by the DUT
        with MAC address |mac| are found in the packet capture.  Fails test if
        any probe request frames are found.

        @param mac: MAC address of the DUT.
        """
        logging.info('Stopping packet capture')
        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))

        logging.info('Analyzing packet capture...')
        probe_req_pcap_filter = '%s and wlan.sa==%s' % (
            tcpdump_analyzer.WLAN_PROBE_REQ_ACCEPTOR, mac)
        # Get all the frames in chronological order.
        frames = tcpdump_analyzer.get_frames(results[0].local_pcap_path,
                                             probe_req_pcap_filter,
                                             reject_bad_fcs=False)
        if len(frames) > 0:
            raise error.TestFail('Packet capture contained probe requests!')

        logging.info('Packet capture contained no probe requests')
    def assert_hostname_and_vendorclass_are_present(self, pcap_result):
        """
        Confirm DHCP Request contains HostName and VendorClass properties.

        @param pcap_result: RemoteCaptureResult tuple.

        """

        logging.info('Analyzing packet capture...')
        dhcp_filter = ('(bootp.option.dhcp == 3) '
                       'and (bootp.option.vendor_class_id == %s) '
                       'and (bootp.option.hostname == %s)' %
                       (self.VENDORCLASS_VALUE, self.HOSTNAME_VALUE))
        dhcp_frames = tcpdump_analyzer.get_frames(pcap_result.local_pcap_path,
                                                  dhcp_filter,
                                                  reject_bad_fcs=False)
        if not dhcp_frames:
            raise error.TestFail('Packet capture did not contain a DHCP '
                                 'negotiation!')
Beispiel #4
0
    def stop_capture_and_get_probe_requests(self):
        """
        Stop packet capture and return probe requests from the DUT.
        have the hardware MAC address.
        """
        logging.debug('Stopping packet capture')
        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))

        logging.debug('Analyzing packet capture...')
        # Get all the frames in chronological order.
        frames = tcpdump_analyzer.get_frames(
            results[0].local_pcap_path,
            tcpdump_analyzer.WLAN_PROBE_REQ_ACCEPTOR,
            bad_fcs='discard')

        return [frame for frame in frames if self._frame_matches_ssid(frame)]
    def check_bitrates_in_capture(self, pcap_result, max_mcs_index):
        """
        Check that frames in a packet capture have expected MCS indices.

        @param pcap_result: RemoteCaptureResult tuple.
        @param max_mcs_index: int MCS index representing the highest possible
                bitrate on this device.

        """
        logging.info('Analyzing packet capture...')
        display_filter = 'udp and ip.src==%s' % self.context.client.wifi_ip
        frames = tcpdump_analyzer.get_frames(
                pcap_result.local_pcap_path,
                display_filter,
                bad_fcs='include')

        logging.info('Grouping frames by MCS index')
        counts = {}
        for frame in frames:
            counts[frame.mcs_index] = counts.get(frame.mcs_index, 0) + 1
        logging.info('Saw WiFi frames with MCS indices: %r', counts)

        # Now figure out the index which the device sent the most packets with.
        dominant_index = None
        num_packets_sent = -1
        for index, num_packets in counts.iteritems():
            if num_packets > num_packets_sent:
                dominant_index = index
                num_packets_sent = num_packets

        # We should see that the device sent more frames with the maximal index
        # than anything else.  This checks that the rate controller is fairly
        # aggressive and using all of the device's capabilities.
        if dominant_index != max_mcs_index:
            raise error.TestFail('Failed to use best possible MCS '
                                 'index %d in a clean RF environment: %r' %
                                 (max_mcs_index, counts))
    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!')
    def _channel_dwell_time_test(self, single_channel):
        """Perform test to determine channel dwell time.

        This function invoke FrameSender to continuously send beacon frames
        for specific number of BSSs with specific delay, the SSIDs of the
        BSS are in hex numerical order. And at the same time, perform wifi scan
        on the DUT. The index in the SSIDs of the scan result will be used to
        interpret the relative start time and end time of the channel scan.

        @param single_channel: bool perform single channel scan if true.

        @return int dwell time in ms.

        """
        dwell_time = 0
        channel = hostap_config.HostapConfig.get_channel_for_frequency(
            self.FREQUENCY_MHZ)
        self.context.router.start_capture(self.FREQUENCY_MHZ)
        ssid_prefix = self._build_ssid_prefix()

        with frame_sender.FrameSender(self.context.router,
                                      'beacon',
                                      channel,
                                      ssid_prefix=ssid_prefix,
                                      num_bss=self.NUM_BSS,
                                      frame_count=0,
                                      delay=self.DELAY_INTERVAL_MILLISECONDS):
            if single_channel:
                frequencies = [self.FREQUENCY_MHZ]
            else:
                frequencies = []
            # Perform scan
            start_time = time.time()
            while time.time() - start_time < self.SCAN_RETRY_TIMEOUT_SECONDS:
                bss_list = self.context.client.iw_runner.scan(
                    self.context.client.wifi_if, frequencies=frequencies)

                if bss_list is not None:
                    break

                time.sleep(0.5)
            else:
                raise error.TestFail('Unable to trigger scan on client.')
            if not bss_list:
                raise error.TestFail('Failed to find any BSS')

            # Remaining work is done outside the FrameSender
            # context. This is to ensure that no additional frames are
            # transmitted while we're waiting for the packet capture
            # to complete.

        pcap_path = self.context.router.stop_capture()[0].local_pcap_path

        # Filter scan result based on ssid prefix to remove any cached
        # BSSs from previous run.
        result_list = [
            bss.ssid for bss in bss_list if bss.ssid.startswith(ssid_prefix)
        ]
        if result_list is None:
            raise error.TestFail('Failed to find any BSS for this test')

        beacon_frames = tcpdump_analyzer.get_frames(
            pcap_path,
            tcpdump_analyzer.WLAN_BEACON_ACCEPTOR,
            bad_fcs='include')
        # Filter beacon frames based on ssid prefix.
        result_beacon_frames = [
            beacon_frame for beacon_frame in beacon_frames
            if beacon_frame.ssid.startswith(ssid_prefix)
        ]
        if result_beacon_frames is None:
            raise error.TestFail('Failed to find any beacons for this test')
        return self._get_dwell_time(result_list, result_beacon_frames)