1#!/usr/bin/env python3 2# 3# Copyright 2017 - Google 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16""" 17 Base Class for Defining Common WiFi Test Functionality 18""" 19 20import copy 21import itertools 22import os 23import time 24 25import acts.controllers.access_point as ap 26 27from acts import asserts 28from acts import signals 29from acts import utils 30from acts.base_test import BaseTestClass 31from acts.signals import TestSignal 32from acts.controllers import android_device 33from acts.controllers.access_point import AccessPoint 34from acts.controllers.ap_lib import hostapd_ap_preset 35from acts.controllers.ap_lib import hostapd_bss_settings 36from acts.controllers.ap_lib import hostapd_constants 37from acts.controllers.ap_lib import hostapd_security 38from acts.keys import Config 39from acts_contrib.test_utils.net import net_test_utils as nutils 40from acts_contrib.test_utils.wifi import wifi_test_utils as wutils 41 42AP_1 = 0 43AP_2 = 1 44MAX_AP_COUNT = 2 45 46 47class WifiBaseTest(BaseTestClass): 48 def __init__(self, configs): 49 super().__init__(configs) 50 self.enable_packet_log = False 51 self.packet_log_2g = hostapd_constants.AP_DEFAULT_CHANNEL_2G 52 self.packet_log_5g = hostapd_constants.AP_DEFAULT_CHANNEL_5G 53 54 def setup_class(self): 55 if hasattr(self, 'attenuators') and self.attenuators: 56 for attenuator in self.attenuators: 57 attenuator.set_atten(0) 58 opt_param = ["country_code_file"] 59 self.unpack_userparams(opt_param_names=opt_param) 60 if self.enable_packet_log and hasattr(self, "packet_capture"): 61 self.packet_logger = self.packet_capture[0] 62 self.packet_logger.configure_monitor_mode("2G", self.packet_log_2g) 63 self.packet_logger.configure_monitor_mode("5G", self.packet_log_5g) 64 if hasattr(self, "android_devices"): 65 for ad in self.android_devices: 66 wutils.wifi_test_device_init(ad) 67 if hasattr(self, "country_code_file"): 68 if isinstance(self.country_code_file, list): 69 self.country_code_file = self.country_code_file[0] 70 if not os.path.isfile(self.country_code_file): 71 self.country_code_file = os.path.join( 72 self.user_params[Config.key_config_path.value], 73 self.country_code_file) 74 self.country_code = utils.load_config( 75 self.country_code_file)["country"] 76 wutils.set_wifi_country_code(ad, self.country_code) 77 78 def setup_test(self): 79 if (hasattr(self, "android_devices")): 80 wutils.start_all_wlan_logs(self.android_devices) 81 self.tcpdump_proc = [] 82 if hasattr(self, "android_devices"): 83 for ad in self.android_devices: 84 proc = nutils.start_tcpdump(ad, self.test_name) 85 self.tcpdump_proc.append((ad, proc)) 86 if hasattr(self, "packet_logger"): 87 self.packet_log_pid = wutils.start_pcap(self.packet_logger, 'dual', 88 self.test_name) 89 90 def teardown_test(self): 91 if (hasattr(self, "android_devices")): 92 wutils.stop_all_wlan_logs(self.android_devices) 93 for proc in self.tcpdump_proc: 94 nutils.stop_tcpdump(proc[0], 95 proc[1], 96 self.test_name, 97 pull_dump=False) 98 self.tcpdump_proc = [] 99 if hasattr(self, "packet_logger") and self.packet_log_pid: 100 wutils.stop_pcap(self.packet_logger, 101 self.packet_log_pid, 102 test_status=True) 103 self.packet_log_pid = {} 104 105 def on_fail(self, test_name, begin_time): 106 if hasattr(self, "android_devices"): 107 for ad in self.android_devices: 108 ad.take_bug_report(test_name, begin_time) 109 ad.cat_adb_log(test_name, begin_time) 110 wutils.get_ssrdumps(ad) 111 wutils.stop_all_wlan_logs(self.android_devices) 112 for ad in self.android_devices: 113 wutils.get_wlan_logs(ad) 114 for proc in self.tcpdump_proc: 115 nutils.stop_tcpdump(proc[0], proc[1], self.test_name) 116 self.tcpdump_proc = [] 117 if hasattr(self, "packet_logger") and self.packet_log_pid: 118 wutils.stop_pcap(self.packet_logger, 119 self.packet_log_pid, 120 test_status=False) 121 self.packet_log_pid = {} 122 123 def get_psk_network( 124 self, 125 mirror_ap, 126 reference_networks, 127 hidden=False, 128 same_ssid=False, 129 security_mode=hostapd_constants.WPA2_STRING, 130 ssid_length_2g=hostapd_constants.AP_SSID_LENGTH_2G, 131 ssid_length_5g=hostapd_constants.AP_SSID_LENGTH_5G, 132 passphrase_length_2g=hostapd_constants.AP_PASSPHRASE_LENGTH_2G, 133 passphrase_length_5g=hostapd_constants.AP_PASSPHRASE_LENGTH_5G): 134 """Generates SSID and passphrase for a WPA2 network using random 135 generator. 136 137 Args: 138 mirror_ap: Boolean, determines if both APs use the same hostapd 139 config or different configs. 140 reference_networks: List of PSK networks. 141 same_ssid: Boolean, determines if both bands on AP use the same 142 SSID. 143 ssid_length_2gecond AP Int, number of characters to use for 2G SSID. 144 ssid_length_5g: Int, number of characters to use for 5G SSID. 145 passphrase_length_2g: Int, length of password for 2G network. 146 passphrase_length_5g: Int, length of password for 5G network. 147 148 Returns: A dict of 2G and 5G network lists for hostapd configuration. 149 150 """ 151 network_dict_2g = {} 152 network_dict_5g = {} 153 ref_5g_security = security_mode 154 ref_2g_security = security_mode 155 156 if same_ssid: 157 ref_2g_ssid = 'xg_%s' % utils.rand_ascii_str(ssid_length_2g) 158 ref_5g_ssid = ref_2g_ssid 159 160 ref_2g_passphrase = utils.rand_ascii_str(passphrase_length_2g) 161 ref_5g_passphrase = ref_2g_passphrase 162 163 else: 164 ref_2g_ssid = '2g_%s' % utils.rand_ascii_str(ssid_length_2g) 165 ref_2g_passphrase = utils.rand_ascii_str(passphrase_length_2g) 166 167 ref_5g_ssid = '5g_%s' % utils.rand_ascii_str(ssid_length_5g) 168 ref_5g_passphrase = utils.rand_ascii_str(passphrase_length_5g) 169 170 network_dict_2g = { 171 "SSID": ref_2g_ssid, 172 "security": ref_2g_security, 173 "password": ref_2g_passphrase, 174 "hiddenSSID": hidden 175 } 176 177 network_dict_5g = { 178 "SSID": ref_5g_ssid, 179 "security": ref_5g_security, 180 "password": ref_5g_passphrase, 181 "hiddenSSID": hidden 182 } 183 184 ap = 0 185 for ap in range(MAX_AP_COUNT): 186 reference_networks.append({ 187 "2g": copy.copy(network_dict_2g), 188 "5g": copy.copy(network_dict_5g) 189 }) 190 if not mirror_ap: 191 break 192 return {"2g": network_dict_2g, "5g": network_dict_5g} 193 194 def get_open_network(self, 195 mirror_ap, 196 open_network, 197 hidden=False, 198 same_ssid=False, 199 ssid_length_2g=hostapd_constants.AP_SSID_LENGTH_2G, 200 ssid_length_5g=hostapd_constants.AP_SSID_LENGTH_5G, 201 security_mode='none'): 202 """Generates SSIDs for a open network using a random generator. 203 204 Args: 205 mirror_ap: Boolean, determines if both APs use the same hostapd 206 config or different configs. 207 open_network: List of open networks. 208 same_ssid: Boolean, determines if both bands on AP use the same 209 SSID. 210 ssid_length_2g: Int, number of characters to use for 2G SSID. 211 ssid_length_5g: Int, number of characters to use for 5G SSID. 212 security_mode: 'none' for open and 'OWE' for WPA3 OWE. 213 214 Returns: A dict of 2G and 5G network lists for hostapd configuration. 215 216 """ 217 network_dict_2g = {} 218 network_dict_5g = {} 219 220 if same_ssid: 221 open_2g_ssid = 'xg_%s' % utils.rand_ascii_str(ssid_length_2g) 222 open_5g_ssid = open_2g_ssid 223 224 else: 225 open_2g_ssid = '2g_%s' % utils.rand_ascii_str(ssid_length_2g) 226 open_5g_ssid = '5g_%s' % utils.rand_ascii_str(ssid_length_5g) 227 228 network_dict_2g = { 229 "SSID": open_2g_ssid, 230 "security": security_mode, 231 "hiddenSSID": hidden 232 } 233 234 network_dict_5g = { 235 "SSID": open_5g_ssid, 236 "security": security_mode, 237 "hiddenSSID": hidden 238 } 239 240 ap = 0 241 for ap in range(MAX_AP_COUNT): 242 open_network.append({ 243 "2g": copy.copy(network_dict_2g), 244 "5g": copy.copy(network_dict_5g) 245 }) 246 if not mirror_ap: 247 break 248 return {"2g": network_dict_2g, "5g": network_dict_5g} 249 250 def get_wep_network( 251 self, 252 mirror_ap, 253 networks, 254 hidden=False, 255 same_ssid=False, 256 ssid_length_2g=hostapd_constants.AP_SSID_LENGTH_2G, 257 ssid_length_5g=hostapd_constants.AP_SSID_LENGTH_5G, 258 passphrase_length_2g=hostapd_constants.AP_PASSPHRASE_LENGTH_2G, 259 passphrase_length_5g=hostapd_constants.AP_PASSPHRASE_LENGTH_5G): 260 """Generates SSID and passphrase for a WEP network using random 261 generator. 262 263 Args: 264 mirror_ap: Boolean, determines if both APs use the same hostapd 265 config or different configs. 266 networks: List of WEP networks. 267 same_ssid: Boolean, determines if both bands on AP use the same 268 SSID. 269 ssid_length_2gecond AP Int, number of characters to use for 2G SSID. 270 ssid_length_5g: Int, number of characters to use for 5G SSID. 271 passphrase_length_2g: Int, length of password for 2G network. 272 passphrase_length_5g: Int, length of password for 5G network. 273 274 Returns: A dict of 2G and 5G network lists for hostapd configuration. 275 276 """ 277 network_dict_2g = {} 278 network_dict_5g = {} 279 ref_5g_security = hostapd_constants.WEP_STRING 280 ref_2g_security = hostapd_constants.WEP_STRING 281 282 if same_ssid: 283 ref_2g_ssid = 'xg_%s' % utils.rand_ascii_str(ssid_length_2g) 284 ref_5g_ssid = ref_2g_ssid 285 286 ref_2g_passphrase = utils.rand_hex_str(passphrase_length_2g) 287 ref_5g_passphrase = ref_2g_passphrase 288 289 else: 290 ref_2g_ssid = '2g_%s' % utils.rand_ascii_str(ssid_length_2g) 291 ref_2g_passphrase = utils.rand_hex_str(passphrase_length_2g) 292 293 ref_5g_ssid = '5g_%s' % utils.rand_ascii_str(ssid_length_5g) 294 ref_5g_passphrase = utils.rand_hex_str(passphrase_length_5g) 295 296 network_dict_2g = { 297 "SSID": ref_2g_ssid, 298 "security": ref_2g_security, 299 "wepKeys": [ref_2g_passphrase] * 4, 300 "hiddenSSID": hidden 301 } 302 303 network_dict_5g = { 304 "SSID": ref_5g_ssid, 305 "security": ref_5g_security, 306 "wepKeys": [ref_2g_passphrase] * 4, 307 "hiddenSSID": hidden 308 } 309 310 ap = 0 311 for ap in range(MAX_AP_COUNT): 312 networks.append({ 313 "2g": copy.copy(network_dict_2g), 314 "5g": copy.copy(network_dict_5g) 315 }) 316 if not mirror_ap: 317 break 318 return {"2g": network_dict_2g, "5g": network_dict_5g} 319 320 def update_bssid(self, ap_instance, ap, network, band): 321 """Get bssid and update network dictionary. 322 323 Args: 324 ap_instance: Accesspoint index that was configured. 325 ap: Accesspoint object corresponding to ap_instance. 326 network: Network dictionary. 327 band: Wifi networks' band. 328 329 """ 330 bssid = ap.get_bssid_from_ssid(network["SSID"], band) 331 332 if network["security"] == hostapd_constants.WPA2_STRING: 333 # TODO:(bamahadev) Change all occurances of reference_networks 334 # to wpa_networks. 335 self.reference_networks[ap_instance][band]["bssid"] = bssid 336 if network["security"] == hostapd_constants.WPA_STRING: 337 self.wpa_networks[ap_instance][band]["bssid"] = bssid 338 if network["security"] == hostapd_constants.WEP_STRING: 339 self.wep_networks[ap_instance][band]["bssid"] = bssid 340 if network["security"] == hostapd_constants.ENT_STRING: 341 if "bssid" not in self.ent_networks[ap_instance][band]: 342 self.ent_networks[ap_instance][band]["bssid"] = bssid 343 else: 344 self.ent_networks_pwd[ap_instance][band]["bssid"] = bssid 345 if network["security"] == 'none': 346 self.open_network[ap_instance][band]["bssid"] = bssid 347 348 def populate_bssid(self, ap_instance, ap, networks_5g, networks_2g): 349 """Get bssid for a given SSID and add it to the network dictionary. 350 351 Args: 352 ap_instance: Accesspoint index that was configured. 353 ap: Accesspoint object corresponding to ap_instance. 354 networks_5g: List of 5g networks configured on the APs. 355 networks_2g: List of 2g networks configured on the APs. 356 357 """ 358 359 if not (networks_5g or networks_2g): 360 return 361 362 for network in networks_5g: 363 if 'channel' in network: 364 continue 365 self.update_bssid(ap_instance, ap, network, 366 hostapd_constants.BAND_5G) 367 368 for network in networks_2g: 369 if 'channel' in network: 370 continue 371 self.update_bssid(ap_instance, ap, network, 372 hostapd_constants.BAND_2G) 373 374 def configure_openwrt_ap_and_start( 375 self, 376 channel_5g=hostapd_constants.AP_DEFAULT_CHANNEL_5G, 377 channel_2g=hostapd_constants.AP_DEFAULT_CHANNEL_2G, 378 channel_5g_ap2=None, 379 channel_2g_ap2=None, 380 ssid_length_2g=hostapd_constants.AP_SSID_LENGTH_2G, 381 passphrase_length_2g=hostapd_constants.AP_PASSPHRASE_LENGTH_2G, 382 ssid_length_5g=hostapd_constants.AP_SSID_LENGTH_5G, 383 passphrase_length_5g=hostapd_constants.AP_PASSPHRASE_LENGTH_5G, 384 mirror_ap=False, 385 hidden=False, 386 same_ssid=False, 387 open_network=False, 388 wpa1_network=False, 389 wpa_network=False, 390 wep_network=False, 391 ent_network=False, 392 ent_network_pwd=False, 393 owe_network=False, 394 sae_network=False, 395 saemixed_network=False, 396 radius_conf_2g=None, 397 radius_conf_5g=None, 398 radius_conf_pwd=None, 399 ap_count=1, 400 ieee80211w=None): 401 """Create, configure and start OpenWrt AP. 402 403 Args: 404 channel_5g: 5G channel to configure. 405 channel_2g: 2G channel to configure. 406 channel_5g_ap2: 5G channel to configure on AP2. 407 channel_2g_ap2: 2G channel to configure on AP2. 408 ssid_length_2g: Int, number of characters to use for 2G SSID. 409 passphrase_length_2g: Int, length of password for 2G network. 410 ssid_length_5g: Int, number of characters to use for 5G SSID. 411 passphrase_length_5g: Int, length of password for 5G network. 412 same_ssid: Boolean, determines if both bands on AP use the same SSID. 413 open_network: Boolean, to check if open network should be configured. 414 wpa_network: Boolean, to check if wpa network should be configured. 415 wep_network: Boolean, to check if wep network should be configured. 416 ent_network: Boolean, to check if ent network should be configured. 417 ent_network_pwd: Boolean, to check if ent pwd network should be configured. 418 owe_network: Boolean, to check if owe network should be configured. 419 sae_network: Boolean, to check if sae network should be configured. 420 saemixed_network: Boolean, to check if saemixed network should be configured. 421 radius_conf_2g: dictionary with enterprise radius server details. 422 radius_conf_5g: dictionary with enterprise radius server details. 423 radius_conf_pwd: dictionary with enterprise radiuse server details. 424 ap_count: APs to configure. 425 ieee80211w:PMF to configure 426 """ 427 if mirror_ap and ap_count == 1: 428 raise ValueError("ap_count cannot be 1 if mirror_ap is True.") 429 if (channel_5g_ap2 or channel_2g_ap2) and ap_count == 1: 430 raise ValueError( 431 "ap_count cannot be 1 if channels of AP2 are provided.") 432 # we are creating a channel list for 2G and 5G bands. The list is of 433 # size 2 and this is based on the assumption that each testbed will have 434 # at most 2 APs. 435 if not channel_5g_ap2: 436 channel_5g_ap2 = channel_5g 437 if not channel_2g_ap2: 438 channel_2g_ap2 = channel_2g 439 channels_2g = [channel_2g, channel_2g_ap2] 440 channels_5g = [channel_5g, channel_5g_ap2] 441 442 self.reference_networks = [] 443 self.wpa1_networks = [] 444 self.wpa_networks = [] 445 self.wep_networks = [] 446 self.ent_networks = [] 447 self.ent_networks_pwd = [] 448 self.open_network = [] 449 self.owe_networks = [] 450 self.sae_networks = [] 451 self.saemixed_networks = [] 452 self.bssid_map = [] 453 for i in range(ap_count): 454 network_list = [] 455 if wpa1_network: 456 wpa1_dict = self.get_psk_network(mirror_ap, 457 self.wpa1_networks, 458 hidden, same_ssid, 459 ssid_length_2g, ssid_length_5g, 460 passphrase_length_2g, 461 passphrase_length_5g) 462 wpa1_dict[hostapd_constants.BAND_2G]["security"] = "psk" 463 wpa1_dict[hostapd_constants.BAND_5G]["security"] = "psk" 464 wpa1_dict[hostapd_constants.BAND_2G]["ieee80211w"] = ieee80211w 465 wpa1_dict[hostapd_constants.BAND_5G]["ieee80211w"] = ieee80211w 466 self.wpa1_networks.append(wpa1_dict) 467 network_list.append(wpa1_dict) 468 if wpa_network: 469 wpa_dict = self.get_psk_network(mirror_ap, 470 self.reference_networks, 471 hidden, same_ssid, 472 ssid_length_2g, ssid_length_5g, 473 passphrase_length_2g, 474 passphrase_length_5g) 475 wpa_dict[hostapd_constants.BAND_2G]["security"] = "psk2" 476 wpa_dict[hostapd_constants.BAND_5G]["security"] = "psk2" 477 wpa_dict[hostapd_constants.BAND_2G]["ieee80211w"] = ieee80211w 478 wpa_dict[hostapd_constants.BAND_5G]["ieee80211w"] = ieee80211w 479 self.wpa_networks.append(wpa_dict) 480 network_list.append(wpa_dict) 481 if wep_network: 482 wep_dict = self.get_wep_network(mirror_ap, self.wep_networks, 483 hidden, same_ssid, 484 ssid_length_2g, ssid_length_5g) 485 network_list.append(wep_dict) 486 if ent_network: 487 ent_dict = self.get_open_network(mirror_ap, self.ent_networks, 488 hidden, same_ssid, 489 ssid_length_2g, 490 ssid_length_5g) 491 ent_dict["2g"]["security"] = "wpa2" 492 ent_dict["2g"].update(radius_conf_2g) 493 ent_dict["5g"]["security"] = "wpa2" 494 ent_dict["5g"].update(radius_conf_5g) 495 network_list.append(ent_dict) 496 if ent_network_pwd: 497 ent_pwd_dict = self.get_open_network(mirror_ap, 498 self.ent_networks_pwd, 499 hidden, same_ssid, 500 ssid_length_2g, 501 ssid_length_5g) 502 ent_pwd_dict["2g"]["security"] = "wpa2" 503 ent_pwd_dict["2g"].update(radius_conf_pwd) 504 ent_pwd_dict["5g"]["security"] = "wpa2" 505 ent_pwd_dict["5g"].update(radius_conf_pwd) 506 network_list.append(ent_pwd_dict) 507 if open_network: 508 open_dict = self.get_open_network(mirror_ap, self.open_network, 509 hidden, same_ssid, 510 ssid_length_2g, 511 ssid_length_5g) 512 network_list.append(open_dict) 513 if owe_network: 514 owe_dict = self.get_open_network(mirror_ap, self.owe_networks, 515 hidden, same_ssid, 516 ssid_length_2g, 517 ssid_length_5g, "OWE") 518 owe_dict[hostapd_constants.BAND_2G]["security"] = "owe" 519 owe_dict[hostapd_constants.BAND_5G]["security"] = "owe" 520 network_list.append(owe_dict) 521 if sae_network: 522 sae_dict = self.get_psk_network(mirror_ap, self.sae_networks, 523 hidden, same_ssid, 524 hostapd_constants.SAE_KEY_MGMT, 525 ssid_length_2g, ssid_length_5g, 526 passphrase_length_2g, 527 passphrase_length_5g) 528 sae_dict[hostapd_constants.BAND_2G]["security"] = "sae" 529 sae_dict[hostapd_constants.BAND_5G]["security"] = "sae" 530 network_list.append(sae_dict) 531 if saemixed_network: 532 saemixed_dict = self.get_psk_network(mirror_ap, self.saemixed_networks, 533 hidden, same_ssid, 534 hostapd_constants.SAE_KEY_MGMT, 535 ssid_length_2g, ssid_length_5g, 536 passphrase_length_2g, 537 passphrase_length_5g) 538 saemixed_dict[hostapd_constants.BAND_2G]["security"] = "sae-mixed" 539 saemixed_dict[hostapd_constants.BAND_5G]["security"] = "sae-mixed" 540 saemixed_dict[hostapd_constants.BAND_2G]["ieee80211w"] = ieee80211w 541 saemixed_dict[hostapd_constants.BAND_5G]["ieee80211w"] = ieee80211w 542 network_list.append(saemixed_dict) 543 self.access_points[i].configure_ap(network_list, channels_2g[i], 544 channels_5g[i]) 545 self.access_points[i].start_ap() 546 self.bssid_map.append( 547 self.access_points[i].get_bssids_for_wifi_networks()) 548 if mirror_ap: 549 self.access_points[i + 1].configure_ap(network_list, 550 channels_2g[i+1], 551 channels_5g[i+1]) 552 self.access_points[i + 1].start_ap() 553 self.bssid_map.append( 554 self.access_points[i + 1].get_bssids_for_wifi_networks()) 555 break 556 557 def legacy_configure_ap_and_start( 558 self, 559 channel_5g=hostapd_constants.AP_DEFAULT_CHANNEL_5G, 560 channel_2g=hostapd_constants.AP_DEFAULT_CHANNEL_2G, 561 max_2g_networks=hostapd_constants.AP_DEFAULT_MAX_SSIDS_2G, 562 max_5g_networks=hostapd_constants.AP_DEFAULT_MAX_SSIDS_5G, 563 ap_ssid_length_2g=hostapd_constants.AP_SSID_LENGTH_2G, 564 ap_passphrase_length_2g=hostapd_constants.AP_PASSPHRASE_LENGTH_2G, 565 ap_ssid_length_5g=hostapd_constants.AP_SSID_LENGTH_5G, 566 ap_passphrase_length_5g=hostapd_constants.AP_PASSPHRASE_LENGTH_5G, 567 hidden=False, 568 same_ssid=False, 569 mirror_ap=True, 570 wpa_network=False, 571 wep_network=False, 572 ent_network=False, 573 radius_conf_2g=None, 574 radius_conf_5g=None, 575 ent_network_pwd=False, 576 radius_conf_pwd=None, 577 ap_count=1): 578 579 config_count = 1 580 count = 0 581 582 # For example, the NetworkSelector tests use 2 APs and require that 583 # both APs are not mirrored. 584 if not mirror_ap and ap_count == 1: 585 raise ValueError("ap_count cannot be 1 if mirror_ap is False.") 586 587 if not mirror_ap: 588 config_count = ap_count 589 590 self.user_params["reference_networks"] = [] 591 self.user_params["open_network"] = [] 592 if wpa_network: 593 self.user_params["wpa_networks"] = [] 594 if wep_network: 595 self.user_params["wep_networks"] = [] 596 if ent_network: 597 self.user_params["ent_networks"] = [] 598 if ent_network_pwd: 599 self.user_params["ent_networks_pwd"] = [] 600 601 # kill hostapd & dhcpd if the cleanup was not successful 602 for i in range(len(self.access_points)): 603 self.log.debug("Check ap state and cleanup") 604 self._cleanup_hostapd_and_dhcpd(i) 605 606 for count in range(config_count): 607 608 network_list_2g = [] 609 network_list_5g = [] 610 611 orig_network_list_2g = [] 612 orig_network_list_5g = [] 613 614 network_list_2g.append({"channel": channel_2g}) 615 network_list_5g.append({"channel": channel_5g}) 616 617 networks_dict = self.get_psk_network( 618 mirror_ap, 619 self.user_params["reference_networks"], 620 hidden=hidden, 621 same_ssid=same_ssid) 622 self.reference_networks = self.user_params["reference_networks"] 623 624 network_list_2g.append(networks_dict["2g"]) 625 network_list_5g.append(networks_dict["5g"]) 626 627 # When same_ssid is set, only configure one set of WPA networks. 628 # We cannot have more than one set because duplicate interface names 629 # are not allowed. 630 # TODO(bmahadev): Provide option to select the type of network, 631 # instead of defaulting to WPA. 632 if not same_ssid: 633 networks_dict = self.get_open_network( 634 mirror_ap, 635 self.user_params["open_network"], 636 hidden=hidden, 637 same_ssid=same_ssid) 638 self.open_network = self.user_params["open_network"] 639 640 network_list_2g.append(networks_dict["2g"]) 641 network_list_5g.append(networks_dict["5g"]) 642 643 if wpa_network: 644 networks_dict = self.get_psk_network( 645 mirror_ap, 646 self.user_params["wpa_networks"], 647 hidden=hidden, 648 same_ssid=same_ssid, 649 security_mode=hostapd_constants.WPA_STRING) 650 self.wpa_networks = self.user_params["wpa_networks"] 651 652 network_list_2g.append(networks_dict["2g"]) 653 network_list_5g.append(networks_dict["5g"]) 654 655 if wep_network: 656 networks_dict = self.get_wep_network( 657 mirror_ap, 658 self.user_params["wep_networks"], 659 hidden=hidden, 660 same_ssid=same_ssid) 661 self.wep_networks = self.user_params["wep_networks"] 662 663 network_list_2g.append(networks_dict["2g"]) 664 network_list_5g.append(networks_dict["5g"]) 665 666 if ent_network: 667 networks_dict = self.get_open_network( 668 mirror_ap, 669 self.user_params["ent_networks"], 670 hidden=hidden, 671 same_ssid=same_ssid) 672 networks_dict["2g"][ 673 "security"] = hostapd_constants.ENT_STRING 674 networks_dict["2g"].update(radius_conf_2g) 675 networks_dict["5g"][ 676 "security"] = hostapd_constants.ENT_STRING 677 networks_dict["5g"].update(radius_conf_5g) 678 self.ent_networks = self.user_params["ent_networks"] 679 680 network_list_2g.append(networks_dict["2g"]) 681 network_list_5g.append(networks_dict["5g"]) 682 683 if ent_network_pwd: 684 networks_dict = self.get_open_network( 685 mirror_ap, 686 self.user_params["ent_networks_pwd"], 687 hidden=hidden, 688 same_ssid=same_ssid) 689 networks_dict["2g"][ 690 "security"] = hostapd_constants.ENT_STRING 691 networks_dict["2g"].update(radius_conf_pwd) 692 networks_dict["5g"][ 693 "security"] = hostapd_constants.ENT_STRING 694 networks_dict["5g"].update(radius_conf_pwd) 695 self.ent_networks_pwd = self.user_params[ 696 "ent_networks_pwd"] 697 698 network_list_2g.append(networks_dict["2g"]) 699 network_list_5g.append(networks_dict["5g"]) 700 701 orig_network_list_5g = copy.copy(network_list_5g) 702 orig_network_list_2g = copy.copy(network_list_2g) 703 704 if len(network_list_5g) > 1: 705 self.config_5g = self._generate_legacy_ap_config( 706 network_list_5g) 707 if len(network_list_2g) > 1: 708 self.config_2g = self._generate_legacy_ap_config( 709 network_list_2g) 710 711 self.access_points[count].start_ap(self.config_2g) 712 self.access_points[count].start_ap(self.config_5g) 713 self.populate_bssid(count, self.access_points[count], 714 orig_network_list_5g, orig_network_list_2g) 715 716 # Repeat configuration on the second router. 717 if mirror_ap and ap_count == 2: 718 self.access_points[AP_2].start_ap(self.config_2g) 719 self.access_points[AP_2].start_ap(self.config_5g) 720 self.populate_bssid(AP_2, self.access_points[AP_2], 721 orig_network_list_5g, orig_network_list_2g) 722 723 def _kill_processes(self, ap, daemon): 724 """ Kill hostapd and dhcpd daemons 725 726 Args: 727 ap: AP to cleanup 728 daemon: process to kill 729 730 Returns: True/False if killing process is successful 731 """ 732 self.log.info("Killing %s" % daemon) 733 pids = ap.ssh.run('pidof %s' % daemon, ignore_status=True) 734 if pids.stdout: 735 ap.ssh.run('kill %s' % pids.stdout, ignore_status=True) 736 time.sleep(3) 737 pids = ap.ssh.run('pidof %s' % daemon, ignore_status=True) 738 if pids.stdout: 739 return False 740 return True 741 742 def _cleanup_hostapd_and_dhcpd(self, count): 743 """ Check if AP was cleaned up properly 744 745 Kill hostapd and dhcpd processes if cleanup was not successful in the 746 last run 747 748 Args: 749 count: AP to check 750 751 Returns: 752 New AccessPoint object if AP required cleanup 753 754 Raises: 755 Error: if the AccessPoint timed out to setup 756 """ 757 ap = self.access_points[count] 758 phy_ifaces = ap.interfaces.get_physical_interface() 759 kill_hostapd = False 760 for iface in phy_ifaces: 761 if '2g_' in iface or '5g_' in iface or 'xg_' in iface: 762 kill_hostapd = True 763 break 764 765 if not kill_hostapd: 766 return 767 768 self.log.debug("Cleanup AP") 769 if not self._kill_processes(ap, 'hostapd') or \ 770 not self._kill_processes(ap, 'dhcpd'): 771 raise ("Failed to cleanup AP") 772 773 ap.__init__(self.user_params['AccessPoint'][count]) 774 775 def _generate_legacy_ap_config(self, network_list): 776 bss_settings = [] 777 wlan_2g = self.access_points[AP_1].wlan_2g 778 wlan_5g = self.access_points[AP_1].wlan_5g 779 ap_settings = network_list.pop(0) 780 # TODO:(bmahadev) This is a bug. We should not have to pop the first 781 # network in the list and treat it as a separate case. Instead, 782 # create_ap_preset() should be able to take NULL ssid and security and 783 # build config based on the bss_Settings alone. 784 hostapd_config_settings = network_list.pop(0) 785 for network in network_list: 786 if "password" in network: 787 bss_settings.append( 788 hostapd_bss_settings.BssSettings( 789 name=network["SSID"], 790 ssid=network["SSID"], 791 hidden=network["hiddenSSID"], 792 security=hostapd_security.Security( 793 security_mode=network["security"], 794 password=network["password"]))) 795 elif "wepKeys" in network: 796 bss_settings.append( 797 hostapd_bss_settings.BssSettings( 798 name=network["SSID"], 799 ssid=network["SSID"], 800 hidden=network["hiddenSSID"], 801 security=hostapd_security.Security( 802 security_mode=network["security"], 803 password=network["wepKeys"][0]))) 804 elif network["security"] == hostapd_constants.ENT_STRING: 805 bss_settings.append( 806 hostapd_bss_settings.BssSettings( 807 name=network["SSID"], 808 ssid=network["SSID"], 809 hidden=network["hiddenSSID"], 810 security=hostapd_security.Security( 811 security_mode=network["security"], 812 radius_server_ip=network["radius_server_ip"], 813 radius_server_port=network["radius_server_port"], 814 radius_server_secret=network[ 815 "radius_server_secret"]))) 816 else: 817 bss_settings.append( 818 hostapd_bss_settings.BssSettings( 819 name=network["SSID"], 820 ssid=network["SSID"], 821 hidden=network["hiddenSSID"])) 822 if "password" in hostapd_config_settings: 823 config = hostapd_ap_preset.create_ap_preset( 824 iface_wlan_2g=wlan_2g, 825 iface_wlan_5g=wlan_5g, 826 channel=ap_settings["channel"], 827 ssid=hostapd_config_settings["SSID"], 828 hidden=hostapd_config_settings["hiddenSSID"], 829 security=hostapd_security.Security( 830 security_mode=hostapd_config_settings["security"], 831 password=hostapd_config_settings["password"]), 832 bss_settings=bss_settings) 833 elif "wepKeys" in hostapd_config_settings: 834 config = hostapd_ap_preset.create_ap_preset( 835 iface_wlan_2g=wlan_2g, 836 iface_wlan_5g=wlan_5g, 837 channel=ap_settings["channel"], 838 ssid=hostapd_config_settings["SSID"], 839 hidden=hostapd_config_settings["hiddenSSID"], 840 security=hostapd_security.Security( 841 security_mode=hostapd_config_settings["security"], 842 password=hostapd_config_settings["wepKeys"][0]), 843 bss_settings=bss_settings) 844 else: 845 config = hostapd_ap_preset.create_ap_preset( 846 iface_wlan_2g=wlan_2g, 847 iface_wlan_5g=wlan_5g, 848 channel=ap_settings["channel"], 849 ssid=hostapd_config_settings["SSID"], 850 hidden=hostapd_config_settings["hiddenSSID"], 851 bss_settings=bss_settings) 852 return config 853 854 def configure_packet_capture( 855 self, 856 channel_5g=hostapd_constants.AP_DEFAULT_CHANNEL_5G, 857 channel_2g=hostapd_constants.AP_DEFAULT_CHANNEL_2G): 858 """Configure packet capture for 2G and 5G bands. 859 860 Args: 861 channel_5g: Channel to set the monitor mode to for 5G band. 862 channel_2g: Channel to set the monitor mode to for 2G band. 863 """ 864 self.packet_capture = self.packet_capture[0] 865 result = self.packet_capture.configure_monitor_mode( 866 hostapd_constants.BAND_2G, channel_2g) 867 if not result: 868 raise ValueError("Failed to configure channel for 2G band") 869 870 result = self.packet_capture.configure_monitor_mode( 871 hostapd_constants.BAND_5G, channel_5g) 872 if not result: 873 raise ValueError("Failed to configure channel for 5G band.") 874 875 @staticmethod 876 def wifi_test_wrap(fn): 877 def _safe_wrap_test_case(self, *args, **kwargs): 878 test_id = "%s:%s:%s" % (self.__class__.__name__, self.test_name, 879 self.log_begin_time.replace(' ', '-')) 880 self.test_id = test_id 881 self.result_detail = "" 882 tries = int(self.user_params.get("wifi_auto_rerun", 3)) 883 for ad in self.android_devices: 884 ad.log_path = self.log_path 885 for i in range(tries + 1): 886 result = True 887 if i > 0: 888 log_string = "[Test Case] RETRY:%s %s" % (i, 889 self.test_name) 890 self.log.info(log_string) 891 self._teardown_test(self.test_name) 892 self._setup_test(self.test_name) 893 try: 894 result = fn(self, *args, **kwargs) 895 except signals.TestFailure as e: 896 self.log.warn("Error msg: %s" % e) 897 if self.result_detail: 898 signal.details = self.result_detail 899 result = False 900 except signals.TestSignal: 901 if self.result_detail: 902 signal.details = self.result_detail 903 raise 904 except Exception as e: 905 self.log.exception(e) 906 asserts.fail(self.result_detail) 907 if result is False: 908 if i < tries: 909 continue 910 else: 911 break 912 if result is not False: 913 asserts.explicit_pass(self.result_detail) 914 else: 915 asserts.fail(self.result_detail) 916 917 return _safe_wrap_test_case 918