1#!/usr/bin/env python3 2# 3# Copyright 2019 - The Android Open Source Project 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 17import itertools 18 19from acts import asserts 20from acts import utils 21from acts.controllers.access_point import setup_ap 22from acts.controllers.ap_lib import hostapd_constants 23from acts.controllers.ap_lib import hostapd_config 24from acts.controllers.ap_lib.hostapd_security import Security 25from acts.controllers.ap_lib.hostapd_utils import generate_random_password 26from acts_contrib.test_utils.abstract_devices.wlan_device import create_wlan_device 27from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest 28 29FREQUENCY_24 = ['2.4GHz'] 30FREQUENCY_5 = ['5GHz'] 31CHANNEL_BANDWIDTH_20 = ['HT20'] 32CHANNEL_BANDWIDTH_40_LOWER = ['HT40-'] 33CHANNEL_BANDWIDTH_40_UPPER = ['HT40+'] 34SECURITY_OPEN = 'open' 35SECURITY_WPA2 = 'wpa2' 36N_MODE = [hostapd_constants.MODE_11N_PURE, hostapd_constants.MODE_11N_MIXED] 37LDPC = [hostapd_constants.N_CAPABILITY_LDPC, ''] 38TX_STBC = [hostapd_constants.N_CAPABILITY_TX_STBC, ''] 39RX_STBC = [hostapd_constants.N_CAPABILITY_RX_STBC1, ''] 40SGI_20 = [hostapd_constants.N_CAPABILITY_SGI20, ''] 41SGI_40 = [hostapd_constants.N_CAPABILITY_SGI40, ''] 42DSSS_CCK = [hostapd_constants.N_CAPABILITY_DSSS_CCK_40, ''] 43INTOLERANT_40 = [hostapd_constants.N_CAPABILITY_40_INTOLERANT, ''] 44MAX_AMPDU_7935 = [hostapd_constants.N_CAPABILITY_MAX_AMSDU_7935, ''] 45SMPS = [hostapd_constants.N_CAPABILITY_SMPS_STATIC, ''] 46 47 48def generate_test_name(settings): 49 """Generates a string based on the n_capabilities for a test case 50 51 Args: 52 settings: A dictionary of hostapd constant n_capabilities. 53 54 Returns: 55 A string that represents a test case name. 56 """ 57 ret = [] 58 for cap in hostapd_constants.N_CAPABILITIES_MAPPING.keys(): 59 if cap in settings['n_capabilities']: 60 ret.append(hostapd_constants.N_CAPABILITIES_MAPPING[cap]) 61 # '+' is used by Mobile Harness as special character, don't use it in test names 62 if settings['chbw'] == 'HT40-': 63 chbw = "HT40Lower" 64 elif settings['chbw'] == 'HT40+': 65 chbw = "HT40Upper" 66 else: 67 chbw = settings['chbw'] 68 return 'test_11n_%s_%s_%s_%s_%s' % (settings['frequency'], chbw, 69 settings['security'], 70 settings['n_mode'], ''.join(ret)) 71 72 73class WlanPhyCompliance11NTest(WifiBaseTest): 74 """Tests for validating 11n PHYS. 75 76 Test Bed Requirement: 77 * One Android device or Fuchsia device 78 * One Access Point 79 """ 80 81 def __init__(self, controllers): 82 super().__init__(controllers) 83 84 def setup_generated_tests(self): 85 test_args = self._generate_24_HT20_test_args() + \ 86 self._generate_24_HT40_lower_test_args() + \ 87 self._generate_24_HT40_upper_test_args() + \ 88 self._generate_5_HT20_test_args() + \ 89 self._generate_5_HT40_lower_test_args() + \ 90 self._generate_5_HT40_upper_test_args() + \ 91 self._generate_24_HT20_wpa2_test_args() + \ 92 self._generate_24_HT40_lower_wpa2_test_args() + \ 93 self._generate_24_HT40_upper_wpa2_test_args() + \ 94 self._generate_5_HT20_wpa2_test_args() + \ 95 self._generate_5_HT40_lower_wpa2_test_args() + \ 96 self._generate_5_HT40_upper_wpa2_test_args() 97 98 self.generate_tests(test_logic=self.setup_and_connect, 99 name_func=generate_test_name, 100 arg_sets=test_args) 101 102 def setup_class(self): 103 super().setup_class() 104 if 'dut' in self.user_params: 105 if self.user_params['dut'] == 'fuchsia_devices': 106 self.dut = create_wlan_device(self.fuchsia_devices[0]) 107 elif self.user_params['dut'] == 'android_devices': 108 self.dut = create_wlan_device(self.android_devices[0]) 109 else: 110 raise ValueError('Invalid DUT specified in config. (%s)' % 111 self.user_params['dut']) 112 else: 113 # Default is an android device, just like the other tests 114 self.dut = create_wlan_device(self.android_devices[0]) 115 116 self.access_point = self.access_points[0] 117 self.access_point.stop_all_aps() 118 119 def setup_test(self): 120 if hasattr(self, "android_devices"): 121 for ad in self.android_devices: 122 ad.droid.wakeLockAcquireBright() 123 ad.droid.wakeUpNow() 124 self.dut.wifi_toggle_state(True) 125 126 def teardown_test(self): 127 if hasattr(self, "android_devices"): 128 for ad in self.android_devices: 129 ad.droid.wakeLockRelease() 130 ad.droid.goToSleepNow() 131 self.dut.turn_location_off_and_scan_toggle_off() 132 self.dut.disconnect() 133 self.dut.reset_wifi() 134 self.download_ap_logs() 135 self.access_point.stop_all_aps() 136 137 def on_fail(self, test_name, begin_time): 138 super().on_fail(test_name, begin_time) 139 self.access_point.stop_all_aps() 140 141 def setup_and_connect(self, ap_settings): 142 """Generates a hostapd config, setups up the AP with that config, then 143 attempts to associate a DUT 144 145 Args: 146 ap_settings: A dictionary of hostapd constant n_capabilities. 147 """ 148 ssid = utils.rand_ascii_str(20) 149 security_profile = None 150 password = None 151 temp_n_capabilities = list(ap_settings['n_capabilities']) 152 n_capabilities = [] 153 for n_capability in temp_n_capabilities: 154 if n_capability in hostapd_constants.N_CAPABILITIES_MAPPING.keys(): 155 n_capabilities.append(n_capability) 156 157 if ap_settings['chbw'] == 'HT20' or ap_settings['chbw'] == 'HT40+': 158 if ap_settings['frequency'] == '2.4GHz': 159 channel = 1 160 elif ap_settings['frequency'] == '5GHz': 161 channel = 36 162 else: 163 raise ValueError('Invalid frequence: %s' % 164 ap_settings['frequency']) 165 166 elif ap_settings['chbw'] == 'HT40-': 167 if ap_settings['frequency'] == '2.4GHz': 168 channel = 11 169 elif ap_settings['frequency'] == '5GHz': 170 channel = 60 171 else: 172 raise ValueError('Invalid frequency: %s' % 173 ap_settings['frequency']) 174 175 else: 176 raise ValueError('Invalid channel bandwidth: %s' % 177 ap_settings['chbw']) 178 179 if ap_settings['chbw'] == 'HT40-' or ap_settings['chbw'] == 'HT40+': 180 if hostapd_config.ht40_plus_allowed(channel): 181 extended_channel = hostapd_constants.N_CAPABILITY_HT40_PLUS 182 elif hostapd_config.ht40_minus_allowed(channel): 183 extended_channel = hostapd_constants.N_CAPABILITY_HT40_MINUS 184 else: 185 raise ValueError('Invalid channel: %s' % channel) 186 n_capabilities.append(extended_channel) 187 188 if ap_settings['security'] == 'wpa2': 189 security_profile = Security( 190 security_mode=SECURITY_WPA2, 191 password=generate_random_password(length=20), 192 wpa_cipher='CCMP', 193 wpa2_cipher='CCMP') 194 password = security_profile.password 195 target_security = hostapd_constants.SECURITY_STRING_TO_DEFAULT_TARGET_SECURITY.get( 196 ap_settings['security'], None) 197 198 mode = ap_settings['n_mode'] 199 if mode not in N_MODE: 200 raise ValueError('Invalid n-mode: %s' % ap_settings['n-mode']) 201 202 setup_ap(access_point=self.access_point, 203 profile_name='whirlwind', 204 mode=mode, 205 channel=channel, 206 n_capabilities=n_capabilities, 207 ac_capabilities=[], 208 force_wmm=True, 209 ssid=ssid, 210 security=security_profile, 211 password=password) 212 asserts.assert_true( 213 self.dut.associate(ssid, 214 target_pwd=password, 215 target_security=target_security), 216 'Failed to connect.') 217 218 def _generate_24_HT20_test_args(self): 219 test_args = [] 220 for combination in itertools.product(FREQUENCY_24, 221 CHANNEL_BANDWIDTH_20, N_MODE, 222 LDPC, TX_STBC, RX_STBC, SGI_20, 223 INTOLERANT_40, MAX_AMPDU_7935, 224 SMPS): 225 test_frequency = combination[0] 226 test_chbw = combination[1] 227 n_mode = combination[2] 228 n_capabilities = combination[3:] 229 test_args.append(({ 230 'frequency': test_frequency, 231 'chbw': test_chbw, 232 'n_mode': n_mode, 233 'security': SECURITY_OPEN, 234 'n_capabilities': n_capabilities, 235 }, )) 236 return test_args 237 238 def _generate_24_HT40_lower_test_args(self): 239 test_args = [] 240 for combination in itertools.product(FREQUENCY_24, 241 CHANNEL_BANDWIDTH_40_LOWER, LDPC, 242 TX_STBC, RX_STBC, SGI_20, SGI_40, 243 MAX_AMPDU_7935, SMPS, DSSS_CCK): 244 test_frequency = combination[0] 245 test_chbw = combination[1] 246 n_capabilities = combination[2:] 247 test_args.append(({ 248 'frequency': test_frequency, 249 'chbw': test_chbw, 250 'n_mode': hostapd_constants.MODE_11N_MIXED, 251 'security': SECURITY_OPEN, 252 'n_capabilities': n_capabilities 253 }, )) 254 return test_args 255 256 def _generate_24_HT40_upper_test_args(self): 257 test_args = [] 258 for combination in itertools.product(FREQUENCY_24, 259 CHANNEL_BANDWIDTH_40_UPPER, LDPC, 260 TX_STBC, RX_STBC, SGI_20, SGI_40, 261 MAX_AMPDU_7935, SMPS, DSSS_CCK): 262 test_frequency = combination[0] 263 test_chbw = combination[1] 264 n_capabilities = combination[2:] 265 test_args.append(({ 266 'frequency': test_frequency, 267 'chbw': test_chbw, 268 'n_mode': hostapd_constants.MODE_11N_MIXED, 269 'security': SECURITY_OPEN, 270 'n_capabilities': n_capabilities 271 }, )) 272 return test_args 273 274 def _generate_5_HT20_test_args(self): 275 test_args = [] 276 for combination in itertools.product(FREQUENCY_5, CHANNEL_BANDWIDTH_20, 277 LDPC, TX_STBC, RX_STBC, SGI_20, 278 INTOLERANT_40, MAX_AMPDU_7935, 279 SMPS): 280 test_frequency = combination[0] 281 test_chbw = combination[1] 282 n_capabilities = combination[2:] 283 test_args.append(({ 284 'frequency': test_frequency, 285 'chbw': test_chbw, 286 'n_mode': hostapd_constants.MODE_11N_MIXED, 287 'security': SECURITY_OPEN, 288 'n_capabilities': n_capabilities 289 }, )) 290 return test_args 291 292 def _generate_5_HT40_lower_test_args(self): 293 test_args = [] 294 for combination in itertools.product(FREQUENCY_5, 295 CHANNEL_BANDWIDTH_40_LOWER, LDPC, 296 TX_STBC, RX_STBC, SGI_20, SGI_40, 297 MAX_AMPDU_7935, SMPS, DSSS_CCK): 298 test_frequency = combination[0] 299 test_chbw = combination[1] 300 n_capabilities = combination[2:] 301 test_args.append(({ 302 'frequency': test_frequency, 303 'chbw': test_chbw, 304 'n_mode': hostapd_constants.MODE_11N_MIXED, 305 'security': SECURITY_OPEN, 306 'n_capabilities': n_capabilities 307 }, )) 308 return test_args 309 310 def _generate_5_HT40_upper_test_args(self): 311 test_args = [] 312 for combination in itertools.product(FREQUENCY_5, 313 CHANNEL_BANDWIDTH_40_UPPER, 314 N_MODE, LDPC, TX_STBC, RX_STBC, 315 SGI_20, SGI_40, MAX_AMPDU_7935, 316 SMPS, DSSS_CCK): 317 test_frequency = combination[0] 318 test_chbw = combination[1] 319 n_mode = combination[2] 320 n_capabilities = combination[3:] 321 test_args.append(({ 322 'frequency': test_frequency, 323 'chbw': test_chbw, 324 'n_mode': n_mode, 325 'security': SECURITY_OPEN, 326 'n_capabilities': n_capabilities 327 }, )) 328 return test_args 329 330 def _generate_24_HT20_wpa2_test_args(self): 331 test_args = [] 332 for combination in itertools.product(FREQUENCY_24, 333 CHANNEL_BANDWIDTH_20, LDPC, 334 TX_STBC, RX_STBC, SGI_20, 335 INTOLERANT_40, MAX_AMPDU_7935, 336 SMPS): 337 test_frequency = combination[0] 338 test_chbw = combination[1] 339 n_capabilities = combination[2:] 340 test_args.append(({ 341 'frequency': test_frequency, 342 'chbw': test_chbw, 343 'n_mode': hostapd_constants.MODE_11N_MIXED, 344 'security': SECURITY_WPA2, 345 'n_capabilities': n_capabilities 346 }, )) 347 return test_args 348 349 def _generate_24_HT40_lower_wpa2_test_args(self): 350 test_args = [] 351 for combination in itertools.product(FREQUENCY_24, 352 CHANNEL_BANDWIDTH_40_LOWER, LDPC, 353 TX_STBC, RX_STBC, SGI_20, SGI_40, 354 MAX_AMPDU_7935, SMPS, DSSS_CCK): 355 test_frequency = combination[0] 356 test_chbw = combination[1] 357 n_capabilities = combination[2:] 358 test_args.append(({ 359 'frequency': test_frequency, 360 'chbw': test_chbw, 361 'n_mode': hostapd_constants.MODE_11N_MIXED, 362 'security': SECURITY_WPA2, 363 'n_capabilities': n_capabilities 364 }, )) 365 return test_args 366 367 def _generate_24_HT40_upper_wpa2_test_args(self): 368 test_args = [] 369 for combination in itertools.product(FREQUENCY_24, 370 CHANNEL_BANDWIDTH_40_UPPER, LDPC, 371 TX_STBC, RX_STBC, SGI_20, SGI_40, 372 MAX_AMPDU_7935, SMPS, DSSS_CCK): 373 test_frequency = combination[0] 374 test_chbw = combination[1] 375 n_capabilities = combination[2:] 376 test_args.append(({ 377 'frequency': test_frequency, 378 'chbw': test_chbw, 379 'n_mode': hostapd_constants.MODE_11N_MIXED, 380 'security': SECURITY_WPA2, 381 'n_capabilities': n_capabilities 382 }, )) 383 return test_args 384 385 def _generate_5_HT20_wpa2_test_args(self): 386 test_args = [] 387 for combination in itertools.product(FREQUENCY_5, CHANNEL_BANDWIDTH_20, 388 LDPC, TX_STBC, RX_STBC, SGI_20, 389 INTOLERANT_40, MAX_AMPDU_7935, 390 SMPS): 391 test_frequency = combination[0] 392 test_chbw = combination[1] 393 n_capabilities = combination[2:] 394 test_args.append(({ 395 'frequency': test_frequency, 396 'chbw': test_chbw, 397 'n_mode': hostapd_constants.MODE_11N_MIXED, 398 'security': SECURITY_WPA2, 399 'n_capabilities': n_capabilities 400 }, )) 401 return test_args 402 403 def _generate_5_HT40_lower_wpa2_test_args(self): 404 test_args = [] 405 for combination in itertools.product(FREQUENCY_5, 406 CHANNEL_BANDWIDTH_40_LOWER, LDPC, 407 TX_STBC, RX_STBC, SGI_20, SGI_40, 408 MAX_AMPDU_7935, SMPS, DSSS_CCK): 409 test_frequency = combination[0] 410 test_chbw = combination[1] 411 n_capabilities = combination[2:] 412 test_args.append(({ 413 'frequency': test_frequency, 414 'chbw': test_chbw, 415 'n_mode': hostapd_constants.MODE_11N_MIXED, 416 'security': SECURITY_WPA2, 417 'n_capabilities': n_capabilities 418 }, )) 419 return test_args 420 421 def _generate_5_HT40_upper_wpa2_test_args(self): 422 test_args = [] 423 for combination in itertools.product(FREQUENCY_5, 424 CHANNEL_BANDWIDTH_40_UPPER, LDPC, 425 TX_STBC, RX_STBC, SGI_20, SGI_40, 426 MAX_AMPDU_7935, SMPS, DSSS_CCK): 427 test_frequency = combination[0] 428 test_chbw = combination[1] 429 n_capabilities = combination[2:] 430 test_args.append(({ 431 'frequency': test_frequency, 432 'chbw': test_chbw, 433 'n_mode': hostapd_constants.MODE_11N_MIXED, 434 'security': SECURITY_WPA2, 435 'n_capabilities': n_capabilities 436 }, )) 437 return test_args 438