]>
Commit | Line | Data |
---|---|---|
7cd0aa7e JM |
1 | # Test cases for VHT operations with hostapd |
2 | # Copyright (c) 2014, Qualcomm Atheros, Inc. | |
ea7526bf | 3 | # Copyright (c) 2013, Intel Corporation |
7cd0aa7e JM |
4 | # |
5 | # This software may be distributed under the terms of the BSD license. | |
6 | # See README for more details. | |
7 | ||
8 | import logging | |
9 | logger = logging.getLogger() | |
6259fd81 | 10 | import os |
ea7526bf | 11 | import subprocess, time |
7cd0aa7e JM |
12 | |
13 | import hwsim_utils | |
14 | import hostapd | |
810dcfb6 | 15 | from wpasupplicant import WpaSupplicant |
2e71d041 | 16 | from utils import * |
6259fd81 | 17 | from test_dfs import wait_dfs_event |
d4792c0c | 18 | from test_ap_csa import csa_supported |
29fb191c | 19 | from test_ap_ht import clear_scan_cache |
7cd0aa7e JM |
20 | |
21 | def vht_supported(): | |
22 | cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE) | |
23 | reg = cmd.stdout.read() | |
24 | if "@ 80)" in reg or "@ 160)" in reg: | |
25 | return True | |
26 | return False | |
27 | ||
28 | def test_ap_vht80(dev, apdev): | |
29 | """VHT with 80 MHz channel width""" | |
30 | try: | |
9d7fdac5 | 31 | hapd = None |
fab49f61 JM |
32 | params = {"ssid": "vht", |
33 | "country_code": "FI", | |
34 | "hw_mode": "a", | |
35 | "channel": "36", | |
36 | "ht_capab": "[HT40+]", | |
37 | "ieee80211n": "1", | |
38 | "ieee80211ac": "1", | |
39 | "vht_oper_chwidth": "1", | |
40 | "vht_oper_centr_freq_seg0_idx": "42"} | |
8b8a1864 | 41 | hapd = hostapd.add_ap(apdev[0], params) |
528a7d22 | 42 | bssid = apdev[0]['bssid'] |
7cd0aa7e JM |
43 | |
44 | dev[0].connect("vht", key_mgmt="NONE", scan_freq="5180") | |
a8375c94 | 45 | hwsim_utils.test_connectivity(dev[0], hapd) |
7e40a881 JM |
46 | sig = dev[0].request("SIGNAL_POLL").splitlines() |
47 | if "FREQUENCY=5180" not in sig: | |
48 | raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig)) | |
49 | if "WIDTH=80 MHz" not in sig: | |
50 | raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig)) | |
528a7d22 JM |
51 | est = dev[0].get_bss(bssid)['est_throughput'] |
52 | if est != "390001": | |
53 | raise Exception("Unexpected BSS est_throughput: " + est) | |
f98fdc4e JM |
54 | status = dev[0].get_status() |
55 | if status["ieee80211ac"] != "1": | |
56 | raise Exception("Unexpected STATUS ieee80211ac value (STA)") | |
96485214 JM |
57 | status = hapd.get_status() |
58 | logger.info("hostapd STATUS: " + str(status)) | |
59 | if status["ieee80211n"] != "1": | |
60 | raise Exception("Unexpected STATUS ieee80211n value") | |
61 | if status["ieee80211ac"] != "1": | |
62 | raise Exception("Unexpected STATUS ieee80211ac value") | |
63 | if status["secondary_channel"] != "1": | |
64 | raise Exception("Unexpected STATUS secondary_channel value") | |
65 | if status["vht_oper_chwidth"] != "1": | |
66 | raise Exception("Unexpected STATUS vht_oper_chwidth value") | |
67 | if status["vht_oper_centr_freq_seg0_idx"] != "42": | |
68 | raise Exception("Unexpected STATUS vht_oper_centr_freq_seg0_idx value") | |
3bee996c JM |
69 | if "vht_caps_info" not in status: |
70 | raise Exception("Missing vht_caps_info") | |
71 | ||
72 | sta = hapd.get_sta(dev[0].own_addr()) | |
73 | logger.info("hostapd STA: " + str(sta)) | |
74 | if "[HT]" not in sta['flags']: | |
75 | raise Exception("Missing STA flag: HT") | |
76 | if "[VHT]" not in sta['flags']: | |
77 | raise Exception("Missing STA flag: VHT") | |
55093c80 JM |
78 | if 'supp_op_classes' not in sta or len(sta['supp_op_classes']) < 2: |
79 | raise Exception("No Supported Operating Classes information for STA") | |
80 | opclass = int(sta['supp_op_classes'][0:2], 16) | |
81 | if opclass != 128: | |
82 | raise Exception("Unexpected Current Operating Class from STA: %d" % opclass) | |
bab493b9 | 83 | except Exception as e: |
7cd0aa7e JM |
84 | if isinstance(e, Exception) and str(e) == "AP startup failed": |
85 | if not vht_supported(): | |
81e787b7 | 86 | raise HwsimSkip("80 MHz channel not supported in regulatory information") |
7cd0aa7e JM |
87 | raise |
88 | finally: | |
9d7fdac5 | 89 | dev[0].request("DISCONNECT") |
2d6889e0 | 90 | clear_regdom(hapd, dev) |
7cd0aa7e | 91 | |
810dcfb6 JM |
92 | def test_ap_vht_wifi_generation(dev, apdev): |
93 | """VHT and wifi_generation""" | |
94 | try: | |
95 | hapd = None | |
fab49f61 JM |
96 | params = {"ssid": "vht", |
97 | "country_code": "FI", | |
98 | "hw_mode": "a", | |
99 | "channel": "36", | |
100 | "ht_capab": "[HT40+]", | |
101 | "ieee80211n": "1", | |
102 | "ieee80211ac": "1", | |
103 | "vht_oper_chwidth": "1", | |
104 | "vht_oper_centr_freq_seg0_idx": "42"} | |
810dcfb6 JM |
105 | hapd = hostapd.add_ap(apdev[0], params) |
106 | bssid = apdev[0]['bssid'] | |
107 | ||
108 | dev[0].connect("vht", key_mgmt="NONE", scan_freq="5180") | |
109 | status = dev[0].get_status() | |
110 | if 'wifi_generation' not in status: | |
111 | # For now, assume this is because of missing kernel support | |
112 | raise HwsimSkip("Association Request IE reporting not supported") | |
113 | #raise Exception("Missing wifi_generation information") | |
114 | if status['wifi_generation'] != "5": | |
115 | raise Exception("Unexpected wifi_generation value: " + status['wifi_generation']) | |
116 | ||
117 | wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') | |
118 | wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") | |
119 | wpas.connect("vht", key_mgmt="NONE", scan_freq="5180") | |
120 | status = wpas.get_status() | |
121 | if 'wifi_generation' not in status: | |
122 | # For now, assume this is because of missing kernel support | |
123 | raise HwsimSkip("Association Request IE reporting not supported") | |
124 | #raise Exception("Missing wifi_generation information (connect)") | |
125 | if status['wifi_generation'] != "5": | |
126 | raise Exception("Unexpected wifi_generation value (connect): " + status['wifi_generation']) | |
127 | except Exception as e: | |
128 | if isinstance(e, Exception) and str(e) == "AP startup failed": | |
129 | if not vht_supported(): | |
130 | raise HwsimSkip("80 MHz channel not supported in regulatory information") | |
131 | raise | |
132 | finally: | |
133 | dev[0].request("DISCONNECT") | |
85873c66 | 134 | clear_regdom(hapd, dev) |
810dcfb6 | 135 | |
5161ea8e | 136 | def vht80_test(apdev, dev, channel, ht_capab): |
cb3c0d96 | 137 | clear_scan_cache(apdev) |
5161ea8e JM |
138 | try: |
139 | hapd = None | |
fab49f61 JM |
140 | params = {"ssid": "vht", |
141 | "country_code": "FI", | |
142 | "hw_mode": "a", | |
143 | "channel": str(channel), | |
144 | "ht_capab": ht_capab, | |
145 | "ieee80211n": "1", | |
146 | "ieee80211ac": "1", | |
147 | "vht_oper_chwidth": "1", | |
148 | "vht_oper_centr_freq_seg0_idx": "42"} | |
afc26df2 | 149 | hapd = hostapd.add_ap(apdev, params) |
5161ea8e JM |
150 | bssid = apdev['bssid'] |
151 | ||
3074cb1f MH |
152 | dev[0].connect("vht", key_mgmt="NONE", |
153 | scan_freq=str(5000 + 5 * channel)) | |
154 | hwsim_utils.test_connectivity(dev[0], hapd) | |
bab493b9 | 155 | except Exception as e: |
5161ea8e JM |
156 | if isinstance(e, Exception) and str(e) == "AP startup failed": |
157 | if not vht_supported(): | |
158 | raise HwsimSkip("80 MHz channel not supported in regulatory information") | |
159 | raise | |
160 | finally: | |
3074cb1f | 161 | clear_regdom(hapd, dev) |
5161ea8e JM |
162 | |
163 | def test_ap_vht80b(dev, apdev): | |
164 | """VHT with 80 MHz channel width (HT40- channel 40)""" | |
3074cb1f | 165 | vht80_test(apdev[0], dev, 40, "[HT40-]") |
5161ea8e JM |
166 | |
167 | def test_ap_vht80c(dev, apdev): | |
168 | """VHT with 80 MHz channel width (HT40+ channel 44)""" | |
3074cb1f | 169 | vht80_test(apdev[0], dev, 44, "[HT40+]") |
5161ea8e JM |
170 | |
171 | def test_ap_vht80d(dev, apdev): | |
172 | """VHT with 80 MHz channel width (HT40- channel 48)""" | |
3074cb1f | 173 | vht80_test(apdev[0], dev, 48, "[HT40-]") |
5161ea8e | 174 | |
7cd0aa7e JM |
175 | def test_ap_vht80_params(dev, apdev): |
176 | """VHT with 80 MHz channel width and number of optional features enabled""" | |
177 | try: | |
9d7fdac5 | 178 | hapd = None |
fab49f61 JM |
179 | params = {"ssid": "vht", |
180 | "country_code": "FI", | |
181 | "hw_mode": "a", | |
182 | "channel": "36", | |
183 | "ht_capab": "[HT40+][SHORT-GI-40][DSS_CCK-40]", | |
184 | "ieee80211n": "1", | |
185 | "ieee80211ac": "1", | |
186 | "vht_oper_chwidth": "1", | |
187 | "vht_capab": "[MAX-MPDU-11454][RXLDPC][SHORT-GI-80][TX-STBC-2BY1][RX-STBC-1][MAX-A-MPDU-LEN-EXP0]", | |
188 | "vht_oper_centr_freq_seg0_idx": "42", | |
189 | "require_vht": "1"} | |
8b8a1864 | 190 | hapd = hostapd.add_ap(apdev[0], params) |
7cd0aa7e | 191 | |
145f35bf JM |
192 | dev[1].connect("vht", key_mgmt="NONE", scan_freq="5180", |
193 | disable_vht="1", wait_connect=False) | |
7cd0aa7e | 194 | dev[0].connect("vht", key_mgmt="NONE", scan_freq="5180") |
2e71d041 JM |
195 | dev[2].connect("vht", key_mgmt="NONE", scan_freq="5180", |
196 | disable_sgi="1") | |
145f35bf JM |
197 | ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"]) |
198 | if ev is None: | |
199 | raise Exception("Association rejection timed out") | |
200 | if "status_code=104" not in ev: | |
201 | raise Exception("Unexpected rejection status code") | |
202 | dev[1].request("DISCONNECT") | |
a8375c94 | 203 | hwsim_utils.test_connectivity(dev[0], hapd) |
2e71d041 JM |
204 | sta0 = hapd.get_sta(dev[0].own_addr()) |
205 | sta2 = hapd.get_sta(dev[2].own_addr()) | |
206 | capab0 = int(sta0['vht_caps_info'], base=16) | |
207 | capab2 = int(sta2['vht_caps_info'], base=16) | |
208 | if capab0 & 0x60 == 0: | |
209 | raise Exception("dev[0] did not support SGI") | |
210 | if capab2 & 0x60 != 0: | |
211 | raise Exception("dev[2] claimed support for SGI") | |
bab493b9 | 212 | except Exception as e: |
7cd0aa7e JM |
213 | if isinstance(e, Exception) and str(e) == "AP startup failed": |
214 | if not vht_supported(): | |
e246d7d5 | 215 | raise HwsimSkip("80 MHz channel not supported in regulatory information") |
7cd0aa7e JM |
216 | raise |
217 | finally: | |
2e71d041 | 218 | clear_regdom(hapd, dev, count=3) |
ea7526bf | 219 | |
6849b3de JM |
220 | def test_ap_vht80_invalid(dev, apdev): |
221 | """VHT with invalid 80 MHz channel configuration (seg1)""" | |
222 | try: | |
223 | hapd = None | |
fab49f61 JM |
224 | params = {"ssid": "vht", |
225 | "country_code": "US", | |
226 | "hw_mode": "a", | |
227 | "channel": "36", | |
228 | "ht_capab": "[HT40+]", | |
229 | "ieee80211n": "1", | |
230 | "ieee80211ac": "1", | |
231 | "vht_oper_chwidth": "1", | |
232 | "vht_oper_centr_freq_seg0_idx": "42", | |
233 | "vht_oper_centr_freq_seg1_idx": "155", | |
234 | 'ieee80211d': '1', | |
235 | 'ieee80211h': '1'} | |
8b8a1864 | 236 | hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) |
6849b3de JM |
237 | # This fails due to unexpected seg1 configuration |
238 | ev = hapd.wait_event(["AP-DISABLED"], timeout=5) | |
239 | if ev is None: | |
240 | raise Exception("AP-DISABLED not reported") | |
bab493b9 | 241 | except Exception as e: |
6849b3de JM |
242 | if isinstance(e, Exception) and str(e) == "AP startup failed": |
243 | if not vht_supported(): | |
244 | raise HwsimSkip("80/160 MHz channel not supported in regulatory information") | |
245 | raise | |
246 | finally: | |
fa4a938f | 247 | clear_regdom(hapd, dev) |
6849b3de JM |
248 | |
249 | def test_ap_vht80_invalid2(dev, apdev): | |
250 | """VHT with invalid 80 MHz channel configuration (seg0)""" | |
251 | try: | |
252 | hapd = None | |
fab49f61 JM |
253 | params = {"ssid": "vht", |
254 | "country_code": "US", | |
255 | "hw_mode": "a", | |
256 | "channel": "36", | |
257 | "ht_capab": "[HT40+]", | |
258 | "ieee80211n": "1", | |
259 | "ieee80211ac": "1", | |
260 | "vht_oper_chwidth": "1", | |
261 | "vht_oper_centr_freq_seg0_idx": "46", | |
262 | 'ieee80211d': '1', | |
263 | 'ieee80211h': '1'} | |
8b8a1864 | 264 | hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) |
6849b3de JM |
265 | # This fails due to invalid seg0 configuration |
266 | ev = hapd.wait_event(["AP-DISABLED"], timeout=5) | |
267 | if ev is None: | |
268 | raise Exception("AP-DISABLED not reported") | |
bab493b9 | 269 | except Exception as e: |
6849b3de JM |
270 | if isinstance(e, Exception) and str(e) == "AP startup failed": |
271 | if not vht_supported(): | |
272 | raise HwsimSkip("80/160 MHz channel not supported in regulatory information") | |
273 | raise | |
274 | finally: | |
9ab2360f | 275 | clear_regdom(hapd, dev) |
6849b3de | 276 | |
ea7526bf | 277 | def test_ap_vht_20(devs, apdevs): |
14637401 | 278 | """VHT and 20 MHz channel""" |
ea7526bf JB |
279 | dev = devs[0] |
280 | ap = apdevs[0] | |
281 | try: | |
9d7fdac5 | 282 | hapd = None |
fab49f61 JM |
283 | params = {"ssid": "test-vht20", |
284 | "country_code": "DE", | |
285 | "hw_mode": "a", | |
286 | "channel": "36", | |
287 | "ieee80211n": "1", | |
288 | "ieee80211ac": "1", | |
289 | "ht_capab": "", | |
290 | "vht_capab": "", | |
291 | "vht_oper_chwidth": "0", | |
292 | "vht_oper_centr_freq_seg0_idx": "0", | |
293 | "supported_rates": "60 120 240 360 480 540", | |
294 | "require_vht": "1"} | |
afc26df2 | 295 | hapd = hostapd.add_ap(ap, params) |
ea7526bf | 296 | dev.connect("test-vht20", scan_freq="5180", key_mgmt="NONE") |
a8375c94 | 297 | hwsim_utils.test_connectivity(dev, hapd) |
55093c80 JM |
298 | |
299 | sta = hapd.get_sta(dev.own_addr()) | |
300 | if 'supp_op_classes' not in sta or len(sta['supp_op_classes']) < 2: | |
301 | raise Exception("No Supported Operating Classes information for STA") | |
302 | opclass = int(sta['supp_op_classes'][0:2], 16) | |
303 | if opclass != 115: | |
304 | raise Exception("Unexpected Current Operating Class from STA: %d" % opclass) | |
ea7526bf | 305 | finally: |
9d7fdac5 | 306 | dev.request("DISCONNECT") |
28a57450 | 307 | clear_regdom(hapd, devs) |
4466fe65 JM |
308 | |
309 | def test_ap_vht_40(devs, apdevs): | |
310 | """VHT and 40 MHz channel""" | |
311 | dev = devs[0] | |
312 | ap = apdevs[0] | |
313 | try: | |
314 | hapd = None | |
fab49f61 JM |
315 | params = {"ssid": "test-vht40", |
316 | "country_code": "DE", | |
317 | "hw_mode": "a", | |
318 | "channel": "36", | |
319 | "ieee80211n": "1", | |
320 | "ieee80211ac": "1", | |
321 | "ht_capab": "[HT40+]", | |
322 | "vht_capab": "", | |
323 | "vht_oper_chwidth": "0", | |
324 | "vht_oper_centr_freq_seg0_idx": "0"} | |
afc26df2 | 325 | hapd = hostapd.add_ap(ap, params) |
4466fe65 JM |
326 | dev.connect("test-vht40", scan_freq="5180", key_mgmt="NONE") |
327 | hwsim_utils.test_connectivity(dev, hapd) | |
55093c80 JM |
328 | |
329 | sta = hapd.get_sta(dev.own_addr()) | |
330 | if 'supp_op_classes' not in sta or len(sta['supp_op_classes']) < 2: | |
331 | raise Exception("No Supported Operating Classes information for STA") | |
332 | opclass = int(sta['supp_op_classes'][0:2], 16) | |
333 | if opclass != 116: | |
334 | raise Exception("Unexpected Current Operating Class from STA: %d" % opclass) | |
4466fe65 JM |
335 | finally: |
336 | dev.request("DISCONNECT") | |
c29855d3 | 337 | clear_regdom(hapd, devs) |
6acecce1 JM |
338 | |
339 | def test_ap_vht_capab_not_supported(dev, apdev): | |
340 | """VHT configuration with driver not supporting all vht_capab entries""" | |
341 | try: | |
fab49f61 JM |
342 | params = {"ssid": "vht", |
343 | "country_code": "FI", | |
344 | "hw_mode": "a", | |
345 | "channel": "36", | |
346 | "ht_capab": "[HT40+][SHORT-GI-40][DSS_CCK-40]", | |
347 | "ieee80211n": "1", | |
348 | "ieee80211ac": "1", | |
349 | "vht_oper_chwidth": "1", | |
350 | "vht_capab": "[MAX-MPDU-7991][MAX-MPDU-11454][VHT160][VHT160-80PLUS80][RXLDPC][SHORT-GI-80][SHORT-GI-160][TX-STBC-2BY1][RX-STBC-1][RX-STBC-12][RX-STBC-123][RX-STBC-1234][SU-BEAMFORMER][SU-BEAMFORMEE][BF-ANTENNA-2][BF-ANTENNA-3][BF-ANTENNA-4][SOUNDING-DIMENSION-2][SOUNDING-DIMENSION-3][SOUNDING-DIMENSION-4][MU-BEAMFORMER][VHT-TXOP-PS][HTC-VHT][MAX-A-MPDU-LEN-EXP0][MAX-A-MPDU-LEN-EXP7][VHT-LINK-ADAPT2][VHT-LINK-ADAPT3][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN]", | |
351 | "vht_oper_centr_freq_seg0_idx": "42", | |
352 | "require_vht": "1"} | |
8b8a1864 | 353 | hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) |
6acecce1 JM |
354 | ev = hapd.wait_event(["AP-DISABLED"], timeout=5) |
355 | if ev is None: | |
356 | raise Exception("Startup failure not reported") | |
357 | for i in range(1, 7): | |
358 | if "OK" not in hapd.request("SET vht_capab [MAX-A-MPDU-LEN-EXP%d]" % i): | |
359 | raise Exception("Unexpected SET failure") | |
360 | finally: | |
f3df0054 | 361 | clear_regdom(hapd, dev) |
6259fd81 JM |
362 | |
363 | def test_ap_vht160(dev, apdev): | |
b9e8f920 | 364 | """VHT with 160 MHz channel width (1)""" |
6259fd81 | 365 | try: |
9d7fdac5 | 366 | hapd = None |
fab49f61 JM |
367 | params = {"ssid": "vht", |
368 | "country_code": "FI", | |
369 | "hw_mode": "a", | |
370 | "channel": "36", | |
371 | "ht_capab": "[HT40+]", | |
372 | "ieee80211n": "1", | |
373 | "ieee80211ac": "1", | |
374 | "vht_oper_chwidth": "2", | |
375 | "vht_oper_centr_freq_seg0_idx": "50", | |
376 | 'ieee80211d': '1', | |
377 | 'ieee80211h': '1'} | |
8b8a1864 | 378 | hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) |
6259fd81 JM |
379 | |
380 | ev = wait_dfs_event(hapd, "DFS-CAC-START", 5) | |
381 | if "DFS-CAC-START" not in ev: | |
382 | raise Exception("Unexpected DFS event") | |
383 | ||
384 | state = hapd.get_status_field("state") | |
385 | if state != "DFS": | |
386 | if state == "DISABLED" and not os.path.exists("dfs"): | |
387 | # Not all systems have recent enough CRDA version and | |
388 | # wireless-regdb changes to support 160 MHz and DFS. For now, | |
389 | # do not report failures for this test case. | |
81e787b7 | 390 | raise HwsimSkip("CRDA or wireless-regdb did not support 160 MHz") |
6259fd81 JM |
391 | raise Exception("Unexpected interface state: " + state) |
392 | ||
b9e8f920 JM |
393 | logger.info("Waiting for CAC to complete") |
394 | ||
395 | ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70) | |
396 | if "success=1" not in ev: | |
397 | raise Exception("CAC failed") | |
398 | if "freq=5180" not in ev: | |
399 | raise Exception("Unexpected DFS freq result") | |
400 | ||
401 | ev = hapd.wait_event(["AP-ENABLED"], timeout=5) | |
402 | if not ev: | |
403 | raise Exception("AP setup timed out") | |
404 | ||
405 | state = hapd.get_status_field("state") | |
406 | if state != "ENABLED": | |
407 | raise Exception("Unexpected interface state") | |
408 | ||
409 | dev[0].connect("vht", key_mgmt="NONE", scan_freq="5180") | |
b586054f | 410 | dev[0].wait_regdom(country_ie=True) |
b9e8f920 JM |
411 | hwsim_utils.test_connectivity(dev[0], hapd) |
412 | sig = dev[0].request("SIGNAL_POLL").splitlines() | |
413 | if "FREQUENCY=5180" not in sig: | |
414 | raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig)) | |
415 | if "WIDTH=160 MHz" not in sig: | |
416 | raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig)) | |
55093c80 JM |
417 | |
418 | sta = hapd.get_sta(dev[0].own_addr()) | |
419 | if 'supp_op_classes' not in sta or len(sta['supp_op_classes']) < 2: | |
420 | raise Exception("No Supported Operating Classes information for STA") | |
421 | opclass = int(sta['supp_op_classes'][0:2], 16) | |
422 | if opclass != 129: | |
423 | raise Exception("Unexpected Current Operating Class from STA: %d" % opclass) | |
bab493b9 | 424 | except Exception as e: |
b9e8f920 JM |
425 | if isinstance(e, Exception) and str(e) == "AP startup failed": |
426 | if not vht_supported(): | |
427 | raise HwsimSkip("80/160 MHz channel not supported in regulatory information") | |
428 | raise | |
429 | finally: | |
b9e8f920 JM |
430 | if hapd: |
431 | hapd.request("DISABLE") | |
e01a492c | 432 | dev[0].disconnect_and_stop_scan() |
b9e8f920 | 433 | subprocess.call(['iw', 'reg', 'set', '00']) |
b586054f | 434 | dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=0.5) |
b9e8f920 JM |
435 | dev[0].flush_scan_cache() |
436 | ||
437 | def test_ap_vht160b(dev, apdev): | |
438 | """VHT with 160 MHz channel width (2)""" | |
439 | try: | |
440 | hapd = None | |
441 | ||
fab49f61 JM |
442 | params = {"ssid": "vht", |
443 | "country_code": "FI", | |
444 | "hw_mode": "a", | |
445 | "channel": "104", | |
446 | "ht_capab": "[HT40-]", | |
447 | "ieee80211n": "1", | |
448 | "ieee80211ac": "1", | |
449 | "vht_oper_chwidth": "2", | |
450 | "vht_oper_centr_freq_seg0_idx": "114", | |
451 | 'ieee80211d': '1', | |
452 | 'ieee80211h': '1'} | |
b9e8f920 | 453 | hapd = hostapd.add_ap(apdev[1], params, wait_enabled=False) |
6259fd81 | 454 | |
b9e8f920 | 455 | ev = wait_dfs_event(hapd, "DFS-CAC-START", 5) |
6259fd81 JM |
456 | if "DFS-CAC-START" not in ev: |
457 | raise Exception("Unexpected DFS event(2)") | |
458 | ||
b9e8f920 | 459 | state = hapd.get_status_field("state") |
6259fd81 | 460 | if state != "DFS": |
b9e8f920 JM |
461 | if state == "DISABLED" and not os.path.exists("dfs"): |
462 | # Not all systems have recent enough CRDA version and | |
463 | # wireless-regdb changes to support 160 MHz and DFS. For now, | |
464 | # do not report failures for this test case. | |
465 | raise HwsimSkip("CRDA or wireless-regdb did not support 160 MHz") | |
466 | raise Exception("Unexpected interface state: " + state) | |
6259fd81 JM |
467 | |
468 | logger.info("Waiting for CAC to complete") | |
469 | ||
470 | ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70) | |
6259fd81 JM |
471 | if "success=1" not in ev: |
472 | raise Exception("CAC failed(2)") | |
24f4ad04 | 473 | if "freq=5520" not in ev: |
6259fd81 JM |
474 | raise Exception("Unexpected DFS freq result(2)") |
475 | ||
b9e8f920 | 476 | ev = hapd.wait_event(["AP-ENABLED"], timeout=5) |
6259fd81 JM |
477 | if not ev: |
478 | raise Exception("AP setup timed out(2)") | |
479 | ||
b9e8f920 | 480 | state = hapd.get_status_field("state") |
6259fd81 JM |
481 | if state != "ENABLED": |
482 | raise Exception("Unexpected interface state(2)") | |
483 | ||
b9e8f920 | 484 | freq = hapd.get_status_field("freq") |
24f4ad04 | 485 | if freq != "5520": |
6259fd81 JM |
486 | raise Exception("Unexpected frequency(2)") |
487 | ||
b9e8f920 | 488 | dev[0].connect("vht", key_mgmt="NONE", scan_freq="5520") |
b586054f | 489 | dev[0].wait_regdom(country_ie=True) |
a8375c94 | 490 | hwsim_utils.test_connectivity(dev[0], hapd) |
c2bf6d3a | 491 | sig = dev[0].request("SIGNAL_POLL").splitlines() |
24f4ad04 | 492 | if "FREQUENCY=5520" not in sig: |
c2bf6d3a JM |
493 | raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig)) |
494 | if "WIDTH=160 MHz" not in sig: | |
495 | raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig)) | |
bab493b9 | 496 | except Exception as e: |
6259fd81 JM |
497 | if isinstance(e, Exception) and str(e) == "AP startup failed": |
498 | if not vht_supported(): | |
81e787b7 | 499 | raise HwsimSkip("80/160 MHz channel not supported in regulatory information") |
6259fd81 JM |
500 | raise |
501 | finally: | |
9d7fdac5 JM |
502 | if hapd: |
503 | hapd.request("DISABLE") | |
e01a492c | 504 | dev[0].disconnect_and_stop_scan() |
c4668009 | 505 | subprocess.call(['iw', 'reg', 'set', '00']) |
b586054f | 506 | dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=0.5) |
9d7fdac5 | 507 | dev[0].flush_scan_cache() |
74ed673f | 508 | |
90bef2c9 JM |
509 | def test_ap_vht160_no_dfs_100_plus(dev, apdev): |
510 | """VHT with 160 MHz channel width and no DFS (100 plus)""" | |
511 | run_ap_vht160_no_dfs(dev, apdev, "100", "[HT40+]") | |
512 | ||
a6cc1e57 | 513 | def test_ap_vht160_no_dfs(dev, apdev): |
90bef2c9 JM |
514 | """VHT with 160 MHz channel width and no DFS (104 minus)""" |
515 | run_ap_vht160_no_dfs(dev, apdev, "104", "[HT40-]") | |
516 | ||
517 | def test_ap_vht160_no_dfs_108_plus(dev, apdev): | |
518 | """VHT with 160 MHz channel width and no DFS (108 plus)""" | |
519 | run_ap_vht160_no_dfs(dev, apdev, "108", "[HT40+]") | |
520 | ||
521 | def test_ap_vht160_no_dfs_112_minus(dev, apdev): | |
522 | """VHT with 160 MHz channel width and no DFS (112 minus)""" | |
523 | run_ap_vht160_no_dfs(dev, apdev, "112", "[HT40-]") | |
524 | ||
525 | def test_ap_vht160_no_dfs_116_plus(dev, apdev): | |
526 | """VHT with 160 MHz channel width and no DFS (116 plus)""" | |
527 | run_ap_vht160_no_dfs(dev, apdev, "116", "[HT40+]") | |
528 | ||
529 | def test_ap_vht160_no_dfs_120_minus(dev, apdev): | |
530 | """VHT with 160 MHz channel width and no DFS (120 minus)""" | |
531 | run_ap_vht160_no_dfs(dev, apdev, "120", "[HT40-]") | |
532 | ||
533 | def test_ap_vht160_no_dfs_124_plus(dev, apdev): | |
534 | """VHT with 160 MHz channel width and no DFS (124 plus)""" | |
535 | run_ap_vht160_no_dfs(dev, apdev, "124", "[HT40+]") | |
536 | ||
537 | def test_ap_vht160_no_dfs_128_minus(dev, apdev): | |
538 | """VHT with 160 MHz channel width and no DFS (128 minus)""" | |
539 | run_ap_vht160_no_dfs(dev, apdev, "128", "[HT40-]") | |
540 | ||
541 | def run_ap_vht160_no_dfs(dev, apdev, channel, ht_capab): | |
a6cc1e57 JM |
542 | try: |
543 | hapd = None | |
fab49f61 JM |
544 | params = {"ssid": "vht", |
545 | "country_code": "ZA", | |
546 | "hw_mode": "a", | |
547 | "channel": channel, | |
548 | "ht_capab": ht_capab, | |
549 | "ieee80211n": "1", | |
550 | "ieee80211ac": "1", | |
551 | "vht_oper_chwidth": "2", | |
552 | "vht_oper_centr_freq_seg0_idx": "114", | |
553 | 'ieee80211d': '1', | |
554 | 'ieee80211h': '1'} | |
8b8a1864 | 555 | hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) |
a6cc1e57 JM |
556 | ev = hapd.wait_event(["AP-ENABLED"], timeout=2) |
557 | if not ev: | |
558 | cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE) | |
559 | reg = cmd.stdout.readlines() | |
560 | for r in reg: | |
561 | if "5490" in r and "DFS" in r: | |
562 | raise HwsimSkip("ZA regulatory rule did not have DFS requirement removed") | |
563 | raise Exception("AP setup timed out") | |
564 | ||
90bef2c9 JM |
565 | freq = str(int(channel) * 5 + 5000) |
566 | dev[0].connect("vht", key_mgmt="NONE", scan_freq=freq) | |
b586054f | 567 | dev[0].wait_regdom(country_ie=True) |
a6cc1e57 JM |
568 | hwsim_utils.test_connectivity(dev[0], hapd) |
569 | sig = dev[0].request("SIGNAL_POLL").splitlines() | |
90bef2c9 | 570 | if "FREQUENCY=" + freq not in sig: |
a6cc1e57 JM |
571 | raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig)) |
572 | if "WIDTH=160 MHz" not in sig: | |
573 | raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig)) | |
bab493b9 | 574 | except Exception as e: |
a6cc1e57 JM |
575 | if isinstance(e, Exception) and str(e) == "AP startup failed": |
576 | if not vht_supported(): | |
577 | raise HwsimSkip("80/160 MHz channel not supported in regulatory information") | |
578 | raise | |
579 | finally: | |
9cff5c32 | 580 | clear_regdom(hapd, dev) |
a6cc1e57 | 581 | |
b6437fa5 JM |
582 | def test_ap_vht160_no_ht40(dev, apdev): |
583 | """VHT with 160 MHz channel width and HT40 disabled""" | |
584 | try: | |
585 | hapd = None | |
fab49f61 JM |
586 | params = {"ssid": "vht", |
587 | "country_code": "ZA", | |
588 | "hw_mode": "a", | |
589 | "channel": "108", | |
590 | "ht_capab": "", | |
591 | "ieee80211n": "1", | |
592 | "ieee80211ac": "1", | |
593 | "vht_oper_chwidth": "2", | |
594 | "vht_oper_centr_freq_seg0_idx": "114", | |
595 | 'ieee80211d': '1', | |
596 | 'ieee80211h': '1'} | |
b6437fa5 JM |
597 | hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) |
598 | ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=2) | |
599 | if not ev: | |
600 | cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE) | |
601 | reg = cmd.stdout.readlines() | |
602 | for r in reg: | |
603 | if "5490" in r and "DFS" in r: | |
604 | raise HwsimSkip("ZA regulatory rule did not have DFS requirement removed") | |
605 | raise Exception("AP setup timed out") | |
606 | if "AP-ENABLED" in ev: | |
607 | # This was supposed to fail due to sec_channel_offset == 0 | |
608 | raise Exception("Unexpected AP-ENABLED") | |
bab493b9 | 609 | except Exception as e: |
b6437fa5 JM |
610 | if isinstance(e, Exception) and str(e) == "AP startup failed": |
611 | if not vht_supported(): | |
612 | raise HwsimSkip("80/160 MHz channel not supported in regulatory information") | |
613 | raise | |
614 | finally: | |
411b9e01 | 615 | clear_regdom(hapd, dev) |
b6437fa5 | 616 | |
74ed673f JM |
617 | def test_ap_vht80plus80(dev, apdev): |
618 | """VHT with 80+80 MHz channel width""" | |
619 | try: | |
9d7fdac5 JM |
620 | hapd = None |
621 | hapd2 = None | |
fab49f61 JM |
622 | params = {"ssid": "vht", |
623 | "country_code": "US", | |
624 | "hw_mode": "a", | |
625 | "channel": "52", | |
626 | "ht_capab": "[HT40+]", | |
627 | "ieee80211n": "1", | |
628 | "ieee80211ac": "1", | |
629 | "vht_oper_chwidth": "3", | |
630 | "vht_oper_centr_freq_seg0_idx": "58", | |
631 | "vht_oper_centr_freq_seg1_idx": "155", | |
632 | 'ieee80211d': '1', | |
633 | 'ieee80211h': '1'} | |
8b8a1864 | 634 | hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) |
74ed673f JM |
635 | # This will actually fail since DFS on 80+80 is not yet supported |
636 | ev = hapd.wait_event(["AP-DISABLED"], timeout=5) | |
637 | # ignore result to avoid breaking the test once 80+80 DFS gets enabled | |
638 | ||
fab49f61 JM |
639 | params = {"ssid": "vht2", |
640 | "country_code": "US", | |
641 | "hw_mode": "a", | |
642 | "channel": "36", | |
643 | "ht_capab": "[HT40+]", | |
644 | "ieee80211n": "1", | |
645 | "ieee80211ac": "1", | |
646 | "vht_oper_chwidth": "3", | |
647 | "vht_oper_centr_freq_seg0_idx": "42", | |
648 | "vht_oper_centr_freq_seg1_idx": "155"} | |
8b8a1864 | 649 | hapd2 = hostapd.add_ap(apdev[1], params, wait_enabled=False) |
74ed673f | 650 | |
e246d7d5 | 651 | ev = hapd2.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=5) |
74ed673f JM |
652 | if not ev: |
653 | raise Exception("AP setup timed out(2)") | |
e246d7d5 JM |
654 | if "AP-DISABLED" in ev: |
655 | # Assume this failed due to missing regulatory update for now | |
656 | raise HwsimSkip("80+80 MHz channel not supported in regulatory information") | |
74ed673f JM |
657 | |
658 | state = hapd2.get_status_field("state") | |
659 | if state != "ENABLED": | |
660 | raise Exception("Unexpected interface state(2)") | |
661 | ||
662 | dev[1].connect("vht2", key_mgmt="NONE", scan_freq="5180") | |
a8375c94 | 663 | hwsim_utils.test_connectivity(dev[1], hapd2) |
c2bf6d3a JM |
664 | sig = dev[1].request("SIGNAL_POLL").splitlines() |
665 | if "FREQUENCY=5180" not in sig: | |
666 | raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig)) | |
667 | if "WIDTH=80+80 MHz" not in sig: | |
668 | raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig)) | |
669 | if "CENTER_FRQ1=5210" not in sig: | |
670 | raise Exception("Unexpected SIGNAL_POLL value(3): " + str(sig)) | |
671 | if "CENTER_FRQ2=5775" not in sig: | |
672 | raise Exception("Unexpected SIGNAL_POLL value(4): " + str(sig)) | |
55093c80 JM |
673 | |
674 | sta = hapd2.get_sta(dev[1].own_addr()) | |
675 | if 'supp_op_classes' not in sta or len(sta['supp_op_classes']) < 2: | |
676 | raise Exception("No Supported Operating Classes information for STA") | |
677 | opclass = int(sta['supp_op_classes'][0:2], 16) | |
678 | if opclass != 130: | |
679 | raise Exception("Unexpected Current Operating Class from STA: %d" % opclass) | |
bab493b9 | 680 | except Exception as e: |
74ed673f JM |
681 | if isinstance(e, Exception) and str(e) == "AP startup failed": |
682 | if not vht_supported(): | |
81e787b7 | 683 | raise HwsimSkip("80/160 MHz channel not supported in regulatory information") |
74ed673f JM |
684 | raise |
685 | finally: | |
9d7fdac5 JM |
686 | dev[0].request("DISCONNECT") |
687 | dev[1].request("DISCONNECT") | |
688 | if hapd: | |
689 | hapd.request("DISABLE") | |
690 | if hapd2: | |
691 | hapd2.request("DISABLE") | |
c4668009 | 692 | subprocess.call(['iw', 'reg', 'set', '00']) |
9d7fdac5 JM |
693 | dev[0].flush_scan_cache() |
694 | dev[1].flush_scan_cache() | |
d4792c0c | 695 | |
6849b3de JM |
696 | def test_ap_vht80plus80_invalid(dev, apdev): |
697 | """VHT with invalid 80+80 MHz channel""" | |
698 | try: | |
699 | hapd = None | |
fab49f61 JM |
700 | params = {"ssid": "vht", |
701 | "country_code": "US", | |
702 | "hw_mode": "a", | |
703 | "channel": "36", | |
704 | "ht_capab": "[HT40+]", | |
705 | "ieee80211n": "1", | |
706 | "ieee80211ac": "1", | |
707 | "vht_oper_chwidth": "3", | |
708 | "vht_oper_centr_freq_seg0_idx": "42", | |
709 | "vht_oper_centr_freq_seg1_idx": "0", | |
710 | 'ieee80211d': '1', | |
711 | 'ieee80211h': '1'} | |
8b8a1864 | 712 | hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) |
6849b3de JM |
713 | # This fails due to missing(invalid) seg1 configuration |
714 | ev = hapd.wait_event(["AP-DISABLED"], timeout=5) | |
715 | if ev is None: | |
716 | raise Exception("AP-DISABLED not reported") | |
bab493b9 | 717 | except Exception as e: |
6849b3de JM |
718 | if isinstance(e, Exception) and str(e) == "AP startup failed": |
719 | if not vht_supported(): | |
720 | raise HwsimSkip("80/160 MHz channel not supported in regulatory information") | |
721 | raise | |
722 | finally: | |
c3aa6e27 | 723 | clear_regdom(hapd, dev) |
6849b3de | 724 | |
d4792c0c JM |
725 | def test_ap_vht80_csa(dev, apdev): |
726 | """VHT with 80 MHz channel width and CSA""" | |
81e787b7 | 727 | csa_supported(dev[0]) |
d4792c0c | 728 | try: |
9d7fdac5 | 729 | hapd = None |
fab49f61 JM |
730 | params = {"ssid": "vht", |
731 | "country_code": "US", | |
732 | "hw_mode": "a", | |
733 | "channel": "149", | |
734 | "ht_capab": "[HT40+]", | |
735 | "ieee80211n": "1", | |
736 | "ieee80211ac": "1", | |
737 | "vht_oper_chwidth": "1", | |
738 | "vht_oper_centr_freq_seg0_idx": "155"} | |
8b8a1864 | 739 | hapd = hostapd.add_ap(apdev[0], params) |
d4792c0c JM |
740 | |
741 | dev[0].connect("vht", key_mgmt="NONE", scan_freq="5745") | |
742 | hwsim_utils.test_connectivity(dev[0], hapd) | |
743 | ||
744 | hapd.request("CHAN_SWITCH 5 5180 ht vht blocktx center_freq1=5210 sec_channel_offset=1 bandwidth=80") | |
64c20a83 JM |
745 | ev = hapd.wait_event(["CTRL-EVENT-STARTED-CHANNEL-SWITCH"], timeout=10) |
746 | if ev is None: | |
747 | raise Exception("Channel switch start event not seen") | |
748 | if "freq=5180" not in ev: | |
749 | raise Exception("Unexpected channel in CS started") | |
750 | ev = hapd.wait_event(["CTRL-EVENT-CHANNEL-SWITCH"], timeout=10) | |
751 | if ev is None: | |
752 | raise Exception("Channel switch completion event not seen") | |
753 | if "freq=5180" not in ev: | |
754 | raise Exception("Unexpected channel in CS completed") | |
d4792c0c JM |
755 | ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10) |
756 | if ev is None: | |
757 | raise Exception("CSA finished event timed out") | |
758 | if "freq=5180" not in ev: | |
759 | raise Exception("Unexpected channel in CSA finished event") | |
760 | time.sleep(0.5) | |
761 | hwsim_utils.test_connectivity(dev[0], hapd) | |
762 | ||
763 | hapd.request("CHAN_SWITCH 5 5745") | |
764 | ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10) | |
765 | if ev is None: | |
766 | raise Exception("CSA finished event timed out") | |
767 | if "freq=5745" not in ev: | |
768 | raise Exception("Unexpected channel in CSA finished event") | |
769 | time.sleep(0.5) | |
770 | hwsim_utils.test_connectivity(dev[0], hapd) | |
771 | ||
772 | # This CSA to same channel will fail in kernel, so use this only for | |
773 | # extra code coverage. | |
774 | hapd.request("CHAN_SWITCH 5 5745") | |
775 | hapd.wait_event(["AP-CSA-FINISHED"], timeout=1) | |
bab493b9 | 776 | except Exception as e: |
d4792c0c JM |
777 | if isinstance(e, Exception) and str(e) == "AP startup failed": |
778 | if not vht_supported(): | |
81e787b7 | 779 | raise HwsimSkip("80 MHz channel not supported in regulatory information") |
d4792c0c JM |
780 | raise |
781 | finally: | |
9d7fdac5 | 782 | dev[0].request("DISCONNECT") |
fec2aea7 | 783 | clear_regdom(hapd, dev) |
496c4e45 | 784 | |
27fa1161 JM |
785 | def test_ap_vht_csa_vht40(dev, apdev): |
786 | """VHT CSA with VHT40 getting enabled""" | |
787 | csa_supported(dev[0]) | |
788 | try: | |
789 | hapd = None | |
fab49f61 JM |
790 | params = {"ssid": "vht", |
791 | "country_code": "US", | |
792 | "hw_mode": "a", | |
793 | "channel": "149", | |
794 | "ht_capab": "[HT40+]", | |
795 | "ieee80211n": "1", | |
796 | "ieee80211ac": "0"} | |
27fa1161 JM |
797 | hapd = hostapd.add_ap(apdev[0], params) |
798 | bssid = hapd.own_addr() | |
799 | ||
800 | dev[0].connect("vht", key_mgmt="NONE", scan_freq="5745") | |
801 | hwsim_utils.test_connectivity(dev[0], hapd) | |
802 | ||
7b1adf2c | 803 | hapd.request("CHAN_SWITCH 5 5765 sec_channel_offset=-1 center_freq1=5755 bandwidth=40 vht") |
27fa1161 JM |
804 | ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10) |
805 | if ev is None: | |
806 | raise Exception("CSA finished event timed out") | |
807 | if "freq=5765" not in ev: | |
808 | raise Exception("Unexpected channel in CSA finished event") | |
12c5c240 | 809 | ev = dev[0].wait_event(["CTRL-EVENT-CHANNEL-SWITCH"], timeout=5) |
27fa1161 JM |
810 | if ev is None: |
811 | raise Exception("Channel switch event not seen") | |
812 | if "freq=5765" not in ev: | |
813 | raise Exception("Channel mismatch: " + ev) | |
ad369d77 JM |
814 | ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5) |
815 | if ev is not None: | |
816 | raise Exception("Unexpected disconnection event from station") | |
27fa1161 JM |
817 | hwsim_utils.test_connectivity(dev[0], hapd) |
818 | ||
819 | dev[1].connect("vht", key_mgmt="NONE", scan_freq="5765") | |
820 | hwsim_utils.test_connectivity(dev[1], hapd) | |
821 | ||
822 | if dev[1].get_status_field("ieee80211ac") != '1': | |
823 | raise Exception("VHT not enabled as part of channel switch") | |
824 | finally: | |
825 | dev[0].request("DISCONNECT") | |
826 | dev[1].request("DISCONNECT") | |
827 | if hapd: | |
828 | hapd.request("DISABLE") | |
829 | subprocess.call(['iw', 'reg', 'set', '00']) | |
830 | dev[0].flush_scan_cache() | |
831 | dev[1].flush_scan_cache() | |
832 | ||
833 | def test_ap_vht_csa_vht20(dev, apdev): | |
834 | """VHT CSA with VHT20 getting enabled""" | |
835 | csa_supported(dev[0]) | |
836 | try: | |
837 | hapd = None | |
fab49f61 JM |
838 | params = {"ssid": "vht", |
839 | "country_code": "US", | |
840 | "hw_mode": "a", | |
841 | "channel": "149", | |
842 | "ht_capab": "[HT40+]", | |
843 | "ieee80211n": "1", | |
844 | "ieee80211ac": "0"} | |
27fa1161 JM |
845 | hapd = hostapd.add_ap(apdev[0], params) |
846 | bssid = hapd.own_addr() | |
847 | ||
848 | dev[0].connect("vht", key_mgmt="NONE", scan_freq="5745") | |
849 | hwsim_utils.test_connectivity(dev[0], hapd) | |
850 | ||
851 | hapd.request("CHAN_SWITCH 5 5200 center_freq1=5200 bandwidth=20 vht") | |
852 | ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10) | |
853 | if ev is None: | |
854 | raise Exception("CSA finished event timed out") | |
855 | if "freq=5200" not in ev: | |
856 | raise Exception("Unexpected channel in CSA finished event") | |
857 | time.sleep(0.5) | |
858 | hwsim_utils.test_connectivity(dev[0], hapd) | |
859 | ||
860 | dev[1].connect("vht", key_mgmt="NONE", scan_freq="5200") | |
861 | hwsim_utils.test_connectivity(dev[1], hapd) | |
862 | ||
863 | if dev[1].get_status_field("ieee80211ac") != '1': | |
864 | raise Exception("VHT not enabled as part of channel switch") | |
865 | finally: | |
866 | dev[0].request("DISCONNECT") | |
867 | dev[1].request("DISCONNECT") | |
868 | if hapd: | |
869 | hapd.request("DISABLE") | |
870 | subprocess.call(['iw', 'reg', 'set', '00']) | |
871 | dev[0].flush_scan_cache() | |
872 | dev[1].flush_scan_cache() | |
873 | ||
874 | def test_ap_vht_csa_vht40_disable(dev, apdev): | |
875 | """VHT CSA with VHT40 getting disabled""" | |
876 | csa_supported(dev[0]) | |
877 | try: | |
878 | hapd = None | |
fab49f61 JM |
879 | params = {"ssid": "vht", |
880 | "country_code": "US", | |
881 | "hw_mode": "a", | |
882 | "channel": "149", | |
883 | "ht_capab": "[HT40+]", | |
884 | "ieee80211n": "1", | |
885 | "ieee80211ac": "1", | |
886 | "vht_capab": "", | |
887 | "vht_oper_chwidth": "0", | |
888 | "vht_oper_centr_freq_seg0_idx": "0"} | |
27fa1161 JM |
889 | hapd = hostapd.add_ap(apdev[0], params) |
890 | bssid = hapd.own_addr() | |
891 | ||
892 | dev[0].connect("vht", key_mgmt="NONE", scan_freq="5745") | |
893 | hwsim_utils.test_connectivity(dev[0], hapd) | |
894 | ||
af6a2b72 | 895 | hapd.request("CHAN_SWITCH 5 5200 center_freq1=5210 sec_channel_offset=1 bandwidth=40 ht") |
27fa1161 JM |
896 | ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10) |
897 | if ev is None: | |
898 | raise Exception("CSA finished event timed out") | |
899 | if "freq=5200" not in ev: | |
900 | raise Exception("Unexpected channel in CSA finished event") | |
79b44113 | 901 | ev = dev[0].wait_event(["CTRL-EVENT-CHANNEL-SWITCH"], timeout=5) |
27fa1161 JM |
902 | if ev is None: |
903 | raise Exception("Channel switch event not seen") | |
904 | if "freq=5200" not in ev: | |
905 | raise Exception("Channel mismatch: " + ev) | |
906 | time.sleep(0.5) | |
907 | hwsim_utils.test_connectivity(dev[0], hapd) | |
908 | ||
909 | dev[1].connect("vht", key_mgmt="NONE", scan_freq="5200") | |
910 | hwsim_utils.test_connectivity(dev[1], hapd) | |
911 | ||
912 | if dev[1].get_status_field("ieee80211ac") == '1': | |
913 | raise Exception("VHT not disabled as part of channel switch") | |
914 | finally: | |
915 | dev[0].request("DISCONNECT") | |
916 | dev[1].request("DISCONNECT") | |
917 | if hapd: | |
918 | hapd.request("DISABLE") | |
919 | subprocess.call(['iw', 'reg', 'set', '00']) | |
920 | dev[0].flush_scan_cache() | |
921 | dev[1].flush_scan_cache() | |
922 | ||
496c4e45 JM |
923 | def test_ap_vht_on_24ghz(dev, apdev): |
924 | """Subset of VHT features on 2.4 GHz""" | |
925 | hapd = None | |
fab49f61 JM |
926 | params = {"ssid": "test-vht-2g", |
927 | "hw_mode": "g", | |
928 | "channel": "1", | |
929 | "ieee80211n": "1", | |
930 | "vendor_vht": "1", | |
931 | "vht_capab": "[MAX-MPDU-11454]", | |
932 | "vht_oper_chwidth": "0", | |
933 | "vht_oper_centr_freq_seg0_idx": "1"} | |
8b8a1864 | 934 | hapd = hostapd.add_ap(apdev[0], params) |
496c4e45 JM |
935 | try: |
936 | if "OK" not in dev[0].request("VENDOR_ELEM_ADD 13 dd1300904c0400bf0c3240820feaff0000eaff0000"): | |
937 | raise Exception("Failed to add vendor element") | |
938 | dev[0].connect("test-vht-2g", scan_freq="2412", key_mgmt="NONE") | |
ef39ac49 | 939 | hapd.wait_sta() |
496c4e45 JM |
940 | hwsim_utils.test_connectivity(dev[0], hapd) |
941 | sta = hapd.get_sta(dev[0].own_addr()) | |
942 | if '[VENDOR_VHT]' not in sta['flags']: | |
943 | raise Exception("No VENDOR_VHT STA flag") | |
944 | ||
945 | dev[1].connect("test-vht-2g", scan_freq="2412", key_mgmt="NONE") | |
ef39ac49 | 946 | hapd.wait_sta() |
496c4e45 JM |
947 | sta = hapd.get_sta(dev[1].own_addr()) |
948 | if '[VENDOR_VHT]' in sta['flags']: | |
949 | raise Exception("Unexpected VENDOR_VHT STA flag") | |
ef39ac49 JM |
950 | |
951 | status = dev[0].get_status() | |
952 | if 'wifi_generation' in status: | |
953 | if status['wifi_generation'] != "4": | |
954 | raise Exception("Unexpected wifi_generation value: " + status['wifi_generation']) | |
955 | ||
956 | status = dev[1].get_status() | |
957 | if 'wifi_generation' in status: | |
958 | if status['wifi_generation'] != "4": | |
959 | raise Exception("Unexpected wifi_generation value(2): " + status['wifi_generation']) | |
960 | finally: | |
961 | dev[0].request("VENDOR_ELEM_REMOVE 13 *") | |
962 | ||
963 | def test_ap_vht_on_24ghz_2(dev, apdev): | |
964 | """Subset of VHT features on 2.4 GHz (2)""" | |
965 | hapd = None | |
966 | params = {"ssid": "test-vht-2g", | |
967 | "hw_mode": "g", | |
968 | "channel": "1", | |
969 | "ieee80211n": "1", | |
970 | "ieee80211ac": "1", | |
971 | "vendor_vht": "1", | |
972 | "vht_capab": "[MAX-MPDU-11454]", | |
973 | "vht_oper_chwidth": "0", | |
974 | "vht_oper_centr_freq_seg0_idx": "1"} | |
975 | hapd = hostapd.add_ap(apdev[0], params) | |
976 | try: | |
977 | if "OK" not in dev[0].request("VENDOR_ELEM_ADD 13 bf0cfa048003aaaa0000aaaa0000dd1300904c0400bf0c3240820feaff0000eaff0000"): | |
978 | raise Exception("Failed to add vendor element") | |
979 | dev[0].connect("test-vht-2g", scan_freq="2412", key_mgmt="NONE") | |
980 | hapd.wait_sta() | |
981 | hwsim_utils.test_connectivity(dev[0], hapd) | |
982 | sta = hapd.get_sta(dev[0].own_addr()) | |
983 | if '[VHT]' not in sta['flags']: | |
984 | raise Exception("No VHT STA flag") | |
985 | ||
986 | dev[1].connect("test-vht-2g", scan_freq="2412", key_mgmt="NONE") | |
987 | hapd.wait_sta() | |
988 | sta = hapd.get_sta(dev[1].own_addr()) | |
989 | if '[VENDOR_VHT]' in sta['flags']: | |
990 | raise Exception("Unexpected VENDOR_VHT STA flag") | |
991 | if '[VHT]' in sta['flags']: | |
992 | raise Exception("Unexpected VHT STA flag") | |
993 | ||
994 | status = dev[0].get_status() | |
995 | if 'wifi_generation' in status: | |
996 | if status['wifi_generation'] != "4": | |
997 | raise Exception("Unexpected wifi_generation value: " + status['wifi_generation']) | |
998 | ||
999 | status = dev[1].get_status() | |
1000 | if 'wifi_generation' in status: | |
1001 | if status['wifi_generation'] != "4": | |
1002 | raise Exception("Unexpected wifi_generation value(2): " + status['wifi_generation']) | |
496c4e45 JM |
1003 | finally: |
1004 | dev[0].request("VENDOR_ELEM_REMOVE 13 *") | |
528a7d22 JM |
1005 | |
1006 | def test_prefer_vht40(dev, apdev): | |
1007 | """Preference on VHT40 over HT40""" | |
1008 | try: | |
1009 | hapd2 = None | |
1010 | ||
fab49f61 JM |
1011 | params = {"ssid": "test", |
1012 | "country_code": "FI", | |
1013 | "hw_mode": "a", | |
1014 | "channel": "36", | |
1015 | "ieee80211n": "1", | |
1016 | "ht_capab": "[HT40+]"} | |
8b8a1864 | 1017 | hapd = hostapd.add_ap(apdev[0], params) |
528a7d22 JM |
1018 | bssid = apdev[0]['bssid'] |
1019 | ||
fab49f61 JM |
1020 | params = {"ssid": "test", |
1021 | "country_code": "FI", | |
1022 | "hw_mode": "a", | |
1023 | "channel": "36", | |
1024 | "ieee80211n": "1", | |
1025 | "ieee80211ac": "1", | |
1026 | "ht_capab": "[HT40+]", | |
1027 | "vht_capab": "", | |
1028 | "vht_oper_chwidth": "0", | |
1029 | "vht_oper_centr_freq_seg0_idx": "0"} | |
8b8a1864 | 1030 | hapd2 = hostapd.add_ap(apdev[1], params) |
528a7d22 JM |
1031 | bssid2 = apdev[1]['bssid'] |
1032 | ||
1033 | dev[0].scan_for_bss(bssid, freq=5180) | |
1034 | dev[0].scan_for_bss(bssid2, freq=5180) | |
1035 | dev[0].connect("test", scan_freq="5180", key_mgmt="NONE") | |
1036 | if dev[0].get_status_field('bssid') != bssid2: | |
1037 | raise Exception("Unexpected BSS selected") | |
1038 | ||
1039 | est = dev[0].get_bss(bssid)['est_throughput'] | |
1040 | if est != "135000": | |
1041 | raise Exception("Unexpected BSS0 est_throughput: " + est) | |
1042 | ||
1043 | est = dev[0].get_bss(bssid2)['est_throughput'] | |
275509ee | 1044 | if est != "180001": |
528a7d22 JM |
1045 | raise Exception("Unexpected BSS1 est_throughput: " + est) |
1046 | finally: | |
1047 | dev[0].request("DISCONNECT") | |
77e16aac MH |
1048 | disable_hapd(hapd) |
1049 | disable_hapd(hapd2) | |
1050 | clear_regdom_dev(dev) | |
39605857 JM |
1051 | |
1052 | def test_ap_vht80_pwr_constraint(dev, apdev): | |
1053 | """VHT with 80 MHz channel width and local power constraint""" | |
1054 | hapd = None | |
1055 | try: | |
fab49f61 JM |
1056 | params = {"ssid": "vht", |
1057 | "country_code": "FI", | |
1058 | "hw_mode": "a", | |
1059 | "channel": "36", | |
1060 | "ht_capab": "[HT40+]", | |
1061 | "ieee80211d": "1", | |
1062 | "local_pwr_constraint": "3", | |
1063 | "ieee80211n": "1", | |
1064 | "ieee80211ac": "1", | |
1065 | "vht_oper_chwidth": "1", | |
1066 | "vht_oper_centr_freq_seg0_idx": "42"} | |
8b8a1864 | 1067 | hapd = hostapd.add_ap(apdev[0], params) |
39605857 JM |
1068 | |
1069 | dev[0].connect("vht", key_mgmt="NONE", scan_freq="5180") | |
b586054f | 1070 | dev[0].wait_regdom(country_ie=True) |
bab493b9 | 1071 | except Exception as e: |
39605857 JM |
1072 | if isinstance(e, Exception) and str(e) == "AP startup failed": |
1073 | if not vht_supported(): | |
1074 | raise HwsimSkip("80 MHz channel not supported in regulatory information") | |
1075 | raise | |
1076 | finally: | |
39605857 JM |
1077 | if hapd: |
1078 | hapd.request("DISABLE") | |
e01a492c | 1079 | dev[0].disconnect_and_stop_scan() |
39605857 | 1080 | subprocess.call(['iw', 'reg', 'set', '00']) |
b586054f | 1081 | dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=0.5) |
39605857 | 1082 | dev[0].flush_scan_cache() |
ff229935 JM |
1083 | |
1084 | def test_ap_vht_use_sta_nsts(dev, apdev): | |
1085 | """VHT with 80 MHz channel width and use_sta_nsts=1""" | |
1086 | try: | |
1087 | hapd = None | |
fab49f61 JM |
1088 | params = {"ssid": "vht", |
1089 | "country_code": "FI", | |
1090 | "hw_mode": "a", | |
1091 | "channel": "36", | |
1092 | "ht_capab": "[HT40+]", | |
1093 | "ieee80211n": "1", | |
1094 | "ieee80211ac": "1", | |
1095 | "vht_oper_chwidth": "1", | |
1096 | "vht_oper_centr_freq_seg0_idx": "42", | |
1097 | "use_sta_nsts": "1"} | |
ff229935 JM |
1098 | hapd = hostapd.add_ap(apdev[0], params) |
1099 | bssid = apdev[0]['bssid'] | |
1100 | ||
1101 | dev[0].connect("vht", key_mgmt="NONE", scan_freq="5180") | |
1102 | hwsim_utils.test_connectivity(dev[0], hapd) | |
bab493b9 | 1103 | except Exception as e: |
ff229935 JM |
1104 | if isinstance(e, Exception) and str(e) == "AP startup failed": |
1105 | if not vht_supported(): | |
1106 | raise HwsimSkip("80 MHz channel not supported in regulatory information") | |
1107 | raise | |
1108 | finally: | |
6749c675 | 1109 | clear_regdom(hapd, dev) |
ab62d2e5 JM |
1110 | |
1111 | def test_ap_vht_tkip(dev, apdev): | |
1112 | """VHT and TKIP""" | |
1113 | try: | |
1114 | hapd = None | |
fab49f61 JM |
1115 | params = {"ssid": "vht", |
1116 | "wpa": "1", | |
1117 | "wpa_key_mgmt": "WPA-PSK", | |
1118 | "wpa_pairwise": "TKIP", | |
1119 | "wpa_passphrase": "12345678", | |
1120 | "country_code": "FI", | |
1121 | "hw_mode": "a", | |
1122 | "channel": "36", | |
1123 | "ht_capab": "[HT40+]", | |
1124 | "ieee80211n": "1", | |
1125 | "ieee80211ac": "1", | |
1126 | "vht_oper_chwidth": "1", | |
1127 | "vht_oper_centr_freq_seg0_idx": "42"} | |
ab62d2e5 JM |
1128 | hapd = hostapd.add_ap(apdev[0], params) |
1129 | bssid = apdev[0]['bssid'] | |
1130 | ||
1131 | dev[0].connect("vht", psk="12345678", scan_freq="5180") | |
1132 | hwsim_utils.test_connectivity(dev[0], hapd) | |
1133 | sig = dev[0].request("SIGNAL_POLL").splitlines() | |
1134 | if "FREQUENCY=5180" not in sig: | |
1135 | raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig)) | |
1136 | if "WIDTH=20 MHz (no HT)" not in sig: | |
1137 | raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig)) | |
1138 | status = hapd.get_status() | |
1139 | logger.info("hostapd STATUS: " + str(status)) | |
1140 | if status["ieee80211n"] != "0": | |
1141 | raise Exception("Unexpected STATUS ieee80211n value") | |
1142 | if status["ieee80211ac"] != "0": | |
1143 | raise Exception("Unexpected STATUS ieee80211ac value") | |
1144 | if status["secondary_channel"] != "0": | |
1145 | raise Exception("Unexpected STATUS secondary_channel value") | |
bab493b9 | 1146 | except Exception as e: |
ab62d2e5 JM |
1147 | if isinstance(e, Exception) and str(e) == "AP startup failed": |
1148 | if not vht_supported(): | |
1149 | raise HwsimSkip("80 MHz channel not supported in regulatory information") | |
1150 | raise | |
1151 | finally: | |
1152 | dev[0].request("DISCONNECT") | |
4ab1ac90 | 1153 | clear_regdom(hapd, dev) |
f366ff24 JM |
1154 | |
1155 | def test_ap_vht_40_fallback_to_20(devs, apdevs): | |
1156 | """VHT and 40 MHz channel configuration falling back to 20 MHz""" | |
1157 | dev = devs[0] | |
1158 | ap = apdevs[0] | |
1159 | try: | |
1160 | hapd = None | |
fab49f61 JM |
1161 | params = {"ssid": "test-vht40", |
1162 | "country_code": "US", | |
1163 | "hw_mode": "a", | |
1164 | "basic_rates": "60 120 240", | |
1165 | "channel": "161", | |
1166 | "ieee80211d": "1", | |
1167 | "ieee80211h": "1", | |
1168 | "ieee80211n": "1", | |
1169 | "ieee80211ac": "1", | |
1170 | "ht_capab": "[HT40+][SHORT-GI-20][SHORT-GI-40][DSSS_CCK-40]", | |
1171 | "vht_capab": "[RXLDPC][SHORT-GI-80][TX-STBC-2BY1][RX-STBC1][MAX-MPDU-11454][MAX-A-MPDU-LEN-EXP7]", | |
1172 | "vht_oper_chwidth": "0", | |
1173 | "vht_oper_centr_freq_seg0_idx": "155"} | |
f366ff24 JM |
1174 | hapd = hostapd.add_ap(ap, params) |
1175 | dev.connect("test-vht40", scan_freq="5805", key_mgmt="NONE") | |
b586054f | 1176 | dev.wait_regdom(country_ie=True) |
f366ff24 JM |
1177 | hwsim_utils.test_connectivity(dev, hapd) |
1178 | finally: | |
44cc7df6 | 1179 | clear_regdom(hapd, devs) |
30a67736 JM |
1180 | |
1181 | def test_ap_vht80_to_24g_ht(dev, apdev): | |
1182 | """VHT with 80 MHz channel width reconfigured to 2.4 GHz HT""" | |
1183 | try: | |
1184 | hapd = None | |
fab49f61 JM |
1185 | params = {"ssid": "vht", |
1186 | "country_code": "FI", | |
1187 | "hw_mode": "a", | |
1188 | "channel": "36", | |
1189 | "ht_capab": "[HT40+]", | |
1190 | "ieee80211n": "1", | |
1191 | "ieee80211ac": "1", | |
1192 | "vht_oper_chwidth": "1", | |
1193 | "vht_capab": "[MAX-MPDU-11454]", | |
1194 | "vht_oper_centr_freq_seg0_idx": "42"} | |
30a67736 JM |
1195 | hapd = hostapd.add_ap(apdev[0], params) |
1196 | bssid = apdev[0]['bssid'] | |
1197 | ||
1198 | hapd.disable() | |
1199 | hapd.set("ieee80211ac", "0") | |
1200 | hapd.set("hw_mode", "g") | |
1201 | hapd.set("channel", "1") | |
1202 | hapd.set("ht_capab", "") | |
1203 | hapd.set("vht_capab", "") | |
1204 | hapd.enable() | |
1205 | ||
1206 | dev[0].connect("vht", key_mgmt="NONE", scan_freq="2412") | |
bab493b9 | 1207 | except Exception as e: |
30a67736 JM |
1208 | if isinstance(e, Exception) and str(e) == "AP startup failed": |
1209 | if not vht_supported(): | |
1210 | raise HwsimSkip("80 MHz channel not supported in regulatory information") | |
1211 | raise | |
1212 | finally: | |
1213 | dev[0].request("DISCONNECT") | |
b57d883c | 1214 | clear_regdom(hapd, dev) |