# Copyright (c) 2013 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
import time

from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import utils
from autotest_lib.client.common_lib.cros.network import interface
from autotest_lib.client.common_lib.cros.network import xmlrpc_datatypes
from autotest_lib.server.cros.network import expected_performance_results
from autotest_lib.server.cros.network import ip_config_context_manager
from autotest_lib.server.cros.network import netperf_runner
from autotest_lib.server.cros.network import netperf_session
from autotest_lib.server.cros.network import wifi_cell_test_base


class network_WiFi_Perf(wifi_cell_test_base.WiFiCellTestBase):
    """Test maximal achievable bandwidth on several channels per band.

    Conducts a performance test for a set of specified router configurations
    and reports results as keyval pairs.

    """

    version = 1

    NETPERF_CONFIGS = [
            netperf_runner.NetperfConfig(
                    netperf_runner.NetperfConfig.TEST_TYPE_TCP_STREAM),
            netperf_runner.NetperfConfig(
                    netperf_runner.NetperfConfig.TEST_TYPE_TCP_MAERTS),
            netperf_runner.NetperfConfig(
                    netperf_runner.NetperfConfig.TEST_TYPE_UDP_STREAM),
            netperf_runner.NetperfConfig(
                    netperf_runner.NetperfConfig.TEST_TYPE_UDP_MAERTS),
            netperf_runner.NetperfConfig(
                    netperf_runner.NetperfConfig.TEST_TYPE_TCP_BIDIRECTIONAL),
            netperf_runner.NetperfConfig(
                    netperf_runner.NetperfConfig.TEST_TYPE_UDP_BIDIRECTIONAL),
    ]

    DEFAULT_ROUTER_LAN_IP_ADDRESS = "192.168.1.50"
    DEFAULT_PCAP_LAN_IP_ADDRESS = "192.168.1.51"
    DEFAULT_ROUTER_LAN_IFACE_NAME = "eth1"
    DEFAULT_PCAP_LAN_IFACE_NAME = "eth1"

    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 list of HostapConfig objects.
        """
        self._should_required = 'should' in commandline_args
        self._power_save_off = 'power_save_off' in commandline_args

        get_arg_value_or_default = lambda attr, default: commandline_args[
                attr] if attr in commandline_args else default
        self._router_lan_ip_addr = get_arg_value_or_default(
                'router_lan_ip_addr', self.DEFAULT_ROUTER_LAN_IP_ADDRESS)
        self._router_lan_iface_name = get_arg_value_or_default(
                'router_lan_iface_name', self.DEFAULT_ROUTER_LAN_IFACE_NAME)
        self._pcap_lan_ip_addr = get_arg_value_or_default(
                'pcap_lan_ip_addr', self.DEFAULT_PCAP_LAN_IP_ADDRESS)
        self._pcap_lan_iface_name = get_arg_value_or_default(
                'pcap_lan_iface_name', self.DEFAULT_PCAP_LAN_IFACE_NAME)

        if 'governor' in commandline_args:
            self._governor = commandline_args['governor']
            # validate governor string. Not all machines will support all of
            # these governors, but this at least ensures that a potentially
            # valid governor was passed in
            if self._governor not in ('performance', 'powersave', 'userspace',
                                      'ondemand', 'conservative', 'schedutil'):
                logging.warning(
                        'Unrecognized CPU governor %s. Running test '
                        'without setting CPU governor...', self._governor)
                self._governor = None
        else:
            self._governor = None
        self._ap_configs = additional_params

    def verify_result(self, result, must_expected_throughput,
                      should_expected_throughput, config, failed_configs,
                      power_save, ap_config):
        """Verfiy that netperf result pass the must and should throughputs.

        @param result: the netperf thoughput result
        @param must_expected_throughput: the min must expected throughput
        @param should_expected_throughput: the min should expected throughput
        @param config: the netperf test type/configuration
        @param failed_configs: a set of failed configuration
        @param power_save: powersaving configuration
        @param ap_config: the AP configuration
        """
        must_tput_failed = False
        should_tput_failed = False
        mustAssertion = netperf_runner.NetperfAssertion(
                throughput_min=must_expected_throughput)
        if not mustAssertion.passes(result):
            logging.error(
                    'Throughput is too low for %s. Expected (must) %0.2f Mbps, got %0.2f.',
                    config.tag, must_expected_throughput, result.throughput)
            must_tput_failed = True
        shouldAssertion = netperf_runner.NetperfAssertion(
                throughput_min=should_expected_throughput)
        if not shouldAssertion.passes(result):
            if self._should_required:
                logging.error(
                        'Throughput is too low for %s. Expected (should) %0.2f Mbps, got %0.2f.',
                        config.tag, should_expected_throughput,
                        result.throughput)
                should_tput_failed = True
            else:
                logging.info(
                        'Throughput is below (should) expectation for %s. Expected (should) %0.2f Mbps, got %0.2f.',
                        config.tag, should_expected_throughput,
                        result.throughput)
        if must_tput_failed or should_tput_failed:
            failed_config_list = [
                    '[test_type=%s' % config.tag,
                    'channel=%d' % ap_config.channel,
                    'power_save_on=%r' % power_save,
                    'measured_Tput=%0.2f' % result.throughput
            ]
            if must_tput_failed:
                failed_config_list.append('must_expected_Tput_failed=%0.2f' %
                                          must_expected_throughput)
            elif should_tput_failed:
                failed_config_list.append('should_expected_Tput_failed=%0.2f' %
                                          should_expected_throughput)
            failed_configs.add(', '.join(failed_config_list) + ']')

    def do_run(self, ap_config, session, power_save, governor):
        """Run a single set of perf tests, for a given AP and DUT config.

        @param ap_config: the AP configuration that is being used
        @param session: a netperf session instance
        @param power_save: whether or not to use power-save mode on the DUT
                           (boolean)
        @ return set of failed configs
        """
        def get_current_governor(host):
            """
            @ return the CPU governor name used on a machine. If cannot find
                     the governor info of the host, or if there are multiple
                     different governors being used on different cores, return
                     'default'.
            """
            try:
                governors = set(utils.get_scaling_governor_states(host))
                if len(governors) != 1:
                    return 'default'
                return next(iter(governors))
            except:
                return 'default'
        if governor:
            client_governor = utils.get_scaling_governor_states(
                    self.context.client.host)
            router_governor = utils.get_scaling_governor_states(
                    self.context.router.host)
            utils.set_scaling_governors(governor, self.context.client.host)
            utils.set_scaling_governors(governor, self.context.router.host)
            governor_name = governor
        else:
            # try to get machine's current governor
            governor_name = get_current_governor(self.context.client.host)
            if governor_name != get_current_governor(self.context.router.host):
                governor_name = 'default'
            if governor_name == self._governor:
                # If CPU governor is already set to self._governor, don't
                # perform the run twice
                return

        failed_configs = set()
        self.context.client.powersave_switch(power_save)
        session.warmup_stations()
        ps_tag = 'PS%s' % ('on' if power_save else 'off')
        governor_tag = 'governor-%s' % governor_name
        ap_config_tag = '_'.join([ap_config.perf_loggable_description,
                                  ps_tag, governor_tag])
        signal_level = self.context.client.wifi_signal_level
        signal_description = '_'.join([ap_config_tag, 'signal'])
        self.write_perf_keyval({signal_description: signal_level})
        for config in self.NETPERF_CONFIGS:
            ch_width = ap_config.channel_width
            if ch_width is None:
                raise error.TestFail(
                        'Failed to get the channel width used by the AP and client'
                )
            expected_throughput = expected_performance_results.get_expected_throughput_wifi(
                    config.test_type_name, ap_config.mode, ch_width)
            results = session.run(config)
            if not results:
                logging.error('Failed to take measurement for %s',
                              config.tag)
                continue
            values = [result.throughput for result in results]
            self.output_perf_value(config.tag, values, units='Mbps',
                                   higher_is_better=True,
                                   graph=ap_config_tag)
            result = netperf_runner.NetperfResult.from_samples(results)
            # TODO(b:172211699): The Gale AP is bad at being an endpoint while simultaneously being a netperf server.
            # The Gale CPU performance becomes a bottleneck at high throughputs. Because of that,
            # the "tcp_rx" tests can't meet expected throughputs that are greater than 100Mbps.
            if (config.test_type_name == netperf_runner.NetperfConfig.
                        TEST_TYPE_TCP_MAERTS) and (expected_throughput[0] >
                                                   100):
                logging.info(
                        "Can't verify any expected throughput greater than 100Mbps on the test configuration tcp_rx"
                )
            else:
                self.verify_result(result, expected_throughput[0],
                                   expected_throughput[1], config,
                                   failed_configs, power_save, ap_config)
            self.write_perf_keyval(result.get_keyval(
                prefix='_'.join([ap_config_tag, config.tag])))
        if governor:
            utils.restore_scaling_governor_states(client_governor,
                    self.context.client.host)
            utils.restore_scaling_governor_states(router_governor,
                    self.context.router.host)
        return failed_configs


    def run_once(self):
        """Test body."""
        start_time = time.time()
        low_throughput_tests = set()

        for ap_config in self._ap_configs:
            # Set up the router and associate the client with it.
            self.context.configure(ap_config)
            # self.context.configure has a similar check - but that one only
            # errors out if the AP *requires* VHT i.e. AP is requesting
            # MODE_11AC_PURE and the client does not support it.
            # For wifi_perf, we don't want to run MODE_11AC_MIXED on the AP if
            # the client does not support VHT, as we are guaranteed to get the
            # same results at 802.11n/HT40 in that case.
            if ap_config.is_11ac and not self.context.client.is_vht_supported():
                raise error.TestNAError('Client does not have AC support')
            assoc_params = xmlrpc_datatypes.AssociationParameters(
                    ssid=self.context.router.get_ssid(),
                    security_config=ap_config.security_config)
            self.context.assert_connect_wifi(assoc_params)

            with ip_config_context_manager.IpConfigContextManager(
            ) as ip_context:

                ip_context.bring_interface_up(self.context.router.host,
                                              self._router_lan_iface_name)
                ip_context.bring_interface_up(self.context.pcap_host.host,
                                              self._pcap_lan_iface_name)
                ip_context.assign_ip_addr_to_iface(self.context.router.host,
                                                   self._router_lan_ip_addr,
                                                   self._router_lan_iface_name)
                ip_context.assign_ip_addr_to_iface(self.context.pcap_host.host,
                                                   self._pcap_lan_ip_addr,
                                                   self._pcap_lan_iface_name)
                ip_context.add_ip_route(self.context.client.host,
                                        self._pcap_lan_ip_addr,
                                        self.context.router.wifi_ip,
                                        self.context.client.wifi_if)
                ip_context.add_ip_route(self.context.pcap_host.host,
                                        self.context.client.wifi_ip,
                                        self._router_lan_ip_addr,
                                        self._router_lan_iface_name)

                pcap_lan_iface = interface.Interface(
                        self._pcap_lan_iface_name, self.context.pcap_host.host)
                session = netperf_session.NetperfSession(
                        self.context.client,
                        self.context.pcap_host,
                        server_interface=pcap_lan_iface)

                # Flag a test error if we disconnect for any reason.
                with self.context.client.assert_no_disconnects():
                    for governor in sorted(set([None, self._governor])):
                        # Run the performance test and record the test types
                        # which failed due to low throughput.
                        low_throughput_tests.update(
                                self.do_run(ap_config, session,
                                            not (self._power_save_off),
                                            governor))

            # Clean up router and client state for the next run.
            self.context.client.shill.disconnect(self.context.router.get_ssid())
            self.context.router.deconfig()
        end_time = time.time()
        logging.info('Running time %0.1f seconds.', end_time - start_time)
        if len(low_throughput_tests) != 0:
            low_throughput_tags = list(low_throughput_tests)
            raise error.TestFail(
                    'Throughput performance too low for test type(s): %s' %
                    ', '.join(low_throughput_tags))
