# Copyright 2019 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import logging

from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros.network import tcpdump_analyzer
from autotest_lib.client.common_lib.cros.network import xmlrpc_datatypes
from autotest_lib.server.cros.network import wifi_cell_test_base


class network_WiFi_APSupportedRates(wifi_cell_test_base.WiFiCellTestBase):
    """Test that the WiFi chip honors the SupportedRates IEs sent by the AP."""
    version = 1

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

        The DUT should not send packets at bitrates that were disabled by the
        AP.

        @param pcap_result: RemoteCaptureResult tuple.
        @param supported_rates: List of upported legacy bitrates (Mbps).

        """
        # Filter notes:
        # (a) Some chips use self-addressed frames to tune channel performance.
        #     They don't carry host-generated traffic, so filter them out.
        # (b) Use TA (not SA), because multicast may retransmit our
        #     "Source-Addressed" frames at rates we don't control.
        # (c) BSSID filter: non-BSSID frames include Ack and BlockAck frames;
        #     these rates tend to match the frames to which they're responding
        #     (i.e., not under DUT's control).
        # (d) QoS null filter: these frames are short (no data payload), and
        #     it's more important that they be reliable (e.g., for PS
        #     transitions) than fast. See b/132825853#comment40,
        #     for example.
        # Items (b) and (c) wouldn't be much problem if our APs actually
        # respected the Supported Rates IEs that we're configuring, but current
        # (2019-06-28) test AP builds do not appear to.
        frame_filter = ('wlan.ta==%s and (not wlan.da==%s) and wlan.bssid==%s'
                        ' and wlan.fc.type_subtype!=%s' %
                        (self.context.client.wifi_mac,
                         self.context.client.wifi_mac,
                         self.context.router.get_hostapd_mac(0),
                         tcpdump_analyzer.WLAN_QOS_NULL_TYPE))
        frames = tcpdump_analyzer.get_frames(pcap_result.local_pcap_path,
                                             frame_filter, reject_bad_fcs=False)
        if not frames:
            raise error.TestError('Failed to capture any relevant frames')

        # Some frames don't have bitrate fields -- for example, if they are
        # using MCS rates (not legacy rates). For MCS rates, that's OK, since
        # that satisfies this test requirement (not using "unsupported legacy
        # rates"). So ignore them.
        bad_frames = [f for f in frames
                      if f.bit_rate is not None and
                         f.bit_rate not in supported_rates]
        if bad_frames:
            # Remove duplicates.
            bad_rates = list(set(f.bit_rate for f in bad_frames))
            logging.error('Unexpected rate for frames:')
            for f in bad_frames:
                logging.error('%s', f)
            raise error.TestFail('Saw frames at rates %r (expected %r).' %
                                 (bad_rates, supported_rates))

    def parse_additional_arguments(self, commandline_args, additional_params):
        """Hook into super class to take control files parameters.

        @param commandline_args dict of parsed parameters from the autotest.
        @param additional_params HostapConfig object.

        """
        self._ap_config = additional_params

    def run_once(self):
        """Verify that we respond sanely to APs that disable legacy bitrates.
        """
        # See b/138406224. ath10k only supports this on CrOS kernels >=4.14.
        if self.context.client.host.get_board().split(':')[1] == 'scarlet':
            raise error.TestNAError('Scarlet does not support this feature on '
                                    'kernel 4.4')

        ap_config = self._ap_config

        # TODO(b/160281713): remove this if we cherry-pick the bitrate fixes
        # and deploy an OS update.
        if (ap_config.frequency < 5000 and
            self.context.capture_host.board == 'whirlwind'):
            raise error.TestNAError('Whirlwind does not capture 802.11g/OFDM '
                                    'rates correctly (b/160281713)')

        self.context.configure(ap_config)
        self.context.capture_host.start_capture(
                ap_config.frequency,
                width_type=ap_config.packet_capture_mode)
        assoc_params = xmlrpc_datatypes.AssociationParameters(
                ssid=self.context.router.get_ssid())
        self.context.assert_connect_wifi(assoc_params)
        self.context.assert_ping_from_dut()
        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))
        self.check_bitrates_in_capture(results[0],
                                       ap_config.supported_rates)
