# Copyright 2017 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 collections
import logging

from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import utils
from autotest_lib.server.cros.network import hostap_config
from autotest_lib.server.cros.network import wifi_cell_test_base

class network_WiFi_Reset(wifi_cell_test_base.WiFiCellTestBase):
    """Test that the WiFi interface can be reset successfully, and that WiFi
    comes back up properly. Also run a few suspend/resume cycles along the way.
    Supports only Marvell (mwifiex) and Qualcomm/Atheros (ath10k) Wifi drivers.
    """

    version = 1

    _MWIFIEX_RESET_PATH = "/sys/kernel/debug/mwifiex/%s/reset"
    _MWIFIEX_RESET_TIMEOUT = 20
    _MWIFIEX_RESET_INTERVAL = 0.5

    _ATH10K_RESET_PATH = \
        '/sys/kernel/debug/ieee80211/%s/ath10k/simulate_fw_crash'

    _NUM_RESETS = 15
    _NUM_SUSPENDS = 5
    _SUSPEND_DELAY = 10

    # Implement these 3 functions for each driver reset mechanism we want to
    # support:
    #  @supported: return True if this driver is supported (e.g., check for
    #    available debugfs/sysfs triggers)
    #  @do_reset: perform a Wifi reset, to simulate a firmware crash/restart.
    #    Different drivers may handle restart in different ways, but this
    #    method should at least ensure the network device is available before
    #    returning.
    #  @need_reboot: (optional) return True if the driver was left in a bad
    #    state such that we should reboot the system (e.g., the driver failed
    #    to recover the network device).
    DriverReset = collections.namedtuple('DriverReset', ['supported',
                                                         'do_reset',
                                                         'need_reboot'])


    @property
    def mwifiex_reset_path(self):
        """Get path to the Wifi interface's reset file."""
        return self._MWIFIEX_RESET_PATH % self.context.client.wifi_if

    def mwifiex_reset_exists(self):
        """Check if the mwifiex reset file is present (i.e., a mwifiex
        interface is present).
        """
        return self.context.client.host.path_exists(self.mwifiex_reset_path)

    def mwifiex_reset(self):
        """Perform mwifiex reset and wait for the interface to come back up."""

        ssid = self.context.router.get_ssid()

        # Adapter will asynchronously reset.
        self.context.client.host.run('echo 1 > ' + self.mwifiex_reset_path)

        # Wait for disconnect. We aren't guaranteed to receive a disconnect
        # event, but shill will at least notice the adapter went away.
        self.context.client.wait_for_service_states(ssid, ['idle'],
                timeout_seconds=20)

        # Now wait for the reset interface file to come back.
        utils.poll_for_condition(
                condition=self.mwifiex_reset_exists,
                exception=error.TestFail(
                        'Failed to reset device %s' %
                        self.context.client.wifi_if),
                timeout=self._MWIFIEX_RESET_TIMEOUT,
                sleep_interval=self._MWIFIEX_RESET_INTERVAL)

    @property
    def ath10k_reset_path(self):
        """Get path to ath10k debugfs reset file"""
        phy_name = self.context.client.wifi_phy_name
        return self._ATH10K_RESET_PATH % phy_name

    def ath10k_reset_exists(self):
        """@return True if ath10k debugfs reset file exists"""
        return self.context.client.host.path_exists(self.ath10k_reset_path)

    def ath10k_reset(self):
        """
        Simulate ath10k firmware crash. mac80211 handles firmware crashes
        transparently, so we don't expect a full disconnect/reconnet event.

        From ath10k debugfs:
        To simulate firmware crash write one of the keywords to this file:
        `soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW
            supports that command.
        `hard` - this will send to firmware command with illegal parameters
            causing firmware crash.
        `assert` - this will send special illegal parameter to firmware to
            cause assert failure and crash.
        `hw-restart` - this will simply queue hw restart without fw/hw actually
            crashing.
        """
        self.context.client.host.run('echo soft > ' + self.ath10k_reset_path)

    def get_reset_driver(self):
        DRIVER_LIST = [
            self.DriverReset(
                supported=self.mwifiex_reset_exists,
                do_reset=self.mwifiex_reset,
                need_reboot=lambda: not self.mwifiex_reset_exists(),
            ),
            self.DriverReset(
                supported=self.ath10k_reset_exists,
                do_reset=self.ath10k_reset,
                need_reboot=lambda: not self.ath10k_reset_exists(),
            ),
        ]

        for driver in DRIVER_LIST:
            if driver.supported():
                return driver
        else:
            raise error.TestNAError('DUT does not support device reset')

    def run_once(self):
        """Body of the test."""

        self.reset_driver = self.get_reset_driver()

        client = self.context.client
        ap_config = hostap_config.HostapConfig(channel=1)
        ssid = self.configure_and_connect_to_ap(ap_config)

        self.context.assert_ping_from_dut()

        router = self.context.router
        ssid = router.get_ssid()

        boot_id = client.host.get_boot_id()

        logging.info("Running %d suspends", self._NUM_SUSPENDS)
        for _ in range(self._NUM_SUSPENDS):
            logging.info("Running %d resets", self._NUM_RESETS)
            for __ in range(self._NUM_RESETS):
                self.reset_driver.do_reset()
                client.wait_for_connection(ssid)
                self.context.assert_ping_from_dut()

            client.do_suspend(self._SUSPEND_DELAY)
            client.host.test_wait_for_resume(boot_id)
            client.wait_for_connection(ssid)

    def cleanup(self):
        """Performs cleanup at exit. May reboot the DUT, to keep the system
        functioning for the next test.
        """

        if hasattr(self, 'reset_driver') and self.reset_driver.need_reboot():
            logging.info("Test left DUT in bad state; rebooting")
            self.context.client.reboot(timeout=60)

        super(network_WiFi_Reset, self).cleanup()
