Snap for 7901677 from 0d271697b3dea7efc4eade3096336dc7a875ea11 to sc-platform-release

Change-Id: I1f82de39d3abf79b1f1874b5bd26801ceb4f1ce7
diff --git a/acts/framework/acts/controllers/asus_axe11000_ap.py b/acts/framework/acts/controllers/asus_axe11000_ap.py
index d19af3b..c549d6e 100644
--- a/acts/framework/acts/controllers/asus_axe11000_ap.py
+++ b/acts/framework/acts/controllers/asus_axe11000_ap.py
@@ -246,7 +246,7 @@
           BAND_2G_RAD_PORT).get_attribute("value")
       dict_2g["radius_secret"] = self.driver.find_element_by_name(
           BAND_2G_RAD_KEY).get_attribute("value")
-    channel_field = self._get_webdriver_elements_for_channels(band)
+    channel_field = self._get_webdriver_elements_for_channels("2g")
     ch_val = self.driver.find_element_by_name(channel_field).get_attribute(
         "value")
     channel = 0
@@ -282,9 +282,9 @@
           BAND_5G_RAD_IP).get_attribute("value")
       dict_5g["radius_port"] = self.driver.find_element_by_name(
           BAND_5G_RAD_PORT).get_attribute("value")
-      dict_2g["radius_secret"] = self.driver.find_element_by_name(
+      dict_5g["radius_secret"] = self.driver.find_element_by_name(
           BAND_5G_RAD_KEY).get_attribute("value")
-    channel_field = self._get_webdriver_elements_for_channels(band)
+    channel_field = self._get_webdriver_elements_for_channels("5g")
     ch_val = self.driver.find_element_by_name(channel_field).get_attribute(
         "value")
     channel = 0
@@ -312,7 +312,7 @@
     if dict_6g["security"] == "sae":
       dict_6g["password"] = self.driver.find_element_by_name(
           BAND_6G_PSK).get_attribute("value")
-    channel_field = self._get_webdriver_elements_for_channels(band)
+    channel_field = self._get_webdriver_elements_for_channels("6g")
     ch_val = self.driver.find_element_by_name(channel_field).get_attribute(
         "value")
     channel = 0
diff --git a/acts/framework/acts/controllers/openwrt_ap.py b/acts/framework/acts/controllers/openwrt_ap.py
index 714ebb2..ac0712d 100644
--- a/acts/framework/acts/controllers/openwrt_ap.py
+++ b/acts/framework/acts/controllers/openwrt_ap.py
@@ -1,14 +1,17 @@
 """Controller for Open WRT access point."""
 
+import random
 import re
 import time
 from acts import logger
+from acts import signals
 from acts.controllers.ap_lib import hostapd_constants
 from acts.controllers.openwrt_lib import network_settings
 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
+from acts.controllers.openwrt_lib.openwrt_constants import OpenWrtWifiSetting
 import yaml
 
 MOBLY_CONTROLLER_CONFIG_NAME = "OpenWrtAP"
@@ -20,11 +23,13 @@
 ENT_SECURITY = "wpa2"
 OWE_SECURITY = "owe"
 SAE_SECURITY = "sae"
+SAEMIXED_SECURITY = "sae-mixed"
 ENABLE_RADIO = "0"
 PMF_ENABLED = 2
 WIFI_2G = "wifi2g"
 WIFI_5G = "wifi5g"
 WAIT_TIME = 20
+DEFAULT_RADIOS = ("radio0", "radio1")
 
 
 def create(configs):
@@ -105,7 +110,7 @@
         lambda msg: "[OpenWrtAP|%s] %s" % (self.ssh_settings.hostname, msg))
     self.wireless_setting = None
     self.network_setting = network_settings.NetworkSettings(
-        self.ssh, config["ssh_config"]["host"], self.log)
+        self.ssh, self.ssh_settings, self.log)
 
   def configure_ap(self, wifi_configs, channel_2g, channel_5g):
     """Configure AP with the required settings.
@@ -292,7 +297,7 @@
       else:
         self.ssh.run(
             'uci set wireless.@wifi-iface[{}].key={}'.format(3, pwd_5g))
-        self.log.info("Set 5G password to :{}".format(pwd_2g))
+        self.log.info("Set 5G password to :{}".format(pwd_5g))
 
     if pwd_2g:
       if len(pwd_2g) < 8 or len(pwd_2g) > 63:
@@ -308,6 +313,89 @@
     self.ssh.run("uci commit wireless")
     self.ssh.run("wifi")
 
+  def set_ssid(self, ssid_5g=None, ssid_2g=None):
+    """Set SSID for individual interface.
+
+    Args:
+        ssid_5g: 8 ~ 63 chars for 5g network.
+        ssid_2g: 8 ~ 63 chars for 2g network.
+    """
+    if ssid_5g:
+      if len(ssid_5g) < 8 or len(ssid_5g) > 63:
+        self.log.error("SSID must be 8~63 characters long")
+      # Only accept ascii letters and digits
+      else:
+        self.ssh.run(
+            'uci set wireless.@wifi-iface[{}].ssid={}'.format(3, ssid_5g))
+        self.log.info("Set 5G SSID to :{}".format(ssid_5g))
+
+    if ssid_2g:
+      if len(ssid_2g) < 8 or len(ssid_2g) > 63:
+        self.log.error("SSID must be 8~63 characters long")
+      # Only accept ascii letters and digits
+      else:
+        self.ssh.run(
+            'uci set wireless.@wifi-iface[{}].ssid={}'.format(2, ssid_2g))
+        self.log.info("Set 2G SSID to :{}".format(ssid_2g))
+
+    self.ssh.run("uci commit wireless")
+    self.ssh.run("wifi")
+
+  def generate_mobility_domain(self):
+      """Generate 4-character hexadecimal ID
+
+      Returns: String; a 4-character hexadecimal ID.
+      """
+      md = "{:04x}".format(random.getrandbits(16))
+      self.log.info("Mobility Domain ID: {}".format(md))
+      return md
+
+  def enable_80211r(self, iface, md):
+    """Enable 802.11r for one single radio.
+
+     Args:
+       iface: index number of wifi-iface.
+              2: radio1
+              3: radio0
+       md: mobility domain. a 4-character hexadecimal ID.
+    Raises: TestSkip if 2g or 5g radio is not up or 802.11r is not enabled.
+     """
+    str_output = self.ssh.run("wifi status").stdout
+    wifi_status = yaml.load(str_output.replace("\t", "").replace("\n", ""),
+                            Loader=yaml.FullLoader)
+    # Check if the radio is up.
+    if iface == OpenWrtWifiSetting.IFACE_2G:
+      if wifi_status['radio1']['up']:
+        self.log.info("2g network is ENABLED")
+      else:
+        raise signals.TestSkip("2g network is NOT ENABLED")
+    elif iface == OpenWrtWifiSetting.IFACE_5G:
+      if wifi_status['radio0']['up']:
+        self.log.info("5g network is ENABLED")
+      else:
+        raise signals.TestSkip("5g network is NOT ENABLED")
+
+    # Setup 802.11r.
+    self.ssh.run(
+        "uci set wireless.@wifi-iface[{}].ieee80211r='1'".format(iface))
+    self.ssh.run(
+        "uci set wireless.@wifi-iface[{}].ft_psk_generate_local='1'"
+          .format(iface))
+    self.ssh.run(
+        "uci set wireless.@wifi-iface[{}].mobility_domain='{}'"
+          .format(iface, md))
+    self.ssh.run(
+        "uci commit wireless")
+    self.ssh.run("wifi")
+
+    # Check if 802.11r is enabled.
+    result = self.ssh.run(
+        "uci get wireless.@wifi-iface[{}].ieee80211r".format(iface)).stdout
+    if result == '1':
+      self.log.info("802.11r is ENABLED")
+    else:
+      raise signals.TestSkip("802.11r is NOT ENABLED")
+
   def generate_wireless_configs(self, wifi_configs):
     """Generate wireless configs to configure.
 
@@ -334,7 +422,8 @@
                                              config["security"],
                                              hostapd_constants.BAND_2G,
                                              password=config["password"],
-                                             hidden=config["hiddenSSID"]))
+                                             hidden=config["hiddenSSID"],
+                                             ieee80211w=config["ieee80211w"]))
         elif config["security"] == PSK1_SECURITY:
           wireless_configs.append(
               wireless_config.WirelessConfig("%s%s" % (WIFI_2G, num_2g),
@@ -342,7 +431,8 @@
                                              config["security"],
                                              hostapd_constants.BAND_2G,
                                              password=config["password"],
-                                             hidden=config["hiddenSSID"]))
+                                             hidden=config["hiddenSSID"],
+                                             ieee80211w=config["ieee80211w"]))
         elif config["security"] == WEP_SECURITY:
           wireless_configs.append(
               wireless_config.WirelessConfig("%s%s" % (WIFI_2G, num_2g),
@@ -375,6 +465,15 @@
                                              password=config["password"],
                                              hidden=config["hiddenSSID"],
                                              ieee80211w=PMF_ENABLED))
+        elif config["security"] == SAEMIXED_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"],
+                                             ieee80211w=config["ieee80211w"]))
         elif config["security"] == ENT_SECURITY:
           wireless_configs.append(
               wireless_config.WirelessConfig(
@@ -396,7 +495,8 @@
                                              config["security"],
                                              hostapd_constants.BAND_5G,
                                              password=config["password"],
-                                             hidden=config["hiddenSSID"]))
+                                             hidden=config["hiddenSSID"],
+                                             ieee80211w=config["ieee80211w"]))
         elif config["security"] == PSK1_SECURITY:
           wireless_configs.append(
               wireless_config.WirelessConfig("%s%s" % (WIFI_5G, num_5g),
@@ -404,7 +504,8 @@
                                              config["security"],
                                              hostapd_constants.BAND_5G,
                                              password=config["password"],
-                                             hidden=config["hiddenSSID"]))
+                                             hidden=config["hiddenSSID"],
+                                             ieee80211w=config["ieee80211w"]))
         elif config["security"] == WEP_SECURITY:
           wireless_configs.append(
               wireless_config.WirelessConfig("%s%s" % (WIFI_5G, num_5g),
@@ -437,6 +538,15 @@
                                              password=config["password"],
                                              hidden=config["hiddenSSID"],
                                              ieee80211w=PMF_ENABLED))
+        elif config["security"] == SAEMIXED_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"],
+                                             ieee80211w=config["ieee80211w"]))
         elif config["security"] == ENT_SECURITY:
           wireless_configs.append(
               wireless_config.WirelessConfig(
@@ -478,6 +588,40 @@
         return wifi_network
     return None
 
+  def get_wifi_status(self, radios=DEFAULT_RADIOS):
+    """Check if radios are up. Default are 2G and 5G bands.
+
+    Args:
+      radios: Wifi interfaces for check status.
+    Returns:
+      True if both radios are up. False if not.
+    """
+    status = True
+    for radio in radios:
+      str_output = self.ssh.run("wifi status %s" % radio).stdout
+      wifi_status = yaml.load(str_output.replace("\t", "").replace("\n", ""),
+                              Loader=yaml.FullLoader)
+      status = wifi_status[radio]["up"] and status
+    return status
+
+  def verify_wifi_status(self, radios=DEFAULT_RADIOS, timeout=20):
+    """Ensure wifi interfaces are ready.
+
+    Args:
+      radios: Wifi interfaces for check status.
+      timeout: An integer that is the number of times to try
+               wait for interface ready.
+    Returns:
+      True if both radios are up. False if not.
+    """
+    start_time = time.time()
+    end_time = start_time + timeout
+    while time.time() < end_time:
+      if self.get_wifi_status(radios):
+        return True
+      time.sleep(1)
+    return False
+
   def close(self):
     """Reset wireless and network settings to default and stop AP."""
     if self.network_setting.config:
diff --git a/acts/framework/acts/controllers/openwrt_lib/network_const.py b/acts/framework/acts/controllers/openwrt_lib/network_const.py
index 76dd34b..0a3fb42 100644
--- a/acts/framework/acts/controllers/openwrt_lib/network_const.py
+++ b/acts/framework/acts/controllers/openwrt_lib/network_const.py
@@ -42,9 +42,55 @@
     }
 }
 
+IPSEC_HYBRID_RSA = {
+    "conn HYBRID_RSA": {
+        "keyexchange": "ikev1",
+        "left": "192.168.1.1",
+        "leftsubnet": "0.0.0.0/0",
+        "leftauth": "pubkey",
+        "leftcert": "serverCert.der",
+        "leftsendcert": "always",
+        "right": "%any",
+        "rightsubnet": "0.0.0.0/0",
+        "rightauth": "pubkey",
+        "rightauth2": "xauth",
+        "xauth": "server",
+        "auto": "add",
+    }
+}
+
+IPSEC_XAUTH_PSK = {
+    "conn XAUTH_PSK": {
+        "keyexchange": "ikev1",
+        "left": "192.168.1.1",
+        "leftsubnet": "0.0.0.0/0",
+        "leftauth": "psk",
+        "right": "%any",
+        "rightsubnet": "0.0.0.0/0",
+        "rightauth": "psk",
+        "rightauth2": "xauth",
+        "auto": "add",
+    }
+}
+
+IPSEC_XAUTH_RSA = {
+    "conn XAUTH_RSA": {
+        "keyexchange": "ikev1",
+        "left": "192.168.1.1",
+        "leftsubnet": "0.0.0.0/0",
+        "leftcert": "serverCert.der",
+        "leftsendcert": "always",
+        "right": "%any",
+        "rightsubnet": "0.0.0.0/0",
+        "rightauth": "xauth",
+        "xauth": "server",
+        "auto": "add",
+    }
+}
+
 # parmas for lx2tpd
 
-XL2TPD_CONF_GLOBAL = [
+XL2TPD_CONF_GLOBAL = (
     "[global]",
     "ipsec saref = no",
     "debug tunnel = no",
@@ -54,9 +100,9 @@
     "access control = no",
     "rand source = dev",
     "port = 1701",
-]
+)
 
-XL2TPD_CONF_INS = [
+XL2TPD_CONF_INS = (
     "[lns default]",
     "require authentication = yes",
     "pass peer = yes",
@@ -64,9 +110,9 @@
     "length bit = yes",
     "refuse pap = yes",
     "refuse chap = yes",
-]
+)
 
-XL2TPD_OPTION = [
+XL2TPD_OPTION = (
     "require-mschap-v2",
     "refuse-mschap",
     "ms-dns 8.8.8.8",
@@ -87,17 +133,17 @@
     "lcp-echo-interval 30",
     "lcp-echo-failure 4",
     "nomppe"
-]
+)
 
 # iptable rules for vpn_pptp
-FIREWALL_RULES_FOR_PPTP = [
+FIREWALL_RULES_FOR_PPTP = (
     "iptables -A input_rule -i ppp+ -j ACCEPT",
     "iptables -A output_rule -o ppp+ -j ACCEPT",
     "iptables -A forwarding_rule -i ppp+ -j ACCEPT"
-]
+)
 
 # iptable rules for vpn_l2tp
-FIREWALL_RULES_FOR_L2TP = [
+FIREWALL_RULES_FOR_L2TP = (
     "iptables -I INPUT  -m policy --dir in --pol ipsec --proto esp -j ACCEPT",
     "iptables -I FORWARD  -m policy --dir in --pol ipsec --proto esp -j ACCEPT",
     "iptables -I FORWARD  -m policy --dir out --pol ipsec --proto esp -j ACCEPT",
@@ -111,7 +157,14 @@
     "iptables -A INPUT -p udp --dport 500 -j ACCEPT",
     "iptables -A INPUT -p udp --dport 4500 -j ACCEPT",
     "iptables -A INPUT -p udp -m policy --dir in --pol ipsec -m udp --dport 1701 -j ACCEPT"
-]
+)
+
+FIREWALL_RULES_DISABLE_DNS_RESPONSE = (
+    "iptables -I OUTPUT -p udp --sport 53 -j DROP",
+    "iptables -I OUTPUT -p tcp --sport 53 -j DROP",
+    "ip6tables -I OUTPUT -p udp --sport 53 -j DROP",
+    "ip6tables -I OUTPUT -p tcp --sport 53 -j DROP",
+)
 
 
 # Object for vpn profile
diff --git a/acts/framework/acts/controllers/openwrt_lib/network_settings.py b/acts/framework/acts/controllers/openwrt_lib/network_settings.py
index 91cdb03..efbd590 100644
--- a/acts/framework/acts/controllers/openwrt_lib/network_settings.py
+++ b/acts/framework/acts/controllers/openwrt_lib/network_settings.py
@@ -13,8 +13,13 @@
 #   limitations under the License.
 
 import re
+import time
+
+from acts import signals
+from acts import utils
 from acts.controllers.openwrt_lib import network_const
 
+
 SERVICE_DNSMASQ = "dnsmasq"
 SERVICE_STUNNEL = "stunnel"
 SERVICE_NETWORK = "network"
@@ -22,8 +27,13 @@
 SERVICE_FIREWALL = "firewall"
 SERVICE_IPSEC = "ipsec"
 SERVICE_XL2TPD = "xl2tpd"
+SERVICE_ODHCPD = "odhcpd"
+SERVICE_NODOGSPLASH = "nodogsplash"
 PPTP_PACKAGE = "pptpd kmod-nf-nathelper-extra"
 L2TP_PACKAGE = "strongswan-full openssl-util xl2tpd"
+NAT6_PACKAGE = "ip6tables kmod-ipt-nat6"
+CAPTIVE_PORTAL_PACKAGE = "nodogsplash"
+MDNS_PACKAGE = "avahi-utils avahi-daemon-service-http avahi-daemon-service-ssh libavahi-client avahi-dbus-daemon"
 STUNNEL_CONFIG_PATH = "/etc/stunnel/DoTServer.conf"
 HISTORY_CONFIG_PATH = "/etc/dirty_configs"
 PPTPD_OPTION_PATH = "/etc/ppp/options.pptpd"
@@ -31,6 +41,7 @@
 XL2TPD_OPTION_CONFIG_PATH = "/etc/ppp/options.xl2tpd"
 FIREWALL_CUSTOM_OPTION_PATH = "/etc/firewall.user"
 PPP_CHAP_SECRET_PATH = "/etc/ppp/chap-secrets"
+TCPDUMP_DIR = "/tmp/tcpdump/"
 LOCALHOST = "192.168.1.1"
 DEFAULT_PACKAGE_INSTALL_TIMEOUT = 200
 
@@ -40,26 +51,30 @@
 
     Attributes:
         ssh: ssh connection object.
-        service_manager: Object manage service configuration
+        ssh_settings: ssh settings for AccessPoint.
+        service_manager: Object manage service configuration.
+        user: username for ssh.
         ip: ip address for AccessPoint.
         log: Logging object for AccessPoint.
         config: A list to store changes on network settings.
-        firewall_rules_list: A list of firewall rule name list
+        firewall_rules_list: A list of firewall rule name list.
         cleanup_map: A dict for compare oppo functions.
         l2tp: profile for vpn l2tp server.
     """
 
-    def __init__(self, ssh, ip, logger):
+    def __init__(self, ssh, ssh_settings, logger):
         """Initialize wireless settings.
 
         Args:
             ssh: ssh connection object.
-            ip: ip address for AccessPoint.
+            ssh_settings: ssh settings for AccessPoint.
             logger: Logging object for AccessPoint.
         """
         self.ssh = ssh
         self.service_manager = ServiceManager(ssh)
-        self.ip = ip
+        self.ssh_settings = ssh_settings
+        self.user = self.ssh_settings.username
+        self.ip = self.ssh_settings.hostname
         self.log = logger
         self.config = set()
         self.firewall_rules_list = []
@@ -67,7 +82,14 @@
             "setup_dns_server": self.remove_dns_server,
             "setup_vpn_pptp_server": self.remove_vpn_pptp_server,
             "setup_vpn_l2tp_server": self.remove_vpn_l2tp_server,
-            "disable_ipv6": self.enable_ipv6
+            "disable_ipv6": self.enable_ipv6,
+            "setup_ipv6_bridge": self.remove_ipv6_bridge,
+            "default_dns": self.del_default_dns,
+            "default_v6_dns": self.del_default_v6_dns,
+            "ipv6_prefer_option": self.remove_ipv6_prefer_option,
+            "block_dns_response": self.unblock_dns_response,
+            "setup_mdns": self.remove_mdns,
+            "setup_captive_portal": self.remove_cpative_portal
         }
         # This map contains cleanup functions to restore the configuration to
         # its default state. We write these keys to HISTORY_CONFIG_PATH prior to
@@ -75,6 +97,7 @@
         # This makes it easier to recover after an aborted test.
         self.update_firewall_rules_list()
         self.cleanup_network_settings()
+        self.clear_tcpdump()
 
     def cleanup_network_settings(self):
         """Reset all changes on Access point."""
@@ -88,7 +111,11 @@
         if self.config:
             temp = self.config.copy()
             for change in temp:
-                self.cleanup_map[change]()
+                change_list = change.split()
+                if len(change_list) > 1:
+                    self.cleanup_map[change_list[0]](*change_list[1:])
+                else:
+                    self.cleanup_map[change]()
             self.config = set()
 
         if self.file_exists(HISTORY_CONFIG_PATH):
@@ -397,11 +424,11 @@
             org: Organization name for generate cert keys.
         """
         self.l2tp = network_const.VpnL2tp(vpn_server_hostname,
-                                           vpn_server_address,
-                                           vpn_username,
-                                           vpn_password,
-                                           psk_secret,
-                                           server_name)
+                                          vpn_server_address,
+                                          vpn_username,
+                                          vpn_password,
+                                          psk_secret,
+                                          server_name)
 
         self.package_install(L2TP_PACKAGE)
         self.config.add("setup_vpn_l2tp_server")
@@ -416,6 +443,8 @@
         self.setup_ppp_secret()
         # /etc/config/firewall & /etc/firewall.user
         self.setup_firewall_rules_for_l2tp()
+        # setup vpn server local ip
+        self.setup_vpn_local_ip()
         # generate cert and key for rsa
         self.generate_vpn_cert_keys(country, org)
         # restart service
@@ -428,6 +457,7 @@
         """Remove l2tp vpn server on OpenWrt."""
         self.config.discard("setup_vpn_l2tp_server")
         self.restore_firewall_rules_for_l2tp()
+        self.remove_vpn_local_ip()
         self.service_manager.need_restart(SERVICE_IPSEC)
         self.service_manager.need_restart(SERVICE_XL2TPD)
         self.service_manager.need_restart(SERVICE_FIREWALL)
@@ -451,28 +481,35 @@
 
     def setup_ipsec(self):
         """Setup ipsec config."""
-        def load_config(data):
+        def load_ipsec_config(data, rightsourceip=False):
             for i in data.keys():
                 config.append(i)
                 for j in data[i].keys():
                     config.append("\t %s=%s" % (j, data[i][j]))
+                if rightsourceip:
+                    config.append("\t rightsourceip=%s.16/26" % self.l2tp.address.rsplit(".", 1)[0])
                 config.append("")
 
         config = []
-        load_config(network_const.IPSEC_CONF)
-        load_config(network_const.IPSEC_L2TP_PSK)
-        load_config(network_const.IPSEC_L2TP_RSA)
+        load_ipsec_config(network_const.IPSEC_CONF)
+        load_ipsec_config(network_const.IPSEC_L2TP_PSK)
+        load_ipsec_config(network_const.IPSEC_L2TP_RSA)
+        load_ipsec_config(network_const.IPSEC_HYBRID_RSA, True)
+        load_ipsec_config(network_const.IPSEC_XAUTH_PSK, True)
+        load_ipsec_config(network_const.IPSEC_XAUTH_RSA, True)
         self.create_config_file("\n".join(config), "/etc/ipsec.conf")
 
         ipsec_secret = []
         ipsec_secret.append(r": PSK \"%s\"" % self.l2tp.psk_secret)
         ipsec_secret.append(r": RSA \"%s\"" % "serverKey.der")
+        ipsec_secret.append(r"%s : XAUTH \"%s\"" % (self.l2tp.username,
+                                                    self.l2tp.password))
         self.create_config_file("\n".join(ipsec_secret), "/etc/ipsec.secrets")
 
     def setup_xl2tpd(self, ip_range=20):
         """Setup xl2tpd config."""
         net_id, host_id = self.l2tp.address.rsplit(".", 1)
-        xl2tpd_conf = network_const.XL2TPD_CONF_GLOBAL
+        xl2tpd_conf = list(network_const.XL2TPD_CONF_GLOBAL)
         xl2tpd_conf.append("auth file = %s" % PPP_CHAP_SECRET_PATH)
         xl2tpd_conf.extend(network_const.XL2TPD_CONF_INS)
         xl2tpd_conf.append("ip range = %s.%s-%s.%s" %
@@ -483,7 +520,7 @@
         xl2tpd_conf.append("pppoptfile = %s" % XL2TPD_OPTION_CONFIG_PATH)
 
         self.create_config_file("\n".join(xl2tpd_conf), XL2TPD_CONFIG_PATH)
-        xl2tpd_option = network_const.XL2TPD_OPTION
+        xl2tpd_option = list(network_const.XL2TPD_OPTION)
         xl2tpd_option.append("name %s" % self.l2tp.name)
         self.create_config_file("\n".join(xl2tpd_option),
                                 XL2TPD_OPTION_CONFIG_PATH)
@@ -574,7 +611,7 @@
             self.ssh.run("uci set firewall.@rule[-1].src='wan'")
             self.ssh.run("uci set firewall.@rule[-1].proto='47'")
 
-        iptable_rules = network_const.FIREWALL_RULES_FOR_PPTP
+        iptable_rules = list(network_const.FIREWALL_RULES_FOR_PPTP)
         self.add_custom_firewall_rules(iptable_rules)
         self.service_manager.need_restart(SERVICE_FIREWALL)
 
@@ -617,7 +654,7 @@
             self.ssh.run("uci set firewall.@rule[-1].proto='ah'")
 
         net_id = self.l2tp.address.rsplit(".", 1)[0]
-        iptable_rules = network_const.FIREWALL_RULES_FOR_L2TP
+        iptable_rules = list(network_const.FIREWALL_RULES_FOR_L2TP)
         iptable_rules.append("iptables -A FORWARD -s %s.0/24"
                              "  -j ACCEPT" % net_id)
         iptable_rules.append("iptables -t nat -A POSTROUTING"
@@ -670,6 +707,24 @@
         """Disable pptp service."""
         self.package_remove(PPTP_PACKAGE)
 
+    def setup_vpn_local_ip(self):
+        """Setup VPN Server local ip on OpenWrt for client ping verify."""
+        self.ssh.run("uci set network.lan2=interface")
+        self.ssh.run("uci set network.lan2.type=bridge")
+        self.ssh.run("uci set network.lan2.ifname=eth1.2")
+        self.ssh.run("uci set network.lan2.proto=static")
+        self.ssh.run("uci set network.lan2.ipaddr=\"%s\"" % self.l2tp.address)
+        self.ssh.run("uci set network.lan2.netmask=255.255.255.0")
+        self.ssh.run("uci set network.lan2=interface")
+        self.service_manager.reload(SERVICE_NETWORK)
+        self.commit_changes()
+
+    def remove_vpn_local_ip(self):
+        """Discard vpn local ip on OpenWrt."""
+        self.ssh.run("uci delete network.lan2")
+        self.service_manager.reload(SERVICE_NETWORK)
+        self.commit_changes()
+
     def enable_ipv6(self):
         """Enable ipv6 on OpenWrt."""
         self.ssh.run("uci set network.lan.ipv6=1")
@@ -688,6 +743,194 @@
         self.service_manager.reload(SERVICE_NETWORK)
         self.commit_changes()
 
+    def setup_ipv6_bridge(self):
+        """Setup ipv6 bridge for client have ability to access network."""
+        self.config.add("setup_ipv6_bridge")
+
+        self.ssh.run("uci set dhcp.lan.dhcpv6=relay")
+        self.ssh.run("uci set dhcp.lan.ra=relay")
+        self.ssh.run("uci set dhcp.lan.ndp=relay")
+
+        self.ssh.run("uci set dhcp.wan6=dhcp")
+        self.ssh.run("uci set dhcp.wan6.dhcpv6=relay")
+        self.ssh.run("uci set dhcp.wan6.ra=relay")
+        self.ssh.run("uci set dhcp.wan6.ndp=relay")
+        self.ssh.run("uci set dhcp.wan6.master=1")
+        self.ssh.run("uci set dhcp.wan6.interface=wan6")
+
+        # Enable service
+        self.service_manager.need_restart(SERVICE_ODHCPD)
+        self.commit_changes()
+
+    def remove_ipv6_bridge(self):
+        """Discard ipv6 bridge on OpenWrt."""
+        if "setup_ipv6_bridge" in self.config:
+            self.config.discard("setup_ipv6_bridge")
+
+            self.ssh.run("uci set dhcp.lan.dhcpv6=server")
+            self.ssh.run("uci set dhcp.lan.ra=server")
+            self.ssh.run("uci delete dhcp.lan.ndp")
+
+            self.ssh.run("uci delete dhcp.wan6")
+
+            self.service_manager.need_restart(SERVICE_ODHCPD)
+            self.commit_changes()
+
+    def _add_dhcp_option(self, args):
+        self.ssh.run("uci add_list dhcp.lan.dhcp_option=\"%s\"" % args)
+
+    def _remove_dhcp_option(self, args):
+        self.ssh.run("uci del_list dhcp.lan.dhcp_option=\"%s\"" % args)
+
+    def add_default_dns(self, addr_list):
+        """Add default dns server for client.
+
+        Args:
+            addr_list: dns ip address for Openwrt client.
+        """
+        self._add_dhcp_option("6,%s" % ",".join(addr_list))
+        self.config.add("default_dns %s" % addr_list)
+        self.service_manager.need_restart(SERVICE_DNSMASQ)
+        self.commit_changes()
+
+    def del_default_dns(self, addr_list):
+        """Remove default dns server for client.
+
+        Args:
+            addr_list: list of dns ip address for Openwrt client.
+        """
+        self._remove_dhcp_option("6,%s" % addr_list)
+        self.config.discard("default_dns %s" % addr_list)
+        self.service_manager.need_restart(SERVICE_DNSMASQ)
+        self.commit_changes()
+
+    def add_default_v6_dns(self, addr_list):
+        """Add default v6 dns server for client.
+
+        Args:
+            addr_list: dns ip address for Openwrt client.
+        """
+        self.ssh.run("uci add_list dhcp.lan.dns=\"%s\"" % addr_list)
+        self.config.add("default_v6_dns %s" % addr_list)
+        self.service_manager.need_restart(SERVICE_ODHCPD)
+        self.commit_changes()
+
+    def del_default_v6_dns(self, addr_list):
+        """Del default v6 dns server for client.
+
+        Args:
+            addr_list: dns ip address for Openwrt client.
+        """
+        self.ssh.run("uci del_list dhcp.lan.dns=\"%s\"" % addr_list)
+        self.config.add("default_v6_dns %s" % addr_list)
+        self.service_manager.need_restart(SERVICE_ODHCPD)
+        self.commit_changes()
+
+    def add_ipv6_prefer_option(self):
+        self._add_dhcp_option("108,1800i")
+        self.config.add("ipv6_prefer_option")
+        self.service_manager.need_restart(SERVICE_DNSMASQ)
+        self.commit_changes()
+
+    def remove_ipv6_prefer_option(self):
+        self._remove_dhcp_option("108,1800i")
+        self.config.discard("ipv6_prefer_option")
+        self.service_manager.need_restart(SERVICE_DNSMASQ)
+        self.commit_changes()
+
+    def start_tcpdump(self, test_name, args="", interface="br-lan"):
+        """"Start tcpdump on OpenWrt.
+
+        Args:
+            test_name: Test name for create tcpdump file name.
+            args: Option args for tcpdump.
+            interface: Interface to logging.
+        Returns:
+            tcpdump_file_name: tcpdump file name on OpenWrt.
+            pid: tcpdump process id.
+        """
+        if not self.path_exists(TCPDUMP_DIR):
+            self.ssh.run("mkdir %s" % TCPDUMP_DIR)
+        tcpdump_file_name = "openwrt_%s_%s.pcap" % (test_name,
+                                                    time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime(time.time())))
+        tcpdump_file_path = "".join([TCPDUMP_DIR, tcpdump_file_name])
+        cmd = "tcpdump -i %s -s0 %s -w %s" % (interface, args, tcpdump_file_path)
+        self.ssh.run_async(cmd)
+        pid = self._get_tcpdump_pid(tcpdump_file_name)
+        if not pid:
+            raise signals.TestFailure("Fail to start tcpdump on OpenWrt.")
+        # Set delay to prevent tcpdump fail to capture target packet.
+        time.sleep(15)
+        return tcpdump_file_name
+
+    def stop_tcpdump(self, tcpdump_file_name, pull_dir=None):
+        """Stop tcpdump on OpenWrt and pull the pcap file.
+
+        Args:
+            tcpdump_file_name: tcpdump file name on OpenWrt.
+            pull_dir: Keep none if no need to pull.
+        Returns:
+            tcpdump abs_path on host.
+        """
+        # Set delay to prevent tcpdump fail to capture target packet.
+        time.sleep(15)
+        pid = self._get_tcpdump_pid(tcpdump_file_name)
+        self.ssh.run("kill -9 %s" % pid, ignore_status=True)
+        if self.path_exists(TCPDUMP_DIR) and pull_dir:
+            tcpdump_path = "".join([TCPDUMP_DIR, tcpdump_file_name])
+            tcpdump_remote_path = "/".join([pull_dir, tcpdump_file_name])
+            tcpdump_local_path = "%s@%s:%s" % (self.user, self.ip, tcpdump_path)
+            utils.exe_cmd("scp %s %s" % (tcpdump_local_path, tcpdump_remote_path))
+
+        if self._get_tcpdump_pid(tcpdump_file_name):
+            raise signals.TestFailure("Failed to stop tcpdump on OpenWrt.")
+        if self.file_exists(tcpdump_path):
+            self.ssh.run("rm -f %s" % tcpdump_path)
+        return tcpdump_remote_path if pull_dir else None
+
+    def clear_tcpdump(self):
+        self.ssh.run("killall tpcdump", ignore_status=True)
+        if self.ssh.run("pgrep tpcdump", ignore_status=True).stdout:
+            raise signals.TestFailure("Failed to clean up tcpdump process.")
+
+    def _get_tcpdump_pid(self, tcpdump_file_name):
+        """Check tcpdump process on OpenWrt."""
+        return self.ssh.run("pgrep -f %s" % (tcpdump_file_name), ignore_status=True).stdout
+
+    def setup_mdns(self):
+        self.config.add("setup_mdns")
+        self.package_install(MDNS_PACKAGE)
+        self.commit_changes()
+
+    def remove_mdns(self):
+        self.config.discard("setup_mdns")
+        self.package_remove(MDNS_PACKAGE)
+        self.commit_changes()
+
+    def block_dns_response(self):
+        self.config.add("block_dns_response")
+        iptable_rules = list(network_const.FIREWALL_RULES_DISABLE_DNS_RESPONSE)
+        self.add_custom_firewall_rules(iptable_rules)
+        self.service_manager.need_restart(SERVICE_FIREWALL)
+        self.commit_changes()
+
+    def unblock_dns_response(self):
+        self.config.discard("block_dns_response")
+        self.remove_custom_firewall_rules()
+        self.service_manager.need_restart(SERVICE_FIREWALL)
+        self.commit_changes()
+
+    def setup_captive_portal(self):
+        self.package_install(CAPTIVE_PORTAL_PACKAGE)
+        self.config.add("setup_captive_portal")
+        self.service_manager.need_restart(SERVICE_NODOGSPLASH)
+        self.commit_changes()
+
+    def remove_cpative_portal(self):
+        self.package_remove(CAPTIVE_PORTAL_PACKAGE)
+        self.config.discard("setup_captive_portal")
+        self.commit_changes()
+
 
 class ServiceManager(object):
     """Class for service on OpenWrt.
@@ -720,6 +963,8 @@
     def restart_services(self):
         """Restart all services need to restart."""
         for service in self._need_restart:
+            if service == SERVICE_NETWORK:
+                self.reload(service)
             self.restart(service)
         self._need_restart = set()
 
diff --git a/acts/framework/acts/controllers/openwrt_lib/openwrt_constants.py b/acts/framework/acts/controllers/openwrt_lib/openwrt_constants.py
index 5848b5b..5ab4124 100644
--- a/acts/framework/acts/controllers/openwrt_lib/openwrt_constants.py
+++ b/acts/framework/acts/controllers/openwrt_lib/openwrt_constants.py
@@ -23,4 +23,8 @@
   WPA2_PSK_DEFAULT = "psk2"
   WPA2_PSK_CCMP = "psk2+ccmp"
   WPA2_PSK_TKIP = "psk2+tkip"
-  WPA2_PSK_TKIP_AND_CCMP = "psk2+tkip+ccmp"
\ No newline at end of file
+  WPA2_PSK_TKIP_AND_CCMP = "psk2+tkip+ccmp"
+
+class OpenWrtWifiSetting:
+  IFACE_2G = 2
+  IFACE_5G = 3
\ No newline at end of file
diff --git a/acts/framework/acts/controllers/openwrt_lib/wireless_settings_applier.py b/acts/framework/acts/controllers/openwrt_lib/wireless_settings_applier.py
index ec0bbf1..a366c02 100644
--- a/acts/framework/acts/controllers/openwrt_lib/wireless_settings_applier.py
+++ b/acts/framework/acts/controllers/openwrt_lib/wireless_settings_applier.py
@@ -15,6 +15,7 @@
 ENT_SECURITY = "wpa2"
 OWE_SECURITY = "owe"
 SAE_SECURITY = "sae"
+SAEMIXED_SECURITY = "sae-mixed"
 ENABLE_RADIO = "0"
 DISABLE_RADIO = "1"
 ENABLE_HIDDEN = "1"
@@ -108,7 +109,8 @@
       self.ssh.run("uci set wireless.%s.encryption='%s'" %
                    (config.name, config.security))
       if config.security == PSK_SECURITY or config.security == SAE_SECURITY\
-              or config.security == PSK1_SECURITY:
+              or config.security == PSK1_SECURITY\
+              or config.security == SAEMIXED_SECURITY:
         self.ssh.run("uci set wireless.%s.key='%s'" %
                      (config.name, config.password))
       elif config.security == WEP_SECURITY:
diff --git a/acts/framework/acts/libs/ota/ota_tools/update_device_ota_tool.py b/acts/framework/acts/libs/ota/ota_tools/update_device_ota_tool.py
index ec5d7d7..7d5d772 100644
--- a/acts/framework/acts/libs/ota/ota_tools/update_device_ota_tool.py
+++ b/acts/framework/acts/libs/ota/ota_tools/update_device_ota_tool.py
@@ -25,7 +25,7 @@
 
 # OTA Packages can be upwards of 1 GB. This may take some time to transfer over
 # USB 2.0. A/B devices must also complete the update in the background.
-UPDATE_TIMEOUT = 30 * 60
+UPDATE_TIMEOUT = 60 * 60
 UPDATE_LOCATION = '/data/ota_package/update.zip'
 
 
diff --git a/acts_tests/acts_contrib/test_utils/net/connectivity_const.py b/acts_tests/acts_contrib/test_utils/net/connectivity_const.py
index 49996c6..591c83f 100644
--- a/acts_tests/acts_contrib/test_utils/net/connectivity_const.py
+++ b/acts_tests/acts_contrib/test_utils/net/connectivity_const.py
@@ -74,13 +74,29 @@
 MULTIPATH_PREFERENCE_PERFORMANCE = 1 << 2
 
 # Private DNS constants
-DNS_GOOGLE = "dns.google"
-DNS_QUAD9 = "dns.quad9.net"
-DNS_CLOUDFLARE = "1dot1dot1dot1.cloudflare-dns.com"
+DNS_GOOGLE_HOSTNAME = "dns.google"
+DNS_QUAD9_HOSTNAME = "dns.quad9.net"
+DNS_CLOUDFLARE_HOSTNAME = "1dot1dot1dot1.cloudflare-dns.com"
+DOH_CLOUDFLARE_HOSTNAME = "cloudflare-dns.com"
 PRIVATE_DNS_MODE_OFF = "off"
 PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic"
 PRIVATE_DNS_MODE_STRICT = "hostname"
 
+DNS_SUPPORT_TYPE = {
+    DNS_GOOGLE_HOSTNAME: ["Do53", "DoT", "DoH"],
+    DNS_CLOUDFLARE_HOSTNAME: ["Do53","DoT"],
+    DOH_CLOUDFLARE_HOSTNAME: ["DoH"]
+}
+
+DNS_GOOGLE_ADDR_V4 = ["8.8.4.4", "8.8.8.8"]
+DNS_GOOGLE_ADDR_V6 = ["2001:4860:4860::8888",
+                      "2001:4860:4860::8844"]
+DNS_CLOUDFLARE_ADDR_V4 = ["1.1.1.1", "1.0.0.1"]
+DOH_CLOUDFLARE_ADDR_V4 = ["104.16.248.249", "104.16.249.249"]
+DOH_CLOUDFLARE_ADDR_V6 = ["2606:4700::6810:f8f9",
+                          "2606:4700::6810:f9f9"]
+
+
 # IpSec constants
 SOCK_STREAM = 1
 SOCK_DGRAM = 2
diff --git a/acts_tests/acts_contrib/test_utils/wifi/WifiBaseTest.py b/acts_tests/acts_contrib/test_utils/wifi/WifiBaseTest.py
index ab87f88..1f80858 100644
--- a/acts_tests/acts_contrib/test_utils/wifi/WifiBaseTest.py
+++ b/acts_tests/acts_contrib/test_utils/wifi/WifiBaseTest.py
@@ -406,10 +406,12 @@
             ent_network_pwd=False,
             owe_network=False,
             sae_network=False,
+            saemixed_network=False,
             radius_conf_2g=None,
             radius_conf_5g=None,
             radius_conf_pwd=None,
-            ap_count=1):
+            ap_count=1,
+            ieee80211w=None):
         """Create, configure and start OpenWrt AP.
 
         Args:
@@ -429,10 +431,12 @@
             ent_network_pwd: Boolean, to check if ent pwd network should be configured.
             owe_network: Boolean, to check if owe network should be configured.
             sae_network: Boolean, to check if sae network should be configured.
+            saemixed_network: Boolean, to check if saemixed 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.
+            ieee80211w:PMF to configure
         """
         if mirror_ap and ap_count == 1:
             raise ValueError("ap_count cannot be 1 if mirror_ap is True.")
@@ -458,6 +462,7 @@
         self.open_network = []
         self.owe_networks = []
         self.sae_networks = []
+        self.saemixed_networks = []
         self.bssid_map = []
         for i in range(ap_count):
             network_list = []
@@ -470,6 +475,8 @@
                                                  passphrase_length_5g)
                 wpa1_dict[hostapd_constants.BAND_2G]["security"] = "psk"
                 wpa1_dict[hostapd_constants.BAND_5G]["security"] = "psk"
+                wpa1_dict[hostapd_constants.BAND_2G]["ieee80211w"] = ieee80211w
+                wpa1_dict[hostapd_constants.BAND_5G]["ieee80211w"] = ieee80211w
                 self.wpa1_networks.append(wpa1_dict)
                 network_list.append(wpa1_dict)
             if wpa_network:
@@ -481,6 +488,8 @@
                                                 passphrase_length_5g)
                 wpa_dict[hostapd_constants.BAND_2G]["security"] = "psk2"
                 wpa_dict[hostapd_constants.BAND_5G]["security"] = "psk2"
+                wpa_dict[hostapd_constants.BAND_2G]["ieee80211w"] = ieee80211w
+                wpa_dict[hostapd_constants.BAND_5G]["ieee80211w"] = ieee80211w
                 self.wpa_networks.append(wpa_dict)
                 network_list.append(wpa_dict)
             if wep_network:
@@ -533,6 +542,18 @@
                 sae_dict[hostapd_constants.BAND_2G]["security"] = "sae"
                 sae_dict[hostapd_constants.BAND_5G]["security"] = "sae"
                 network_list.append(sae_dict)
+            if saemixed_network:
+                saemixed_dict = self.get_psk_network(mirror_ap, self.saemixed_networks,
+                                                hidden, same_ssid,
+                                                hostapd_constants.SAE_KEY_MGMT,
+                                                ssid_length_2g, ssid_length_5g,
+                                                passphrase_length_2g,
+                                                passphrase_length_5g)
+                saemixed_dict[hostapd_constants.BAND_2G]["security"] = "sae-mixed"
+                saemixed_dict[hostapd_constants.BAND_5G]["security"] = "sae-mixed"
+                saemixed_dict[hostapd_constants.BAND_2G]["ieee80211w"] = ieee80211w
+                saemixed_dict[hostapd_constants.BAND_5G]["ieee80211w"] = ieee80211w
+                network_list.append(saemixed_dict)
             self.access_points[i].configure_ap(network_list, channels_2g[i],
                                                channels_5g[i])
             self.access_points[i].start_ap()
diff --git a/acts_tests/acts_contrib/test_utils/wifi/wifi_test_utils.py b/acts_tests/acts_contrib/test_utils/wifi/wifi_test_utils.py
index 420afb8..2e3f336 100755
--- a/acts_tests/acts_contrib/test_utils/wifi/wifi_test_utils.py
+++ b/acts_tests/acts_contrib/test_utils/wifi/wifi_test_utils.py
@@ -909,13 +909,18 @@
         True: if network_ssid is found in scan results.
         False: if network_ssid is not found in scan results.
     """
+    start_time = time.time()
     for num_tries in range(max_tries):
         if start_wifi_connection_scan_and_return_status(ad):
             scan_results = ad.droid.wifiGetScanResults()
             match_results = match_networks({WifiEnums.SSID_KEY: network_ssid},
                                            scan_results)
             if len(match_results) > 0:
+                ad.log.debug("Found network in %s seconds." %
+                             (time.time() - start_time))
                 return True
+    ad.log.debug("Did not find network in %s seconds." %
+                 (time.time() - start_time))
     return False
 
 
@@ -1466,11 +1471,9 @@
         ad.droid.wifiStopTrackingStateChange()
 
 
-def connect_to_wifi_network(ad,
-                            network,
-                            assert_on_fail=True,
-                            check_connectivity=True,
-                            hidden=False):
+def connect_to_wifi_network(ad, network, assert_on_fail=True,
+                            check_connectivity=True, hidden=False,
+                            num_of_scan_tries=3, num_of_connect_tries=3):
     """Connection logic for open and psk wifi networks.
 
     Args:
@@ -1479,16 +1482,20 @@
         assert_on_fail: If true, errors from wifi_connect will raise
                         test failure signals.
         hidden: Is the Wifi network hidden.
+        num_of_scan_tries: The number of times to try scan
+                           interface before declaring failure.
+        num_of_connect_tries: The number of times to try
+                              connect wifi before declaring failure.
     """
     if hidden:
         start_wifi_connection_scan_and_ensure_network_not_found(
-            ad, network[WifiEnums.SSID_KEY])
+            ad, network[WifiEnums.SSID_KEY], max_tries=num_of_scan_tries)
     else:
         start_wifi_connection_scan_and_ensure_network_found(
-            ad, network[WifiEnums.SSID_KEY])
+            ad, network[WifiEnums.SSID_KEY], max_tries=num_of_scan_tries)
     wifi_connect(ad,
                  network,
-                 num_of_tries=3,
+                 num_of_tries=num_of_connect_tries,
                  assert_on_fail=assert_on_fail,
                  check_connectivity=check_connectivity)
 
diff --git a/acts_tests/tests/google/net/CaptivePortalTest.py b/acts_tests/tests/google/net/CaptivePortalTest.py
index eaafa25..7542ee9 100644
--- a/acts_tests/tests/google/net/CaptivePortalTest.py
+++ b/acts_tests/tests/google/net/CaptivePortalTest.py
@@ -16,6 +16,7 @@
 import time
 
 from acts import asserts
+from acts.controllers.openwrt_ap import MOBLY_CONTROLLER_CONFIG_NAME as OPENWRT
 from acts import base_test
 from acts.test_decorators import test_tracker_info
 from acts_contrib.test_utils.net import connectivity_const as cconst
@@ -33,8 +34,8 @@
 SIGN_IN_NOTIFICATION = "Sign in to network"
 
 
-class CaptivePortalTest(base_test.BaseTestClass):
-    """Tests for Captive portal."""
+class CaptivePortalTest(WifiBaseTest):
+    """Check device can access the network after pass captive portal check."""
 
     def setup_class(self):
         """Setup devices for tests and unpack params.
@@ -48,10 +49,20 @@
           4. uic_zip: Zip file location of UICD application
         """
         self.dut = self.android_devices[0]
-        req_params = ["rk_captive_portal", "gg_captive_portal"]
-        self.unpack_userparams(req_param_names=req_params,)
+        opt_params = ["rk_captive_portal", "gg_captive_portal",
+                      "configure_OpenWrt", "wifi_network"]
+        self.unpack_userparams(opt_param_names=opt_params,)
         wutils.wifi_test_device_init(self.dut)
 
+        if OPENWRT in self.user_params:
+            self.openwrt = self.access_points[0]
+            if hasattr(self, "configure_OpenWrt") and self.configure_OpenWrt == "skip":
+                self.dut.log.info("Skip configure Wifi interface due to config setup.")
+            else:
+                self.configure_openwrt_ap_and_start(wpa_network=True)
+                self.wifi_network = self.openwrt.get_wifi_network()
+            self.openwrt.network_setting.setup_captive_portal()
+
     def teardown_class(self):
         """Reset devices."""
         cutils.set_private_dns(self.dut, cconst.PRIVATE_DNS_MODE_OPPORTUNISTIC)
@@ -76,7 +87,7 @@
             uutils.has_element(self.dut, text="Network & internet"),
             "Failed to find 'Network & internet' icon")
         uutils.wait_and_click(self.dut, text="Network & internet")
-        uutils.wait_and_click(self.dut, text="Not connected")
+        uutils.wait_and_click(self.dut, text="Internet")
 
     def _verify_sign_in_notification(self):
         """Verify sign in notification shows for captive portal."""
@@ -225,3 +236,44 @@
 
         # verify connection to captive portal network
         self._verify_captive_portal(self.gg_captive_portal)
+
+    @test_tracker_info(uuid="c25a1be7-f202-41c4-ac95-bed1720833ab")
+    def test_openwrt_captive_portal_default(self):
+        """Verify captive portal network.
+
+        Steps:
+            1. Set default private dns mode
+            2. Connect to openwrt captive portal network
+            3. Verify connectivity
+        """
+        cutils.set_private_dns(self.dut, cconst.PRIVATE_DNS_MODE_OPPORTUNISTIC)
+        self.openwrt.network_setting.service_manager.restart("nodogsplash")
+        self._verify_captive_portal(self.wifi_network, click_accept="Continue")
+
+    @test_tracker_info(uuid="1419e36d-0303-44ba-bc60-4d707b45ef48")
+    def test_openwrt_captive_portal_private_dns_off(self):
+        """Verify captive portal network.
+
+        Steps:
+            1. Turn off private dns mode
+            2. Connect to openwrt captive portal network
+            3. Verify connectivity
+        """
+        cutils.set_private_dns(self.dut, cconst.PRIVATE_DNS_MODE_OFF)
+        self.openwrt.network_setting.service_manager.restart("nodogsplash")
+        self._verify_captive_portal(self.wifi_network, click_accept="Continue")
+
+    @test_tracker_info(uuid="5aae44ee-fa62-47b9-9b3d-8121f9f92da1")
+    def test_openwrt_captive_portal_private_dns_strict(self):
+        """Verify captive portal network.
+
+        Steps:
+            1. Set strict private dns mode
+            2. Connect to openwrt captive portal network
+            3. Verify connectivity
+        """
+        cutils.set_private_dns(self.dut,
+                               cconst.PRIVATE_DNS_MODE_STRICT,
+                               cconst.DNS_GOOGLE)
+        self.openwrt.network_setting.service_manager.restart("nodogsplash")
+        self._verify_captive_portal(self.wifi_network, click_accept="Continue")
diff --git a/acts_tests/tests/google/net/DNSTest.py b/acts_tests/tests/google/net/DNSTest.py
new file mode 100644
index 0000000..d0f99d9
--- /dev/null
+++ b/acts_tests/tests/google/net/DNSTest.py
@@ -0,0 +1,132 @@
+#
+#   Copyright 2021 - The Android Open Source Project
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+import random
+
+from acts import asserts
+from acts.controllers.openwrt_ap import MOBLY_CONTROLLER_CONFIG_NAME as OPENWRT
+from acts_contrib.test_utils.wifi import wifi_test_utils as wutils
+from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest
+from scapy.all import rdpcap, DNSRR, DNSQR, IP, IPv6
+
+
+WLAN = "wlan0"
+PING_ADDR = "google.com"
+
+
+class DNSTest(WifiBaseTest):
+    """DNS related test for Android."""
+
+    def setup_class(self):
+        self.dut = self.android_devices[0]
+        wutils.wifi_test_device_init(self.dut)
+
+        req_params = []
+        opt_param = ["wifi_network", "configure_OpenWrt"]
+        self.unpack_userparams(
+            req_param_names=req_params, opt_param_names=opt_param)
+
+        asserts.assert_true(OPENWRT in self.user_params,
+                            "OpenWrtAP is not in testbed.")
+        self.openwrt = self.access_points[0]
+        if hasattr(self, "configure_OpenWrt") and self.configure_OpenWrt == "skip":
+            self.dut.log.info("Skip configure Wifi interface due to config setup.")
+        else:
+            self.configure_openwrt_ap_and_start(wpa_network=True)
+            self.wifi_network = self.openwrt.get_wifi_network()
+
+        asserts.assert_true(self.openwrt.verify_wifi_status(),
+                            "OpenWrt Wifi interface is not ready.")
+
+    def teardown_class(self):
+        """Reset wifi to make sure VPN tears down cleanly."""
+        wutils.reset_wifi(self.dut)
+
+    def teardown_test(self):
+        """Reset wifi to make sure VPN tears down cleanly."""
+        wutils.reset_wifi(self.dut)
+
+    def ping(self, addr, ignore_status=True, timeout=60):
+        """Start a ping from DUT and return ping result.
+
+        Args:
+            addr: Address to ping.
+            ignore_status: ignore non zero return.
+            timeout: cmd timeout.
+        Returns:
+            Boolean for ping result.
+        """
+        return "100%" not in self.dut.adb.shell("ping -c 1 %s" % addr,
+                                                ignore_status=ignore_status,
+                                                timeout=timeout)
+
+    def generate_query_qname(self):
+        """Return a random query name."""
+        return "%s-ds.metric.gstatic.com" % random.randint(0, 99999999)
+
+    def test_dns_query(self):
+        # Setup environment
+        wutils.connect_to_wifi_network(self.dut, self.wifi_network)
+        # Start tcpdump on OpenWrt
+        remote_pcap_path = self.openwrt.network_setting.start_tcpdump(self.test_name)
+        # Generate query name
+        test_qname = self.generate_query_qname()
+        self.dut.log.info("Test query name = %s" % test_qname)
+        # Start send a query
+        ping_result = self.ping(test_qname)
+        local_pcap_path = self.openwrt.network_setting.stop_tcpdump(remote_pcap_path,
+                                                                    self.dut.device_log_path)
+        # Check DNSRR.rrname in tcpdump to verify DNS response
+        packets = rdpcap(local_pcap_path)
+        self.dut.log.info("pcap file path : %s" % local_pcap_path)
+        pkt_count = 0
+        for pkt in packets:
+            if pkt.haslayer(DNSRR) and pkt[DNSRR].rrname.decode().strip(".") == test_qname:
+                pkt_count = pkt_count + 1
+        self.dut.log.info("DNS query response count : %s" % pkt_count)
+        if not ping_result:
+            asserts.assert_true(pkt_count > 0,
+                                "Did not find match standard query response in tcpdump.")
+        asserts.assert_true(ping_result, "Device ping fail.")
+
+    def test_dns_query_retransmit(self):
+        # Setup environment
+        wutils.connect_to_wifi_network(self.dut, self.wifi_network)
+        self.openwrt.network_setting.block_dns_response()
+        # Start tcpdump on OpenWrt
+        remote_pcap_path = self.openwrt.network_setting.start_tcpdump(self.test_name)
+        # Generate query name
+        test_qname = self.generate_query_qname()
+        self.dut.log.info("Test query name = %s" % test_qname)
+        # Start send a query
+        self.ping(test_qname)
+        local_pcap_path = self.openwrt.network_setting.stop_tcpdump(remote_pcap_path,
+                                                                    self.dut.device_log_path)
+        # Check DNSQR.qname in tcpdump to verify device retransmit the query
+        packets = rdpcap(local_pcap_path)
+        self.dut.log.info("pcap file path : %s" % local_pcap_path)
+        pkt_count = 0
+        pkt6_count = 0
+        for pkt in packets:
+            if pkt.haslayer(DNSQR) and pkt[DNSQR].qname.decode().strip(".") == test_qname:
+                if pkt.haslayer(IP):
+                    pkt_count = pkt_count + 1
+                if pkt.haslayer(IPv6):
+                    pkt6_count = pkt6_count + 1
+        self.dut.log.info("IPv4 DNS query count : %s" % pkt_count)
+        self.dut.log.info("IPv6 DNS query count : %s" % pkt6_count)
+        self.openwrt.network_setting.unblock_dns_response()
+        asserts.assert_true(pkt_count >= 2 or pkt6_count >= 2,
+                            "Did not find match standard query in tcpdump.")
diff --git a/acts_tests/tests/google/net/DhcpTest.py b/acts_tests/tests/google/net/DhcpTest.py
new file mode 100644
index 0000000..739f6ca
--- /dev/null
+++ b/acts_tests/tests/google/net/DhcpTest.py
@@ -0,0 +1,92 @@
+#
+#   Copyright 2021 - The Android Open Source Project
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+import time
+
+from acts import asserts
+from acts.controllers.openwrt_ap import MOBLY_CONTROLLER_CONFIG_NAME as OPENWRT
+from acts_contrib.test_utils.wifi import wifi_test_utils as wutils
+from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest
+
+WLAN = "wlan0"
+PING_ADDR = "google.com"
+
+
+class DhcpTest(WifiBaseTest):
+    """DHCP related test for Android."""
+
+    def setup_class(self):
+        self.dut = self.android_devices[0]
+
+        wutils.wifi_test_device_init(self.dut)
+        asserts.assert_true(OPENWRT in self.user_params,
+                            "OpenWrtAP is not in testbed.")
+        self.openwrt = self.access_points[0]
+        self.configure_openwrt_ap_and_start(wpa_network=True)
+        self.wifi_network = self.openwrt.get_wifi_network()
+        self.openwrt.network_setting.setup_ipv6_bridge()
+        asserts.assert_true(self.openwrt.verify_wifi_status(),
+                            "OpenWrt Wifi interface is not ready.")
+    def teardown_class(self):
+        """Reset wifi to make sure VPN tears down cleanly."""
+        wutils.reset_wifi(self.dut)
+
+    def teardown_test(self):
+        """Reset wifi to make sure VPN tears down cleanly."""
+        wutils.reset_wifi(self.dut)
+
+    def _verify_ping(self, option="", dest=PING_ADDR):
+        try:
+            out = self.dut.adb.shell("ping%s -c1 %s" % (option, dest))
+            return "100%" not in out
+        except Exception as e:
+            self.dut.log.debug(e)
+            return False
+
+    def _verify_device_address(self, ipv4=True, ipv6=True, timeout=15):
+        """Verify device get assign address on wireless interface."""
+        current_time = time.time()
+        while time.time() < current_time + timeout:
+            try:
+                if ipv4:
+                    ipv4_addr = self.dut.droid.connectivityGetIPv4Addresses(WLAN)[0]
+                    self.dut.log.info("ipv4_address is %s" % ipv4_addr)
+                if ipv6:
+                    ipv6_addr = self.dut.droid.connectivityGetIPv6Addresses(WLAN)[0]
+                    self.dut.log.info("ipv6_address is %s" % ipv6_addr)
+                return True
+            except:
+                time.sleep(1)
+        return False
+
+    def test_ipv4_ipv6_network(self):
+        """Verify device can get both ipv4 ipv6 address."""
+        wutils.connect_to_wifi_network(self.dut, self.wifi_network)
+
+        asserts.assert_true(self._verify_device_address(),
+                            "Fail to get ipv4/ipv6 address.")
+        asserts.assert_true(self._verify_ping(), "Fail to ping on ipv4.")
+        asserts.assert_true(self._verify_ping("6"), "Fail to ping on ipv6.")
+
+    def test_ipv6_only_prefer_option(self):
+        """Verify DUT can only get ipv6 address and ping out."""
+        self.openwrt.network_setting.add_ipv6_prefer_option()
+        wutils.connect_to_wifi_network(self.dut, self.wifi_network)
+
+        asserts.assert_true(self._verify_device_address(ipv4=False),
+                            "Fail to get ipv6 address.")
+        asserts.assert_false(self._verify_ping(),
+                             "Should not ping on success on ipv4.")
+        asserts.assert_true(self._verify_ping("6"),
+                            "Fail to ping on ipv6.")
diff --git a/acts_tests/tests/google/net/DnsOverHttpsTest.py b/acts_tests/tests/google/net/DnsOverHttpsTest.py
new file mode 100644
index 0000000..56f3792
--- /dev/null
+++ b/acts_tests/tests/google/net/DnsOverHttpsTest.py
@@ -0,0 +1,295 @@
+#
+#   Copyright 2021 - The Android Open Source Project
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+import time
+
+from acts import asserts
+from acts.controllers.openwrt_ap import MOBLY_CONTROLLER_CONFIG_NAME as OPENWRT
+from acts.test_decorators import test_tracker_info
+from acts_contrib.test_utils.net import connectivity_const as cconst
+from acts_contrib.test_utils.net import connectivity_test_utils as cutils
+from acts_contrib.test_utils.net.net_test_utils import start_tcpdump
+from acts_contrib.test_utils.net.net_test_utils import stop_tcpdump
+from acts_contrib.test_utils.wifi import wifi_test_utils as wutils
+from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest
+from scapy.all import rdpcap
+from scapy.all import Scapy_Exception
+from scapy.all import TCP
+from scapy.all import UDP
+
+
+DEFAULT_DNS_TIMEOUT = 5
+
+
+class DnsOverHttpsTest(WifiBaseTest):
+    """Tests for DnsoverHttps feature."""
+
+    def setup_class(self):
+        """Setup devices and OpenWrt for DnsoverHttps test and unpack params."""
+
+        self.dut = self.android_devices[0]
+        if len(self.android_devices) > 1:
+            self.dut_b = self.android_devices[1]
+        for ad in self.android_devices:
+            wutils.reset_wifi(ad)
+            ad.droid.setPrivateDnsMode(True)
+        req_params = ("ping_hosts",)
+        opt_params = ("wifi_network", "configure_OpenWrt",
+                      "ipv4_only_network", "ipv4_ipv6_network")
+        self.unpack_userparams(req_param_names=req_params,
+                               opt_param_names=opt_params)
+        if OPENWRT in self.user_params:
+            self.openwrt = self.access_points[0]
+            if hasattr(self, "configure_OpenWrt") and self.configure_OpenWrt == "skip":
+                self.dut.log.info("Skip configure Wifi interface due to config setup.")
+            else:
+                self.configure_openwrt_ap_and_start(wpa_network=True)
+        self.tcpdump_pid = None
+        self.default_dns = None
+        self.default_dns_v6 = None
+        self._setup_doh(self.dut, self.get_wifi_network())
+
+    def teardown_test(self):
+        wutils.reset_wifi(self.dut)
+        if OPENWRT in self.user_params:
+            self.openwrt.network_setting.del_default_dns(self.default_dns)
+            self.default_dns = None
+            self.default_dns_v6 = None
+
+    def teardown_class(self):
+        for ad in self.android_devices:
+            ad.droid.setPrivateDnsMode(True)
+            self._setup_doh(ad, self.get_wifi_network(), enable=False)
+
+    def on_fail(self, test_name, begin_time):
+        self.dut.take_bug_report(test_name, begin_time)
+
+    def get_wifi_network(self, ipv6_supported=False):
+        """Return fit network for conditions.
+
+        Args:
+            ipv6_supported: Boolean for select network.
+        Returns:
+            A dict for network object for connect wifi.
+        """
+        if OPENWRT in self.user_params:
+            if ipv6_supported:
+                self.openwrt.network_setting.enable_ipv6()
+                self.openwrt.network_setting.setup_ipv6_bridge()
+            else:
+                self.openwrt.network_setting.disable_ipv6()
+                self.openwrt.network_setting.remove_ipv6_bridge()
+            if self.default_dns:
+                self.openwrt.network_setting.add_default_dns(self.default_dns)
+            if self.default_dns_v6:
+                for ipv6_dns in self.default_dns_v6:
+                    self.openwrt.network_setting.add_default_v6_dns(ipv6_dns)
+            if hasattr(self, "configure_OpenWrt") and self.configure_OpenWrt == "skip":
+                return self.wifi_network
+            return self.openwrt.get_wifi_network()
+        if ipv6_supported:
+            return self.ipv4_ipv6_network
+        return self.ipv4_only_network
+
+    def _verify_doh_queries(self, pcap_file, over_https):
+        """Verify if DNS queries were over https or not.
+
+        Args:
+            pcap_file: tcpdump file
+            over_https: True if excepted all dns go through doh.
+        """
+        try:
+            packets = rdpcap(pcap_file)
+        except Scapy_Exception:
+            asserts.fail("Not a valid pcap file")
+
+        for pkt in packets:
+            summary = "%s" % pkt.summary()
+            for host in self.ping_hosts:
+                host = host.split(".")[-2]
+                if UDP in pkt and pkt[UDP].sport == 53 and host in summary:
+                    if over_https:
+                        asserts.fail("Found query to port 53: %s" % summary)
+                    else:
+                        self.dut.log.info("Found query to port 53: %s" % summary)
+                if TCP in pkt and pkt[TCP].sport == 853:
+                    asserts.fail("Found query to port 853: %s" % summary)
+
+    def _test_public_doh_mode(self, ad, net, dns_mode, hostname=None):
+        """Test step for DoH.
+
+        Args:
+            ad: android device object.
+            net: wifi network to connect to, LTE network if None.
+            dns_mode: private DNS mode.
+            hostname: private DNS hostname to set to.
+        """
+
+        # set private dns mode
+        if dns_mode:
+            cutils.set_private_dns(self.dut, dns_mode, hostname)
+        # connect to wifi
+        wutils.start_wifi_connection_scan_and_ensure_network_found(
+            self.dut, net[wutils.WifiEnums.SSID_KEY])
+        wutils.wifi_connect(self.dut, net)
+        self._verify_tls_completed()
+
+        # start tcpdump on the device
+        self.tcpdump_pid = start_tcpdump(self.dut, self.test_name)
+
+        # ping hosts should pass
+        for host in self.ping_hosts:
+            self.log.info("Pinging %s" % host)
+            status = wutils.validate_connection(self.dut, host)
+            asserts.assert_true(status, "Failed to ping host %s" % host)
+            self.log.info("Ping successful")
+
+        # stop tcpdump
+        pcap_file = stop_tcpdump(self.dut, self.tcpdump_pid, self.test_name)
+
+        # verify DNS queries
+        overhttps = dns_mode != cconst.PRIVATE_DNS_MODE_OFF
+        self._verify_doh_queries(pcap_file, overhttps)
+
+        # reset wifi
+        wutils.reset_wifi(self.dut)
+
+    def _verify_tls_completed(self, retry_count=5):
+        """Verify tls finish verification process.
+
+        Expect all private dns server status, should be
+        "success", or "fail".
+
+        Args:
+            retry_count: int for retry times.
+        Raises:
+            TimeoutError: if TLS verification stuck in processing.
+        """
+        for attempt in range(retry_count):
+            out = self.dut.adb.shell("dumpsys dnsresolver")
+            if "status{in_process}" in out:
+                if attempt + 1 < retry_count:
+                    self.dut.log.info("DoT still validating, retrying...")
+                    time.sleep(DEFAULT_DNS_TIMEOUT)
+            else:
+                return
+        raise TimeoutError("Fail to completed TLS verification.")
+
+    def _setup_doh(self, ad, net, enable=True):
+        """Enable/Disable DoH option.
+
+        Args:
+            ad: android devies.
+            net: network as wifi.
+            enable: if True, sets the 'doh' experiment flag.
+        """
+        if enable:
+            ad.adb.shell("setprop persist.device_config.netd_native.doh 1")
+        else:
+            ad.adb.shell("setprop persist.device_config.netd_native.doh 0")
+        wutils.wifi_connect(ad, net)
+        wutils.reset_wifi(ad)
+        out = ad.adb.shell("dumpsys dnsresolver |grep doh")
+        ad.log.debug(out)
+
+    def test_mix_server_ipv4_only_wifi_network_with_dns_strict_mode(self):
+        """Test doh flag with below situation.
+
+        - Android device in strict mode
+        - DNS server supporting both Dns, DoT and DoH protocols
+        - IPv4-only network
+        """
+        self._test_public_doh_mode(self.dut, self.get_wifi_network(),
+                                   cconst.PRIVATE_DNS_MODE_STRICT,
+                                   hostname=cconst.DNS_GOOGLE_HOSTNAME)
+
+    def test_mix_server_ipv4_ipv6_wifi_network_with_dns_strict_mode(self):
+        """Test doh flag with below situation.
+
+        - Android device in strict mode
+        - DNS server supporting both Dns, DoT and DoH protocols
+        - IPv4-IPv6 network
+        """
+        self._test_public_doh_mode(self.dut, self.get_wifi_network(),
+                                   cconst.PRIVATE_DNS_MODE_STRICT,
+                                   hostname=cconst.DNS_GOOGLE_HOSTNAME)
+
+    def test_pure_server_ipv4_only_wifi_network_with_dns_strict_mode(self):
+        """Test doh flag with below situation.
+
+        - Android device in strict mode
+        - DNS server only supporting DoH protocols
+        - IPv4-only network
+        """
+        self._test_public_doh_mode(self.dut, self.get_wifi_network(),
+                                   cconst.PRIVATE_DNS_MODE_STRICT,
+                                   hostname=cconst.DOH_CLOUDFLARE_HOSTNAME)
+
+    def test_pure_server_ipv4_ipv6_wifi_network_with_dns_strict_mode(self):
+        """Test doh flag with below situation.
+
+        - Android device in strict mode
+        - DNS server only supporting DoH protocols
+        - IPv4-IPv6 network
+        """
+        self._test_public_doh_mode(self.dut, self.get_wifi_network(),
+                                   cconst.PRIVATE_DNS_MODE_STRICT,
+                                   hostname=cconst.DOH_CLOUDFLARE_HOSTNAME)
+
+    def test_mix_server_ipv4_only_wifi_network_with_dns_opportunistic_mode(self):
+        """Test doh flag with below situation.
+
+        - Android device in opportunistic mode
+        - DNS server supporting both Dns, DoT and DoH protocols
+        - IPv4-only network
+        """
+        self.default_dns = cconst.DNS_GOOGLE_ADDR_V4
+        self._test_public_doh_mode(self.dut, self.get_wifi_network(),
+                                   cconst.PRIVATE_DNS_MODE_OPPORTUNISTIC)
+
+    def test_mix_server_ipv4_ipv6_wifi_network_with_dns_opportunistic_mode(self):
+        """Test doh flag with below situation.
+
+        - Android device in opportunistic mode
+        - DNS server supporting both Dns, DoT and DoH protocols
+        - IPv4-IPv6 network
+        """
+        self.default_dns = cconst.DNS_GOOGLE_ADDR_V4
+        self.default_dns_v6 = cconst.DNS_GOOGLE_ADDR_V6
+        self._test_public_doh_mode(self.dut, self.get_wifi_network(),
+                                   cconst.PRIVATE_DNS_MODE_OPPORTUNISTIC)
+
+    def test_mix_server_ipv4_only_wifi_network_with_dns_off_mode(self):
+        """Test doh with below situation.
+
+        - Android device in dns off mode
+        - DNS server supporting both Dns, DoT and DoH protocols
+        - IPv4-only network
+        """
+        self.default_dns = cconst.DNS_GOOGLE_ADDR_V4
+        self._test_public_doh_mode(self.dut, self.get_wifi_network(),
+                                   cconst.PRIVATE_DNS_MODE_OFF)
+
+    def test_mix_server_ipv4_ipv6_wifi_network_with_dns_off_mode(self):
+        """Test doh with below situation.
+
+        - Android device in dns off mode
+        - DNS server supporting both Dns, DoT and DoH protocols
+        - IPv4-IPv6 network
+        """
+        self.default_dns = cconst.DNS_GOOGLE_ADDR_V4
+        self.default_dns_v6 = cconst.DNS_GOOGLE_ADDR_V6
+        self._test_public_doh_mode(self.dut, self.get_wifi_network(),
+                                   cconst.PRIVATE_DNS_MODE_OFF)
diff --git a/acts_tests/tests/google/net/LegacyVpnTest.py b/acts_tests/tests/google/net/LegacyVpnTest.py
index 6e9710b..4003a2f 100644
--- a/acts_tests/tests/google/net/LegacyVpnTest.py
+++ b/acts_tests/tests/google/net/LegacyVpnTest.py
@@ -43,7 +43,8 @@
         req_params = [
             x for x in req_params if not x.startswith("__")
         ]
-        opt_params = ["wifi_network", "vpn_cert_country", "vpn_cert_org"]
+        opt_params = ["wifi_network", "vpn_cert_country",
+                      "vpn_cert_org", "configure_OpenWrt"]
         self.unpack_userparams(req_param_names=req_params,
                                opt_param_names=opt_params)
 
@@ -51,8 +52,12 @@
         wutils.wifi_toggle_state(self.dut, True)
         if OPENWRT in self.user_params:
             self.openwrt = self.access_points[0]
-            self.configure_openwrt_ap_and_start(wpa_network=True)
-            self.wifi_network = self.openwrt.get_wifi_network()
+            if hasattr(self, "configure_OpenWrt") and self.configure_OpenWrt == "skip":
+                self.dut.log.info("Skip configure Wifi interface due to config setup.")
+            else:
+                self.configure_openwrt_ap_and_start(wpa_network=True)
+                self.wifi_network = self.openwrt.get_wifi_network()
+
             # Wait for OpenWrt statement update
             time.sleep(10)
             self.openwrt.network_setting.setup_vpn_pptp_server(
diff --git a/acts_tests/tests/google/net/MutlicastDNSTest.py b/acts_tests/tests/google/net/MutlicastDNSTest.py
new file mode 100644
index 0000000..475ad45
--- /dev/null
+++ b/acts_tests/tests/google/net/MutlicastDNSTest.py
@@ -0,0 +1,79 @@
+#
+#   Copyright 2021 - The Android Open Source Project
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+
+from acts import asserts
+from acts.controllers.openwrt_ap import MOBLY_CONTROLLER_CONFIG_NAME as OPENWRT
+from acts.test_decorators import test_tracker_info
+from acts_contrib.test_utils.wifi import wifi_test_utils as wutils
+from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest
+
+
+class MulticastDNSTest(WifiBaseTest):
+    """Verify Multicast DNS can work on Android devices."""
+
+    def setup_class(self):
+        """Setup Openwrt and unpack params for mDNS test."""
+        self.dut = self.android_devices[0]
+        req_params = []
+        opt_params = ["configure_OpenWrt", "wifi_network"]
+        self.unpack_userparams(req_params, opt_params)
+        if OPENWRT in self.user_params:
+            self.openwrt = self.access_points[0]
+            if hasattr(self, "configure_OpenWrt") and self.configure_OpenWrt == "skip":
+                self.dut.log.info("Skip configure Wifi interface due to config setup.")
+            else:
+                self.configure_openwrt_ap_and_start(wpa_network=True)
+                self.wifi_network = self.openwrt.get_wifi_network()
+
+    def on_fail(self, test_name, begin_time):
+        """Take bugreport if test failed."""
+        self.dut.take_bug_report(test_name, begin_time)
+
+    def teardown_test(self):
+        """Reset wifi settings after test case."""
+        wutils.reset_wifi(self.dut)
+
+    def verify_ping(self, hostname, expect_ping_pass=True):
+        """Verify if result of the ping as excepted.
+
+        Args:
+            hostname: ping address.
+            expect_ping_pass: excepted ping result is True or False.
+        Returns:
+            Boolean if ping result work as expected.
+        """
+        out = self.dut.adb.shell("ping -c 1 %s" % hostname)
+        result = ("100%" not in out) == expect_ping_pass
+        if not result:
+            self.dut.log.info(out)
+        return result
+
+    def test_mdns_query_ipv4_only(self):
+        """Verify mdns query work in ipv4 only network."""
+        self.openwrt.network_setting.disable_ipv6()
+        self.openwrt.network_setting.setup_mdns()
+        wutils.wifi_connect(self.dut, self.wifi_network)
+        asserts.assert_true(self.verify_ping("openwrt.local"),
+                            "Fail to ping openwrt.local.")
+
+    def test_mdns_query_ipv4_ipv6(self):
+        """Verify mdns query work in ipv4 & ipv6 network."""
+        self.openwrt.network_setting.enable_ipv6()
+        self.openwrt.network_setting.setup_mdns()
+        wutils.wifi_connect(self.dut, self.wifi_network)
+        asserts.assert_true(self.verify_ping("openwrt.local"),
+                            "Fail to ping openwrt.local.")
+
diff --git a/acts_tests/tests/google/wifi/WifiBridgedApTest.py b/acts_tests/tests/google/wifi/WifiBridgedApTest.py
index 87b980c..5cc94d6 100644
--- a/acts_tests/tests/google/wifi/WifiBridgedApTest.py
+++ b/acts_tests/tests/google/wifi/WifiBridgedApTest.py
@@ -25,16 +25,18 @@
 from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest
 from acts.controllers.ap_lib.hostapd_constants import BAND_2G
 from acts.controllers.ap_lib.hostapd_constants import BAND_5G
+from acts.controllers.ap_lib import hostapd_constants
 
 
 WifiEnums = wutils.WifiEnums
+# Each wait time add 5 seconds as buffer.
 BRIDGED_AP_LAUNCH_INTERVAL_5_SECONDS = 5
-BRIDGED_AP_SHUTDOWN_INTERVAL_5_MINUTES = 300
+BRIDGED_AP_SHUTDOWN_INTERVAL_5_MINUTES = 305
 BRIDGED_AP_SHUTDOWN_INTERVAL_5_SECONDS = 5
-SOFT_AP_SHUTDOWN_INTERVAL_10_MINUTES = 600
-INTERVAL_9_MINUTES = 540
-INTERVAL_2_MINUTES = 120
-INTERVAL_1_MINUTES = 60
+SOFT_AP_SHUTDOWN_INTERVAL_10_MINUTES = 605
+INTERVAL_9_MINUTES = 545
+INTERVAL_2_MINUTES = 125
+INTERVAL_1_MINUTES = 65
 
 
 class WifiBridgedApTest(WifiBaseTest):
@@ -44,6 +46,7 @@
         * Android device x 1 with BridgedAp supported.
         * Android devices x2 as clients, at least Android 10.
         * OpenWrt AP x 1.
+        * Google Wi-Fi x 2 as packet captures.
     """
 
     def setup_class(self):
@@ -59,9 +62,6 @@
         if not self.dut.droid.wifiIsBridgedApConcurrencySupported():
             raise signals.TestAbortClass("Legacy phone is not supported")
 
-        for ad in self.android_devices:
-            wutils.wifi_test_device_init(ad)
-
         req_params = ["dbs_supported_models"]
         opt_param = ["cnss_diag_file", "pixel_models"]
 
@@ -85,6 +85,16 @@
             wutils.set_wifi_country_code(
                 ad, wutils.WifiEnums.CountryCode.US)
 
+        # Stop packet captures.
+        if hasattr(self, "sniffer_procs"):
+            for i in range(len(self.sniffer_procs)):
+                try:
+                    wutils.stop_pcap(
+                        self.packet_capture[i], self.sniffer_procs[i], False)
+                    logging.info("packet_capture[{}] is STOPPED".format(i))
+                except:
+                    logging.info("packet_capture[{}] is NOT STOPPED".format(i))
+
     def teardown_class(self):
         super().teardown_class()
         for ad in self.android_devices:
@@ -102,7 +112,7 @@
         country = ad.droid.wifiGetCountryCode()
         asserts.assert_true(country == country_code,
                             "country code {} is not set".format(country_code))
-        ad.log.info("code code set to : {}".format(country))
+        ad.log.info("Country code set to : {}".format(country))
 
     def verify_clients_support_wpa3_sae(self, *args):
         """Check if clients support WPA3 SAE.
@@ -125,13 +135,16 @@
                    e,g,. [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
                           WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G]
         """
+        self.dut.log.info("Length of infos: {}, Length of bands: {}"
+                          .format(len(infos), len(bands)))
         asserts.assert_true(len(infos) == len(bands),
-                            "length of infos and bands not matched")
+                            "There should be {} BridgedAp instance, "
+                            "instead of {}".format(len(bands), len(infos)))
         if len(bands) == 1 and (bands[0] == WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G):
             asserts.assert_true(infos[0][wifi_constants.
                                 SOFTAP_INFO_FREQUENCY_CALLBACK_KEY]
                                 in WifiEnums.softap_band_frequencies[bands[0]],
-                                "This should be a %s instance", bands[0])
+                                "This should be a {} instance".format(bands[0]))
         if len(bands) == 2 and (bands[0] == WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G):
             asserts.assert_true((infos[0][wifi_constants.
                                 SOFTAP_INFO_FREQUENCY_CALLBACK_KEY]
@@ -171,6 +184,19 @@
                    e,g,. [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
                           WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G]
             freq_equal: True if need to check SoftAp freq equals to STA freq.
+
+        Returns:
+            infos: A List of SoftAp info, e.g.,
+                [{'autoShutdownTimeoutMillis': 600000,
+                  'bandwidth': 4,
+                  'bssid': '12:dd:0b:b9:4b:cc',
+                  'frequency': 5180,
+                  'wifiStandard': 6},
+                 {'autoShutdownTimeoutMillis': 600000,
+                  'bandwidth': 2,
+                  'bssid': '12:22:f4:b9:4b:cc',
+                  'frequency': 2462,
+                  'wifiStandard': 4}]
         """
         callbackId = ad.droid.registerSoftApCallback()
         infos = wutils.get_current_softap_infos(ad, callbackId, True)
@@ -178,6 +204,7 @@
         if freq_equal:
             self.verify_softap_freq_equals_to_ap_freq(ad, infos)
         ad.droid.unregisterSoftApCallback(callbackId)
+        return infos
 
     def verify_expected_number_of_softap_clients(self, ad, number):
         """Verify the number of softap clients.
@@ -219,6 +246,148 @@
             logging.info("Wait {} minutes".format(interval/60))
             time.sleep(interval)
 
+    def generate_softap_config(self, security):
+        """Return a soft ap config
+
+        Args:
+            security: String; represent certain security. e.g., "WPA3_SAE"
+        """
+        config = wutils.create_softap_config()
+        config[WifiEnums.SECURITY] = security
+        return config
+
+    def enable_bridged_ap(self, ad, security, bands, **kwargs):
+        """Enable BridgedAp.
+
+        Args:
+            security: String; represent certain security. e.g., "WPA3_SAE"
+            bands: specifies the band list for the soft ap.
+        """
+        self.config = self.generate_softap_config(security)
+        wutils.save_wifi_soft_ap_config(
+                                        ad,
+                                        self.config,
+                                        bands=bands,
+                                        **kwargs)
+        wutils.start_wifi_tethering_saved_config(self.dut)
+        # Wait 5 seconds for BridgedAp launch.
+        self.wait_interval(BRIDGED_AP_LAUNCH_INTERVAL_5_SECONDS)
+
+    def sniffing_bridgedap_channels(self, infos):
+        """Sniff BridgedAp channels.
+
+        Args:
+            infos: A List of SoftAp info. e.g.,
+                [{'autoShutdownTimeoutMillis': 600000,
+                  'bandwidth': 4,
+                  'bssid': '12:dd:0b:b9:4b:cc',
+                  'frequency': 5180,
+                  'wifiStandard': 6},
+                 {'autoShutdownTimeoutMillis': 600000,
+                  'bandwidth': 2,
+                  'bssid': '12:22:f4:b9:4b:cc',
+                  'frequency': 2462,
+                  'wifiStandard': 4}]
+        """
+        if hasattr(self, "packet_capture") and len(self.packet_capture) == 2:
+            # Create sniffer_config.
+            self.sniffer_config = {}
+            for i in range(len(infos)):
+                if (infos[i][WifiEnums.frequency_key] in
+                   WifiEnums.ALL_5G_FREQUENCIES):
+                    self.sniffer_config[BAND_5G] = WifiEnums.freq_to_channel[
+                        int(infos[i][WifiEnums.frequency_key])]
+                if (infos[i][WifiEnums.frequency_key] in
+                   WifiEnums.ALL_2G_FREQUENCIES):
+                    self.sniffer_config[BAND_2G] = WifiEnums.freq_to_channel[
+                        int(infos[i][WifiEnums.frequency_key])]
+            logging.info("sniffer_config : {}".format(self.sniffer_config))
+
+            # Enable sniffers.
+            self.sniffer_procs = []
+            for i in range(len(self.sniffer_config)):
+                self.packet_capture[i].log.info(
+                    "Enable packet_capture[{}]".format(i))
+                result = self.packet_capture[i].configure_monitor_mode(
+                    list(self.sniffer_config.keys())[i],
+                    list(self.sniffer_config.values())[i])
+                if not result:
+                    logging.error("Failed to enable packet_capture"
+                                  "on {}".format(self.packet_capture[i]))
+                self.pcap_procs = wutils.start_pcap(
+                    self.packet_capture[i],
+                    list(self.sniffer_config.keys())[i],
+                    self.test_name)
+                self.sniffer_procs.append(self.pcap_procs)
+            logging.info("sniffer_procs: {}".format(self.sniffer_procs))
+        else:
+            logging.warning("Packet_capture not enabled, "
+                            "because two packet_capture hardware required")
+
+    def sniffing_ap_channels(self, channel1, channel2):
+        """Sniff on two Wi-Fi channels.
+
+        Args:
+            channel1: Integer; a Wi-Fi channel, e.g., 6.
+            channel2: Integer; a Wi-Fi channel, e,g,. 36.
+        """
+        if not channel1:
+            channel1 = hostapd_constants.AP_DEFAULT_CHANNEL_2G
+        if not channel2:
+            channel2 = hostapd_constants.AP_DEFAULT_CHANNEL_5G
+
+        if hasattr(self, "packet_capture") and len(self.packet_capture) == 2:
+            # Create sniffer_config.
+            self.sniffer_config = {}
+            if channel1 in WifiEnums.channel_2G_to_freq:
+                self.sniffer_config[BAND_2G] = channel1
+            if channel1 in WifiEnums.channel_5G_to_freq:
+                self.sniffer_config[BAND_5G] = channel1
+            if channel2 in WifiEnums.channel_2G_to_freq:
+                self.sniffer_config[BAND_2G] = channel2
+            if channel2 in WifiEnums.channel_5G_to_freq:
+                self.sniffer_config[BAND_5G] = channel2
+            logging.info("sniffer_config : {}".format(self.sniffer_config))
+
+            # Enable sniffers.
+            self.sniffer_procs = []
+            for i in range(len(self.sniffer_config)):
+                self.packet_capture[i].log.info(
+                    "Enable packet_capture[{}]".format(i))
+                result = self.packet_capture[i].configure_monitor_mode(
+                    list(self.sniffer_config.keys())[i],
+                    list(self.sniffer_config.values())[i])
+                if not result:
+                    logging.error("Failed to enable packet_capture"
+                                  "on {}".format(self.packet_capture[i]))
+                self.pcap_procs = wutils.start_pcap(
+                    self.packet_capture[i],
+                    list(self.sniffer_config.keys())[i],
+                    self.test_name)
+                self.sniffer_procs.append(self.pcap_procs)
+            logging.info("sniffer_procs: {}".format(self.sniffer_procs))
+        else:
+            logging.debug("Packet_capture not enabled, "
+                          "because two packet_capture hardware required")
+
+    def start_ap(self, channel_2g, channel_5g):
+        """Enable OpenWrt AP with specific 2G/5G channels
+
+        Args:
+            channel_2g: Integer; a 2G channel, e.g., 6.
+            channel_5g: Integer; a 5G channel, e,g,. 36
+        """
+        if not channel_2g:
+            channel_2g = hostapd_constants.AP_DEFAULT_CHANNEL_2G
+        if not channel_5g:
+            channel_5g = hostapd_constants.AP_DEFAULT_CHANNEL_5G
+
+        # Enable OpenWrt AP.
+        if "OpenWrtAP" in self.user_params:
+            self.configure_openwrt_ap_and_start(wpa_network=True,
+                                                channel_2g=channel_2g,
+                                                channel_5g=channel_5g)
+
     def two_clients_connect_to_wifi_network(self, dut1, dut2, config):
         """Connect two clients to different BridgedAp instances.
            This function will be called only when BridgedAp ON.
@@ -269,10 +438,46 @@
         asserts.assert_true(client2_bssid == bssid_2g,
                             "Client2 does not connect to the 2G instance")
 
+    def client_connects_to_a_bridgeap(self, ad, band):
+        """One client connects to a BridgeAp instance
+
+        Args:
+            band: String; '2g' or '5g'.
+        """
+        callbackId = self.dut.droid.registerSoftApCallback()
+        infos = wutils.get_current_softap_infos(self.dut, callbackId, True)
+        self.dut.droid.unregisterSoftApCallback(callbackId)
+        # Make one client connects to 2G instance if band == '2g'.
+        if band == BAND_2G:
+            if (infos[0][wifi_constants.SOFTAP_INFO_FREQUENCY_CALLBACK_KEY]
+               in WifiEnums.ALL_2G_FREQUENCIES):
+                bssid_2g = (infos[0][wifi_constants.
+                            SOFTAP_INFO_BSSID_CALLBACK_KEY])
+            else:
+                bssid_2g = (infos[1][wifi_constants.
+                            SOFTAP_INFO_BSSID_CALLBACK_KEY])
+            config_2g = self.config.copy()
+            config_2g[WifiEnums.BSSID_KEY] = bssid_2g
+            wutils.connect_to_wifi_network(ad, config_2g,
+                                           check_connectivity=False)
+        # Make one client connects to 5G instance if band == '5g'.
+        elif band == BAND_5G:
+            if (infos[0][wifi_constants.SOFTAP_INFO_FREQUENCY_CALLBACK_KEY]
+               in WifiEnums.ALL_5G_FREQUENCIES):
+                bssid_5g = (infos[0][wifi_constants.
+                            SOFTAP_INFO_BSSID_CALLBACK_KEY])
+            else:
+                bssid_5g = (infos[1][wifi_constants.
+                            SOFTAP_INFO_BSSID_CALLBACK_KEY])
+            config_5g = self.config.copy()
+            config_5g[WifiEnums.BSSID_KEY] = bssid_5g
+            wutils.connect_to_wifi_network(ad, config_5g,
+                                           check_connectivity=False)
+
     # Tests
 
     @test_tracker_info(uuid="6f776b4a-b080-4b52-a330-52aa641b18f2")
-    def test_two_clients_ping_on_bridged_ap_band_2_and_5_with_wpa3_in_country_us(self):
+    def test_two_clients_ping_bridged_ap_5g_2g_wpa3_country_us(self):
         """Test clients on different instances can ping each other.
 
         Steps:
@@ -282,14 +487,15 @@
             Enable BridgedAp with bridged configuration.
             RegisterSoftApCallback.
             Check the bridged AP enabled succeed.
+            start sniffer and sniffing on BridgedAp channels.
             Force client#1 connect to 5G.
             Force client#2 connect to 2.4G.
             Trigger client#1 and client#2 each other.
+            Stop sniffers.
             Restore config.
         """
         # Backup config
         original_softap_config = self.dut.droid.wifiGetApConfiguration()
-
         # Make sure clients support WPA3 SAE.
         self.verify_clients_support_wpa3_sae(self.client1, self.client2)
         # Make sure DUT is able to enable BridgedAp.
@@ -298,19 +504,125 @@
         asserts.skip_if(not is_supported, "BridgedAp is not supported in {}"
                         .format(wutils.WifiEnums.CountryCode.US))
 
-        # Enable BridgedAp
-        config = wutils.create_softap_config()
-        config[WifiEnums.SECURITY] = WifiEnums.SoftApSecurityType.WPA3_SAE
-        wutils.save_wifi_soft_ap_config(
-            self.dut, config,
-            bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
-                   WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
-        wutils.start_wifi_tethering_saved_config(self.dut)
-        # Wait 5 seconds for BridgedAp launch.
-        self.wait_interval(BRIDGED_AP_LAUNCH_INTERVAL_5_SECONDS)
+        # Enable BridgedAp and verify both 2G,5G instances have been enabled.
+        self.enable_bridged_ap(self.dut,
+                               WifiEnums.SoftApSecurityType.WPA3_SAE,
+                               bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                                      WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
+        infos = self.verify_number_band_freq_of_bridged_ap(
+            self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                       WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G], False)
+
+        self.sniffing_bridgedap_channels(infos)
 
         self.two_clients_connect_to_wifi_network(self.client1, self.client2,
-                                                 config)
+                                                 self.config)
+        # Trigger client#1 and client#2 ping each other.
+        wutils.validate_ping_between_two_clients(self.client1, self.client2)
+
+        # Restore config
+        wutils.save_wifi_soft_ap_config(self.dut, original_softap_config)
+    @test_tracker_info(uuid="8685a6cb-f7be-4384-b25b-23cecb4cb6dc")
+    def test_two_clients_ping_bridged_ap_5g_2g_wpa3_sae_transition_country_us(self):
+        """Test clients on different instances can ping each other.
+
+        Steps:
+            Refer to test_two_clients_ping_bridged_ap_5g_2g_wpa3_country_us,
+            but this case enable WPA3/WPA2-Personal SoftAp security type.
+        """
+        # Backup config
+        original_softap_config = self.dut.droid.wifiGetApConfiguration()
+        # Make sure clients support WPA3 SAE.
+        self.verify_clients_support_wpa3_sae(self.client1, self.client2)
+        # Make sure DUT is able to enable BridgedAp.
+        is_supported = wutils.check_available_channels_in_bands_2_5(
+            self.dut, wutils.WifiEnums.CountryCode.US)
+        asserts.skip_if(not is_supported, "BridgedAp is not supported in {}"
+                        .format(wutils.WifiEnums.CountryCode.US))
+
+        # Enable BridgedAp and verify both 2G,5G instances have been enabled.
+        self.enable_bridged_ap(self.dut,
+                               WifiEnums.SoftApSecurityType.WPA3_SAE_TRANSITION,
+                               bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                                      WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
+        infos = self.verify_number_band_freq_of_bridged_ap(
+            self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                       WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G], False)
+
+        self.sniffing_bridgedap_channels(infos)
+
+        self.two_clients_connect_to_wifi_network(self.client1, self.client2,
+                                                 self.config)
+        # Trigger client#1 and client#2 ping each other.
+        wutils.validate_ping_between_two_clients(self.client1, self.client2)
+
+        # Restore config
+        wutils.save_wifi_soft_ap_config(self.dut, original_softap_config)
+
+    @test_tracker_info(uuid="b217d4de-cd09-4a8f-b27d-302ae5b86c7e")
+    def test_two_clients_ping_bridged_ap_5g_2g_wpa2_country_us(self):
+        """Test clients on different instances can ping each other.
+
+        Steps:
+            Refer to test_two_clients_ping_bridged_ap_5g_2g_wpa3_country_us,
+            but this case enable WPA2-Personal SoftAp security type.
+        """
+        # Backup config
+        original_softap_config = self.dut.droid.wifiGetApConfiguration()
+        # Make sure DUT is able to enable BridgedAp.
+        is_supported = wutils.check_available_channels_in_bands_2_5(
+            self.dut, wutils.WifiEnums.CountryCode.US)
+        asserts.skip_if(not is_supported, "BridgedAp is not supported in {}"
+                        .format(wutils.WifiEnums.CountryCode.US))
+
+        # Enable BridgedAp and verify both 2G,5G instances have been enabled.
+        self.enable_bridged_ap(self.dut,
+                               WifiEnums.SoftApSecurityType.WPA2,
+                               bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                                      WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
+        infos = self.verify_number_band_freq_of_bridged_ap(
+            self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                       WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G], False)
+
+        self.sniffing_bridgedap_channels(infos)
+
+        self.two_clients_connect_to_wifi_network(self.client1, self.client2,
+                                                 self.config)
+        # Trigger client#1 and client#2 ping each other.
+        wutils.validate_ping_between_two_clients(self.client1, self.client2)
+
+        # Restore config
+        wutils.save_wifi_soft_ap_config(self.dut, original_softap_config)
+
+    @test_tracker_info(uuid="ef98a5ea-c7d5-4cc4-a2f8-e5fd44648788")
+    def test_two_clients_ping_bridged_ap_5g_2g_no_security_country_us(self):
+        """Test clients on different instances can ping each other.
+
+        Steps:
+            Refer to test_two_clients_ping_bridged_ap_5g_2g_wpa3_country_us,
+            but this case enable OPEN SoftAp security type.
+        """
+        # Backup config
+        original_softap_config = self.dut.droid.wifiGetApConfiguration()
+        # Make sure DUT is able to enable BridgedAp.
+        is_supported = wutils.check_available_channels_in_bands_2_5(
+            self.dut, wutils.WifiEnums.CountryCode.US)
+        asserts.skip_if(not is_supported, "BridgedAp is not supported in {}"
+                        .format(wutils.WifiEnums.CountryCode.US))
+
+        # Enable BridgedAp and verify both 2G,5G instances have been enabled.
+        self.enable_bridged_ap(self.dut,
+                               WifiEnums.SoftApSecurityType.OPEN,
+                               bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                                      WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
+        infos = self.verify_number_band_freq_of_bridged_ap(
+            self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                       WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G], False)
+
+        self.sniffing_bridgedap_channels(infos)
+
+        self.two_clients_connect_to_wifi_network(self.client1, self.client2,
+                                                 self.config)
         # Trigger client#1 and client#2 ping each other.
         wutils.validate_ping_between_two_clients(self.client1, self.client2)
 
@@ -325,8 +637,10 @@
         Steps:
             Backup config.
             DUT enable BridgedAp.
+            start sniffer and sniffing on AP channels.
             DUT connect to a 5G DFS channel Wi-Fi network.
             Verify 5G instance is shutdown.
+            Stop sniffers.
             Restore config.
         """
         # Backup config
@@ -338,28 +652,19 @@
         asserts.skip_if(not is_supported, "BridgedAp is not supported in {}"
                         .format(wutils.WifiEnums.CountryCode.US))
 
-        # Enable BridgedAp
-        config = wutils.create_softap_config()
-        config[WifiEnums.SECURITY] = WifiEnums.SoftApSecurityType.WPA3_SAE
-        wutils.save_wifi_soft_ap_config(
-            self.dut, config,
-            bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
-                   WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
-        wutils.start_wifi_tethering_saved_config(self.dut)
-        # Wait 5 seconds for BridgedAp launch.
-        self.wait_interval(BRIDGED_AP_LAUNCH_INTERVAL_5_SECONDS)
+        # Enable BridgedAp and verify both 2G,5G instances have been enabled.
+        self.enable_bridged_ap(self.dut,
+                               WifiEnums.SoftApSecurityType.WPA3_SAE,
+                               bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                                      WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
         self.verify_number_band_freq_of_bridged_ap(
             self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
                        WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G], False)
 
-        # STA connect to a 5G DFS Channel.
+        self.sniffing_ap_channels(channel1=None, channel2=132)
+        self.start_ap(channel_2g=None, channel_5g=132)
         wutils.wifi_toggle_state(self.dut, True)
-        if "OpenWrtAP" in self.user_params:
-            self.configure_openwrt_ap_and_start(wpa_network=True,
-                                                channel_2g=6,
-                                                channel_5g=132)
-            wutils.connect_to_wifi_network(self.dut,
-                                           self.wpa_networks[0][BAND_5G])
+        wutils.connect_to_wifi_network(self.dut, self.wpa_networks[0][BAND_5G])
 
         self.verify_number_band_freq_of_bridged_ap(
             self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G], False)
@@ -374,8 +679,10 @@
         Steps:
             Backup config.
             DUT enable BridgedAp.
+            start sniffer and sniffing on AP channels.
             DUT connect to a 5G non-DFS channel Wi-Fi network.
             Verify STA frequency equals to 5G BridgedAp frequency.
+            Stop sniffers.
             Restore config.
         """
         # Backup config
@@ -387,25 +694,19 @@
         asserts.skip_if(not is_supported, "BridgedAp is not supported in {}"
                         .format(wutils.WifiEnums.CountryCode.US))
 
-        # Enable BridgedAp
-        config = wutils.create_softap_config()
-        config[WifiEnums.SECURITY] = WifiEnums.SoftApSecurityType.WPA3_SAE
-        wutils.save_wifi_soft_ap_config(
-            self.dut, config,
-            bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
-                   WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
-        wutils.start_wifi_tethering_saved_config(self.dut)
-        # Wait 5 seconds for BridgedAp launch.
-        self.wait_interval(BRIDGED_AP_LAUNCH_INTERVAL_5_SECONDS)
+        # Enable BridgedAp and verify both 2G,5G instances have been enabled.
+        self.enable_bridged_ap(self.dut,
+                               WifiEnums.SoftApSecurityType.WPA3_SAE,
+                               bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                                      WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
+        self.verify_number_band_freq_of_bridged_ap(
+            self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                       WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G], False)
 
-        # STA connect to a 5G Non-DFS Channel.
+        self.sniffing_ap_channels(channel1=None, channel2=36)
+        self.start_ap(channel_2g=None, channel_5g=36)
         wutils.wifi_toggle_state(self.dut, True)
-        if "OpenWrtAP" in self.user_params:
-            self.configure_openwrt_ap_and_start(wpa_network=True,
-                                                channel_2g=6,
-                                                channel_5g=36)
-            wutils.connect_to_wifi_network(self.dut,
-                                           self.wpa_networks[0][BAND_5G])
+        wutils.connect_to_wifi_network(self.dut, self.wpa_networks[0][BAND_5G])
 
         self.verify_number_band_freq_of_bridged_ap(
             self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
@@ -421,8 +722,10 @@
         Steps:
             Backup config.
             DUT enable BridgedAp.
+            start sniffer and sniffing on AP channels.
             STA connect to a 2G Wi-Fi network.
             Verify STA frequency equals to 2G BridgedAp frequency.
+            Stop sniffers.
             Restore config.
         """
         # Backup config
@@ -434,25 +737,19 @@
         asserts.skip_if(not is_supported, "BridgedAp is not supported in {}"
                         .format(wutils.WifiEnums.CountryCode.US))
 
-        # Enable BridgedAp
-        config = wutils.create_softap_config()
-        config[WifiEnums.SECURITY] = WifiEnums.SoftApSecurityType.WPA3_SAE
-        wutils.save_wifi_soft_ap_config(
-            self.dut, config,
-            bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
-                   WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
-        wutils.start_wifi_tethering_saved_config(self.dut)
-        # Wait 5 seconds for BridgedAp launch.
-        self.wait_interval(BRIDGED_AP_LAUNCH_INTERVAL_5_SECONDS)
+        # Enable BridgedAp and verify both 2G,5G instances have been enabled.
+        self.enable_bridged_ap(self.dut,
+                               WifiEnums.SoftApSecurityType.WPA3_SAE,
+                               bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                                      WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
+        self.verify_number_band_freq_of_bridged_ap(
+            self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                       WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G], False)
 
-        # STA connect to a 2G Channel.
+        self.sniffing_ap_channels(channel1=6, channel2=None)
+        self.start_ap(channel_2g=6, channel_5g=None)
         wutils.wifi_toggle_state(self.dut, True)
-        if "OpenWrtAP" in self.user_params:
-            self.configure_openwrt_ap_and_start(wpa_network=True,
-                                                channel_2g=6,
-                                                channel_5g=36)
-            wutils.connect_to_wifi_network(self.dut,
-                                           self.wpa_networks[0][BAND_2G])
+        wutils.connect_to_wifi_network(self.dut, self.wpa_networks[0][BAND_2G])
 
         self.verify_number_band_freq_of_bridged_ap(
             self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
@@ -468,9 +765,12 @@
 
         Steps:
             Backup config.
+            start sniffer and sniffing on AP channels.
+            Enable a Wi-Fi network.
             DUT connect to a 5G DFS channel Wi-Fi network.
             DUT enable BridgedAp.
             Verify 5G instance is shutdown and only 2G instance enabled.
+            Stop sniffers.
             Restore config.
         """
         # Backup config
@@ -482,26 +782,16 @@
         asserts.skip_if(not is_supported, "BridgedAp is not supported in {}"
                         .format(wutils.WifiEnums.CountryCode.US))
 
-        # STA connect to a 5G DFS Channel.
+        self.sniffing_ap_channels(channel1=None, channel2=132)
+        self.start_ap(channel_2g=None, channel_5g=132)
         wutils.wifi_toggle_state(self.dut, True)
-        if "OpenWrtAP" in self.user_params:
-            self.configure_openwrt_ap_and_start(wpa_network=True,
-                                                channel_2g=6,
-                                                channel_5g=132)
-            wutils.connect_to_wifi_network(self.dut,
-                                           self.wpa_networks[0][BAND_5G])
+        wutils.connect_to_wifi_network(self.dut, self.wpa_networks[0][BAND_5G])
 
         # Enable BridgedAp
-        config = wutils.create_softap_config()
-        config[WifiEnums.SECURITY] = WifiEnums.SoftApSecurityType.WPA3_SAE
-        wutils.save_wifi_soft_ap_config(
-            self.dut, config,
-            bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
-                   WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
-        wutils.start_wifi_tethering_saved_config(self.dut)
-        # Wait 5 seconds for BridgedAp launch.
-        self.wait_interval(BRIDGED_AP_LAUNCH_INTERVAL_5_SECONDS)
-
+        self.enable_bridged_ap(self.dut,
+                               WifiEnums.SoftApSecurityType.WPA3_SAE,
+                               bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                                      WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
         # # Verify only 2G instance enabled.
         self.verify_number_band_freq_of_bridged_ap(
             self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G], False)
@@ -515,9 +805,12 @@
 
         Steps:
             Backup config.
+            start sniffer and sniffing on AP channels.
+            Enable a Wi-Fi network.
             DUT connect to a 5G non-DFS channel Wi-Fi network.
             DUT enable BridgedAp.
             Verify STA frequency equals to 5G BridgedAp frequency.
+            Stop sniffers.
             Restore config.
         """
         # Backup config
@@ -529,26 +822,16 @@
         asserts.skip_if(not is_supported, "BridgedAp is not supported in {}"
                         .format(wutils.WifiEnums.CountryCode.US))
 
-        # STA connect to a 5G non-DFS Channel.
+        self.sniffing_ap_channels(channel1=None, channel2=36)
+        self.start_ap(channel_2g=None, channel_5g=36)
         wutils.wifi_toggle_state(self.dut, True)
-        if "OpenWrtAP" in self.user_params:
-            self.configure_openwrt_ap_and_start(wpa_network=True,
-                                                channel_2g=6,
-                                                channel_5g=36)
-            wutils.connect_to_wifi_network(self.dut,
-                                           self.wpa_networks[0][BAND_5G])
+        wutils.connect_to_wifi_network(self.dut, self.wpa_networks[0][BAND_5G])
 
-        # Enable BridgedAp
-        config = wutils.create_softap_config()
-        config[WifiEnums.SECURITY] = WifiEnums.SoftApSecurityType.WPA3_SAE
-        wutils.save_wifi_soft_ap_config(
-            self.dut, config,
-            bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
-                   WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
-        wutils.start_wifi_tethering_saved_config(self.dut)
-        # Wait 5 seconds for BridgedAp launch.
-        self.wait_interval(BRIDGED_AP_LAUNCH_INTERVAL_5_SECONDS)
-
+        # Enable BridgedAp and verify both 2G,5G instances have been enabled.
+        self.enable_bridged_ap(self.dut,
+                               WifiEnums.SoftApSecurityType.WPA3_SAE,
+                               bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                                      WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
         # Verify STA frequency equals to 5G BridgedAp frequency.
         self.verify_number_band_freq_of_bridged_ap(
             self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
@@ -563,9 +846,12 @@
 
         Steps:
             Backup config.
+            start sniffer and sniffing on AP channels.
+            Enable a Wi-Fi network.
             DUT connect to a 2G Wi-Fi network.
             DUT enable BridgedAp.
             Verify STA frequency equals to 2G BridgedAp frequency.
+            Stop sniffers.
             Restore config.
         """
         # Backup config
@@ -577,25 +863,16 @@
         asserts.skip_if(not is_supported, "BridgedAp is not supported in {}"
                         .format(wutils.WifiEnums.CountryCode.US))
 
-        # STA connect to a 2G Channel.
+        self.sniffing_ap_channels(channel1=6, channel2=None)
+        self.start_ap(channel_2g=6, channel_5g=None)
         wutils.wifi_toggle_state(self.dut, True)
-        if "OpenWrtAP" in self.user_params:
-            self.configure_openwrt_ap_and_start(wpa_network=True,
-                                                channel_2g=6,
-                                                channel_5g=36)
-            wutils.connect_to_wifi_network(self.dut,
-                                           self.wpa_networks[0][BAND_2G])
-        # Enable BridgedAp
-        config = wutils.create_softap_config()
-        config[WifiEnums.SECURITY] = WifiEnums.SoftApSecurityType.WPA3_SAE
-        wutils.save_wifi_soft_ap_config(
-            self.dut, config,
-            bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
-                   WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
-        wutils.start_wifi_tethering_saved_config(self.dut)
-        # Wait 5 seconds for BridgedAp launch.
-        self.wait_interval(BRIDGED_AP_LAUNCH_INTERVAL_5_SECONDS)
+        wutils.connect_to_wifi_network(self.dut, self.wpa_networks[0][BAND_2G])
 
+        # Enable BridgedAp and verify both 2G,5G instances have been enabled.
+        self.enable_bridged_ap(self.dut,
+                               WifiEnums.SoftApSecurityType.WPA3_SAE,
+                               bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                                      WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
         self.verify_number_band_freq_of_bridged_ap(
             self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
                        WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G], True)
@@ -627,16 +904,14 @@
         asserts.skip_if(not is_supported, "BridgedAp is not supported in {}"
                         .format(wutils.WifiEnums.CountryCode.US))
 
-        # Enable BridgedAp
-        config = wutils.create_softap_config()
-        config[WifiEnums.SECURITY] = WifiEnums.SoftApSecurityType.WPA3_SAE
-        wutils.save_wifi_soft_ap_config(
-            self.dut, config,
-            bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
-                   WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
-        wutils.start_wifi_tethering_saved_config(self.dut)
-        # Wait 5 seconds for BridgedAp launch.
-        self.wait_interval(BRIDGED_AP_LAUNCH_INTERVAL_5_SECONDS)
+        # Enable BridgedAp and verify both 2G,5G instances have been enabled.
+        self.enable_bridged_ap(self.dut,
+                               WifiEnums.SoftApSecurityType.WPA3_SAE,
+                               bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                                      WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
+        infos = self.verify_number_band_freq_of_bridged_ap(
+            self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                       WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G], False)
 
         # No client connection, wait 5 minutes, verify 5G is shutdown.
         self.verify_expected_number_of_softap_clients(self.dut, 0)
@@ -659,6 +934,7 @@
         Steps:
             Backup config.
             DUT turns ON BridgedAp.
+            start sniffer and sniffing on BridgedAp channels.
             Verify no client connect to the BridgedAp.
             Wait for 5 minutes.
             Verify that 5G BridgedAp instance is shutdown.
@@ -666,6 +942,7 @@
             The client disconnect from 2G BridgedAp.
             Wait for 10 minutes.
             Verify 2G BridgedAp is shutdown, no BridgedAp instance enabled.
+            Stop sniffers.
             Restore config.
         """
         # Backup config
@@ -677,19 +954,17 @@
         asserts.skip_if(not is_supported, "BridgedAp is not supported in {}"
                         .format(wutils.WifiEnums.CountryCode.US))
 
-        # Enable BridgedAp
-        config = wutils.create_softap_config()
-        config[WifiEnums.SECURITY] = WifiEnums.SoftApSecurityType.WPA3_SAE
-        wutils.save_wifi_soft_ap_config(
-            self.dut, config,
-            bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
-                   WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
-        wutils.start_wifi_tethering_saved_config(self.dut)
-        self.wait_interval(BRIDGED_AP_LAUNCH_INTERVAL_5_SECONDS)
-        self.verify_number_band_freq_of_bridged_ap(
+        # Enable BridgedAp and verify both 2G,5G instances have been enabled.
+        self.enable_bridged_ap(self.dut,
+                               WifiEnums.SoftApSecurityType.WPA3_SAE,
+                               bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                                      WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
+        infos = self.verify_number_band_freq_of_bridged_ap(
             self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
                        WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G], False)
 
+        self.sniffing_bridgedap_channels(infos)
+
         # Verify no connection to BridgedAp, wait for 5 mins, 5G shutdown.
         self.verify_expected_number_of_softap_clients(self.dut, 0)
         self.wait_interval(BRIDGED_AP_SHUTDOWN_INTERVAL_5_MINUTES)
@@ -701,7 +976,7 @@
         infos = wutils.get_current_softap_infos(self.dut, callbackId, True)
         self.dut.droid.unregisterSoftApCallback(callbackId)
         bssid_2g = infos[0][wifi_constants.SOFTAP_INFO_BSSID_CALLBACK_KEY]
-        config_2g = config.copy()
+        config_2g = self.config.copy()
         config_2g[WifiEnums.BSSID_KEY] = bssid_2g
         wutils.connect_to_wifi_network(self.client1, config_2g,
                                        check_connectivity=False)
@@ -733,6 +1008,7 @@
         Steps:
             Backup config.
             DUT turns ON BridgedAp.
+            start sniffer and sniffing on BridgedAp channels.
             Verify no client connect to the BridgedAp.
             Wait for 5 minutes.
             Verify that 5G BridgedAp instance is shutdown.
@@ -740,6 +1016,7 @@
             The client disconnect from 2G BridgedAp at 9th minutes.
             Wait for 10 minutes.
             Verify 2G BridgedAp is shutdown, no BridgedAp instance enabled.
+            Stop sniffers.
             Restore config.
         """
         # Backup config
@@ -751,21 +1028,19 @@
         asserts.skip_if(not is_supported, "BridgedAp is not supported in {}"
                         .format(wutils.WifiEnums.CountryCode.US))
 
-        # Enable BridgedAp
-        config = wutils.create_softap_config()
-        config[WifiEnums.SECURITY] = WifiEnums.SoftApSecurityType.WPA3_SAE
-        wutils.save_wifi_soft_ap_config(
-            self.dut, config,
-            bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
-                   WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G],
-            bridged_opportunistic_shutdown_enabled=True,
-            shutdown_timeout_enable=True)
-        wutils.start_wifi_tethering_saved_config(self.dut)
-        self.wait_interval(BRIDGED_AP_LAUNCH_INTERVAL_5_SECONDS)
-
-        self.verify_number_band_freq_of_bridged_ap(
+        # Enable BridgedAp and verify both 2G,5G instances have been enabled.
+        self.enable_bridged_ap(self.dut,
+                               WifiEnums.SoftApSecurityType.WPA3_SAE,
+                               bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                                      WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G],
+                               bridged_opportunistic_shutdown_enabled=True,
+                               shutdown_timeout_enable=True)
+        infos = self.verify_number_band_freq_of_bridged_ap(
             self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
                        WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G], False)
+
+        self.sniffing_bridgedap_channels(infos)
+
         self.verify_expected_number_of_softap_clients(self.dut, 0)
         self.wait_interval(BRIDGED_AP_SHUTDOWN_INTERVAL_5_MINUTES)
         self.verify_number_band_freq_of_bridged_ap(
@@ -777,7 +1052,7 @@
         infos = wutils.get_current_softap_infos(self.dut, callbackId, True)
         self.dut.droid.unregisterSoftApCallback(callbackId)
         bssid_2g = infos[0][wifi_constants.SOFTAP_INFO_BSSID_CALLBACK_KEY]
-        config_2g = config.copy()
+        config_2g = self.config.copy()
         config_2g[WifiEnums.BSSID_KEY] = bssid_2g
         wutils.connect_to_wifi_network(self.client1, config_2g,
                                        check_connectivity=False)
@@ -818,18 +1093,243 @@
 
         # Set country code to JP and enable BridgedAp
         self.set_country_code_and_verify(self.dut, WifiEnums.CountryCode.JAPAN)
-        config = wutils.create_softap_config()
-        config[WifiEnums.SECURITY] = WifiEnums.SoftApSecurityType.WPA3_SAE
-        wutils.save_wifi_soft_ap_config(
-            self.dut, config,
-            bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
-                   WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
-        wutils.start_wifi_tethering_saved_config(self.dut)
-        self.wait_interval(BRIDGED_AP_LAUNCH_INTERVAL_5_SECONDS)
 
+        # Enable BridgedAp
+        self.enable_bridged_ap(self.dut,
+                               WifiEnums.SoftApSecurityType.WPA3_SAE,
+                               bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                                      WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
         # Verify only 2G BridgedAp instance enabled.
+        infos = self.verify_number_band_freq_of_bridged_ap(
+            self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G], False)
+        self.sniffing_bridgedap_channels(infos)
+
+        # Restore config
+        wutils.save_wifi_soft_ap_config(self.dut, original_softap_config)
+
+    @test_tracker_info(uuid="b5c7c6df-b181-4bba-a7b3-48fad0d7fa98")
+    def test_bridged_ap_5g_2g_shutdown_2g_after_5_minutes(self):
+        """Test the BridgeAp shutdown mechanism.
+
+        Steps:
+            Backup config.
+            DUT turns ON BridgedAp.
+            start sniffer and sniffing on BridgedAp channels.
+            A Client connect to BridgeAp 5G instance.
+            Wait for 5 minutes.
+            Verify 2G instance is shutdown and only 5G instance exists.
+            Stop sniffers.
+            Restore config."""
+        # Backup config
+        original_softap_config = self.dut.droid.wifiGetApConfiguration()
+
+        # Make sure DUT is able to enable BridgedAp.
+        is_supported = wutils.check_available_channels_in_bands_2_5(
+            self.dut, wutils.WifiEnums.CountryCode.US)
+        asserts.skip_if(not is_supported, "BridgedAp is not supported in {}"
+                        .format(wutils.WifiEnums.CountryCode.US))
+
+        # Enable BridgedAp and verify both 2G,5G instances have been enabled.
+        self.enable_bridged_ap(self.dut,
+                               WifiEnums.SoftApSecurityType.WPA3_SAE,
+                               bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                                      WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
+        infos = self.verify_number_band_freq_of_bridged_ap(
+            self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                       WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G], False)
+
+        self.sniffing_bridgedap_channels(infos)
+
+        # Client connects to the 5G BridgedAp instance.
+        self.client_connects_to_a_bridgeap(self.client1, BAND_5G)
+        self.wait_interval(BRIDGED_AP_SHUTDOWN_INTERVAL_5_MINUTES)
+        # Verify there is only one client connects to the BridgedAp.
+        self.verify_expected_number_of_softap_clients(self.dut, 1)
+        # Verify the BridgedAp instance is 5G.
+        self.verify_number_band_freq_of_bridged_ap(
+            self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G], False)
+        # Restore config
+        wutils.save_wifi_soft_ap_config(self.dut, original_softap_config)
+
+    @test_tracker_info(uuid="683b2c7f-7f24-4324-be09-0b6554d5d7a8")
+    def test_bridged_ap_5g_2g_shutdown_5g_after_5_minutes(self):
+        """Test the BridgeAp shutdown mechanism.
+
+        Steps:
+            Backup config.
+            DUT turns ON BridgedAp.
+            start sniffer and sniffing on BridgedAp channels.
+            A Client connect to BridgeAp 2G instance.
+            Wait for 5 minutes.
+            Verify 5G instance is shutdown and only 2G instance exists.
+            Stop sniffers.
+            Restore config."""
+        # Backup config
+        original_softap_config = self.dut.droid.wifiGetApConfiguration()
+
+        # Make sure DUT is able to enable BridgedAp.
+        is_supported = wutils.check_available_channels_in_bands_2_5(
+            self.dut, wutils.WifiEnums.CountryCode.US)
+        asserts.skip_if(not is_supported, "BridgedAp is not supported in {}"
+                        .format(wutils.WifiEnums.CountryCode.US))
+
+        # Enable BridgedAp and verify both 2G,5G instances have been enabled.
+        self.enable_bridged_ap(self.dut,
+                               WifiEnums.SoftApSecurityType.WPA3_SAE,
+                               bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                                      WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
+        infos = self.verify_number_band_freq_of_bridged_ap(
+            self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                       WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G], False)
+        self.sniffing_bridgedap_channels(infos)
+
+        # Client connects to the 2G BridgedAp instance.
+        self.client_connects_to_a_bridgeap(self.client1, BAND_2G)
+        self.wait_interval(BRIDGED_AP_SHUTDOWN_INTERVAL_5_MINUTES)
+        # Verify there is only one client connects to the BridgedAp.
+        self.verify_expected_number_of_softap_clients(self.dut, 1)
+        # Verify the BridgedAp instance is 2G.
         self.verify_number_band_freq_of_bridged_ap(
             self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G], False)
+        # Restore config
+        wutils.save_wifi_soft_ap_config(self.dut, original_softap_config)
 
+    @test_tracker_info(uuid="6de46e5b-04c3-4fba-a21d-e914a3e34e24")
+    def test_bridged_ap_5g_2g_no_shutdown_after_5_minutes(self):
+        """Test clients on different instances can ping each other.
+
+        Steps:
+            Backup config.
+            Make sure clients support WPA3 SAE.
+            Make sure DUT is able to enable BridgedAp.
+            Enable BridgedAp with bridged configuration.
+            RegisterSoftApCallback.
+            Check the bridged AP enabled succeed.
+            start sniffer and sniffing on BridgedAp channels.
+            Client#1 connect to 5G instance.
+            Client#2 connect to 2G instance.
+            Wait for 5 minutes.
+            Verify both 2G/5G BridgedAp instances are exist.
+            Stop sniffers.
+            Restore config.
+        """
+        # Backup config
+        original_softap_config = self.dut.droid.wifiGetApConfiguration()
+        # Make sure clients support WPA3 SAE.
+        self.verify_clients_support_wpa3_sae(self.client1, self.client2)
+        # Make sure DUT is able to enable BridgedAp.
+        is_supported = wutils.check_available_channels_in_bands_2_5(
+            self.dut, wutils.WifiEnums.CountryCode.US)
+        asserts.skip_if(not is_supported, "BridgedAp is not supported in {}"
+                        .format(wutils.WifiEnums.CountryCode.US))
+
+        # Enable BridgedAp and verify both 2G,5G instances have been enabled.
+        self.enable_bridged_ap(self.dut,
+                               WifiEnums.SoftApSecurityType.WPA3_SAE,
+                               bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                                      WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G])
+        infos = self.verify_number_band_freq_of_bridged_ap(
+            self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                       WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G], False)
+
+        self.sniffing_bridgedap_channels(infos)
+
+        self.two_clients_connect_to_wifi_network(self.client1, self.client2,
+                                                 self.config)
+        self.wait_interval(BRIDGED_AP_SHUTDOWN_INTERVAL_5_MINUTES)
+        # Verify there are two clients connect to the BridgedAp.
+        self.verify_expected_number_of_softap_clients(self.dut, 2)
+        # Verify both 2G/5G BridgedAp instances are exist.
+        self.verify_number_band_freq_of_bridged_ap(
+            self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                       WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G], False)
+        # Restore config
+        wutils.save_wifi_soft_ap_config(self.dut, original_softap_config)
+
+    @test_tracker_info(uuid="f8742dfb-5232-4fe8-b568-3a99a9356d59")
+    def test_bridged_ap_5g_2g_extend_compatibility_on_no_shutdown_5g(self):
+        """Test BridgedAp mechanism when "Extend compatibility is ON.
+
+        Steps:
+            Backup config.
+            Make sure clients support WPA3 SAE.
+            Make sure DUT is able to enable BridgedAp.
+            Enable BridgedAp with Extend compatibility is ON.
+            RegisterSoftApCallback.
+            Check the bridged AP enabled succeed.
+            start sniffer and sniffing on BridgedAp channels.
+            Client#1 connect to 2G.
+            Verify both 2G/5G instances are exist.
+            Stop sniffers.
+            Restore config.
+        """
+        # Backup config
+        original_softap_config = self.dut.droid.wifiGetApConfiguration()
+        # Make sure clients support WPA3 SAE.
+        self.verify_clients_support_wpa3_sae(self.client1, self.client2)
+        # Make sure DUT is able to enable BridgedAp.
+        is_supported = wutils.check_available_channels_in_bands_2_5(
+            self.dut, wutils.WifiEnums.CountryCode.US)
+        asserts.skip_if(not is_supported, "BridgedAp is not supported in {}"
+                        .format(wutils.WifiEnums.CountryCode.US))
+        # Enable BridgedAp with "Extend compatibility set to ON".
+        self.enable_bridged_ap(self.dut,
+                               WifiEnums.SoftApSecurityType.WPA3_SAE,
+                               bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                                      WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G],
+                               bridged_opportunistic_shutdown_enabled=False)
+        # Client connects to the 2G BridgedAp instance and wait 5 minutes.
+        self.client_connects_to_a_bridgeap(self.client1, BAND_2G)
+        self.wait_interval(BRIDGED_AP_SHUTDOWN_INTERVAL_5_MINUTES)
+        # Verify there are two clients connect to the BridgedAp.
+        self.verify_expected_number_of_softap_clients(self.dut, 2)
+        # Verify both 2G/5G BridgedAp instances exist.
+        self.verify_number_band_freq_of_bridged_ap(
+            self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                       WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G], False)
+        # Restore config
+        wutils.save_wifi_soft_ap_config(self.dut, original_softap_config)
+
+    @test_tracker_info(uuid="050f8dd8-ed38-4f7a-87a9-9dbdade58cc7")
+    def test_bridged_ap_5g_2g_extend_compatibility_on_no_shutdown_2g(self):
+        """Test BridgedAp mechanism when "Extend compatibility is ON.
+
+        Steps:
+            Backup config.
+            Make sure clients support WPA3 SAE.
+            Make sure DUT is able to enable BridgedAp.
+            Enable BridgedAp with Extend compatibility is ON.
+            RegisterSoftApCallback.
+            Check the bridged AP enabled succeed.
+            start sniffer and sniffing on BridgedAp channels.
+            Client#1 connect to 5G.
+            Verify both 2G/5G instances are exist.
+            Stop sniffers.
+            Restore config.
+        """
+        # Backup config
+        original_softap_config = self.dut.droid.wifiGetApConfiguration()
+        # Make sure clients support WPA3 SAE.
+        self.verify_clients_support_wpa3_sae(self.client1, self.client2)
+        # Make sure DUT is able to enable BridgedAp.
+        is_supported = wutils.check_available_channels_in_bands_2_5(
+            self.dut, wutils.WifiEnums.CountryCode.US)
+        asserts.skip_if(not is_supported, "BridgedAp is not supported in {}"
+                        .format(wutils.WifiEnums.CountryCode.US))
+        # Enable BridgedAp with "Extend compatibility set to ON".
+        self.enable_bridged_ap(self.dut,
+                               WifiEnums.SoftApSecurityType.WPA3_SAE,
+                               bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                                      WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G],
+                               bridged_opportunistic_shutdown_enabled=False)
+        # Client connects to the 5G BridgedAp instance and wait 5 minutes.
+        self.client_connects_to_a_bridgeap(self.client1, BAND_5G)
+        self.wait_interval(BRIDGED_AP_SHUTDOWN_INTERVAL_5_MINUTES)
+        # Verify there are two clients connect to the BridgedAp.
+        self.verify_expected_number_of_softap_clients(self.dut, 2)
+        # Verify both 2G/5G BridgedAp instances exist.
+        self.verify_number_band_freq_of_bridged_ap(
+            self.dut, [WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G,
+                       WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G], False)
         # Restore config
         wutils.save_wifi_soft_ap_config(self.dut, original_softap_config)
diff --git a/acts_tests/tests/google/wifi/WifiEnterpriseRoamingTest.py b/acts_tests/tests/google/wifi/WifiEnterpriseRoamingTest.py
index 6eea512..daf9b1a 100644
--- a/acts_tests/tests/google/wifi/WifiEnterpriseRoamingTest.py
+++ b/acts_tests/tests/google/wifi/WifiEnterpriseRoamingTest.py
@@ -103,6 +103,14 @@
             Ent.EAP: int(EAP.SIM),
             WifiEnums.SSID_KEY: self.ent_roaming_ssid,
         }
+        self.config_aka = {
+            Ent.EAP: int(EAP.AKA),
+            WifiEnums.SSID_KEY: self.ent_roaming_ssid,
+        }
+        self.config_aka_prime = {
+            Ent.EAP: int(EAP.AKA_PRIME),
+            WifiEnums.SSID_KEY: self.ent_roaming_ssid,
+        }
         self.attn_a = self.attenuators[0]
         self.attn_b = self.attenuators[2]
         if "OpenWrtAP" in self.user_params:
@@ -236,4 +244,16 @@
         config[WifiEnums.Enterprise.PHASE2] = WifiEnums.EapPhase2.GTC.value
         self.roaming_between_a_and_b_logic(config)
 
-    """ Tests End """
+    @test_tracker_info(uuid="e014fc94-a547-4aa7-953e-cff3bfe3f20c")
+    def test_roaming_with_config_sim(self):
+        self.roaming_between_a_and_b_logic(self.config_sim)
+
+    @test_tracker_info(uuid="2e45a59e-ec22-4bf4-811f-1a3a4b9bb330")
+    def test_roaming_with_config_aka(self):
+        self.roaming_between_a_and_b_logic(self.config_aka)
+
+    @test_tracker_info(uuid="63ebfdf5-e765-47ff-9754-f60e3f6e7409")
+    def test_roaming_with_config_aka_prime(self):
+        self.roaming_between_a_and_b_logic(self.config_aka_prime)
+
+    """ Tests End """
\ No newline at end of file
diff --git a/acts_tests/tests/google/wifi/WifiPasspointTest.py b/acts_tests/tests/google/wifi/WifiPasspointTest.py
index 4949195..3c78e06 100755
--- a/acts_tests/tests/google/wifi/WifiPasspointTest.py
+++ b/acts_tests/tests/google/wifi/WifiPasspointTest.py
@@ -367,7 +367,9 @@
         current_ssid = current_passpoint[WifiEnums.SSID_KEY]
         if current_ssid not in passpoint_ssid:
            raise signals.TestFailure("Device did not connect to any of the "
-                                     "configured Passpoint networks.")
+                                     "configured Passpoint networks."
+                                     "current: {}, expected: {}"
+                                     .format(current_ssid, passpoint_ssid))
 
         expected_ssid =  self.passpoint_networks[0][WifiEnums.SSID_KEY]
         if current_ssid in expected_ssid:
diff --git a/acts_tests/tests/google/wifi/WifiRoamingTest.py b/acts_tests/tests/google/wifi/WifiRoamingTest.py
index c70e56f..2af178b 100644
--- a/acts_tests/tests/google/wifi/WifiRoamingTest.py
+++ b/acts_tests/tests/google/wifi/WifiRoamingTest.py
@@ -23,6 +23,7 @@
 from acts_contrib.test_utils.wifi import wifi_test_utils as wutils
 from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest
 from acts_contrib.test_utils.wifi.aware import aware_test_utils as autils
+from acts.controllers.openwrt_lib.openwrt_constants import OpenWrtWifiSetting
 import os
 
 WifiEnums = wutils.WifiEnums
@@ -427,3 +428,777 @@
             self.log.info("Roaming failed to AP2 with incorrect BSSID")
             wutils.wait_for_disconnect(self.dut)
             self.log.info("Device is disconnect")
+
+    @test_tracker_info(uuid="641b35c1-7bf8-4d85-a813-1bc30d7bd0d4")
+    def test_roaming_between_psk_2g_to_psk_5g(self):
+        """Verify psk when after roaming from 2.4 Ghz to 5 Ghz with OpenWrtAP
+
+         Steps:
+             1. Configure 2 APs
+             2. Configure AP2 5Ghz and AP1 2.4Ghz WiFi to same SSID and password
+             3. Connect DUT to AP1 2.4Ghz WiFi
+             4. Roam to AP2 5Ghz WiFi
+             5. Verify the DUT can connect from 2.4Ghz to 5Ghz
+        """
+        # Use OpenWrt as Wi-Fi AP when it's available in testbed.
+        asserts.skip_if("OpenWrtAP" not in self.user_params, "OpenWrtAP not in user_params")
+        self.configure_openwrt_ap_and_start(wpa_network=True,
+                                            ap_count=2)
+        self.openwrt1 = self.access_points[0]
+        self.openwrt2 = self.access_points[1]
+        ap1_network = self.reference_networks[0]["2g"]
+        ap2_network = self.reference_networks[1]["5g"]
+        # Get & Setup APs' BSSIDs.
+        ap1_network["bssid"] = self.bssid_map[0]["2g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]]
+
+        # Change 2 APs to same password and SSID
+        self.openwrt1.set_ssid(ssid_2g="testSSID")
+        self.openwrt2.set_ssid(ssid_5g="testSSID")
+        self.openwrt2.set_password(pwd_5g=ap1_network["password"])
+        ap1_network["SSID"] = "testSSID"
+        ap2_network["SSID"] = "testSSID"
+        ap2_network["password"] = ap1_network["password"]
+
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+
+    @test_tracker_info(uuid="fa1fe3bb-abb9-4d75-88bd-cd88c04073c6")
+    def test_roaming_between_psk_withoutPMF_5g(self):
+        """Verify psk without PMF when after roaming with OpenWrtAP
+
+         Steps:
+             1. Configure 2 APs without PMF
+             2. Connect DUT to AP1
+             3. Roam to AP2
+             4. Verify the DUT can connect after roaming
+        """
+        # Use OpenWrt as Wi-Fi AP when it's available in testbed.
+        asserts.skip_if("OpenWrtAP" not in self.user_params, "OpenWrtAP not in user_params")
+        self.configure_openwrt_ap_and_start(wpa_network=True,
+                                            ap_count=2,
+                                            mirror_ap=True,
+                                            ieee80211w=0)
+        ap1_network = self.reference_networks[0]["5g"]
+        ap2_network = self.reference_networks[1]["5g"]
+        # Get & Setup APs' BSSIDs.
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]]
+
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+
+    @test_tracker_info(uuid="496e048a-3da5-45c4-aa0f-c5bd127eb06f")
+    def test_roaming_between_psk_withPMF_5g(self):
+        """Verify psk with PMF when after roaming with OpenWrtAP
+
+         Steps:
+             1. Configure 2 APs with PMF
+             2. Connect DUT to AP1
+             3. Roam to AP2
+             4. Verify the DUT can connect after roaming
+        """
+        # Use OpenWrt as Wi-Fi AP when it's available in testbed.
+        asserts.skip_if("OpenWrtAP" not in self.user_params, "OpenWrtAP not in user_params")
+        self.configure_openwrt_ap_and_start(wpa_network=True,
+                                            ap_count=2,
+                                            mirror_ap=True,
+                                            ieee80211w=2)
+        ap1_network = self.reference_networks[0]["5g"]
+        ap2_network = self.reference_networks[1]["5g"]
+        # Get & Setup APs' BSSIDs.
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]]
+
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+
+    @test_tracker_info(uuid="524c97c5-4bca-46b0-97f9-aad749768cd8")
+    def test_roaming_between_psk_wPMF_to_psk_woPMF_5g(self):
+        """Verify psk with/without PMF when after roaming with OpenWrtAP
+
+         Steps:
+             1. Configure 2 APs without PMF
+             2. Configure AP1 with PMF
+             3. Connect DUT to AP1
+             4. Roam to AP2
+             5. Verify the DUT can connect after roaming
+        """
+        # Use OpenWrt as Wi-Fi AP when it's available in testbed.
+        asserts.skip_if("OpenWrtAP" not in self.user_params, "OpenWrtAP not in user_params")
+        self.configure_openwrt_ap_and_start(wpa_network=True,
+                                            ap_count=2,
+                                            mirror_ap=True,
+                                            ieee80211w=0)
+        self.openwrt1 = self.access_points[0]
+        self.openwrt2 = self.access_points[1]
+        ap1_network = self.reference_networks[0]["5g"]
+        ap2_network = self.reference_networks[1]["5g"]
+        # Get & Setup APs' BSSIDs.
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]]
+
+        # Configure AP1 to enable PMF.
+        self.configure_openwrt_ap_and_start(wpa_network=True,
+                                            ieee80211w=2)
+        ap1_network = self.reference_networks[0]["5g"]
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+
+        # Change AP2 password and SSID same as AP1.
+        self.openwrt2.set_password(pwd_5g=ap1_network["password"])
+        self.openwrt2.set_ssid(ssid_5g=ap1_network["SSID"])
+        ap2_network["SSID"] = ap1_network["SSID"]
+        ap2_network["password"] = ap1_network["password"]
+
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+
+    @test_tracker_info(uuid="714ceac1-d8af-4679-9385-2c9c6d885634")
+    def test_roaming_between_psk_woPMF_to_psk_wPMF_5g(self):
+        """Verify psk without/with PMF when after roaming with OpenWrtAP
+
+         Steps:
+             1. Configure 2 APs with PMF
+             2. Configure AP1 without PMF
+             3. Connect DUT to AP1
+             4. Roam to AP2
+             5. Verify the DUT can connect after roaming
+        """
+        # Use OpenWrt as Wi-Fi AP when it's available in testbed.
+        asserts.skip_if("OpenWrtAP" not in self.user_params, "OpenWrtAP not in user_params")
+        self.configure_openwrt_ap_and_start(wpa_network=True,
+                                            ap_count=2,
+                                            mirror_ap=True,
+                                            ieee80211w=2)
+        self.openwrt1 = self.access_points[0]
+        self.openwrt2 = self.access_points[1]
+        ap1_network = self.reference_networks[0]["5g"]
+        ap2_network = self.reference_networks[1]["5g"]
+        # Get & Setup APs' BSSIDs.
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]]
+
+        # Configure AP1 to disable PMF.
+        self.configure_openwrt_ap_and_start(wpa_network=True,
+                                            ieee80211w=0)
+        ap1_network = self.reference_networks[0]["5g"]
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+
+        # Change AP2 password and SSID same as AP1.
+        self.openwrt2.set_password(pwd_5g=ap1_network["password"])
+        self.openwrt2.set_ssid(ssid_5g=ap1_network["SSID"])
+        ap2_network["SSID"] = ap1_network["SSID"]
+        ap2_network["password"] = ap1_network["password"]
+
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+
+    @test_tracker_info(uuid="4b201d7b-38ec-49c2-95c3-81cba51ba11d")
+    def test_roaming_between_psk_capablePMF_5g(self):
+        """Verify psk capable PMF when after roaming with OpenWrtAP
+
+         Steps:
+             1. Configure 2 APs with capable PMF
+             2. Connect DUT to AP1
+             3. Roam to AP2
+             4. Verify the DUT can connect after roaming
+        """
+        # Use OpenWrt as Wi-Fi AP when it's available in testbed.
+        asserts.skip_if("OpenWrtAP" not in self.user_params, "OpenWrtAP not in user_params")
+        self.configure_openwrt_ap_and_start(wpa_network=True,
+                                            ap_count=2,
+                                            mirror_ap=True,
+                                            ieee80211w=1)
+        ap1_network = self.reference_networks[0]["5g"]
+        ap2_network = self.reference_networks[1]["5g"]
+        # Get & Setup APs' BSSIDs.
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]]
+
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+
+    @test_tracker_info(uuid="588a9279-1f84-44d2-acbb-051c5ba0bcb1")
+    def test_roaming_between_psk_capPMF_to_psk_woPMF_5g(self):
+        """Verify psk capable/without PMF when after roaming with OpenWrtAP
+
+         Steps:
+             1. Configure 2 APs without PMF
+             2. Configure AP1 with capable PMF
+             3. Connect DUT to AP1
+             4. Roam to AP2
+             5. Verify the DUT can connect after roaming
+        """
+        # Use OpenWrt as Wi-Fi AP when it's available in testbed.
+        asserts.skip_if("OpenWrtAP" not in self.user_params, "OpenWrtAP not in user_params")
+        self.configure_openwrt_ap_and_start(wpa_network=True,
+                                            ap_count=2,
+                                            mirror_ap=True,
+                                            ieee80211w=0)
+        self.openwrt1 = self.access_points[0]
+        self.openwrt2 = self.access_points[1]
+        ap1_network = self.reference_networks[0]["5g"]
+        ap2_network = self.reference_networks[1]["5g"]
+        # Get & Setup APs' BSSIDs.
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]]
+
+        # Configure AP1 to enable capable PMF.
+        self.configure_openwrt_ap_and_start(wpa_network=True,
+                                            ieee80211w=1)
+        ap1_network = self.reference_networks[0]["5g"]
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+
+        # Change AP2 password and SSID same as AP1.
+        self.openwrt2.set_password(pwd_5g=ap1_network["password"])
+        self.openwrt2.set_ssid(ssid_5g=ap1_network["SSID"])
+        ap2_network["SSID"] = ap1_network["SSID"]
+        ap2_network["password"] = ap1_network["password"]
+
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+
+    @test_tracker_info(uuid="d239b56d-515c-4589-b63a-ebce62c321af")
+    def test_roaming_between_psk_capPMF_to_psk_wPMF_5g(self):
+        """Verify psk capable/with PMF when after roaming with OpenWrtAP
+
+         Steps:
+             1. Configure 2 APs with PMF
+             2. Configure AP1 with capable PMF
+             3. Connect DUT to AP1
+             4. Roam to AP2
+             5. Verify the DUT can connect after roaming
+        """
+        # Use OpenWrt as Wi-Fi AP when it's available in testbed.
+        asserts.skip_if("OpenWrtAP" not in self.user_params, "OpenWrtAP not in user_params")
+        self.configure_openwrt_ap_and_start(wpa_network=True,
+                                            ap_count=2,
+                                            mirror_ap=True,
+                                            ieee80211w=2)
+        self.openwrt1 = self.access_points[0]
+        self.openwrt2 = self.access_points[1]
+        ap1_network = self.reference_networks[0]["5g"]
+        ap2_network = self.reference_networks[1]["5g"]
+        # Get & Setup APs' BSSIDs.
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]]
+
+        # Configure AP1 to enable capable PMF.
+        self.configure_openwrt_ap_and_start(wpa_network=True,
+                                                ieee80211w=1)
+        ap1_network = self.reference_networks[0]["5g"]
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+
+        # Change AP2 password and SSID same as AP1.
+        self.openwrt2.set_password(pwd_5g=ap1_network["password"])
+        self.openwrt2.set_ssid(ssid_5g=ap1_network["SSID"])
+        ap2_network["SSID"] = ap1_network["SSID"]
+        ap2_network["password"] = ap1_network["password"]
+
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+
+    @test_tracker_info(uuid="57ec9401-b336-40cb-bc46-c2b4cfc22516")
+    def test_roaming_between_psk_wPMF_to_psk_capPMF_5g(self):
+        """Verify psk with/capable PMF when after roaming with OpenWrtAP
+
+         Steps:
+             1. Configure 2 APs with capable PMF
+             2. Configure AP1 with PMF
+             3. Connect DUT to AP1
+             4. Roam to AP2
+             5. Verify the DUT can connect after roaming
+        """
+        # Use OpenWrt as Wi-Fi AP when it's available in testbed.
+        asserts.skip_if("OpenWrtAP" not in self.user_params, "OpenWrtAP not in user_params")
+        self.configure_openwrt_ap_and_start(wpa_network=True,
+                                            ap_count=2,
+                                            mirror_ap=True,
+                                            ieee80211w=1)
+        self.openwrt1 = self.access_points[0]
+        self.openwrt2 = self.access_points[1]
+        ap1_network = self.reference_networks[0]["5g"]
+        ap2_network = self.reference_networks[1]["5g"]
+        # Get & Setup APs' BSSIDs.
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]]
+
+        # Configure AP1 to enable PMF.
+        self.configure_openwrt_ap_and_start(wpa_network=True,
+                                            ieee80211w=2)
+        ap1_network = self.reference_networks[0]["5g"]
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+
+        # Change AP2 password and SSID same as AP1.
+        self.openwrt2.set_password(pwd_5g=ap1_network["password"])
+        self.openwrt2.set_ssid(ssid_5g=ap1_network["SSID"])
+        ap2_network["SSID"] = ap1_network["SSID"]
+        ap2_network["password"] = ap1_network["password"]
+
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+
+    @test_tracker_info(uuid="a32d24f0-36cc-41f0-90b4-db74973db29f")
+    def test_roaming_between_psk_woPMF_to_psk_capPMF_5g(self):
+        """Verify psk without/capable PMF when after roaming with OpenWrtAP
+
+         Steps:
+             1. Configure 2 APs with capable PMF
+             2. Configure AP1 without PMF
+             3. Connect DUT to AP1
+             4. Roam to AP2
+             5. Verify the DUT can connect after roaming
+        """
+        # Use OpenWrt as Wi-Fi AP when it's available in testbed.
+        asserts.skip_if("OpenWrtAP" not in self.user_params, "OpenWrtAP not in user_params")
+        self.configure_openwrt_ap_and_start(wpa_network=True,
+                                            ap_count=2,
+                                            mirror_ap=True,
+                                            ieee80211w=1)
+        self.openwrt1 = self.access_points[0]
+        self.openwrt2 = self.access_points[1]
+        ap1_network = self.reference_networks[0]["5g"]
+        ap2_network = self.reference_networks[1]["5g"]
+        # Get & Setup APs' BSSIDs.
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]]
+
+        # Configure AP1 to disable PMF.
+        self.configure_openwrt_ap_and_start(wpa_network=True,
+                                            ieee80211w=0)
+        ap1_network = self.reference_networks[0]["5g"]
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+
+        # Change AP2 password and SSID same as AP1.
+        self.openwrt2.set_password(pwd_5g=ap1_network["password"])
+        self.openwrt2.set_ssid(ssid_5g=ap1_network["SSID"])
+        ap2_network["SSID"] = ap1_network["SSID"]
+        ap2_network["password"] = ap1_network["password"]
+
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+
+    @test_tracker_info(uuid="44f45dc9-e85c-419d-bbab-d02e9548a377")
+    def test_roaming_between_psk_to_saemixed_woPMF_5g(self):
+        """Verify psk to saemixed without PMF when after roaming with OpenWrtAP
+
+         Steps:
+             1. Configure 2 APs security type to saemixed without PMF
+             2. Configure AP1 security type to psk
+             3. Connect DUT to AP1
+             4. Roam to AP2
+             5. Verify the DUT can connect after roaming
+        """
+        # Use OpenWrt as Wi-Fi AP when it's available in testbed.
+        asserts.skip_if("OpenWrtAP" not in self.user_params, "OpenWrtAP not in user_params")
+        self.configure_openwrt_ap_and_start(saemixed_network=True,
+                                            ap_count=2,
+                                            mirror_ap=True,
+                                            ieee80211w=0)
+        self.openwrt1 = self.access_points[0]
+        self.openwrt2 = self.access_points[1]
+        ap1_network = self.saemixed_networks[0]["5g"]
+        ap2_network = self.saemixed_networks[1]["5g"]
+        # Get & Setup APs' BSSIDs.
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]]
+
+        # Configure AP1 security type.
+        self.configure_openwrt_ap_and_start(wpa_network=True)
+        ap1_network = self.reference_networks[0]["5g"]
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+
+        # Change AP2 password and SSID same as AP1.
+        self.openwrt2.set_password(pwd_5g=ap1_network["password"])
+        self.openwrt2.set_ssid(ssid_5g=ap1_network["SSID"])
+        ap2_network["SSID"] = ap1_network["SSID"]
+        ap2_network["password"] = ap1_network["password"]
+
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+
+    @test_tracker_info(uuid="9827f3b3-51cd-406b-ba2b-3ef4a9df7378")
+    def test_roaming_between_psk_to_saemixed_wPMF_5g(self):
+        """Verify psk to saemixed with PMF when after roaming with OpenWrtAP
+
+         Steps:
+             1. Configure 2 APs security type to saemixed with PMF
+             2. Configure AP1 security type to psk
+             3. Connect DUT to AP1
+             4. Roam to AP2
+             5. Verify the DUT can connect after roaming
+        """
+        # Use OpenWrt as Wi-Fi AP when it's available in testbed.
+        asserts.skip_if("OpenWrtAP" not in self.user_params, "OpenWrtAP not in user_params")
+        self.configure_openwrt_ap_and_start(saemixed_network=True,
+                                            ap_count=2,
+                                            mirror_ap=True,
+                                            ieee80211w=2)
+        self.openwrt1 = self.access_points[0]
+        self.openwrt2 = self.access_points[1]
+        ap1_network = self.saemixed_networks[0]["5g"]
+        ap2_network = self.saemixed_networks[1]["5g"]
+        # Get & Setup APs' BSSIDs.
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]]
+
+        # Configure AP1 security type.
+        self.configure_openwrt_ap_and_start(wpa_network=True)
+        ap1_network = self.reference_networks[0]["5g"]
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+
+        # Change AP2 password and SSID same as AP1.
+        self.openwrt2.set_password(pwd_5g=ap1_network["password"])
+        self.openwrt2.set_ssid(ssid_5g=ap1_network["SSID"])
+        ap2_network["SSID"] = ap1_network["SSID"]
+        ap2_network["password"] = ap1_network["password"]
+
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+
+    @test_tracker_info(uuid="037602b1-2ce8-4dbb-b46a-00e0a582d976")
+    def test_roaming_between_saemixed_withoutPMF_5g(self):
+        """Verify saemixed without PMF when after roaming with OpenWrtAP
+
+         Steps:
+             1. Configure 2 APs to saemixed without PMF
+             2. Connect DUT to AP1
+             3. Roam to AP2
+             4. Verify the DUT can connect after roaming
+        """
+        # Use OpenWrt as Wi-Fi AP when it's available in testbed.
+        asserts.skip_if("OpenWrtAP" not in self.user_params, "OpenWrtAP not in user_params")
+        self.configure_openwrt_ap_and_start(saemixed_network=True,
+                                            ap_count=2,
+                                            mirror_ap=True,
+                                            ieee80211w=0)
+        ap1_network = self.saemixed_networks[0]["5g"]
+        ap2_network = self.saemixed_networks[1]["5g"]
+        # Get & Setup APs' BSSIDs.
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]]
+
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+
+    @test_tracker_info(uuid="94514f72-9e90-4d73-bba5-65b95e721cd8")
+    def test_roaming_between_saemixed_withPMF_5g(self):
+        """Verify saemixed with PMF when after roaming with OpenWrtAP
+
+         Steps:
+             1. Configure 2 APs to saemixed with PMF
+             2. Connect DUT to AP1
+             3. Roam to AP2
+             4. Verify the DUT can connect after roaming
+        """
+        # Use OpenWrt as Wi-Fi AP when it's available in testbed.
+        asserts.skip_if("OpenWrtAP" not in self.user_params, "OpenWrtAP not in user_params")
+        self.configure_openwrt_ap_and_start(saemixed_network=True,
+                                            ap_count=2,
+                                            mirror_ap=True,
+                                            ieee80211w=2)
+        ap1_network = self.saemixed_networks[0]["5g"]
+        ap2_network = self.saemixed_networks[1]["5g"]
+        # Get & Setup APs' BSSIDs.
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]]
+
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+
+    @test_tracker_info(uuid="05834382-5c3f-48d9-a6e6-8794ebf176f8")
+    def test_roaming_between_saemixed_woPMF_to_saemixed_wPMF_5g(self):
+        """Verify saemixed without/with PMF when after roaming with OpenWrtAP
+
+         Steps:
+             1. Configure 2 APs to saemixed with PMF
+             2. Configure AP1 to saemixed without PMF
+             3. Connect DUT to AP1
+             4. Roam to AP2
+             5. Verify the DUT can connect after roaming
+        """
+        # Use OpenWrt as Wi-Fi AP when it's available in testbed.
+        asserts.skip_if("OpenWrtAP" not in self.user_params, "OpenWrtAP not in user_params")
+        self.configure_openwrt_ap_and_start(saemixed_network=True,
+                                            ap_count=2,
+                                            mirror_ap=True,
+                                            ieee80211w=2)
+        self.openwrt1 = self.access_points[0]
+        self.openwrt2 = self.access_points[1]
+        ap1_network = self.saemixed_networks[0]["5g"]
+        ap2_network = self.saemixed_networks[1]["5g"]
+        # Get & Setup APs' BSSIDs.
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]]
+
+        # Configure AP1 to disable PMF.
+        self.configure_openwrt_ap_and_start(saemixed_network=True,
+                                            ieee80211w=0)
+        ap1_network = self.saemixed_networks[0]["5g"]
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+
+        # Change AP2 password and SSID same as AP1.
+        self.openwrt2.set_password(pwd_5g=ap1_network["password"])
+        self.openwrt2.set_ssid(ssid_5g=ap1_network["SSID"])
+        ap2_network["SSID"] = ap1_network["SSID"]
+        ap2_network["password"] = ap1_network["password"]
+
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+
+    @test_tracker_info(uuid="4d7cba89-40f1-4a2a-891d-4bb757f73442")
+    def test_roaming_between_saemixed_wPMF_to_saemixed_woPMF_5g(self):
+        """Verify saemixed with/without PMF when after roaming with OpenWrtAP
+
+         Steps:
+             1. Configure 2 APs to saemixed without PMF
+             2. Configure AP1 to saemixed with PMF
+             3. Connect DUT to AP1
+             4. Roam to AP2
+             5. Verify the DUT can connect after roaming
+        """
+        # Use OpenWrt as Wi-Fi AP when it's available in testbed.
+        asserts.skip_if("OpenWrtAP" not in self.user_params, "OpenWrtAP not in user_params")
+        self.configure_openwrt_ap_and_start(saemixed_network=True,
+                                            ap_count=2,
+                                            mirror_ap=True,
+                                            ieee80211w=0)
+        self.openwrt1 = self.access_points[0]
+        self.openwrt2 = self.access_points[1]
+        ap1_network = self.saemixed_networks[0]["5g"]
+        ap2_network = self.saemixed_networks[1]["5g"]
+        # Get & Setup APs' BSSIDs.
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]]
+
+        # Configure AP1 to enable PMF.
+        self.configure_openwrt_ap_and_start(saemixed_network=True,
+                                            ieee80211w=2)
+        ap1_network = self.saemixed_networks[0]["5g"]
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+
+        # Change AP2 password and SSID same as AP1.
+        self.openwrt2.set_password(pwd_5g=ap1_network["password"])
+        self.openwrt2.set_ssid(ssid_5g=ap1_network["SSID"])
+        ap2_network["SSID"] = ap1_network["SSID"]
+        ap2_network["password"] = ap1_network["password"]
+
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+
+    @test_tracker_info(uuid="57caaf0a-5251-4191-b4d1-de31d7c12295")
+    def test_roaming_between_sae_to_saemixed_woPMF_5g(self):
+        """Verify sae to saemixed without PMF when after roaming with OpenWrtAP
+
+         Steps:
+             1. Configure 2 APs security type to saemixed without PMF
+             2. Configure AP1 security type to sae
+             3. Connect DUT to AP1
+             4. Roam to AP2
+             5. Verify the DUT can connect after roaming
+        """
+        # Use OpenWrt as Wi-Fi AP when it's available in testbed.
+        asserts.skip_if("OpenWrtAP" not in self.user_params, "OpenWrtAP not in user_params")
+        self.configure_openwrt_ap_and_start(saemixed_network=True,
+                                            ap_count=2,
+                                            mirror_ap=True,
+                                            ieee80211w=0)
+        self.openwrt1 = self.access_points[0]
+        self.openwrt2 = self.access_points[1]
+        ap1_network = self.saemixed_networks[0]["5g"]
+        ap2_network = self.saemixed_networks[1]["5g"]
+        # Get & Setup APs' BSSIDs.
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]]
+
+        # Configure AP1 security type.
+        self.configure_openwrt_ap_and_start(sae_network=True)
+        ap1_network = self.sae_networks[0]["5g"]
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+
+        # Change AP2 password and SSID same as AP1.
+        self.openwrt2.set_password(pwd_5g=ap1_network["password"])
+        self.openwrt2.set_ssid(ssid_5g=ap1_network["SSID"])
+        ap2_network["SSID"] = ap1_network["SSID"]
+        ap2_network["password"] = ap1_network["password"]
+
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+
+    @test_tracker_info(uuid="0f5ca9d9-ef40-4a95-bf55-4c78358a9a3e")
+    def test_roaming_between_sae_to_saemixed_wPMF_5g(self):
+        """Verify sae to saemixed with PMF when after roaming with OpenWrtAP
+
+         Steps:
+             1. Configure 2 APs security type to saemixed with PMF
+             2. Configure AP1 security type to sae
+             3. Connect DUT to AP1
+             4. Roam to AP2
+             5. Verify the DUT can connect after roaming
+        """
+        # Use OpenWrt as Wi-Fi AP when it's available in testbed.
+        asserts.skip_if("OpenWrtAP" not in self.user_params, "OpenWrtAP not in user_params")
+        self.configure_openwrt_ap_and_start(saemixed_network=True,
+                                            ap_count=2,
+                                            mirror_ap=True,
+                                            ieee80211w=2)
+        self.openwrt1 = self.access_points[0]
+        self.openwrt2 = self.access_points[1]
+        ap1_network = self.saemixed_networks[0]["5g"]
+        ap2_network = self.saemixed_networks[1]["5g"]
+        # Get & Setup APs' BSSIDs.
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]]
+
+        # Configure AP1 security type.
+        self.configure_openwrt_ap_and_start(sae_network=True)
+        ap1_network = self.sae_networks[0]["5g"]
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+
+        # Change AP2 password and SSID same as AP1.
+        self.openwrt2.set_password(pwd_5g=ap1_network["password"])
+        self.openwrt2.set_ssid(ssid_5g=ap1_network["SSID"])
+        ap2_network["SSID"] = ap1_network["SSID"]
+        ap2_network["password"] = ap1_network["password"]
+
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+
+    @test_tracker_info(uuid="e875233f-d242-4ddd-b357-8e3e215af050")
+    def test_roaming_fail_between_psk_to_sae_5g(self):
+        """Verify fail with diff security type after roaming with OpenWrtAP
+
+         Steps:
+             1. Configure 2 APs security type to sae
+             2. Configure AP1 security type to psk
+             3. Connect DUT to AP1
+             4. Roam to AP2
+             5. Verify the DUT can't connect to AP2 after roaming
+        """
+        # Use OpenWrt as Wi-Fi AP when it's available in testbed.
+        asserts.skip_if("OpenWrtAP" not in self.user_params, "OpenWrtAP not in user_params")
+        self.configure_openwrt_ap_and_start(sae_network=True,
+                                            ap_count=2,
+                                            mirror_ap=True)
+        self.openwrt1 = self.access_points[0]
+        self.openwrt2 = self.access_points[1]
+        ap1_network = self.sae_networks[0]["5g"]
+        ap2_network = self.sae_networks[1]["5g"]
+        # Get & Setup APs' BSSIDs.
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]]
+
+        # Configure AP1 security type.
+        self.configure_openwrt_ap_and_start(wpa_network=True)
+        ap1_network = self.reference_networks[0]["5g"]
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+
+        # Change AP2 password and SSID same as AP1.
+        self.openwrt2.set_password(pwd_5g=ap1_network["password"])
+        self.openwrt2.set_ssid(ssid_5g=ap1_network["SSID"])
+        ap2_network["SSID"] = ap1_network["SSID"]
+        ap2_network["password"] = ap1_network["password"]
+
+        try:
+          # DUT roaming from AP1 to AP2 with diff security type.
+          self.dut.log.info("Roaming via WPA2 AP1 to SAE AP2 [{}]"
+                            .format(ap2_network["bssid"]))
+          self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+        except:
+          self.dut.log.info("Failed roaming to AP2 with diff security type")
+        else:
+          raise signals.TestFailure("DUT unexpectedly connect to Wi-Fi.")
+
+    @test_tracker_info(uuid="76098016-56a4-4b92-8c13-7333a21c9a1b")
+    def test_roaming_between_psk_to_saemixed_2g(self):
+        """Verify psk to saemixed with 11n when after roaming with OpenWrtAP
+
+         Steps:
+             1. Configure 2 APs security type to saemixed with 11n mode
+             2. Configure AP1 security type to psk with 11n mode
+             3. Connect DUT to AP1
+             4. Roam to AP2
+             5. Verify the DUT can connect after roaming
+        """
+        # Use OpenWrt as Wi-Fi AP when it's available in testbed.
+        asserts.skip_if("OpenWrtAP" not in self.user_params, "OpenWrtAP not in user_params")
+        self.configure_openwrt_ap_and_start(saemixed_network=True,
+                                            ap_count=2,
+                                            mirror_ap=True)
+        self.openwrt1 = self.access_points[0]
+        self.openwrt2 = self.access_points[1]
+        ap1_network = self.saemixed_networks[0]["2g"]
+        ap2_network = self.saemixed_networks[1]["2g"]
+        # Get & Setup APs' BSSIDs.
+        ap1_network["bssid"] = self.bssid_map[0]["2g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["2g"][ap2_network["SSID"]]
+
+        # Configure AP1 security type.
+        self.configure_openwrt_ap_and_start(wpa_network=True)
+        ap1_network = self.reference_networks[0]["2g"]
+        ap1_network["bssid"] = self.bssid_map[0]["2g"][ap1_network["SSID"]]
+
+        # Change AP2 password and SSID same as AP1.
+        self.openwrt2.set_password(pwd_2g=ap1_network["password"])
+        self.openwrt2.set_ssid(ssid_2g=ap1_network["SSID"])
+        ap2_network["SSID"] = ap1_network["SSID"]
+        ap2_network["password"] = ap1_network["password"]
+
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+
+    @test_tracker_info(uuid="2caf668d-6b05-4ba5-ac6b-1ec989fdf9ff")
+    def test_roaming_between_psk1_to_saemixed_2g(self):
+        """Verify psk1 to saemixed with 11n when after roaming with OpenWrtAP
+
+         Steps:
+             1. Configure 2 APs security type to saemixed with 11n mode
+             2. Configure AP1 security type to psk1 with 11n mode
+             3. Connect DUT to AP1
+             4. Roam to AP2
+             5. Verify the DUT can connect after roaming
+        """
+        # Use OpenWrt as Wi-Fi AP when it's available in testbed.
+        asserts.skip_if("OpenWrtAP" not in self.user_params, "OpenWrtAP not in user_params")
+        self.configure_openwrt_ap_and_start(saemixed_network=True,
+                                            ap_count=2,
+                                            mirror_ap=True)
+        self.openwrt1 = self.access_points[0]
+        self.openwrt2 = self.access_points[1]
+        ap1_network = self.saemixed_networks[0]["2g"]
+        ap2_network = self.saemixed_networks[1]["2g"]
+        # Get & Setup APs' BSSIDs.
+        ap1_network["bssid"] = self.bssid_map[0]["2g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["2g"][ap2_network["SSID"]]
+
+        # Configure AP1 security type.
+        self.configure_openwrt_ap_and_start(wpa1_network=True)
+        ap1_network = self.wpa1_networks[0]["2g"]
+        ap1_network["bssid"] = self.bssid_map[0]["2g"][ap1_network["SSID"]]
+
+        # Change AP2 password and SSID same as AP1.
+        self.openwrt2.set_password(pwd_2g=ap1_network["password"])
+        self.openwrt2.set_ssid(ssid_2g=ap1_network["SSID"])
+        ap2_network["SSID"] = ap1_network["SSID"]
+        ap2_network["password"] = ap1_network["password"]
+
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+
+    @test_tracker_info(uuid="cc8781ec-12fb-47a4-86d4-80d13231c75d")
+    def test_connect_to_wpa2_psk_2g_80211r(self):
+        """Test WPA2-PSK 802.11r 2G connectivity ant roaming."""
+        if "OpenWrtAP" in self.user_params:
+            self.openwrt1 = self.access_points[0]
+            self.openwrt2 = self.access_points[1]
+            self.configure_openwrt_ap_and_start(wpa_network=True,
+                                                ap_count=2,
+                                                mirror_ap=True)
+        ap1_network = self.reference_networks[0]["2g"]
+        ap2_network = self.reference_networks[1]["2g"]
+        ap1_network["bssid"] = self.bssid_map[0]["2g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["2g"][ap2_network["SSID"]]
+
+        md = self.openwrt1.generate_mobility_domain()
+        self.openwrt1.enable_80211r(OpenWrtWifiSetting.IFACE_2G, md)
+        self.openwrt2.enable_80211r(OpenWrtWifiSetting.IFACE_2G, md)
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
+
+    @test_tracker_info(uuid="8b0ee65e-bba2-4786-a8b9-8990316d123d")
+    def test_connect_to_wpa2_psk_5g_80211r(self):
+        """Test WPA2-PSK 802.11r 5G connectivity and roaming."""
+        if "OpenWrtAP" in self.user_params:
+            self.openwrt1 = self.access_points[0]
+            self.openwrt2 = self.access_points[1]
+            self.configure_openwrt_ap_and_start(wpa_network=True,
+                                                ap_count=2,
+                                                mirror_ap=True)
+        ap1_network = self.reference_networks[0]["5g"]
+        ap2_network = self.reference_networks[1]["5g"]
+        ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]]
+        ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]]
+
+        md = self.openwrt1.generate_mobility_domain()
+        self.openwrt1.enable_80211r(OpenWrtWifiSetting.IFACE_5G, md)
+        self.openwrt2.enable_80211r(OpenWrtWifiSetting.IFACE_5G, md)
+        self.roaming_from_AP1_and_AP2(ap1_network, ap2_network)
diff --git a/acts_tests/tests/google/wifi/WifiSoftApAcsTest.py b/acts_tests/tests/google/wifi/WifiSoftApAcsTest.py
index 974a784..da7877d 100644
--- a/acts_tests/tests/google/wifi/WifiSoftApAcsTest.py
+++ b/acts_tests/tests/google/wifi/WifiSoftApAcsTest.py
@@ -150,6 +150,8 @@
             self.log.debug("DUT is connected to softAP %s with details: %s" %
                            (softap[wutils.WifiEnums.SSID_KEY], softap_info))
             frequency = softap_info['frequency']
+            self.dut.log.info("DUT SoftAp operates on Channel: {}".
+                              format(WifiEnums.freq_to_channel[frequency]))
             if frequency > 0:
                 break
             time.sleep(1) # frequency not updated yet, try again after a delay
@@ -194,6 +196,10 @@
             return channel
         # Connect to the AP and start IPerf traffic, while we bring up softap.
         wutils.connect_to_wifi_network(self.dut_client, network)
+        freq = self.dut_client.droid.wifiGetConnectionInfo()["frequency"]
+        ap_chan = wutils.WifiEnums.freq_to_channel[freq]
+        self.dut_client.log.info("{} operates on channel: {}"
+                                 .format(network["SSID"], ap_chan))
         wutils.verify_11ax_wifi_connection(
             self.dut_client, self.wifi6_models, "wifi6_ap" in self.user_params)
         t = Thread(target=self.run_iperf_client,args=((network,self.dut_client),))
diff --git a/acts_tests/tests/google/wifi/WifiTeleCoexTest.py b/acts_tests/tests/google/wifi/WifiTeleCoexTest.py
index 6619ba4..7260919 100644
--- a/acts_tests/tests/google/wifi/WifiTeleCoexTest.py
+++ b/acts_tests/tests/google/wifi/WifiTeleCoexTest.py
@@ -6,6 +6,7 @@
 import acts.base_test
 import acts_contrib.test_utils.wifi.wifi_test_utils as wifi_utils
 import acts_contrib.test_utils.tel.tel_test_utils as tele_utils
+import acts_contrib.test_utils.tel.tel_mms_utils as mms_utils
 import acts.utils
 
 from acts import asserts
@@ -28,6 +29,7 @@
 WIFI_SSID = "wifi_network_ssid"
 WIFI_PWD = "wifi_network_pass"
 STRESS_COUNT = "stress_iteration"
+DEFAULT_TIMEOUT = 10
 
 class WifiTeleCoexTest(TelephonyBaseTest):
     """Tests for WiFi, Celular Co-existance."""
@@ -57,6 +59,7 @@
         for ad in self.android_devices:
             ad.droid.wakeLockAcquireBright()
             ad.droid.wakeUpNow()
+            ad.droid.telephonyToggleDataConnection(True)
         wifi_utils.wifi_toggle_state(self.dut, True)
 
 
@@ -64,8 +67,9 @@
         """ End test make sure the DUT return idle"""
         for ad in self.android_devices:
             wifi_utils.reset_wifi(ad)
+            ad.droid.telephonyToggleDataConnection(False)
         tele_utils.ensure_phones_idle(self.log, self.android_devices)
-
+        nutil.stop_usb_tethering(self.dut)
 
     """Helper Functions"""
 
@@ -453,4 +457,121 @@
             self.connect_to_wifi(self.dut, self.network)
         except:
             raise signals.TestFailure("The Wifi connect failed after modem restart."
-                "WiFi State = %d" %self.dut.droid.wifiCheckState())
\ No newline at end of file
+                "WiFi State = %d" %self.dut.droid.wifiCheckState())
+
+    @test_tracker_info(uuid="a72ff9da-3855-4c21-b447-b80f43227961")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_internet_accessing_over_wifi_and_mms_test(self):
+
+        """Verify when MMS is working WLAN connection can work normally as well.
+
+        Raises:
+          signals.TestFailure: Internet_connection is stop
+
+        Steps:
+            1. Connect to WiFi
+            2. Prepare two DUT for testing (DUT1 and DUT2)
+            3. Send 5 MMS from DUT1 to DUT2
+
+        Verification:
+            The internet cannot be impacted by MMS delivery.
+            MMS can be sent / received successfully and content is correct.
+        """
+        self.dut1 = self.android_devices[0]
+        self.dut2 = self.android_devices[1]
+        self.connect_to_wifi(self.dut1, self.network)
+        wifi_utils.wifi_toggle_state(self.dut2, True)
+        self.connect_to_wifi(self.dut2, self.network)
+        mms = 5
+        for count in range(mms):
+            mms_utils._mms_test(self.log, self.ads)
+            if not tele_utils.verify_internet_connection(
+                    self.dut2.log, self.dut2):
+                    raise signals.TestFailure("The internet connection is stop."
+                        "Current WiFi state is %d"
+                        % self.dut2.droid.wifiCheckState())
+            time.sleep(30)
+
+    @test_tracker_info(uuid="a7d774e4-ead3-465c-b4a6-f39a6397dfe3")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_internet_accessing_wifi_and_data_test(self):
+
+        """Verify interwork between Wi-Fi and data.
+
+        Raises:
+          signals.TestFailure: Internet_connection is stop for WiFi off or
+          Data off
+
+        Steps:
+            1. Connect to WiFi
+            2. To Wi-Fi and data switched for 5 times,
+            3. DUT is kept awake during testing.
+        Verification:
+            The internet cannot be impacted after data path switched
+
+        """
+        self.dut = self.android_devices[0]
+        self.connect_to_wifi(self.dut, self.network)
+        data_count = 5
+        for count in range(data_count):
+            wifi_utils.wifi_toggle_state(self.dut, False)
+            time.sleep(60)
+            if not tele_utils.verify_internet_connection(
+                    self.dut.log, self.dut):
+                raise signals.TestFailure(
+                    "The internet connection is stop"
+                    "for WiFi off. Current WiFi state is %d"
+                    % self.dut.droid.wifiCheckState())
+            wifi_utils.wifi_toggle_state(self.dut, True)
+            time.sleep(DEFAULT_TIMEOUT)
+            self.dut.log.info("DUT data is disable")
+            self.dut.droid.telephonyToggleDataConnection(False)
+            time.sleep(30)
+            if not tele_utils.verify_internet_connection(
+                    self.dut.log, self.dut):
+                raise signals.TestFailure(
+                    "The internet connection is stop"
+                    "for Data off. Current WiFi state is %d"
+                    % self.dut.droid.wifiCheckState())
+            self.dut.log.info("DUT data is enable")
+            self.dut.droid.telephonyToggleDataConnection(True)
+            time.sleep(DEFAULT_TIMEOUT)
+
+    @test_tracker_info(uuid="e53adef6-d537-4098-a354-1e63457ab444")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_internet_accessing_wifi_and_usb_tethering(self):
+
+        """Verify interwork between Wi-Fi and USB_TETHERED.
+
+        Raises:
+          signals.TestFailure: Internet_connection is stop for enable or
+          disable USB tethering
+
+        Steps:
+            1.Connect to WiFi
+            2. enable/disable USB tethering for 5 cycles,
+
+        Verification:
+            The Internet cannot be impacted after enable/disable USB tethering
+
+        """
+        self.dut = self.android_devices[0]
+        nutil.verify_lte_data_and_tethering_supported(self.dut)
+        self.connect_to_wifi(self.dut, self.network)
+        usb_count = 5
+        for count in range(usb_count):
+            time.sleep(DEFAULT_TIMEOUT)
+            nutil.start_usb_tethering(self.dut)
+            time.sleep(DEFAULT_TIMEOUT)
+            if not tele_utils.verify_internet_connection(
+                    self.dut.log, self.dut):
+                raise signals.TestFailure("The internet connection is stop"
+                    "for tethering enable. Current WiFi state is %d"
+                    % self.dut.droid.wifiCheckState())
+            nutil.stop_usb_tethering(self.dut)
+            time.sleep(DEFAULT_TIMEOUT)
+            if not tele_utils.verify_internet_connection(
+                    self.dut.log, self.dut):
+                raise signals.TestFailure("The internet connection is stop"
+                    "for tethering disable. Current WiFi state is %d"
+                    % self.dut.droid.wifiCheckState())
diff --git a/acts_tests/tests/google/wifi/WifiWpa2PersonalTest.py b/acts_tests/tests/google/wifi/WifiWpa2PersonalTest.py
index 71c8a18..65b8235 100644
--- a/acts_tests/tests/google/wifi/WifiWpa2PersonalTest.py
+++ b/acts_tests/tests/google/wifi/WifiWpa2PersonalTest.py
@@ -14,13 +14,15 @@
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
 
-
+import time
 import acts_contrib.test_utils.wifi.wifi_test_utils as wutils
 from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest
 from acts.controllers.ap_lib import hostapd_constants
 from acts.controllers.openwrt_lib.openwrt_constants import OpenWrtWifiSecurity
 from acts.test_decorators import test_tracker_info
 from acts import asserts
+from acts import utils
+from acts import signals
 
 
 WifiEnums = wutils.WifiEnums
@@ -40,8 +42,9 @@
   def setup_class(self):
     super().setup_class()
     self.dut = self.android_devices[0]
+    req_params = ["roaming_attn"]
     opt_params = ["pixel_models", "cnss_diag_file"]
-    self.unpack_userparams(opt_params)
+    self.unpack_userparams(req_params, opt_params)
 
   def setup_test(self):
     super().setup_test()
@@ -175,3 +178,159 @@
     wutils.connect_to_wifi_network(self.dut, self.wpa2_psk_5g)
     self.verify_wpa_network_encryption(
         OpenWrtWifiSecurity.WPA2_PSK_TKIP_AND_CCMP)
+
+  @test_tracker_info(uuid="4e8286a0-1b7c-4186-9d86-1cc5cd7a6be2")
+  def test_connect_to_wpa2_psk_ccmp_2g_after_airplane_mode(self):
+    """Test Wi-Fi reconnection after enabling Airplane Mode.
+
+    Steps:
+        DUT connect to 2GHz Wi-Fi network.
+        DUT turns ON Airplane Mode.
+        DUT turns ON Wi-Fi.
+        DUT verify internet connection with HTTP ping.
+        DUT turns OFF Airplane Mode.
+        DUT verify internet connection with HTTP ping.
+    """
+    self.start_openwrt()
+    self.openwrt.log.info("Enable WPA2-PSK CCMP on OpenWrt AP")
+    self.openwrt.set_wpa_encryption(OpenWrtWifiSecurity.WPA2_PSK_CCMP)
+    wutils.connect_to_wifi_network(self.dut, self.wpa2_psk_2g)
+    self.verify_wpa_network_encryption(OpenWrtWifiSecurity.WPA2_PSK_CCMP)
+    # Turn ON DUT's Airplane Mode.
+    self.dut.log.info("Toggle Airplane Mode ON")
+    utils.force_airplane_mode(self.dut, True)
+    self.dut.log.info("Toggle Wi-Fi ON")
+    # Turn ON DUT's Wi-Fi
+    wutils.wifi_toggle_state(self.dut, True)
+    wutils.wait_for_connect(self.dut,
+                            self.wpa2_psk_2g[WifiEnums.SSID_KEY])
+    wutils.validate_connection(self.dut)
+    utils.force_airplane_mode(self.dut, False)
+    wutils.validate_connection(self.dut)
+
+  @test_tracker_info(uuid="091c9b6a-d729-41d0-85e7-acf777aa3d1f")
+  def test_connect_to_wpa2_psk_ccmp_2g_after_wifi_off(self):
+    """Test Wi-Fi reconnection after Turn OFF Wi-Fi.
+
+    Steps:
+        DUT connect to 2GHz Wi-Fi network.
+        DUT turns OFF Wi-Fi.
+        DUT turns ON Wi-Fi.
+        DUT verify internet connection with HTTP ping.
+    """
+    self.start_openwrt()
+    self.openwrt.log.info("Enable WPA2-PSK CCMP on OpenWrt AP")
+    self.openwrt.set_wpa_encryption(OpenWrtWifiSecurity.WPA2_PSK_CCMP)
+    wutils.connect_to_wifi_network(self.dut, self.wpa2_psk_2g)
+    self.verify_wpa_network_encryption(OpenWrtWifiSecurity.WPA2_PSK_CCMP)
+    self.dut.log.info("Toggle Wi-Fi OFF")
+    # Turn OFF DUT's Wi-Fi then Turn if ON.
+    wutils.wifi_toggle_state(self.dut, False)
+    wutils.wifi_toggle_state(self.dut, True)
+    wutils.wait_for_connect(self.dut,
+                            self.wpa2_psk_2g[WifiEnums.SSID_KEY])
+    wutils.validate_connection(self.dut)
+
+  @test_tracker_info(uuid="9eb74878-1527-4c5b-980e-1a9305f601aa")
+  def test_connect_to_wpa2_psk_ccmp_2g_after_suspend_resume(self):
+    """Test Wi-Fi reconnection after Suspend.
+
+    Steps:
+        DUT connect to 2GHz Wi-Fi network.
+        DUT suspend and resume.
+        DUT verify internet connection with HTTP ping.
+    """
+    self.start_openwrt()
+    self.openwrt.log.info("Enable WPA2-PSK CCMP on OpenWrt AP")
+    self.openwrt.set_wpa_encryption(OpenWrtWifiSecurity.WPA2_PSK_CCMP)
+    wutils.connect_to_wifi_network(self.dut, self.wpa2_psk_2g)
+    self.verify_wpa_network_encryption(OpenWrtWifiSecurity.WPA2_PSK_CCMP)
+    self.dut.log.info("Suspend the DUT and wait for 10 seconds")
+    # Suspend and Resume the DUT.
+    self.dut.go_to_sleep()
+    time.sleep(10)
+    self.dut.log.info("Resume the DUT")
+    self.dut.wakeup_screen()
+    wutils.validate_connection(self.dut)
+
+  @test_tracker_info(uuid="44e5d946-620a-4e30-9578-f921460fe3f3")
+  def test_connect_to_wpa2_psk_ccmp_2g_after_reboot(self):
+    """Test Wi-Fi reconnection after reboot.
+
+    Steps:
+        DUT connect to 2GHz Wi-Fi network.
+        DUT reboot.
+        DUT verify internet connection with HTTP ping.
+    """
+    self.start_openwrt()
+    self.openwrt.log.info("Enable WPA2-PSK CCMP on OpenWrt AP")
+    self.openwrt.set_wpa_encryption(OpenWrtWifiSecurity.WPA2_PSK_CCMP)
+    wutils.connect_to_wifi_network(self.dut, self.wpa2_psk_2g)
+    self.verify_wpa_network_encryption(OpenWrtWifiSecurity.WPA2_PSK_CCMP)
+    # Reboot the DUT.
+    self.dut.log.info("Reboot the DUT")
+    self.dut.reboot()
+    self.dut.wait_for_boot_completion()
+    wutils.wait_for_connect(self.dut,
+                            self.wpa2_psk_2g[WifiEnums.SSID_KEY])
+    wutils.validate_connection(self.dut)
+
+  @test_tracker_info(uuid="7cb462c8-0a6e-4f33-b2fc-bf630d57e087")
+  def test_connect_to_wpa2_psk_ccmp_2g_after_incorrect_password(self):
+    """Test Wi-Fi reconnection after incorrect password.
+
+    Steps:
+        DUT connect to 2GHz Wi-Fi network.
+        DUT try to connect to the Wi-Fi network with incorrect password.
+        Connection fail as expected.
+        DUT connect to the Wi-Fi network with correct password.
+        DUT verify internet connection with HTTP ping.
+    """
+    self.start_openwrt()
+    self.openwrt.log.info("Enable WPA2-PSK CCMP on OpenWrt AP")
+    self.openwrt.set_wpa_encryption(OpenWrtWifiSecurity.WPA2_PSK_CCMP)
+    self.wpa2_psk_2g_fail = self.wpa2_psk_2g.copy()
+    self.wpa2_psk_2g_fail["password"] = "incorrect_password"
+    # Try to connect a Wi-Fi network with incorrect password.
+    try:
+      self.dut.log.info("Connect to Wi-Fi with wrong password")
+      wutils.wifi_connect(self.dut, self.wpa2_psk_2g_fail, num_of_tries=1)
+    except:
+      self.dut.log.info("Connect to Wi-Fi with correct password")
+      wutils.wifi_connect(self.dut, self.wpa2_psk_2g)
+    else:
+      raise signals.TestFailure("DUT connect to Wi-Fi with wrong password")
+    self.verify_wpa_network_encryption(OpenWrtWifiSecurity.WPA2_PSK_CCMP)
+    wutils.validate_connection(self.dut)
+
+  @test_tracker_info(uuid="890712de-2a3e-4b24-8529-e93893c8d99c")
+  def test_connect_to_wpa2_psk_ccmp_2g_after_out_of_range(self):
+    """Test Wi-Fi reconnection after out of range.
+
+    Steps:
+        DUT connect to 2GHz Wi-Fi network.
+        DUT out of Wi-Fi range.
+        Make Wi-Fi network is not visible by DUT.
+        DUT back in Wi-Fi range.
+        Wi-Fi network is visible by DUT.
+        DUT connect to the Wi-Fi network.
+        DUT verify internet connection with HTTP ping.
+    """
+    self.start_openwrt()
+    self.openwrt.log.info("Enable WPA2-PSK CCMP on OpenWrt AP")
+    self.openwrt.set_wpa_encryption(OpenWrtWifiSecurity.WPA2_PSK_CCMP)
+    wutils.connect_to_wifi_network(self.dut, self.wpa2_psk_2g)
+    # Make the DUT out of range.
+    wutils.set_attns(self.attenuators,
+                     "atten1_off_atten2_off",
+                     self.roaming_attn)
+    wutils.start_wifi_connection_scan_and_ensure_network_not_found(
+        self.dut,
+        self.wpa2_psk_2g[WifiEnums.SSID_KEY])
+    # Make the DUT back in range.
+    wutils.set_attns(self.attenuators,
+                     "atten1_on_atten2_on",
+                     self.roaming_attn)
+    wutils.start_wifi_connection_scan_and_ensure_network_found(
+        self.dut, self.wpa2_psk_2g[WifiEnums.SSID_KEY])
+    wutils.connect_to_wifi_network(self.dut, self.wpa2_psk_2g)