[OpenWrt] Add OpenWrt support to WiFi tests

Cherry picked changes from 'master'

Bug: 158349179
Fixes: 158349179
Test: Verified the changes
Merged-In: I182bf13c65583a8cdca6a9632ea9833930bdbc0d
Change-Id: Ib9e749bebf84571df2806276dc80e1f3c8d6bcb0
Exempt-From-Owner-Approval: Cherry picked from git_master
diff --git a/acts/framework/acts/controllers/__init__.py b/acts/framework/acts/controllers/__init__.py
index da302ce..d2dca69 100644
--- a/acts/framework/acts/controllers/__init__.py
+++ b/acts/framework/acts/controllers/__init__.py
@@ -26,5 +26,5 @@
 __all__ = [
     "android_device", "attenuator", "bluetooth_pts_device", "monsoon",
     "access_point", "iperf_server", "packet_sender", "arduino_wifi_dongle",
-    "packet_capture", "fuchsia_device"
+    "packet_capture", "fuchsia_device", "openwrt_ap"
 ]
diff --git a/acts/framework/acts/controllers/openwrt_ap.py b/acts/framework/acts/controllers/openwrt_ap.py
new file mode 100644
index 0000000..05bd38c
--- /dev/null
+++ b/acts/framework/acts/controllers/openwrt_ap.py
@@ -0,0 +1,253 @@
+"""Controller for Open WRT access point."""
+
+import time
+
+from acts import logger
+from acts.controllers.ap_lib import hostapd_constants
+from acts.controllers.openwrt_lib import wireless_config
+from acts.controllers.openwrt_lib import wireless_settings_applier
+from acts.controllers.utils_lib.ssh import connection
+from acts.controllers.utils_lib.ssh import settings
+
+MOBLY_CONTROLLER_CONFIG_NAME = "OpenWrtAP"
+ACTS_CONTROLLER_REFERENCE_NAME = "access_points"
+OPEN_SECURITY = "none"
+PSK_SECURITY = "psk2"
+WEP_SECURITY = "wep"
+ENT_SECURITY = "wpa2"
+ENABLE_RADIO = "0"
+WIFI_2G = "wifi2g"
+WIFI_5G = "wifi5g"
+
+
+def create(configs):
+  """Creates ap controllers from a json config.
+
+  Creates an ap controller from either a list, or a single element. The element
+  can either be just the hostname or a dictionary containing the hostname and
+  username of the AP to connect to over SSH.
+
+  Args:
+    configs: The json configs that represent this controller.
+
+  Returns:
+    AccessPoint object
+
+  Example:
+    Below is the config file entry for OpenWrtAP as a list. A testbed can have
+    1 or more APs to configure. Each AP has a "ssh_config" key to provide SSH
+    login information. OpenWrtAP#__init__() uses this to create SSH object.
+
+      "OpenWrtAP": [
+        {
+          "ssh_config": {
+            "user" : "root",
+            "host" : "192.168.1.1"
+          }
+        },
+        {
+          "ssh_config": {
+            "user" : "root",
+            "host" : "192.168.1.2"
+          }
+        }
+      ]
+  """
+  return [OpenWrtAP(c) for c in configs]
+
+
+def destroy(aps):
+  """Destroys a list of AccessPoints.
+
+  Args:
+    aps: The list of AccessPoints to destroy.
+  """
+  for ap in aps:
+    ap.close()
+    ap.close_ssh()
+
+
+def get_info(aps):
+  """Get information on a list of access points.
+
+  Args:
+    aps: A list of AccessPoints.
+
+  Returns:
+    A list of all aps hostname.
+  """
+  return [ap.ssh_settings.hostname for ap in aps]
+
+
+class OpenWrtAP(object):
+  """An AccessPoint controller.
+
+  Attributes:
+    log: Logging object for AccessPoint.
+    ssh: The ssh connection to the AP.
+    ssh_settings: The ssh settings being used by the ssh connection.
+    wireless_setting: object holding wireless configuration.
+  """
+
+  def __init__(self, config):
+    """Initialize AP."""
+    self.ssh_settings = settings.from_config(config["ssh_config"])
+    self.ssh = connection.SshConnection(self.ssh_settings)
+    self.log = logger.create_logger(
+        lambda msg: "[OpenWrtAP|%s] %s" % (self.ssh_settings.hostname, msg))
+    self.wireless_setting = None
+
+  def configure_ap(self, wifi_configs, channel_2g, channel_5g):
+    """Configure AP with the required settings.
+
+    Each test class inherits WifiBaseTest. Based on the test, we may need to
+    configure PSK, WEP, OPEN, ENT networks on 2G and 5G bands in any
+    combination. We call WifiBaseTest methods get_psk_network(),
+    get_open_network(), get_wep_network() and get_ent_network() to create
+    dictionaries which contains this information. 'wifi_configs' is a list of
+    such dictionaries. Example below configures 2 WiFi networks - 1 PSK 2G and
+    1 Open 5G on one AP. configure_ap() is called from WifiBaseTest to
+    configure the APs.
+
+    wifi_configs = [
+      {
+        '2g': {
+          'SSID': '2g_AkqXWPK4',
+          'security': 'psk2',
+          'password': 'YgYuXqDO9H',
+          'hiddenSSID': False
+        },
+      },
+      {
+        '5g': {
+          'SSID': '5g_8IcMR1Sg',
+          'security': 'none',
+          'hiddenSSID': False
+        },
+      }
+    ]
+
+    Args:
+      wifi_configs: list of network settings for 2G and 5G bands.
+      channel_2g: channel for 2G band.
+      channel_5g: channel for 5G band.
+    """
+    # generate wifi configs to configure
+    wireless_configs = self.generate_wireless_configs(wifi_configs)
+    self.wireless_setting = wireless_settings_applier.WirelessSettingsApplier(
+        self.ssh, wireless_configs, channel_2g, channel_5g)
+    self.wireless_setting.apply_wireless_settings()
+
+  def start_ap(self):
+    """Starts the AP with the settings in /etc/config/wireless."""
+    self.ssh.run("wifi up")
+    time.sleep(9)  # wait for sometime for AP to come up
+
+  def stop_ap(self):
+    """Stops the AP."""
+    self.ssh.run("wifi down")
+    time.sleep(9)  # wait for sometime for AP to go down
+
+  def generate_wireless_configs(self, wifi_configs):
+    """Generate wireless configs to configure.
+
+    Converts wifi_configs from configure_ap() to a list of 'WirelessConfig'
+    objects. Each object represents a wifi network to configure on the AP.
+
+    Args:
+      wifi_configs: Network list of different security types and bands.
+
+    Returns:
+      wireless configuration for openwrt AP.
+    """
+    num_2g = 1
+    num_5g = 1
+    wireless_configs = []
+
+    for i in range(len(wifi_configs)):
+      if hostapd_constants.BAND_2G in wifi_configs[i]:
+        config = wifi_configs[i][hostapd_constants.BAND_2G]
+        if config["security"] == PSK_SECURITY:
+          wireless_configs.append(
+              wireless_config.WirelessConfig("%s%s" % (WIFI_2G, num_2g),
+                                             config["SSID"],
+                                             config["security"],
+                                             hostapd_constants.BAND_2G,
+                                             password=config["password"],
+                                             hidden=config["hiddenSSID"]))
+        elif config["security"] == WEP_SECURITY:
+          wireless_configs.append(
+              wireless_config.WirelessConfig("%s%s" % (WIFI_2G, num_2g),
+                                             config["SSID"],
+                                             config["security"],
+                                             hostapd_constants.BAND_2G,
+                                             wep_key=config["wepKeys"][0],
+                                             hidden=config["hiddenSSID"]))
+        elif config["security"] == OPEN_SECURITY:
+          wireless_configs.append(
+              wireless_config.WirelessConfig("%s%s" % (WIFI_2G, num_2g),
+                                             config["SSID"],
+                                             config["security"],
+                                             hostapd_constants.BAND_2G,
+                                             hidden=config["hiddenSSID"]))
+        elif config["security"] == ENT_SECURITY:
+          wireless_configs.append(
+              wireless_config.WirelessConfig(
+                  "%s%s" % (WIFI_2G, num_2g),
+                  config["SSID"],
+                  config["security"],
+                  hostapd_constants.BAND_2G,
+                  radius_server_ip=config["radius_server_ip"],
+                  radius_server_port=config["radius_server_port"],
+                  radius_server_secret=config["radius_server_secret"],
+                  hidden=config["hiddenSSID"]))
+        num_2g += 1
+      if hostapd_constants.BAND_5G in wifi_configs[i]:
+        config = wifi_configs[i][hostapd_constants.BAND_5G]
+        if config["security"] == PSK_SECURITY:
+          wireless_configs.append(
+              wireless_config.WirelessConfig("%s%s" % (WIFI_5G, num_5g),
+                                             config["SSID"],
+                                             config["security"],
+                                             hostapd_constants.BAND_5G,
+                                             password=config["password"],
+                                             hidden=config["hiddenSSID"]))
+        elif config["security"] == WEP_SECURITY:
+          wireless_configs.append(
+              wireless_config.WirelessConfig("%s%s" % (WIFI_5G, num_5g),
+                                             config["SSID"],
+                                             config["security"],
+                                             hostapd_constants.BAND_5G,
+                                             wep_key=config["wepKeys"][0],
+                                             hidden=config["hiddenSSID"]))
+        elif config["security"] == OPEN_SECURITY:
+          wireless_configs.append(
+              wireless_config.WirelessConfig("%s%s" % (WIFI_5G, num_5g),
+                                             config["SSID"],
+                                             config["security"],
+                                             hostapd_constants.BAND_5G,
+                                             hidden=config["hiddenSSID"]))
+        elif config["security"] == ENT_SECURITY:
+          wireless_configs.append(
+              wireless_config.WirelessConfig(
+                  "%s%s" % (WIFI_5G, num_5g),
+                  config["SSID"],
+                  config["security"],
+                  hostapd_constants.BAND_5G,
+                  radius_server_ip=config["radius_server_ip"],
+                  radius_server_port=config["radius_server_port"],
+                  radius_server_secret=config["radius_server_secret"],
+                  hidden=config["hiddenSSID"]))
+        num_5g += 1
+
+    return wireless_configs
+
+  def close(self):
+    """Reset wireless settings to default and stop AP."""
+    if self.wireless_setting:
+      self.wireless_setting.cleanup_wireless_settings()
+
+  def close_ssh(self):
+    """Close SSH connection to AP."""
+    self.ssh.close()
+
diff --git a/acts/framework/acts/controllers/openwrt_lib/__init__.py b/acts/framework/acts/controllers/openwrt_lib/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/acts/framework/acts/controllers/openwrt_lib/__init__.py
diff --git a/acts/framework/acts/controllers/openwrt_lib/wireless_config.py b/acts/framework/acts/controllers/openwrt_lib/wireless_config.py
new file mode 100644
index 0000000..ea89636
--- /dev/null
+++ b/acts/framework/acts/controllers/openwrt_lib/wireless_config.py
@@ -0,0 +1,50 @@
+"""Class for Wireless config."""
+
+NET_IFACE = "lan"
+
+
+class WirelessConfig(object):
+  """Creates an object to hold wireless config.
+
+  Attributes:
+    name: name of the wireless config
+    ssid: SSID of the network.
+    security: security of the wifi network.
+    band: band of the wifi network.
+    iface: network interface of the wifi network.
+    password: password for psk network.
+    wep_key: wep keys for wep network.
+    wep_key_num: key number for wep network.
+    radius_server_ip: IP address of radius server.
+    radius_server_port: Port number of radius server.
+    radius_server_secret: Secret key of radius server.
+    hidden: Boolean, if the wifi network is hidden.
+  """
+
+  def __init__(
+      self,
+      name,
+      ssid,
+      security,
+      band,
+      iface=NET_IFACE,
+      password=None,
+      wep_key=None,
+      wep_key_num=1,
+      radius_server_ip=None,
+      radius_server_port=None,
+      radius_server_secret=None,
+      hidden=False):
+    self.name = name
+    self.ssid = ssid
+    self.security = security
+    self.band = band
+    self.iface = iface
+    self.password = password
+    self.wep_key = wep_key
+    self.wep_key_num = wep_key_num
+    self.radius_server_ip = radius_server_ip
+    self.radius_server_port = radius_server_port
+    self.radius_server_secret = radius_server_secret
+    self.hidden = hidden
+
diff --git a/acts/framework/acts/controllers/openwrt_lib/wireless_settings_applier.py b/acts/framework/acts/controllers/openwrt_lib/wireless_settings_applier.py
new file mode 100644
index 0000000..cfb94d1
--- /dev/null
+++ b/acts/framework/acts/controllers/openwrt_lib/wireless_settings_applier.py
@@ -0,0 +1,124 @@
+"""Class to configure wireless settings."""
+
+import time
+from acts.controllers.ap_lib import hostapd_constants
+
+LEASE_FILE = "/tmp/dhcp.leases"
+DNSMASQ_RESTART = "/etc/init.d/dnsmasq restart"
+OPEN_SECURITY = "none"
+PSK_SECURITY = "psk2"
+WEP_SECURITY = "wep"
+ENT_SECURITY = "wpa2"
+ENABLE_RADIO = "0"
+DISABLE_RADIO = "1"
+ENABLE_HIDDEN = "1"
+
+
+class WirelessSettingsApplier(object):
+  """Class for wireless settings.
+
+  Attributes:
+    ssh: ssh object for the AP.
+    wireless_configs: a list of
+      acts.controllers.openwrt_lib.wireless_config.WirelessConfig.
+    channel_2g: channel for 2G band.
+    channel_5g: channel for 5G band.
+  """
+
+  def __init__(self, ssh, configs, channel_2g, channel_5g):
+    """Initialize wireless settings.
+
+    Args:
+      ssh: ssh connection object.
+      configs: a list of
+        acts.controllers.openwrt_lib.wireless_config.WirelessConfig.
+      channel_2g: channel for 2G band.
+      channel_5g: channel for 5G band.
+    """
+    self.ssh = ssh
+    self.wireless_configs = configs
+    self.channel_2g = channel_2g
+    self.channel_5g = channel_5g
+
+  def apply_wireless_settings(self):
+    """Configure wireless settings from a list of configs."""
+
+    # set channels for 2G and 5G bands
+    self.ssh.run("uci set wireless.radio1.channel='%s'" % self.channel_2g)
+    self.ssh.run("uci set wireless.radio0.channel='%s'" % self.channel_5g)
+
+    # disable default OpenWrt SSID
+    self.ssh.run("uci set wireless.default_radio1.disabled='%s'" %
+                 DISABLE_RADIO)
+    self.ssh.run("uci set wireless.default_radio0.disabled='%s'" %
+                 DISABLE_RADIO)
+
+    # Enable radios
+    self.ssh.run("uci set wireless.radio1.disabled='%s'" % ENABLE_RADIO)
+    self.ssh.run("uci set wireless.radio0.disabled='%s'" % ENABLE_RADIO)
+
+    for config in self.wireless_configs:
+
+      # configure open network
+      if config.security == OPEN_SECURITY:
+        if config.band == hostapd_constants.BAND_2G:
+          self.ssh.run("uci set wireless.default_radio1.ssid='%s'" %
+                       config.ssid)
+          self.ssh.run("uci set wireless.default_radio1.disabled='%s'" %
+                       ENABLE_RADIO)
+          if config.hidden:
+            self.ssh.run("uci set wireless.default_radio1.hidden='%s'" %
+                         ENABLE_HIDDEN)
+        elif config.band == hostapd_constants.BAND_5G:
+          self.ssh.run("uci set wireless.default_radio0.ssid='%s'" %
+                       config.ssid)
+          self.ssh.run("uci set wireless.default_radio0.disabled='%s'" %
+                       ENABLE_RADIO)
+          if config.hidden:
+            self.ssh.run("uci set wireless.default_radio0.hidden='%s'" %
+                         ENABLE_HIDDEN)
+        continue
+
+      self.ssh.run("uci set wireless.%s='wifi-iface'" % config.name)
+      if config.band == hostapd_constants.BAND_2G:
+        self.ssh.run("uci set wireless.%s.device='radio1'" % config.name)
+      else:
+        self.ssh.run("uci set wireless.%s.device='radio0'" % config.name)
+      self.ssh.run("uci set wireless.%s.network='%s'" %
+                   (config.name, config.iface))
+      self.ssh.run("uci set wireless.%s.mode='ap'" % config.name)
+      self.ssh.run("uci set wireless.%s.ssid='%s'" %
+                   (config.name, config.ssid))
+      self.ssh.run("uci set wireless.%s.encryption='%s'" %
+                   (config.name, config.security))
+      if config.security == PSK_SECURITY:
+        self.ssh.run("uci set wireless.%s.key='%s'" %
+                     (config.name, config.password))
+      elif config.security == WEP_SECURITY:
+        self.ssh.run("uci set wireless.%s.key%s='%s'" %
+                     (config.name, config.wep_key_num, config.wep_key))
+        self.ssh.run("uci set wireless.%s.key='%s'" %
+                     (config.name, config.wep_key_num))
+      elif config.security == ENT_SECURITY:
+        self.ssh.run("uci set wireless.%s.auth_secret='%s'" %
+                     (config.name, config.radius_server_secret))
+        self.ssh.run("uci set wireless.%s.auth_server='%s'" %
+                     (config.name, config.radius_server_ip))
+        self.ssh.run("uci set wireless.%s.auth_port='%s'" %
+                     (config.name, config.radius_server_port))
+      if config.hidden:
+        self.ssh.run("uci set wireless.%s.hidden='%s'" %
+                     (config.name, ENABLE_HIDDEN))
+
+    self.ssh.run("uci commit wireless")
+    self.ssh.run("cp %s %s.tmp" % (LEASE_FILE, LEASE_FILE))
+
+  def cleanup_wireless_settings(self):
+    """Reset wireless settings to default."""
+    self.ssh.run("wifi down")
+    self.ssh.run("rm -f /etc/config/wireless")
+    self.ssh.run("wifi config")
+    self.ssh.run("cp %s.tmp %s" % (LEASE_FILE, LEASE_FILE))
+    self.ssh.run(DNSMASQ_RESTART)
+    time.sleep(9)
+
diff --git a/acts/framework/acts/keys.py b/acts/framework/acts/keys.py
index ed2d12b..3883f81 100644
--- a/acts/framework/acts/keys.py
+++ b/acts/framework/acts/keys.py
@@ -55,6 +55,7 @@
     key_sniffer = 'Sniffer'
     key_arduino_wifi_dongle = 'ArduinoWifiDongle'
     key_packet_capture = 'PacketCapture'
+    key_openwrt_ap = 'OpenWrtAP'
     # Internal keys, used internally, not exposed to user's config files.
     ikey_user_param = 'user_params'
     ikey_testbed_name = 'testbed_name'
@@ -78,6 +79,7 @@
     m_key_sniffer = 'sniffer'
     m_key_arduino_wifi_dongle = 'arduino_wifi_dongle'
     m_key_packet_capture = 'packet_capture'
+    m_key_openwrt_ap = 'openwrt_ap'
 
     # A list of keys whose values in configs should not be passed to test
     # classes without unpacking first.
@@ -101,6 +103,7 @@
         key_chameleon_device,
         key_arduino_wifi_dongle,
         key_packet_capture,
+        key_openwrt_ap,
     ]
 
     # Keys that are file or folder paths.
diff --git a/acts/framework/acts/test_utils/wifi/WifiBaseTest.py b/acts/framework/acts/test_utils/wifi/WifiBaseTest.py
index 122709f..e79d03e 100644
--- a/acts/framework/acts/test_utils/wifi/WifiBaseTest.py
+++ b/acts/framework/acts/test_utils/wifi/WifiBaseTest.py
@@ -295,6 +295,112 @@
             self.update_bssid(ap_instance, ap, network,
                 hostapd_constants.BAND_2G)
 
+    def configure_openwrt_ap_and_start(
+            self,
+            channel_5g=hostapd_constants.AP_DEFAULT_CHANNEL_5G,
+            channel_2g=hostapd_constants.AP_DEFAULT_CHANNEL_2G,
+            ssid_length_2g=hostapd_constants.AP_SSID_LENGTH_2G,
+            passphrase_length_2g=hostapd_constants.AP_PASSPHRASE_LENGTH_2G,
+            ssid_length_5g=hostapd_constants.AP_SSID_LENGTH_5G,
+            passphrase_length_5g=hostapd_constants.AP_PASSPHRASE_LENGTH_5G,
+            mirror_ap=False,
+            hidden=False,
+            same_ssid=False,
+            open_network=False,
+            wpa_network=False,
+            wep_network=False,
+            ent_network=False,
+            ent_network_pwd=False,
+            radius_conf_2g=None,
+            radius_conf_5g=None,
+            radius_conf_pwd=None,
+            ap_count=1):
+        """Create, configure and start OpenWrt AP.
+
+        Args:
+            channel_5g: 5G channel to configure.
+            channel_2g: 2G channel to configure.
+            ssid_length_2g: Int, number of characters to use for 2G SSID.
+            passphrase_length_2g: Int, length of password for 2G network.
+            ssid_length_5g: Int, number of characters to use for 5G SSID.
+            passphrase_length_5g: Int, length of password for 5G network.
+            same_ssid: Boolean, determines if both bands on AP use the same SSID.
+            open_network: Boolean, to check if open network should be configured.
+            wpa_network: Boolean, to check if wpa network should be configured.
+            wep_network: Boolean, to check if wep network should be configured.
+            ent_network: Boolean, to check if ent network should be configured.
+            ent_network_pwd: Boolean, to check if ent pwd network should be configured.
+            radius_conf_2g: dictionary with enterprise radius server details.
+            radius_conf_5g: dictionary with enterprise radius server details.
+            radius_conf_pwd: dictionary with enterprise radiuse server details.
+            ap_count: APs to configure.
+        """
+        self.reference_networks = []
+        self.wpa_networks = []
+        self.wep_networks = []
+        self.ent_networks = []
+        self.ent_networks_pwd = []
+        self.open_network = []
+        for _ in range(ap_count):
+            network_list = []
+            if wpa_network:
+                wpa_dict = self.get_psk_network(mirror_ap,
+                                                self.reference_networks,
+                                                hidden,
+                                                same_ssid,
+                                                ssid_length_2g,
+                                                ssid_length_5g,
+                                                passphrase_length_2g,
+                                                passphrase_length_5g)
+                wpa_dict[hostapd_constants.BAND_2G]["security"] = "psk2"
+                wpa_dict[hostapd_constants.BAND_5G]["security"] = "psk2"
+                self.wpa_networks.append(wpa_dict)
+                network_list.append(wpa_dict)
+            if wep_network:
+                wep_dict = self.get_wep_network(mirror_ap,
+                                                self.wep_networks,
+                                                hidden,
+                                                same_ssid,
+                                                ssid_length_2g,
+                                                ssid_length_5g)
+                network_list.append(wep_dict)
+            if ent_network:
+                ent_dict = self.get_open_network(mirror_ap,
+                                                 self.ent_networks,
+                                                 hidden,
+                                                 same_ssid,
+                                                 ssid_length_2g,
+                                                 ssid_length_5g)
+                ent_dict["2g"]["security"] = "wpa2"
+                ent_dict["2g"].update(radius_conf_2g)
+                ent_dict["5g"]["security"] = "wpa2"
+                ent_dict["5g"].update(radius_conf_5g)
+                network_list.append(ent_dict)
+            if ent_network_pwd:
+                ent_pwd_dict = self.get_open_network(mirror_ap,
+                                                     self.ent_networks_pwd,
+                                                     hidden,
+                                                     same_ssid,
+                                                     ssid_length_2g,
+                                                     ssid_length_5g)
+                ent_pwd_dict["2g"]["security"] = "wpa2"
+                ent_pwd_dict["2g"].update(radius_conf_pwd)
+                ent_pwd_dict["5g"]["security"] = "wpa2"
+                ent_pwd_dict["5g"].update(radius_conf_pwd)
+                network_list.append(ent_pwd_dict)
+            if open_network:
+                open_dict = self.get_open_network(mirror_ap,
+                                                  self.open_network,
+                                                  hidden,
+                                                  same_ssid,
+                                                  ssid_length_2g,
+                                                  ssid_length_5g)
+                network_list.append(open_dict)
+            self.access_points[_].configure_ap(network_list,
+                                               channel_2g,
+                                               channel_5g)
+            self.access_points[_].start_ap()
+
     def legacy_configure_ap_and_start(
             self,
             channel_5g=hostapd_constants.AP_DEFAULT_CHANNEL_5G,
diff --git a/acts/tests/google/wifi/WifiCrashTest.py b/acts/tests/google/wifi/WifiCrashTest.py
index e6cbe2e..f76b1ed 100644
--- a/acts/tests/google/wifi/WifiCrashTest.py
+++ b/acts/tests/google/wifi/WifiCrashTest.py
@@ -55,6 +55,8 @@
 
         if "AccessPoint" in self.user_params:
             self.legacy_configure_ap_and_start()
+        elif "OpenWrtAP" in self.user_params:
+            self.configure_openwrt_ap_and_start(wpa_network=True)
 
         asserts.assert_true(
             len(self.reference_networks) > 0,
diff --git a/acts/tests/google/wifi/WifiEnterpriseTest.py b/acts/tests/google/wifi/WifiEnterpriseTest.py
index a76f568..20f5e9f 100644
--- a/acts/tests/google/wifi/WifiEnterpriseTest.py
+++ b/acts/tests/google/wifi/WifiEnterpriseTest.py
@@ -65,6 +65,13 @@
                 radius_conf_5g=self.radius_conf_5g,
                 ent_network_pwd=True,
                 radius_conf_pwd=self.radius_conf_pwd,)
+        elif "OpenWrtAP" in self.user_params:
+            self.configure_openwrt_ap_and_start(
+                ent_network=True,
+                radius_conf_2g=self.radius_conf_2g,
+                radius_conf_5g=self.radius_conf_5g,
+                ent_network_pwd=True,
+                radius_conf_pwd=self.radius_conf_pwd,)
         self.ent_network_2g = self.ent_networks[0]["2g"]
         self.ent_network_5g = self.ent_networks[0]["5g"]
         self.ent_network_pwd = self.ent_networks_pwd[0]["2g"]
diff --git a/acts/tests/google/wifi/WifiHiddenSSIDTest.py b/acts/tests/google/wifi/WifiHiddenSSIDTest.py
index a68144d..38f3442 100644
--- a/acts/tests/google/wifi/WifiHiddenSSIDTest.py
+++ b/acts/tests/google/wifi/WifiHiddenSSIDTest.py
@@ -51,6 +51,10 @@
 
         if "AccessPoint" in self.user_params:
             self.legacy_configure_ap_and_start(hidden=True)
+        elif "OpenWrtAP" in self.user_params:
+            self.configure_openwrt_ap_and_start(open_network=True,
+                                                wpa_network=True,
+                                                hidden=True)
 
         asserts.assert_true(
             len(self.reference_networks) > 0,
diff --git a/acts/tests/google/wifi/WifiLinkProbeTest.py b/acts/tests/google/wifi/WifiLinkProbeTest.py
index fdf8178..d50abde 100644
--- a/acts/tests/google/wifi/WifiLinkProbeTest.py
+++ b/acts/tests/google/wifi/WifiLinkProbeTest.py
@@ -47,6 +47,8 @@
 
         if "AccessPoint" in self.user_params:
             self.legacy_configure_ap_and_start()
+        elif "OpenWrtAP" in self.user_params:
+            self.configure_openwrt_ap_and_start(wpa_network=True)
         self.configure_packet_capture()
 
         asserts.assert_true(len(self.reference_networks) > 0,
diff --git a/acts/tests/google/wifi/WifiMacRandomizationTest.py b/acts/tests/google/wifi/WifiMacRandomizationTest.py
index 7456f8a..aba6035 100644
--- a/acts/tests/google/wifi/WifiMacRandomizationTest.py
+++ b/acts/tests/google/wifi/WifiMacRandomizationTest.py
@@ -79,7 +79,12 @@
         self.configure_packet_capture()
 
         if "AccessPoint" in self.user_params:
-            self.legacy_configure_ap_and_start(wep_network=True, ap_count=2)
+            self.legacy_configure_ap_and_start(wep_network=True,
+                                               ap_count=2)
+        elif "OpenWrtAP" in self.user_params:
+            self.configure_openwrt_ap_and_start(open_network=True,
+                                                wpa_network=True,
+                                                wep_network=True)
 
         asserts.assert_true(
             len(self.reference_networks) > 0,
diff --git a/acts/tests/google/wifi/WifiManagerTest.py b/acts/tests/google/wifi/WifiManagerTest.py
index d7107ca..9d7f8a0 100644
--- a/acts/tests/google/wifi/WifiManagerTest.py
+++ b/acts/tests/google/wifi/WifiManagerTest.py
@@ -70,6 +70,10 @@
 
         if "AccessPoint" in self.user_params:
             self.legacy_configure_ap_and_start(wpa_network=True, wep_network=True)
+        elif "OpenWrtAP" in self.user_params:
+            self.configure_openwrt_ap_and_start(open_network=True,
+                                                wpa_network=True,
+                                                wep_network=True)
 
         asserts.assert_true(
             len(self.reference_networks) > 0,
diff --git a/acts/tests/google/wifi/WifiNetworkRequestTest.py b/acts/tests/google/wifi/WifiNetworkRequestTest.py
index 58e90ca..7a1d8bc 100644
--- a/acts/tests/google/wifi/WifiNetworkRequestTest.py
+++ b/acts/tests/google/wifi/WifiNetworkRequestTest.py
@@ -61,6 +61,10 @@
         if "AccessPoint" in self.user_params:
             self.legacy_configure_ap_and_start(wpa_network=True,
                                                wep_network=True)
+        elif "OpenWrtAP" in self.user_params:
+            self.configure_openwrt_ap_and_start(open_network=True,
+                                                wpa_network=True,
+                                                wep_network=True)
 
         asserts.assert_true(
             len(self.reference_networks) > 0,
diff --git a/acts/tests/google/wifi/WifiNetworkSuggestionTest.py b/acts/tests/google/wifi/WifiNetworkSuggestionTest.py
index fdd73ce..b3140c6 100644
--- a/acts/tests/google/wifi/WifiNetworkSuggestionTest.py
+++ b/acts/tests/google/wifi/WifiNetworkSuggestionTest.py
@@ -76,7 +76,9 @@
                 wpa_network=True, ent_network=True,
                 radius_conf_2g=self.radius_conf_2g,
                 radius_conf_5g=self.radius_conf_5g,)
-
+        elif "OpenWrtAP" in self.user_params:
+            self.configure_openwrt_ap_and_start(open_network=True,
+                                                wpa_network=True,)
         if hasattr(self, "reference_networks") and \
             isinstance(self.reference_networks, list):
               self.wpa_psk_2g = self.reference_networks[0]["2g"]
@@ -84,23 +86,6 @@
         if hasattr(self, "open_network") and isinstance(self.open_network,list):
             self.open_2g = self.open_network[0]["2g"]
             self.open_5g = self.open_network[0]["5g"]
-        if hasattr(self, "ent_networks") and isinstance(self.ent_networks,list):
-            self.ent_network_2g = self.ent_networks[0]["2g"]
-            self.ent_network_5g = self.ent_networks[0]["5g"]
-            self.config_aka = {
-                Ent.EAP: int(EAP.AKA),
-                WifiEnums.SSID_KEY: self.ent_network_2g[WifiEnums.SSID_KEY],
-                "carrierId": str(self.dut.droid.telephonyGetSimCarrierId()),
-            }
-            self.config_ttls = {
-                Ent.EAP: int(EAP.TTLS),
-                Ent.CA_CERT: self.ca_cert,
-                Ent.IDENTITY: self.eap_identity,
-                Ent.PASSWORD: self.eap_password,
-                Ent.PHASE2: int(EapPhase2.MSCHAPV2),
-                WifiEnums.SSID_KEY: self.ent_network_2g[WifiEnums.SSID_KEY],
-                Ent.ALTSUBJECT_MATCH: self.altsubject_match,
-            }
         if hasattr(self, "hidden_networks") and \
             isinstance(self.hidden_networks, list):
               self.hidden_network = self.hidden_networks[0]
@@ -120,6 +105,15 @@
         wutils.wifi_toggle_state(self.dut, True)
         self.dut.ed.clear_all_events()
         self.clear_carrier_approved(str(self.dut.droid.telephonyGetSimCarrierId()))
+        if "_ent_" in self.test_name:
+            if "OpenWrtAP" in self.user_params:
+                self.access_points[0].close()
+                self.configure_openwrt_ap_and_start(
+                    ent_network=True,
+                    radius_conf_2g=self.radius_conf_2g,
+                    radius_conf_5g=self.radius_conf_5g,)
+            self.ent_network_2g = self.ent_networks[0]["2g"]
+            self.ent_network_5g = self.ent_networks[0]["5g"]
 
     def teardown_test(self):
         self.dut.droid.wakeLockRelease()
@@ -478,6 +472,11 @@
         6. Remove suggestions and ensure device doesn't connect back to it.
         7. Reboot the device again, ensure user approval is kept
         """
+        self.config_aka = {
+            Ent.EAP: int(EAP.AKA),
+            WifiEnums.SSID_KEY: self.ent_network_2g[WifiEnums.SSID_KEY],
+            "carrierId": str(self.dut.droid.telephonyGetSimCarrierId()),
+        }
         if "carrierId" in self.config_aka:
             self.set_carrier_approved(self.config_aka["carrierId"], True)
         self._test_connect_to_wifi_network_reboot_config_store(
@@ -500,6 +499,15 @@
         6. Remove suggestions and ensure device doesn't connect back to it.
         7. Reboot the device again, ensure user approval is kept
         """
+        self.config_ttls = {
+            Ent.EAP: int(EAP.TTLS),
+            Ent.CA_CERT: self.ca_cert,
+            Ent.IDENTITY: self.eap_identity,
+            Ent.PASSWORD: self.eap_password,
+            Ent.PHASE2: int(EapPhase2.MSCHAPV2),
+            WifiEnums.SSID_KEY: self.ent_network_2g[WifiEnums.SSID_KEY],
+            Ent.ALTSUBJECT_MATCH: self.altsubject_match,
+        }
         config = dict(self.config_ttls)
         config[WifiEnums.Enterprise.PHASE2] = WifiEnums.EapPhase2.PAP.value
 
diff --git a/acts/tests/google/wifi/WifiScannerMultiScanTest.py b/acts/tests/google/wifi/WifiScannerMultiScanTest.py
index f8804bb..0b4d44e 100755
--- a/acts/tests/google/wifi/WifiScannerMultiScanTest.py
+++ b/acts/tests/google/wifi/WifiScannerMultiScanTest.py
@@ -263,6 +263,8 @@
 
         if "AccessPoint" in self.user_params:
             self.legacy_configure_ap_and_start()
+        elif "OpenWrtAP" in self.user_params:
+            self.configure_openwrt_ap_and_start(open_network=True)
 
         self.wifi_chs = WifiChannelUS(self.dut.model)
 
diff --git a/acts/tests/google/wifi/WifiSoftApAcsTest.py b/acts/tests/google/wifi/WifiSoftApAcsTest.py
index dc99381..22d08b1 100644
--- a/acts/tests/google/wifi/WifiSoftApAcsTest.py
+++ b/acts/tests/google/wifi/WifiSoftApAcsTest.py
@@ -174,15 +174,20 @@
             channel_5g: The channel number to use for 5GHz network.
 
         """
+        if not channel_2g:
+            channel_2g = hostapd_constants.AP_DEFAULT_CHANNEL_2G
+        if not channel_5g:
+            channel_5g = hostapd_constants.AP_DEFAULT_CHANNEL_5G
         if "AccessPoint" in self.user_params:
-            if not channel_2g:
-                channel_2g = hostapd_constants.AP_DEFAULT_CHANNEL_2G
-            if not channel_5g:
-                channel_5g = hostapd_constants.AP_DEFAULT_CHANNEL_5G
             self.legacy_configure_ap_and_start(wpa_network=True,
                                                wep_network=True,
                                                channel_2g=channel_2g,
                                                channel_5g=channel_5g)
+        elif "OpenWrtAP" in self.user_params:
+            self.configure_openwrt_ap_and_start(wpa_network=True,
+                                                wep_network=True,
+                                                channel_2g=channel_2g,
+                                                channel_5g=channel_5g)
 
     def start_traffic_and_softap(self, network, softap_band):
         """Start iPerf traffic on client dut, during softAP bring-up on dut.
diff --git a/acts/tests/google/wifi/WifiSoftApTest.py b/acts/tests/google/wifi/WifiSoftApTest.py
index 8faf1c5..7c7840d 100644
--- a/acts/tests/google/wifi/WifiSoftApTest.py
+++ b/acts/tests/google/wifi/WifiSoftApTest.py
@@ -52,6 +52,8 @@
             req_param_names=req_params, opt_param_names=opt_param)
         if "AccessPoint" in self.user_params:
             self.legacy_configure_ap_and_start()
+        elif "OpenWrtAP" in self.user_params:
+            self.configure_openwrt_ap_and_start(open_network=True)
         self.open_network = self.open_network[0]["2g"]
         # Do a simple version of init - mainly just sync the time and enable
         # verbose logging.  This test will fail if the DUT has a sim and cell
diff --git a/acts/tests/google/wifi/WifiStaApConcurrencyTest.py b/acts/tests/google/wifi/WifiStaApConcurrencyTest.py
index d44b7dc..fc4f69a 100644
--- a/acts/tests/google/wifi/WifiStaApConcurrencyTest.py
+++ b/acts/tests/google/wifi/WifiStaApConcurrencyTest.py
@@ -95,12 +95,13 @@
         self.turn_location_on_and_scan_toggle_on()
         wutils.wifi_toggle_state(self.dut, True)
         self.access_points[0].close()
-        try:
-            del self.user_params["reference_networks"]
-            del self.user_params["open_network"]
-        except KeyError as e:
-            self.log.warn("There is no 'reference_network' or "
-                          "'open_network' to delete")
+        if "AccessPoint" in self.user_params:
+            try:
+                del self.user_params["reference_networks"]
+                del self.user_params["open_network"]
+            except KeyError as e:
+                self.log.warn("There is no 'reference_network' or "
+                              "'open_network' to delete")
 
     def on_fail(self, test_name, begin_time):
         for ad in self.android_devices:
@@ -121,8 +122,13 @@
             channel_2g = hostapd_constants.AP_DEFAULT_CHANNEL_2G
         if not channel_5g:
             channel_5g = hostapd_constants.AP_DEFAULT_CHANNEL_5G
-        self.legacy_configure_ap_and_start(channel_2g=channel_2g,
-                                           channel_5g=channel_5g)
+        if "AccessPoint" in self.user_params:
+            self.legacy_configure_ap_and_start(channel_2g=channel_2g,
+                                               channel_5g=channel_5g)
+        elif "OpenWrtAP" in self.user_params:
+            self.configure_openwrt_ap_and_start(open_network=True,
+                                                channel_2g=channel_2g,
+                                                channel_5g=channel_5g)
         self.open_2g = self.open_network[0]["2g"]
         self.open_5g = self.open_network[0]["5g"]
 
diff --git a/acts/tests/google/wifi/WifiWakeTest.py b/acts/tests/google/wifi/WifiWakeTest.py
index 82e2419..7495863 100644
--- a/acts/tests/google/wifi/WifiWakeTest.py
+++ b/acts/tests/google/wifi/WifiWakeTest.py
@@ -57,6 +57,9 @@
 
         if "AccessPoint" in self.user_params:
             self.legacy_configure_ap_and_start(mirror_ap=False, ap_count=2)
+        elif "OpenWrtAP" in self.user_params:
+            self.configure_openwrt_ap_and_start(wpa_network=True,
+                                                ap_count=2)
 
         # use 2G since Wifi Wake does not work if an AP is on a 5G DFS channel
         self.ap_a = self.reference_networks[0]["2g"]
@@ -64,28 +67,46 @@
 
         self.ap_a_atten = self.attenuators[0]
         self.ap_b_atten = self.attenuators[2]
+        if "OpenWrtAP" in self.user_params:
+            self.ap_b_atten = self.attenuators[1]
 
     # TODO(b/119040540): this method of disabling/re-enabling Wifi on APs is
     # hacky, switch to using public methods when they are implemented
     def ap_a_off(self):
+        if "OpenWrtAP" in self.user_params:
+            self.access_points[0].stop_ap()
+            self.log.info('Turned AP A off')
+            return
         ap_a_hostapd = self.access_points[0]._aps['wlan0'].hostapd
         if ap_a_hostapd.is_alive():
             ap_a_hostapd.stop()
             self.log.info('Turned AP A off')
 
     def ap_a_on(self):
+        if "OpenWrtAP" in self.user_params:
+            self.access_points[0].start_ap()
+            self.log.info('Turned AP A on')
+            return
         ap_a_hostapd = self.access_points[0]._aps['wlan0'].hostapd
         if not ap_a_hostapd.is_alive():
             ap_a_hostapd.start(ap_a_hostapd.config)
             self.log.info('Turned AP A on')
 
     def ap_b_off(self):
+        if "OpenWrtAP" in self.user_params:
+            self.access_points[1].stop_ap()
+            self.log.info('Turned AP B off')
+            return
         ap_b_hostapd = self.access_points[1]._aps['wlan0'].hostapd
         if ap_b_hostapd.is_alive():
             ap_b_hostapd.stop()
             self.log.info('Turned AP B off')
 
     def ap_b_on(self):
+        if "OpenWrtAP" in self.user_params:
+            self.access_points[1].start_ap()
+            self.log.info('Turned AP B on')
+            return
         ap_b_hostapd = self.access_points[1]._aps['wlan0'].hostapd
         if not ap_b_hostapd.is_alive():
             ap_b_hostapd.start(ap_b_hostapd.config)