blob: 010e26dfa83f12fa4424ec967c277a3e5542b526 [file] [log] [blame]
Mark De Ruyter1a7ae572018-03-02 15:35:36 -08001#!/usr/bin/env python3
Joe Brennan8c24a812017-04-13 14:27:05 -07002#
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.
Bindu Mahadev2ebdcec2018-05-03 19:51:24 +000016"""
17 Base Class for Defining Common WiFi Test Functionality
18"""
Joe Brennan8c24a812017-04-13 14:27:05 -070019
Bindu Mahadev1f227e02017-07-06 00:24:58 +000020import copy
21import itertools
Bindu Mahadev2ebdcec2018-05-03 19:51:24 +000022import time
23
24import acts.controllers.access_point as ap
Bindu Mahadevedf17162017-07-07 03:46:55 +000025
Joe Brennan8c24a812017-04-13 14:27:05 -070026from acts import asserts
27from acts import utils
28from acts.base_test import BaseTestClass
Bindu Mahadev2ebdcec2018-05-03 19:51:24 +000029from acts.signals import TestSignal
30from acts.controllers import android_device
Joe Brennan8c24a812017-04-13 14:27:05 -070031from acts.controllers.ap_lib import hostapd_ap_preset
32from acts.controllers.ap_lib import hostapd_bss_settings
33from acts.controllers.ap_lib import hostapd_constants
34from acts.controllers.ap_lib import hostapd_security
35
Bindu Mahadeve7d47c32018-07-03 16:48:03 -070036AP_1 = 0
37AP_2 = 1
38MAX_AP_COUNT = 2
Joe Brennan8c24a812017-04-13 14:27:05 -070039
40class WifiBaseTest(BaseTestClass):
41 def __init__(self, controllers):
42 BaseTestClass.__init__(self, controllers)
Bindu Mahadevd3eaf5d2018-05-08 15:32:26 -070043 if hasattr(self, 'attenuators') and self.attenuators:
Bindu Mahadev3bb29fa2017-08-10 16:08:20 +000044 for attenuator in self.attenuators:
45 attenuator.set_atten(0)
Joe Brennan8c24a812017-04-13 14:27:05 -070046
Bindu Mahadev72725d12017-06-05 03:11:30 +000047 def get_wpa2_network(
48 self,
Bindu Mahadeve7d47c32018-07-03 16:48:03 -070049 mirror_ap,
50 reference_networks,
Bindu Mahadev1c895c22018-01-18 18:20:43 -080051 hidden=False,
Bindu Mahadeve7d47c32018-07-03 16:48:03 -070052 same_ssid=False,
Bindu Mahadev72725d12017-06-05 03:11:30 +000053 ssid_length_2g=hostapd_constants.AP_SSID_LENGTH_2G,
54 ssid_length_5g=hostapd_constants.AP_SSID_LENGTH_5G,
55 passphrase_length_2g=hostapd_constants.AP_PASSPHRASE_LENGTH_2G,
56 passphrase_length_5g=hostapd_constants.AP_PASSPHRASE_LENGTH_5G):
Bindu Mahadev72725d12017-06-05 03:11:30 +000057 """Generates SSID and passphrase for a WPA2 network using random
58 generator.
59
60 Args:
Bindu Mahadeve7d47c32018-07-03 16:48:03 -070061 mirror_ap: Boolean, determines if both APs use the same hostapd
62 config or different configs.
63 reference_networks: List of PSK networks.
64 same_ssid: Boolean, determines if both bands on AP use the same
65 SSID.
66 ssid_length_2gecond AP Int, number of characters to use for 2G SSID.
Bindu Mahadev72725d12017-06-05 03:11:30 +000067 ssid_length_5g: Int, number of characters to use for 5G SSID.
68 passphrase_length_2g: Int, length of password for 2G network.
69 passphrase_length_5g: Int, length of password for 5G network.
Bindu Mahadeve7d47c32018-07-03 16:48:03 -070070
Bindu Mahadev72725d12017-06-05 03:11:30 +000071 Returns: A dict of 2G and 5G network lists for hostapd configuration.
72
73 """
74 network_dict_2g = {}
75 network_dict_5g = {}
76 ref_5g_security = hostapd_constants.WPA2_STRING
77 ref_2g_security = hostapd_constants.WPA2_STRING
Bindu Mahadev72725d12017-06-05 03:11:30 +000078
Bindu Mahadeve7d47c32018-07-03 16:48:03 -070079 if same_ssid:
80 ref_2g_ssid = 'xg_%s' % utils.rand_ascii_str(ssid_length_2g)
81 ref_5g_ssid = ref_2g_ssid
Bindu Mahadev72725d12017-06-05 03:11:30 +000082
Bindu Mahadeve7d47c32018-07-03 16:48:03 -070083 ref_2g_passphrase = utils.rand_ascii_str(passphrase_length_2g)
84 ref_5g_passphrase = ref_2g_passphrase
85
86 else:
87 ref_2g_ssid = '2g_%s' % utils.rand_ascii_str(ssid_length_2g)
88 ref_2g_passphrase = utils.rand_ascii_str(passphrase_length_2g)
89
90 ref_5g_ssid = '5g_%s' % utils.rand_ascii_str(ssid_length_5g)
91 ref_5g_passphrase = utils.rand_ascii_str(passphrase_length_5g)
Bindu Mahadev72725d12017-06-05 03:11:30 +000092
Bindu Mahadev1c895c22018-01-18 18:20:43 -080093 if hidden:
Bindu Mahadev2ebdcec2018-05-03 19:51:24 +000094 network_dict_2g = {
95 "SSID": ref_2g_ssid,
96 "security": ref_2g_security,
97 "password": ref_2g_passphrase,
Bindu Mahadevd3eaf5d2018-05-08 15:32:26 -070098 "hiddenSSID": True
Bindu Mahadev2ebdcec2018-05-03 19:51:24 +000099 }
Bindu Mahadev72725d12017-06-05 03:11:30 +0000100
Bindu Mahadev2ebdcec2018-05-03 19:51:24 +0000101 network_dict_5g = {
102 "SSID": ref_5g_ssid,
103 "security": ref_5g_security,
104 "password": ref_5g_passphrase,
Bindu Mahadevd3eaf5d2018-05-08 15:32:26 -0700105 "hiddenSSID": True
Bindu Mahadev2ebdcec2018-05-03 19:51:24 +0000106 }
Bindu Mahadev1c895c22018-01-18 18:20:43 -0800107 else:
108 network_dict_2g = {
109 "SSID": ref_2g_ssid,
110 "security": ref_2g_security,
111 "password": ref_2g_passphrase
112 }
113
114 network_dict_5g = {
115 "SSID": ref_5g_ssid,
116 "security": ref_5g_security,
117 "password": ref_5g_passphrase
118 }
119
Bindu Mahadevd07198d2017-09-15 14:06:54 -0700120 ap = 0
Bindu Mahadeve7d47c32018-07-03 16:48:03 -0700121 for ap in range(MAX_AP_COUNT):
122 reference_networks.append({
123 "2g": copy.copy(network_dict_2g),
124 "5g": copy.copy(network_dict_5g)
Bindu Mahadev72725d12017-06-05 03:11:30 +0000125 })
Bindu Mahadeve7d47c32018-07-03 16:48:03 -0700126 if not mirror_ap:
127 break
Bindu Mahadev72725d12017-06-05 03:11:30 +0000128 return {"2g": network_dict_2g, "5g": network_dict_5g}
129
markdr56939012017-07-26 12:48:43 -0700130 def get_open_network(self,
Bindu Mahadeve7d47c32018-07-03 16:48:03 -0700131 mirror_ap,
132 open_network,
Bindu Mahadev1c895c22018-01-18 18:20:43 -0800133 hidden=False,
Bindu Mahadeve7d47c32018-07-03 16:48:03 -0700134 same_ssid=False,
markdr56939012017-07-26 12:48:43 -0700135 ssid_length_2g=hostapd_constants.AP_SSID_LENGTH_2G,
136 ssid_length_5g=hostapd_constants.AP_SSID_LENGTH_5G):
Bindu Mahadev72725d12017-06-05 03:11:30 +0000137 """Generates SSIDs for a open network using a random generator.
138
139 Args:
Bindu Mahadeve7d47c32018-07-03 16:48:03 -0700140 mirror_ap: Boolean, determines if both APs use the same hostapd
141 config or different configs.
142 open_network: List of open networks.
143 same_ssid: Boolean, determines if both bands on AP use the same
144 SSID.
Bindu Mahadev72725d12017-06-05 03:11:30 +0000145 ssid_length_2g: Int, number of characters to use for 2G SSID.
146 ssid_length_5g: Int, number of characters to use for 5G SSID.
Bindu Mahadeve7d47c32018-07-03 16:48:03 -0700147
Bindu Mahadev72725d12017-06-05 03:11:30 +0000148 Returns: A dict of 2G and 5G network lists for hostapd configuration.
149
150 """
151 network_dict_2g = {}
152 network_dict_5g = {}
Bindu Mahadeve7d47c32018-07-03 16:48:03 -0700153
154 if same_ssid:
155 open_2g_ssid = 'xg_%s' % utils.rand_ascii_str(ssid_length_2g)
156 open_5g_ssid = open_2g_ssid
157
158 else:
159 open_2g_ssid = '2g_%s' % utils.rand_ascii_str(ssid_length_2g)
160 open_5g_ssid = '5g_%s' % utils.rand_ascii_str(ssid_length_5g)
161
Bindu Mahadev1c895c22018-01-18 18:20:43 -0800162 if hidden:
163 network_dict_2g = {
Bindu Mahadev2ebdcec2018-05-03 19:51:24 +0000164 "SSID": open_2g_ssid,
165 "security": 'none',
Bindu Mahadevd3eaf5d2018-05-08 15:32:26 -0700166 "hiddenSSID": True
Bindu Mahadev1c895c22018-01-18 18:20:43 -0800167 }
168
169 network_dict_5g = {
Bindu Mahadev2ebdcec2018-05-03 19:51:24 +0000170 "SSID": open_5g_ssid,
171 "security": 'none',
Bindu Mahadevd3eaf5d2018-05-08 15:32:26 -0700172 "hiddenSSID": True
Bindu Mahadev1c895c22018-01-18 18:20:43 -0800173 }
174 else:
175 network_dict_2g = {
176 "SSID": open_2g_ssid,
177 "security": 'none'
178 }
179
180 network_dict_5g = {
181 "SSID": open_5g_ssid,
182 "security": 'none'
183 }
184
Bindu Mahadevd07198d2017-09-15 14:06:54 -0700185 ap = 0
Bindu Mahadeve7d47c32018-07-03 16:48:03 -0700186 for ap in range(MAX_AP_COUNT):
187 open_network.append({
188 "2g": copy.copy(network_dict_2g),
189 "5g": copy.copy(network_dict_5g)
Bindu Mahadev72725d12017-06-05 03:11:30 +0000190 })
Bindu Mahadeve7d47c32018-07-03 16:48:03 -0700191 if not mirror_ap:
192 break
Bindu Mahadev72725d12017-06-05 03:11:30 +0000193 return {"2g": network_dict_2g, "5g": network_dict_5g}
194
Bindu Mahadeve7d47c32018-07-03 16:48:03 -0700195 def update_bssid(self, ap_instance, ap, network, band):
196 """Get bssid and update network dictionary.
197
198 Args:
199 ap_instance: Accesspoint index that was configured.
200 ap: Accesspoint object corresponding to ap_instance.
201 network: Network dictionary.
202 band: Wifi networks' band.
203
204 """
205 bssid = ap.get_bssid_from_ssid(network["SSID"], band)
206
207 if network["security"] == hostapd_constants.WPA2_STRING:
208 # TODO:(bamahadev) Change all occurances of reference_networks
209 # to wpa_networks.
210 self.reference_networks[ap_instance][band]["bssid"] = bssid
211
212 if network["security"] == 'none':
213 self.open_network[ap_instance][band]["bssid"] = bssid
214
Bindu Mahadev2ebdcec2018-05-03 19:51:24 +0000215 def populate_bssid(self, ap_instance, ap, networks_5g, networks_2g):
Bindu Mahadev1f227e02017-07-06 00:24:58 +0000216 """Get bssid for a given SSID and add it to the network dictionary.
217
218 Args:
Bindu Mahadevd07198d2017-09-15 14:06:54 -0700219 ap_instance: Accesspoint index that was configured.
220 ap: Accesspoint object corresponding to ap_instance.
Mark De Ruyterdee24c22018-04-13 17:34:44 -0700221 networks_5g: List of 5g networks configured on the APs.
Bindu Mahadev2ebdcec2018-05-03 19:51:24 +0000222 networks_2g: List of 2g networks configured on the APs.
Bindu Mahadev1f227e02017-07-06 00:24:58 +0000223
224 """
225
Bindu Mahadev2ebdcec2018-05-03 19:51:24 +0000226 if not (networks_5g or networks_2g):
Bindu Mahadev1f227e02017-07-06 00:24:58 +0000227 return
228
Bindu Mahadeve7d47c32018-07-03 16:48:03 -0700229 for network in networks_5g:
Bindu Mahadev1f227e02017-07-06 00:24:58 +0000230 if 'channel' in network:
231 continue
Bindu Mahadeve7d47c32018-07-03 16:48:03 -0700232 self.update_bssid(ap_instance, ap, network,
233 hostapd_constants.BAND_5G)
234
235 for network in networks_2g:
236 if 'channel' in network:
237 continue
238 self.update_bssid(ap_instance, ap, network,
239 hostapd_constants.BAND_2G)
Bindu Mahadev1f227e02017-07-06 00:24:58 +0000240
Joe Brennan8c24a812017-04-13 14:27:05 -0700241 def legacy_configure_ap_and_start(
242 self,
Mark De Ruyterdee24c22018-04-13 17:34:44 -0700243 channel_5g=hostapd_constants.AP_DEFAULT_CHANNEL_5G,
Bindu Mahadev2ebdcec2018-05-03 19:51:24 +0000244 channel_2g=hostapd_constants.AP_DEFAULT_CHANNEL_2G,
245 max_2g_networks=hostapd_constants.AP_DEFAULT_MAX_SSIDS_2G,
246 max_5g_networks=hostapd_constants.AP_DEFAULT_MAX_SSIDS_5G,
247 ap_ssid_length_2g=hostapd_constants.AP_SSID_LENGTH_2G,
248 ap_passphrase_length_2g=hostapd_constants.AP_PASSPHRASE_LENGTH_2G,
249 ap_ssid_length_5g=hostapd_constants.AP_SSID_LENGTH_5G,
250 ap_passphrase_length_5g=hostapd_constants.AP_PASSPHRASE_LENGTH_5G,
251 hidden=False,
Bindu Mahadeve7d47c32018-07-03 16:48:03 -0700252 same_ssid=False,
253 mirror_ap=True,
Bindu Mahadev72725d12017-06-05 03:11:30 +0000254 ap_count=1):
Joe Brennan8c24a812017-04-13 14:27:05 -0700255 asserts.assert_true(
256 len(self.user_params["AccessPoint"]) == 2,
Bindu Mahadev2ebdcec2018-05-03 19:51:24 +0000257 "Exactly two access points must be specified. \
258 Each access point has 2 radios, one each for 2.4GHZ \
259 and 5GHz. A test can choose to use one or both APs.")
Joe Brennan8c24a812017-04-13 14:27:05 -0700260
Bindu Mahadeve7d47c32018-07-03 16:48:03 -0700261 config_count = 1
262 count = 0
263
264 if mirror_ap and ap_count == 1:
265 raise ValueError("ap_count cannot be 1 if mirror_ap is True.")
266
267 if not mirror_ap:
268 config_count = ap_count
269
270 self.user_params["reference_networks"] = []
271 self.user_params["open_network"] = []
272
273 for count in range(config_count):
274
275 network_list_2g = []
276 network_list_5g = []
277
278 orig_network_list_2g = []
279 orig_network_list_5g = []
280
281 network_list_2g.append({"channel": channel_2g})
282 network_list_5g.append({"channel": channel_5g})
283
284 networks_dict = self.get_wpa2_network(
285 mirror_ap,
286 self.user_params["reference_networks"],
287 hidden=hidden,
288 same_ssid=same_ssid)
289 self.reference_networks = self.user_params["reference_networks"]
290
Bindu Mahadev72725d12017-06-05 03:11:30 +0000291 network_list_2g.append(networks_dict["2g"])
292 network_list_5g.append(networks_dict["5g"])
Joe Brennan8c24a812017-04-13 14:27:05 -0700293
Bindu Mahadeve7d47c32018-07-03 16:48:03 -0700294 # When same_ssid is set, only configure one set of WPA networks.
295 # We cannot have more than one set because duplicate interface names
296 # are not allowed.
297 # TODO(bmahadev): Provide option to select the type of network,
298 # instead of defaulting to WPA.
299 if not same_ssid:
300 networks_dict = self.get_open_network(
301 mirror_ap,
302 self.user_params["open_network"],
303 hidden=hidden,
304 same_ssid=same_ssid)
305 self.open_network = self.user_params["open_network"]
Joe Brennan8c24a812017-04-13 14:27:05 -0700306
Bindu Mahadeve7d47c32018-07-03 16:48:03 -0700307 network_list_2g.append(networks_dict["2g"])
308 network_list_5g.append(networks_dict["5g"])
Bindu Mahadev1f227e02017-07-06 00:24:58 +0000309
Bindu Mahadeve7d47c32018-07-03 16:48:03 -0700310 orig_network_list_5g = copy.copy(network_list_5g)
311 orig_network_list_2g = copy.copy(network_list_2g)
312
313 if len(network_list_5g) > 1:
314 self.config_5g = self._generate_legacy_ap_config(network_list_5g)
315 if len(network_list_2g) > 1:
316 self.config_2g = self._generate_legacy_ap_config(network_list_2g)
317
318 self.access_points[count].start_ap(self.config_2g)
319 self.access_points[count].start_ap(self.config_5g)
320 self.populate_bssid(count, self.access_points[count], orig_network_list_5g,
Bindu Mahadev2ebdcec2018-05-03 19:51:24 +0000321 orig_network_list_2g)
Bindu Mahadev72725d12017-06-05 03:11:30 +0000322
Bindu Mahadeve7d47c32018-07-03 16:48:03 -0700323 # Repeat configuration on the second router.
324 if mirror_ap and ap_count == 2:
325 self.access_points[AP_2].start_ap(self.config_2g)
326 self.access_points[AP_2].start_ap(self.config_5g)
327 self.populate_bssid(AP_2, self.access_points[AP_2],
328 orig_network_list_5g, orig_network_list_2g)
329
Joe Brennan8c24a812017-04-13 14:27:05 -0700330 def _generate_legacy_ap_config(self, network_list):
331 bss_settings = []
332 ap_settings = network_list.pop(0)
Bindu Mahadev1f227e02017-07-06 00:24:58 +0000333 # TODO:(bmahadev) This is a bug. We should not have to pop the first
334 # network in the list and treat it as a separate case. Instead,
335 # create_ap_preset() should be able to take NULL ssid and security and
336 # build config based on the bss_Settings alone.
Joe Brennan8c24a812017-04-13 14:27:05 -0700337 hostapd_config_settings = network_list.pop(0)
338 for network in network_list:
Bindu Mahadev1c895c22018-01-18 18:20:43 -0800339 if "password" in network and "hiddenSSID" in network:
340 bss_settings.append(
341 hostapd_bss_settings.BssSettings(
342 name=network["SSID"],
343 ssid=network["SSID"],
344 hidden=True,
345 security=hostapd_security.Security(
346 security_mode=network["security"],
347 password=network["password"])))
348 elif "password" in network and not "hiddenSSID" in network:
Joe Brennan8c24a812017-04-13 14:27:05 -0700349 bss_settings.append(
350 hostapd_bss_settings.BssSettings(
Bindu Mahadev72725d12017-06-05 03:11:30 +0000351 name=network["SSID"],
352 ssid=network["SSID"],
Joe Brennan8c24a812017-04-13 14:27:05 -0700353 security=hostapd_security.Security(
354 security_mode=network["security"],
Bindu Mahadev72725d12017-06-05 03:11:30 +0000355 password=network["password"])))
Bindu Mahadev1c895c22018-01-18 18:20:43 -0800356 elif not "password" in network and "hiddenSSID" in network:
Joe Brennan8c24a812017-04-13 14:27:05 -0700357 bss_settings.append(
358 hostapd_bss_settings.BssSettings(
Bindu Mahadev1c895c22018-01-18 18:20:43 -0800359 name=network["SSID"],
360 ssid=network["SSID"],
361 hidden=True))
362 elif not "password" in network and not "hiddenSSID" in network:
363 bss_settings.append(
364 hostapd_bss_settings.BssSettings(
365 name=network["SSID"],
366 ssid=network["SSID"]))
Bindu Mahadev72725d12017-06-05 03:11:30 +0000367 if "password" in hostapd_config_settings:
Joe Brennan8c24a812017-04-13 14:27:05 -0700368 config = hostapd_ap_preset.create_ap_preset(
369 channel=ap_settings["channel"],
Bindu Mahadev72725d12017-06-05 03:11:30 +0000370 ssid=hostapd_config_settings["SSID"],
Joe Brennan8c24a812017-04-13 14:27:05 -0700371 security=hostapd_security.Security(
372 security_mode=hostapd_config_settings["security"],
Bindu Mahadev72725d12017-06-05 03:11:30 +0000373 password=hostapd_config_settings["password"]),
markdr56939012017-07-26 12:48:43 -0700374 bss_settings=bss_settings,
375 profile_name='whirlwind')
Joe Brennan8c24a812017-04-13 14:27:05 -0700376 else:
377 config = hostapd_ap_preset.create_ap_preset(
378 channel=ap_settings["channel"],
Bindu Mahadev72725d12017-06-05 03:11:30 +0000379 ssid=hostapd_config_settings["SSID"],
Joe Brennan8c24a812017-04-13 14:27:05 -0700380 bss_settings=bss_settings,
381 profile_name='whirlwind')
Joe Brennan8c24a812017-04-13 14:27:05 -0700382 return config