tests: Pass full apdev to add_ap() function (1)
[mech_eap.git] / tests / hwsim / test_ap_vht.py
1 # Test cases for VHT operations with hostapd
2 # Copyright (c) 2014, Qualcomm Atheros, Inc.
3 # Copyright (c) 2013, Intel Corporation
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()
10 import os
11 import subprocess, time
12
13 import hwsim_utils
14 import hostapd
15 from utils import HwsimSkip
16 from test_dfs import wait_dfs_event
17 from test_ap_csa import csa_supported
18 from test_ap_ht import clear_scan_cache
19
20 def vht_supported():
21     cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE)
22     reg = cmd.stdout.read()
23     if "@ 80)" in reg or "@ 160)" in reg:
24         return True
25     return False
26
27 def test_ap_vht80(dev, apdev):
28     """VHT with 80 MHz channel width"""
29     try:
30         hapd = None
31         params = { "ssid": "vht",
32                    "country_code": "FI",
33                    "hw_mode": "a",
34                    "channel": "36",
35                    "ht_capab": "[HT40+]",
36                    "ieee80211n": "1",
37                    "ieee80211ac": "1",
38                    "vht_oper_chwidth": "1",
39                    "vht_oper_centr_freq_seg0_idx": "42" }
40         hapd = hostapd.add_ap(apdev[0], params)
41         bssid = apdev[0]['bssid']
42
43         dev[0].connect("vht", key_mgmt="NONE", scan_freq="5180")
44         hwsim_utils.test_connectivity(dev[0], hapd)
45         sig = dev[0].request("SIGNAL_POLL").splitlines()
46         if "FREQUENCY=5180" not in sig:
47             raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig))
48         if "WIDTH=80 MHz" not in sig:
49             raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
50         est = dev[0].get_bss(bssid)['est_throughput']
51         if est != "390001":
52             raise Exception("Unexpected BSS est_throughput: " + est)
53     except Exception, e:
54         if isinstance(e, Exception) and str(e) == "AP startup failed":
55             if not vht_supported():
56                 raise HwsimSkip("80 MHz channel not supported in regulatory information")
57         raise
58     finally:
59         dev[0].request("DISCONNECT")
60         if hapd:
61             hapd.request("DISABLE")
62         subprocess.call(['iw', 'reg', 'set', '00'])
63         dev[0].flush_scan_cache()
64
65 def vht80_test(apdev, dev, channel, ht_capab):
66     clear_scan_cache(apdev['ifname'])
67     try:
68         hapd = None
69         params = { "ssid": "vht",
70                    "country_code": "FI",
71                    "hw_mode": "a",
72                    "channel": str(channel),
73                    "ht_capab": ht_capab,
74                    "ieee80211n": "1",
75                    "ieee80211ac": "1",
76                    "vht_oper_chwidth": "1",
77                    "vht_oper_centr_freq_seg0_idx": "42" }
78         hapd = hostapd.add_ap(apdev['ifname'], params)
79         bssid = apdev['bssid']
80
81         dev.connect("vht", key_mgmt="NONE", scan_freq=str(5000 + 5 * channel))
82         hwsim_utils.test_connectivity(dev, hapd)
83     except Exception, e:
84         if isinstance(e, Exception) and str(e) == "AP startup failed":
85             if not vht_supported():
86                 raise HwsimSkip("80 MHz channel not supported in regulatory information")
87         raise
88     finally:
89         dev.request("DISCONNECT")
90         if hapd:
91             hapd.request("DISABLE")
92         subprocess.call(['iw', 'reg', 'set', '00'])
93         dev.flush_scan_cache()
94
95 def test_ap_vht80b(dev, apdev):
96     """VHT with 80 MHz channel width (HT40- channel 40)"""
97     vht80_test(apdev[0], dev[0], 40, "[HT40-]")
98
99 def test_ap_vht80c(dev, apdev):
100     """VHT with 80 MHz channel width (HT40+ channel 44)"""
101     vht80_test(apdev[0], dev[0], 44, "[HT40+]")
102
103 def test_ap_vht80d(dev, apdev):
104     """VHT with 80 MHz channel width (HT40- channel 48)"""
105     vht80_test(apdev[0], dev[0], 48, "[HT40-]")
106
107 def test_ap_vht80_params(dev, apdev):
108     """VHT with 80 MHz channel width and number of optional features enabled"""
109     try:
110         hapd = None
111         params = { "ssid": "vht",
112                    "country_code": "FI",
113                    "hw_mode": "a",
114                    "channel": "36",
115                    "ht_capab": "[HT40+][SHORT-GI-40][DSS_CCK-40]",
116                    "ieee80211n": "1",
117                    "ieee80211ac": "1",
118                    "vht_oper_chwidth": "1",
119                    "vht_capab": "[MAX-MPDU-11454][RXLDPC][SHORT-GI-80][TX-STBC-2BY1][RX-STBC-1][MAX-A-MPDU-LEN-EXP0]",
120                    "vht_oper_centr_freq_seg0_idx": "42",
121                    "require_vht": "1" }
122         hapd = hostapd.add_ap(apdev[0], params)
123
124         dev[1].connect("vht", key_mgmt="NONE", scan_freq="5180",
125                        disable_vht="1", wait_connect=False)
126         dev[0].connect("vht", key_mgmt="NONE", scan_freq="5180")
127         ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
128         if ev is None:
129             raise Exception("Association rejection timed out")
130         if "status_code=104" not in ev:
131             raise Exception("Unexpected rejection status code")
132         dev[1].request("DISCONNECT")
133         hwsim_utils.test_connectivity(dev[0], hapd)
134     except Exception, e:
135         if isinstance(e, Exception) and str(e) == "AP startup failed":
136             if not vht_supported():
137                 raise HwsimSkip("80 MHz channel not supported in regulatory information")
138         raise
139     finally:
140         dev[0].request("DISCONNECT")
141         dev[1].request("DISCONNECT")
142         if hapd:
143             hapd.request("DISABLE")
144         subprocess.call(['iw', 'reg', 'set', '00'])
145         dev[0].flush_scan_cache()
146         dev[1].flush_scan_cache()
147
148 def test_ap_vht80_invalid(dev, apdev):
149     """VHT with invalid 80 MHz channel configuration (seg1)"""
150     try:
151         hapd = None
152         params = { "ssid": "vht",
153                    "country_code": "US",
154                    "hw_mode": "a",
155                    "channel": "36",
156                    "ht_capab": "[HT40+]",
157                    "ieee80211n": "1",
158                    "ieee80211ac": "1",
159                    "vht_oper_chwidth": "1",
160                    "vht_oper_centr_freq_seg0_idx": "42",
161                    "vht_oper_centr_freq_seg1_idx": "155",
162                    'ieee80211d': '1',
163                    'ieee80211h': '1' }
164         hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
165         # This fails due to unexpected seg1 configuration
166         ev = hapd.wait_event(["AP-DISABLED"], timeout=5)
167         if ev is None:
168             raise Exception("AP-DISABLED not reported")
169     except Exception, e:
170         if isinstance(e, Exception) and str(e) == "AP startup failed":
171             if not vht_supported():
172                 raise HwsimSkip("80/160 MHz channel not supported in regulatory information")
173         raise
174     finally:
175         if hapd:
176             hapd.request("DISABLE")
177         subprocess.call(['iw', 'reg', 'set', '00'])
178
179 def test_ap_vht80_invalid2(dev, apdev):
180     """VHT with invalid 80 MHz channel configuration (seg0)"""
181     try:
182         hapd = None
183         params = { "ssid": "vht",
184                    "country_code": "US",
185                    "hw_mode": "a",
186                    "channel": "36",
187                    "ht_capab": "[HT40+]",
188                    "ieee80211n": "1",
189                    "ieee80211ac": "1",
190                    "vht_oper_chwidth": "1",
191                    "vht_oper_centr_freq_seg0_idx": "46",
192                    'ieee80211d': '1',
193                    'ieee80211h': '1' }
194         hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
195         # This fails due to invalid seg0 configuration
196         ev = hapd.wait_event(["AP-DISABLED"], timeout=5)
197         if ev is None:
198             raise Exception("AP-DISABLED not reported")
199     except Exception, e:
200         if isinstance(e, Exception) and str(e) == "AP startup failed":
201             if not vht_supported():
202                 raise HwsimSkip("80/160 MHz channel not supported in regulatory information")
203         raise
204     finally:
205         if hapd:
206             hapd.request("DISABLE")
207         subprocess.call(['iw', 'reg', 'set', '00'])
208
209 def test_ap_vht_20(devs, apdevs):
210     """VHT and 20 MHz channel"""
211     dev = devs[0]
212     ap = apdevs[0]
213     try:
214         hapd = None
215         params = { "ssid": "test-vht20",
216                    "country_code": "DE",
217                    "hw_mode": "a",
218                    "channel": "36",
219                    "ieee80211n": "1",
220                    "ieee80211ac": "1",
221                    "ht_capab": "",
222                    "vht_capab": "",
223                    "vht_oper_chwidth": "0",
224                    "vht_oper_centr_freq_seg0_idx": "0",
225                    "supported_rates": "60 120 240 360 480 540",
226                    "require_vht": "1",
227                  }
228         hapd = hostapd.add_ap(ap['ifname'], params)
229         dev.connect("test-vht20", scan_freq="5180", key_mgmt="NONE")
230         hwsim_utils.test_connectivity(dev, hapd)
231     finally:
232         dev.request("DISCONNECT")
233         if hapd:
234             hapd.request("DISABLE")
235         subprocess.call(['iw', 'reg', 'set', '00'])
236         dev.flush_scan_cache()
237
238 def test_ap_vht_40(devs, apdevs):
239     """VHT and 40 MHz channel"""
240     dev = devs[0]
241     ap = apdevs[0]
242     try:
243         hapd = None
244         params = { "ssid": "test-vht40",
245                    "country_code": "DE",
246                    "hw_mode": "a",
247                    "channel": "36",
248                    "ieee80211n": "1",
249                    "ieee80211ac": "1",
250                    "ht_capab": "[HT40+]",
251                    "vht_capab": "",
252                    "vht_oper_chwidth": "0",
253                    "vht_oper_centr_freq_seg0_idx": "0",
254                  }
255         hapd = hostapd.add_ap(ap['ifname'], params)
256         dev.connect("test-vht40", scan_freq="5180", key_mgmt="NONE")
257         hwsim_utils.test_connectivity(dev, hapd)
258     finally:
259         dev.request("DISCONNECT")
260         if hapd:
261             hapd.request("DISABLE")
262         subprocess.call(['iw', 'reg', 'set', '00'])
263         dev.flush_scan_cache()
264
265 def test_ap_vht_capab_not_supported(dev, apdev):
266     """VHT configuration with driver not supporting all vht_capab entries"""
267     try:
268         params = { "ssid": "vht",
269                    "country_code": "FI",
270                    "hw_mode": "a",
271                    "channel": "36",
272                    "ht_capab": "[HT40+][SHORT-GI-40][DSS_CCK-40]",
273                    "ieee80211n": "1",
274                    "ieee80211ac": "1",
275                    "vht_oper_chwidth": "1",
276                    "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]",
277                    "vht_oper_centr_freq_seg0_idx": "42",
278                    "require_vht": "1" }
279         hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
280         ev = hapd.wait_event(["AP-DISABLED"], timeout=5)
281         if ev is None:
282             raise Exception("Startup failure not reported")
283         for i in range(1, 7):
284             if "OK" not in hapd.request("SET vht_capab [MAX-A-MPDU-LEN-EXP%d]" % i):
285                 raise Exception("Unexpected SET failure")
286     finally:
287         subprocess.call(['iw', 'reg', 'set', '00'])
288
289 def test_ap_vht160(dev, apdev):
290     """VHT with 160 MHz channel width"""
291     try:
292         hapd = None
293         hapd2 = None
294         params = { "ssid": "vht",
295                    "country_code": "FI",
296                    "hw_mode": "a",
297                    "channel": "36",
298                    "ht_capab": "[HT40+]",
299                    "ieee80211n": "1",
300                    "ieee80211ac": "1",
301                    "vht_oper_chwidth": "2",
302                    "vht_oper_centr_freq_seg0_idx": "50",
303                    'ieee80211d': '1',
304                    'ieee80211h': '1' }
305         hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
306
307         ev = wait_dfs_event(hapd, "DFS-CAC-START", 5)
308         if "DFS-CAC-START" not in ev:
309             raise Exception("Unexpected DFS event")
310
311         state = hapd.get_status_field("state")
312         if state != "DFS":
313             if state == "DISABLED" and not os.path.exists("dfs"):
314                 # Not all systems have recent enough CRDA version and
315                 # wireless-regdb changes to support 160 MHz and DFS. For now,
316                 # do not report failures for this test case.
317                 raise HwsimSkip("CRDA or wireless-regdb did not support 160 MHz")
318             raise Exception("Unexpected interface state: " + state)
319
320         params = { "ssid": "vht2",
321                    "country_code": "FI",
322                    "hw_mode": "a",
323                    "channel": "104",
324                    "ht_capab": "[HT40-]",
325                    "ieee80211n": "1",
326                    "ieee80211ac": "1",
327                    "vht_oper_chwidth": "2",
328                    "vht_oper_centr_freq_seg0_idx": "114",
329                    'ieee80211d': '1',
330                    'ieee80211h': '1' }
331         hapd2 = hostapd.add_ap(apdev[1], params, wait_enabled=False)
332
333         ev = wait_dfs_event(hapd2, "DFS-CAC-START", 5)
334         if "DFS-CAC-START" not in ev:
335             raise Exception("Unexpected DFS event(2)")
336
337         state = hapd2.get_status_field("state")
338         if state != "DFS":
339             raise Exception("Unexpected interface state(2): " + state)
340
341         logger.info("Waiting for CAC to complete")
342
343         ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
344         if "success=1" not in ev:
345             raise Exception("CAC failed")
346         if "freq=5180" not in ev:
347             raise Exception("Unexpected DFS freq result")
348
349         ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
350         if not ev:
351             raise Exception("AP setup timed out")
352
353         state = hapd.get_status_field("state")
354         if state != "ENABLED":
355             raise Exception("Unexpected interface state")
356
357         ev = wait_dfs_event(hapd2, "DFS-CAC-COMPLETED", 70)
358         if "success=1" not in ev:
359             raise Exception("CAC failed(2)")
360         if "freq=5520" not in ev:
361             raise Exception("Unexpected DFS freq result(2)")
362
363         ev = hapd2.wait_event(["AP-ENABLED"], timeout=5)
364         if not ev:
365             raise Exception("AP setup timed out(2)")
366
367         state = hapd2.get_status_field("state")
368         if state != "ENABLED":
369             raise Exception("Unexpected interface state(2)")
370
371         freq = hapd2.get_status_field("freq")
372         if freq != "5520":
373             raise Exception("Unexpected frequency(2)")
374
375         dev[0].connect("vht", key_mgmt="NONE", scan_freq="5180")
376         hwsim_utils.test_connectivity(dev[0], hapd)
377         sig = dev[0].request("SIGNAL_POLL").splitlines()
378         if "FREQUENCY=5180" not in sig:
379             raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig))
380         if "WIDTH=160 MHz" not in sig:
381             raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
382         dev[1].connect("vht2", key_mgmt="NONE", scan_freq="5520")
383         hwsim_utils.test_connectivity(dev[1], hapd2)
384         sig = dev[1].request("SIGNAL_POLL").splitlines()
385         if "FREQUENCY=5520" not in sig:
386             raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig))
387         if "WIDTH=160 MHz" not in sig:
388             raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
389     except Exception, e:
390         if isinstance(e, Exception) and str(e) == "AP startup failed":
391             if not vht_supported():
392                 raise HwsimSkip("80/160 MHz channel not supported in regulatory information")
393         raise
394     finally:
395         dev[0].request("DISCONNECT")
396         dev[1].request("DISCONNECT")
397         if hapd:
398             hapd.request("DISABLE")
399         if hapd2:
400             hapd2.request("DISABLE")
401         subprocess.call(['iw', 'reg', 'set', '00'])
402         dev[0].flush_scan_cache()
403         dev[1].flush_scan_cache()
404
405 def test_ap_vht160_no_dfs(dev, apdev):
406     """VHT with 160 MHz channel width and no DFS"""
407     try:
408         hapd = None
409         params = { "ssid": "vht",
410                    "country_code": "ZA",
411                    "hw_mode": "a",
412                    "channel": "104",
413                    "ht_capab": "[HT40-]",
414                    "ieee80211n": "1",
415                    "ieee80211ac": "1",
416                    "vht_oper_chwidth": "2",
417                    "vht_oper_centr_freq_seg0_idx": "114",
418                    'ieee80211d': '1',
419                    'ieee80211h': '1' }
420         hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
421         ev = hapd.wait_event(["AP-ENABLED"], timeout=2)
422         if not ev:
423             cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE)
424             reg = cmd.stdout.readlines()
425             for r in reg:
426                 if "5490" in r and "DFS" in r:
427                     raise HwsimSkip("ZA regulatory rule did not have DFS requirement removed")
428             raise Exception("AP setup timed out")
429
430         dev[0].connect("vht", key_mgmt="NONE", scan_freq="5520")
431         hwsim_utils.test_connectivity(dev[0], hapd)
432         sig = dev[0].request("SIGNAL_POLL").splitlines()
433         if "FREQUENCY=5520" not in sig:
434             raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig))
435         if "WIDTH=160 MHz" not in sig:
436             raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
437     except Exception, e:
438         if isinstance(e, Exception) and str(e) == "AP startup failed":
439             if not vht_supported():
440                 raise HwsimSkip("80/160 MHz channel not supported in regulatory information")
441         raise
442     finally:
443         dev[0].request("DISCONNECT")
444         if hapd:
445             hapd.request("DISABLE")
446         subprocess.call(['iw', 'reg', 'set', '00'])
447         dev[0].flush_scan_cache()
448
449 def test_ap_vht80plus80(dev, apdev):
450     """VHT with 80+80 MHz channel width"""
451     try:
452         hapd = None
453         hapd2 = None
454         params = { "ssid": "vht",
455                    "country_code": "US",
456                    "hw_mode": "a",
457                    "channel": "52",
458                    "ht_capab": "[HT40+]",
459                    "ieee80211n": "1",
460                    "ieee80211ac": "1",
461                    "vht_oper_chwidth": "3",
462                    "vht_oper_centr_freq_seg0_idx": "58",
463                    "vht_oper_centr_freq_seg1_idx": "155",
464                    'ieee80211d': '1',
465                    'ieee80211h': '1' }
466         hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
467         # This will actually fail since DFS on 80+80 is not yet supported
468         ev = hapd.wait_event(["AP-DISABLED"], timeout=5)
469         # ignore result to avoid breaking the test once 80+80 DFS gets enabled
470
471         params = { "ssid": "vht2",
472                    "country_code": "US",
473                    "hw_mode": "a",
474                    "channel": "36",
475                    "ht_capab": "[HT40+]",
476                    "ieee80211n": "1",
477                    "ieee80211ac": "1",
478                    "vht_oper_chwidth": "3",
479                    "vht_oper_centr_freq_seg0_idx": "42",
480                    "vht_oper_centr_freq_seg1_idx": "155" }
481         hapd2 = hostapd.add_ap(apdev[1], params, wait_enabled=False)
482
483         ev = hapd2.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=5)
484         if not ev:
485             raise Exception("AP setup timed out(2)")
486         if "AP-DISABLED" in ev:
487             # Assume this failed due to missing regulatory update for now
488             raise HwsimSkip("80+80 MHz channel not supported in regulatory information")
489
490         state = hapd2.get_status_field("state")
491         if state != "ENABLED":
492             raise Exception("Unexpected interface state(2)")
493
494         dev[1].connect("vht2", key_mgmt="NONE", scan_freq="5180")
495         hwsim_utils.test_connectivity(dev[1], hapd2)
496         sig = dev[1].request("SIGNAL_POLL").splitlines()
497         if "FREQUENCY=5180" not in sig:
498             raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig))
499         if "WIDTH=80+80 MHz" not in sig:
500             raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
501         if "CENTER_FRQ1=5210" not in sig:
502             raise Exception("Unexpected SIGNAL_POLL value(3): " + str(sig))
503         if "CENTER_FRQ2=5775" not in sig:
504             raise Exception("Unexpected SIGNAL_POLL value(4): " + str(sig))
505     except Exception, e:
506         if isinstance(e, Exception) and str(e) == "AP startup failed":
507             if not vht_supported():
508                 raise HwsimSkip("80/160 MHz channel not supported in regulatory information")
509         raise
510     finally:
511         dev[0].request("DISCONNECT")
512         dev[1].request("DISCONNECT")
513         if hapd:
514             hapd.request("DISABLE")
515         if hapd2:
516             hapd2.request("DISABLE")
517         subprocess.call(['iw', 'reg', 'set', '00'])
518         dev[0].flush_scan_cache()
519         dev[1].flush_scan_cache()
520
521 def test_ap_vht80plus80_invalid(dev, apdev):
522     """VHT with invalid 80+80 MHz channel"""
523     try:
524         hapd = None
525         params = { "ssid": "vht",
526                    "country_code": "US",
527                    "hw_mode": "a",
528                    "channel": "36",
529                    "ht_capab": "[HT40+]",
530                    "ieee80211n": "1",
531                    "ieee80211ac": "1",
532                    "vht_oper_chwidth": "3",
533                    "vht_oper_centr_freq_seg0_idx": "42",
534                    "vht_oper_centr_freq_seg1_idx": "0",
535                    'ieee80211d': '1',
536                    'ieee80211h': '1' }
537         hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
538         # This fails due to missing(invalid) seg1 configuration
539         ev = hapd.wait_event(["AP-DISABLED"], timeout=5)
540         if ev is None:
541             raise Exception("AP-DISABLED not reported")
542     except Exception, e:
543         if isinstance(e, Exception) and str(e) == "AP startup failed":
544             if not vht_supported():
545                 raise HwsimSkip("80/160 MHz channel not supported in regulatory information")
546         raise
547     finally:
548         if hapd:
549             hapd.request("DISABLE")
550         subprocess.call(['iw', 'reg', 'set', '00'])
551
552 def test_ap_vht80_csa(dev, apdev):
553     """VHT with 80 MHz channel width and CSA"""
554     csa_supported(dev[0])
555     try:
556         hapd = None
557         params = { "ssid": "vht",
558                    "country_code": "US",
559                    "hw_mode": "a",
560                    "channel": "149",
561                    "ht_capab": "[HT40+]",
562                    "ieee80211n": "1",
563                    "ieee80211ac": "1",
564                    "vht_oper_chwidth": "1",
565                    "vht_oper_centr_freq_seg0_idx": "155" }
566         hapd = hostapd.add_ap(apdev[0], params)
567
568         dev[0].connect("vht", key_mgmt="NONE", scan_freq="5745")
569         hwsim_utils.test_connectivity(dev[0], hapd)
570
571         hapd.request("CHAN_SWITCH 5 5180 ht vht blocktx center_freq1=5210 sec_channel_offset=1 bandwidth=80")
572         ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
573         if ev is None:
574             raise Exception("CSA finished event timed out")
575         if "freq=5180" not in ev:
576             raise Exception("Unexpected channel in CSA finished event")
577         time.sleep(0.5)
578         hwsim_utils.test_connectivity(dev[0], hapd)
579
580         hapd.request("CHAN_SWITCH 5 5745")
581         ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
582         if ev is None:
583             raise Exception("CSA finished event timed out")
584         if "freq=5745" not in ev:
585             raise Exception("Unexpected channel in CSA finished event")
586         time.sleep(0.5)
587         hwsim_utils.test_connectivity(dev[0], hapd)
588
589         # This CSA to same channel will fail in kernel, so use this only for
590         # extra code coverage.
591         hapd.request("CHAN_SWITCH 5 5745")
592         hapd.wait_event(["AP-CSA-FINISHED"], timeout=1)
593     except Exception, e:
594         if isinstance(e, Exception) and str(e) == "AP startup failed":
595             if not vht_supported():
596                 raise HwsimSkip("80 MHz channel not supported in regulatory information")
597         raise
598     finally:
599         dev[0].request("DISCONNECT")
600         if hapd:
601             hapd.request("DISABLE")
602         subprocess.call(['iw', 'reg', 'set', '00'])
603         dev[0].flush_scan_cache()
604
605 def test_ap_vht_on_24ghz(dev, apdev):
606     """Subset of VHT features on 2.4 GHz"""
607     hapd = None
608     params = { "ssid": "test-vht-2g",
609                "hw_mode": "g",
610                "channel": "1",
611                "ieee80211n": "1",
612                "vendor_vht": "1",
613                "vht_capab": "[MAX-MPDU-11454]",
614                "vht_oper_chwidth": "0",
615                "vht_oper_centr_freq_seg0_idx": "1"
616     }
617     hapd = hostapd.add_ap(apdev[0], params)
618     try:
619         if "OK" not in dev[0].request("VENDOR_ELEM_ADD 13 dd1300904c0400bf0c3240820feaff0000eaff0000"):
620             raise Exception("Failed to add vendor element")
621         dev[0].connect("test-vht-2g", scan_freq="2412", key_mgmt="NONE")
622         hwsim_utils.test_connectivity(dev[0], hapd)
623         sta = hapd.get_sta(dev[0].own_addr())
624         if '[VENDOR_VHT]' not in sta['flags']:
625             raise Exception("No VENDOR_VHT STA flag")
626
627         dev[1].connect("test-vht-2g", scan_freq="2412", key_mgmt="NONE")
628         sta = hapd.get_sta(dev[1].own_addr())
629         if '[VENDOR_VHT]' in sta['flags']:
630             raise Exception("Unexpected VENDOR_VHT STA flag")
631     finally:
632         dev[0].request("VENDOR_ELEM_REMOVE 13 *")
633
634 def test_prefer_vht40(dev, apdev):
635     """Preference on VHT40 over HT40"""
636     try:
637         hapd2 = None
638
639         params = { "ssid": "test",
640                    "country_code": "FI",
641                    "hw_mode": "a",
642                    "channel": "36",
643                    "ieee80211n": "1",
644                    "ht_capab": "[HT40+]" }
645         hapd = hostapd.add_ap(apdev[0], params)
646         bssid = apdev[0]['bssid']
647
648         params = { "ssid": "test",
649                    "country_code": "FI",
650                    "hw_mode": "a",
651                    "channel": "36",
652                    "ieee80211n": "1",
653                    "ieee80211ac": "1",
654                    "ht_capab": "[HT40+]",
655                    "vht_capab": "",
656                    "vht_oper_chwidth": "0",
657                    "vht_oper_centr_freq_seg0_idx": "0",
658                  }
659         hapd2 = hostapd.add_ap(apdev[1], params)
660         bssid2 = apdev[1]['bssid']
661
662         dev[0].scan_for_bss(bssid, freq=5180)
663         dev[0].scan_for_bss(bssid2, freq=5180)
664         dev[0].connect("test", scan_freq="5180", key_mgmt="NONE")
665         if dev[0].get_status_field('bssid') != bssid2:
666             raise Exception("Unexpected BSS selected")
667
668         est = dev[0].get_bss(bssid)['est_throughput']
669         if est != "135000":
670             raise Exception("Unexpected BSS0 est_throughput: " + est)
671
672         est = dev[0].get_bss(bssid2)['est_throughput']
673         if est != "135001":
674             raise Exception("Unexpected BSS1 est_throughput: " + est)
675     finally:
676         dev[0].request("DISCONNECT")
677         if hapd2:
678             hapd2.request("DISABLE")
679         subprocess.call(['iw', 'reg', 'set', '00'])
680         dev[0].flush_scan_cache()
681
682 def test_ap_vht80_pwr_constraint(dev, apdev):
683     """VHT with 80 MHz channel width and local power constraint"""
684     hapd = None
685     try:
686         params = { "ssid": "vht",
687                    "country_code": "FI",
688                    "hw_mode": "a",
689                    "channel": "36",
690                    "ht_capab": "[HT40+]",
691                    "ieee80211d": "1",
692                    "local_pwr_constraint": "3",
693                    "ieee80211n": "1",
694                    "ieee80211ac": "1",
695                    "vht_oper_chwidth": "1",
696                    "vht_oper_centr_freq_seg0_idx": "42" }
697         hapd = hostapd.add_ap(apdev[0], params)
698
699         dev[0].connect("vht", key_mgmt="NONE", scan_freq="5180")
700     except Exception, e:
701         if isinstance(e, Exception) and str(e) == "AP startup failed":
702             if not vht_supported():
703                 raise HwsimSkip("80 MHz channel not supported in regulatory information")
704         raise
705     finally:
706         dev[0].request("DISCONNECT")
707         if hapd:
708             hapd.request("DISABLE")
709         subprocess.call(['iw', 'reg', 'set', '00'])
710         dev[0].flush_scan_cache()