tests: Use apdev[0] more consistently in ap_ht
[mech_eap.git] / tests / hwsim / test_ap_ht.py
1 # Test cases for HT operations with hostapd
2 # Copyright (c) 2013-2014, Jouni Malinen <j@w1.fi>
3 #
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
6
7 import time
8 import logging
9 logger = logging.getLogger()
10 import struct
11 import subprocess
12
13 import hostapd
14 from utils import HwsimSkip, alloc_fail
15 import hwsim_utils
16 from test_ap_csa import csa_supported
17
18 def clear_scan_cache(apdev):
19     ifname = apdev['ifname']
20     subprocess.call(['ifconfig', ifname, 'up'])
21     subprocess.call(['iw', ifname, 'scan', 'trigger', 'freq', '2412', 'flush'])
22     time.sleep(0.1)
23     subprocess.call(['ifconfig', ifname, 'down'])
24
25 def test_ap_ht40_scan(dev, apdev):
26     """HT40 co-ex scan"""
27     clear_scan_cache(apdev[0])
28     params = { "ssid": "test-ht40",
29                "channel": "5",
30                "ht_capab": "[HT40-]"}
31     hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
32
33     state = hapd.get_status_field("state")
34     if state != "HT_SCAN":
35         time.sleep(0.1)
36         state = hapd.get_status_field("state")
37         if state != "HT_SCAN":
38             raise Exception("Unexpected interface state - expected HT_SCAN")
39
40     ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
41     if not ev:
42         raise Exception("AP setup timed out")
43
44     state = hapd.get_status_field("state")
45     if state != "ENABLED":
46         raise Exception("Unexpected interface state - expected ENABLED")
47
48     freq = hapd.get_status_field("freq")
49     if freq != "2432":
50         raise Exception("Unexpected frequency")
51     pri = hapd.get_status_field("channel")
52     if pri != "5":
53         raise Exception("Unexpected primary channel")
54     sec = hapd.get_status_field("secondary_channel")
55     if sec != "-1":
56         raise Exception("Unexpected secondary channel")
57
58     dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
59
60 def test_ap_ht40_scan_conflict(dev, apdev):
61     """HT40 co-ex scan conflict"""
62     clear_scan_cache(apdev[0])
63     params = { "ssid": "test-ht40",
64                "channel": "6",
65                "ht_capab": "[HT40+]"}
66     hostapd.add_ap(apdev[1], params)
67
68     params = { "ssid": "test-ht40",
69                "channel": "5",
70                "ht_capab": "[HT40-]"}
71     hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
72
73     state = hapd.get_status_field("state")
74     if state != "HT_SCAN":
75         time.sleep(0.1)
76         state = hapd.get_status_field("state")
77         if state != "HT_SCAN":
78             raise Exception("Unexpected interface state - expected HT_SCAN")
79
80     ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
81     if not ev:
82         raise Exception("AP setup timed out")
83
84     state = hapd.get_status_field("state")
85     if state != "ENABLED":
86         raise Exception("Unexpected interface state - expected ENABLED")
87
88     freq = hapd.get_status_field("freq")
89     if freq != "2432":
90         raise Exception("Unexpected frequency")
91     pri = hapd.get_status_field("channel")
92     if pri != "5":
93         raise Exception("Unexpected primary channel")
94     sec = hapd.get_status_field("secondary_channel")
95     if sec != "0":
96         raise Exception("Unexpected secondary channel: " + sec)
97
98     dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
99
100 def test_ap_ht40_scan_conflict2(dev, apdev):
101     """HT40 co-ex scan conflict (HT40-)"""
102     clear_scan_cache(apdev[0])
103     params = { "ssid": "test-ht40",
104                "channel": "11",
105                "ht_capab": "[HT40-]"}
106     hostapd.add_ap(apdev[1], params)
107
108     params = { "ssid": "test-ht40",
109                "channel": "1",
110                "ht_capab": "[HT40+]"}
111     hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
112
113     state = hapd.get_status_field("state")
114     if state != "HT_SCAN":
115         time.sleep(0.1)
116         state = hapd.get_status_field("state")
117         if state != "HT_SCAN":
118             raise Exception("Unexpected interface state - expected HT_SCAN")
119
120     ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
121     if not ev:
122         raise Exception("AP setup timed out")
123
124     state = hapd.get_status_field("state")
125     if state != "ENABLED":
126         raise Exception("Unexpected interface state - expected ENABLED")
127
128     freq = hapd.get_status_field("freq")
129     if freq != "2412":
130         raise Exception("Unexpected frequency")
131     pri = hapd.get_status_field("channel")
132     if pri != "1":
133         raise Exception("Unexpected primary channel")
134     sec = hapd.get_status_field("secondary_channel")
135     if sec != "0":
136         raise Exception("Unexpected secondary channel: " + sec)
137
138     dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
139
140 def test_ap_ht40_scan_not_affected(dev, apdev):
141     """HT40 co-ex scan and other BSS not affected"""
142     clear_scan_cache(apdev[0])
143     params = { "ssid": "test-ht20",
144                "channel": "11" }
145     hostapd.add_ap(apdev[1], params)
146
147     subprocess.call(['ifconfig', apdev[0]['ifname'], 'up'])
148     subprocess.call(['iw', apdev[0]['ifname'], 'scan', 'trigger', 'freq', '2462'])
149     time.sleep(0.5)
150     subprocess.call(['iw', apdev[0]['ifname'], 'scan', 'dump'],
151                     stdout=open('/dev/null', 'w'))
152     time.sleep(0.1)
153     subprocess.call(['ifconfig', apdev[0]['ifname'], 'down'])
154
155     params = { "ssid": "test-ht40",
156                "channel": "1",
157                "ht_capab": "[HT40+]"}
158     hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
159
160     state = hapd.get_status_field("state")
161     if state != "HT_SCAN":
162         time.sleep(0.1)
163         state = hapd.get_status_field("state")
164         if state != "HT_SCAN":
165             raise Exception("Unexpected interface state - expected HT_SCAN")
166
167     ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
168     if not ev:
169         raise Exception("AP setup timed out")
170
171     state = hapd.get_status_field("state")
172     if state != "ENABLED":
173         raise Exception("Unexpected interface state - expected ENABLED")
174
175     freq = hapd.get_status_field("freq")
176     if freq != "2412":
177         raise Exception("Unexpected frequency")
178     pri = hapd.get_status_field("channel")
179     if pri != "1":
180         raise Exception("Unexpected primary channel")
181     sec = hapd.get_status_field("secondary_channel")
182     if sec != "1":
183         raise Exception("Unexpected secondary channel: " + sec)
184
185     dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
186
187 def test_ap_ht40_scan_legacy_conflict(dev, apdev):
188     """HT40 co-ex scan conflict with legacy 20 MHz AP"""
189     clear_scan_cache(apdev[0])
190     params = { "ssid": "legacy-20",
191                "channel": "7", "ieee80211n": "0" }
192     hostapd.add_ap(apdev[1], params)
193
194     params = { "ssid": "test-ht40",
195                "channel": "5",
196                "ht_capab": "[HT40-]"}
197     hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
198
199     state = hapd.get_status_field("state")
200     if state != "HT_SCAN":
201         time.sleep(0.1)
202         state = hapd.get_status_field("state")
203         if state != "HT_SCAN":
204             raise Exception("Unexpected interface state - expected HT_SCAN")
205
206     ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
207     if not ev:
208         raise Exception("AP setup timed out")
209
210     state = hapd.get_status_field("state")
211     if state != "ENABLED":
212         raise Exception("Unexpected interface state - expected ENABLED")
213
214     freq = hapd.get_status_field("freq")
215     if freq != "2432":
216         raise Exception("Unexpected frequency: " + freq)
217     pri = hapd.get_status_field("channel")
218     if pri != "5":
219         raise Exception("Unexpected primary channel: " + pri)
220     sec = hapd.get_status_field("secondary_channel")
221     if sec != "0":
222         raise Exception("Unexpected secondary channel: " + sec)
223
224     dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
225
226 def test_ap_ht40_scan_ht20_conflict(dev, apdev):
227     """HT40 co-ex scan conflict with HT 20 MHz AP"""
228     clear_scan_cache(apdev[0])
229     params = { "ssid": "ht-20",
230                "channel": "7", "ieee80211n": "1" }
231     hostapd.add_ap(apdev[1], params)
232
233     params = { "ssid": "test-ht40",
234                "channel": "5",
235                "ht_capab": "[HT40-]"}
236     hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
237
238     state = hapd.get_status_field("state")
239     if state != "HT_SCAN":
240         time.sleep(0.1)
241         state = hapd.get_status_field("state")
242         if state != "HT_SCAN":
243             raise Exception("Unexpected interface state - expected HT_SCAN")
244
245     ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
246     if not ev:
247         raise Exception("AP setup timed out")
248
249     state = hapd.get_status_field("state")
250     if state != "ENABLED":
251         raise Exception("Unexpected interface state - expected ENABLED")
252
253     freq = hapd.get_status_field("freq")
254     if freq != "2432":
255         raise Exception("Unexpected frequency: " + freq)
256     pri = hapd.get_status_field("channel")
257     if pri != "5":
258         raise Exception("Unexpected primary channel: " + pri)
259     sec = hapd.get_status_field("secondary_channel")
260     if sec != "0":
261         raise Exception("Unexpected secondary channel: " + sec)
262
263     dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
264
265 def test_ap_ht40_scan_intolerant(dev, apdev):
266     """HT40 co-ex scan finding an AP advertising 40 MHz intolerant"""
267     clear_scan_cache(apdev[0])
268     params = { "ssid": "another-bss",
269                "channel": "1",
270                "ht_capab": "[40-INTOLERANT]" }
271     hostapd.add_ap(apdev[1], params)
272
273     params = { "ssid": "test-ht40",
274                "channel": "1",
275                "ht_capab": "[HT40+]"}
276     hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
277
278     state = hapd.get_status_field("state")
279     if state != "HT_SCAN":
280         time.sleep(0.1)
281         state = hapd.get_status_field("state")
282         if state != "HT_SCAN":
283             raise Exception("Unexpected interface state - expected HT_SCAN")
284
285     ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
286     if not ev:
287         raise Exception("AP setup timed out")
288
289     state = hapd.get_status_field("state")
290     if state != "ENABLED":
291         raise Exception("Unexpected interface state - expected ENABLED")
292
293     freq = hapd.get_status_field("freq")
294     if freq != "2412":
295         raise Exception("Unexpected frequency: " + freq)
296     pri = hapd.get_status_field("channel")
297     if pri != "1":
298         raise Exception("Unexpected primary channel: " + pri)
299     sec = hapd.get_status_field("secondary_channel")
300     if sec != "0":
301         raise Exception("Unexpected secondary channel: " + sec)
302
303     dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
304
305 def test_ap_ht40_scan_match(dev, apdev):
306     """HT40 co-ex scan matching configuration"""
307     clear_scan_cache(apdev[0])
308     params = { "ssid": "test-ht40",
309                "channel": "5",
310                "ht_capab": "[HT40-]"}
311     hostapd.add_ap(apdev[1], params)
312
313     params = { "ssid": "test-ht40",
314                "channel": "5",
315                "ht_capab": "[HT40-]"}
316     hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
317
318     state = hapd.get_status_field("state")
319     if state != "HT_SCAN":
320         time.sleep(0.1)
321         state = hapd.get_status_field("state")
322         if state != "HT_SCAN":
323             raise Exception("Unexpected interface state - expected HT_SCAN")
324
325     ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
326     if not ev:
327         raise Exception("AP setup timed out")
328
329     state = hapd.get_status_field("state")
330     if state != "ENABLED":
331         raise Exception("Unexpected interface state - expected ENABLED")
332
333     freq = hapd.get_status_field("freq")
334     if freq != "2432":
335         raise Exception("Unexpected frequency")
336     pri = hapd.get_status_field("channel")
337     if pri != "5":
338         raise Exception("Unexpected primary channel")
339     sec = hapd.get_status_field("secondary_channel")
340     if sec != "-1":
341         raise Exception("Unexpected secondary channel: " + sec)
342
343     dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
344
345 def test_ap_ht40_5ghz_match(dev, apdev):
346     """HT40 co-ex scan on 5 GHz with matching pri/sec channel"""
347     clear_scan_cache(apdev[0])
348     try:
349         hapd = None
350         hapd2 = None
351         params = { "ssid": "test-ht40",
352                    "hw_mode": "a",
353                    "channel": "36",
354                    "country_code": "US",
355                    "ht_capab": "[HT40+]"}
356         hapd2 = hostapd.add_ap(apdev[1], params)
357
358         params = { "ssid": "test-ht40",
359                    "hw_mode": "a",
360                    "channel": "36",
361                    "ht_capab": "[HT40+]"}
362         hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
363
364         state = hapd.get_status_field("state")
365         if state != "HT_SCAN":
366             time.sleep(0.1)
367             state = hapd.get_status_field("state")
368             if state != "HT_SCAN":
369                 raise Exception("Unexpected interface state - expected HT_SCAN")
370
371         ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
372         if not ev:
373             raise Exception("AP setup timed out")
374
375         state = hapd.get_status_field("state")
376         if state != "ENABLED":
377             raise Exception("Unexpected interface state - expected ENABLED")
378
379         freq = hapd.get_status_field("freq")
380         if freq != "5180":
381             raise Exception("Unexpected frequency")
382         pri = hapd.get_status_field("channel")
383         if pri != "36":
384             raise Exception("Unexpected primary channel")
385         sec = hapd.get_status_field("secondary_channel")
386         if sec != "1":
387             raise Exception("Unexpected secondary channel: " + sec)
388
389         dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
390     finally:
391         dev[0].request("DISCONNECT")
392         if hapd:
393             hapd.request("DISABLE")
394         if hapd2:
395             hapd2.request("DISABLE")
396         subprocess.call(['iw', 'reg', 'set', '00'])
397         dev[0].flush_scan_cache()
398
399 def test_ap_ht40_5ghz_switch(dev, apdev):
400     """HT40 co-ex scan on 5 GHz switching pri/sec channel"""
401     clear_scan_cache(apdev[0])
402     try:
403         hapd = None
404         hapd2 = None
405         params = { "ssid": "test-ht40",
406                    "hw_mode": "a",
407                    "channel": "36",
408                    "country_code": "US",
409                    "ht_capab": "[HT40+]"}
410         hapd2 = hostapd.add_ap(apdev[1], params)
411
412         params = { "ssid": "test-ht40",
413                    "hw_mode": "a",
414                    "channel": "40",
415                    "ht_capab": "[HT40-]"}
416         hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
417
418         state = hapd.get_status_field("state")
419         if state != "HT_SCAN":
420             time.sleep(0.1)
421             state = hapd.get_status_field("state")
422             if state != "HT_SCAN":
423                 raise Exception("Unexpected interface state - expected HT_SCAN")
424
425         ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
426         if not ev:
427             raise Exception("AP setup timed out")
428
429         state = hapd.get_status_field("state")
430         if state != "ENABLED":
431             raise Exception("Unexpected interface state - expected ENABLED")
432
433         freq = hapd.get_status_field("freq")
434         if freq != "5180":
435             raise Exception("Unexpected frequency: " + freq)
436         pri = hapd.get_status_field("channel")
437         if pri != "36":
438             raise Exception("Unexpected primary channel: " + pri)
439         sec = hapd.get_status_field("secondary_channel")
440         if sec != "1":
441             raise Exception("Unexpected secondary channel: " + sec)
442
443         dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
444     finally:
445         dev[0].request("DISCONNECT")
446         if hapd:
447             hapd.request("DISABLE")
448         if hapd2:
449             hapd2.request("DISABLE")
450         subprocess.call(['iw', 'reg', 'set', '00'])
451
452 def test_ap_ht40_5ghz_switch2(dev, apdev):
453     """HT40 co-ex scan on 5 GHz switching pri/sec channel (2)"""
454     clear_scan_cache(apdev[0])
455     try:
456         hapd = None
457         hapd2 = None
458         params = { "ssid": "test-ht40",
459                    "hw_mode": "a",
460                    "channel": "36",
461                    "country_code": "US",
462                    "ht_capab": "[HT40+]"}
463         hapd2 = hostapd.add_ap(apdev[1], params)
464
465         id = dev[0].add_network()
466         dev[0].set_network(id, "mode", "2")
467         dev[0].set_network_quoted(id, "ssid", "wpas-ap-open")
468         dev[0].set_network(id, "key_mgmt", "NONE")
469         dev[0].set_network(id, "frequency", "5200")
470         dev[0].set_network(id, "scan_freq", "5200")
471         dev[0].select_network(id)
472         time.sleep(1)
473
474         params = { "ssid": "test-ht40",
475                    "hw_mode": "a",
476                    "channel": "40",
477                    "ht_capab": "[HT40-]"}
478         hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
479
480         state = hapd.get_status_field("state")
481         if state != "HT_SCAN":
482             time.sleep(0.1)
483             state = hapd.get_status_field("state")
484             if state != "HT_SCAN":
485                 raise Exception("Unexpected interface state - expected HT_SCAN")
486
487         ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
488         if not ev:
489             raise Exception("AP setup timed out")
490
491         state = hapd.get_status_field("state")
492         if state != "ENABLED":
493             raise Exception("Unexpected interface state - expected ENABLED")
494
495         freq = hapd.get_status_field("freq")
496         if freq != "5180":
497             raise Exception("Unexpected frequency: " + freq)
498         pri = hapd.get_status_field("channel")
499         if pri != "36":
500             raise Exception("Unexpected primary channel: " + pri)
501         sec = hapd.get_status_field("secondary_channel")
502         if sec != "1":
503             raise Exception("Unexpected secondary channel: " + sec)
504
505         dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
506     finally:
507         dev[0].request("DISCONNECT")
508         if hapd:
509             hapd.request("DISABLE")
510         if hapd2:
511             hapd2.request("DISABLE")
512         subprocess.call(['iw', 'reg', 'set', '00'])
513         dev[0].flush_scan_cache()
514
515 def test_obss_scan(dev, apdev):
516     """Overlapping BSS scan request"""
517     params = { "ssid": "obss-scan",
518                "channel": "6",
519                "ht_capab": "[HT40-]",
520                "obss_interval": "10" }
521     hapd = hostapd.add_ap(apdev[0], params)
522
523     params = { "ssid": "another-bss",
524                "channel": "9",
525                "ieee80211n": "0" }
526     hostapd.add_ap(apdev[1], params)
527
528     dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
529     hapd.set("ext_mgmt_frame_handling", "1")
530     logger.info("Waiting for OBSS scan to occur")
531     ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=15)
532     if ev is None:
533         raise Exception("Timed out while waiting for OBSS scan to start")
534     ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
535     if ev is None:
536         raise Exception("Timed out while waiting for OBSS scan results")
537     received = False
538     for i in range(0, 4):
539         frame = hapd.mgmt_rx(timeout=5)
540         if frame is None:
541             raise Exception("MGMT RX wait timed out")
542         if frame['subtype'] != 13:
543             continue
544         payload = frame['payload']
545         if len(payload) < 3:
546             continue
547         (category, action, ie) = struct.unpack('BBB', payload[0:3])
548         if category != 4:
549             continue
550         if action != 0:
551             continue
552         if ie == 72:
553             logger.info("20/40 BSS Coexistence report received")
554             received = True
555             break
556     if not received:
557         raise Exception("20/40 BSS Coexistence report not seen")
558
559 def test_obss_scan_40_intolerant(dev, apdev):
560     """Overlapping BSS scan request with 40 MHz intolerant AP"""
561     params = { "ssid": "obss-scan",
562                "channel": "6",
563                "ht_capab": "[HT40-]",
564                "obss_interval": "10" }
565     hapd = hostapd.add_ap(apdev[0], params)
566
567     params = { "ssid": "another-bss",
568                "channel": "7",
569                "ht_capab": "[40-INTOLERANT]" }
570     hostapd.add_ap(apdev[1], params)
571
572     dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
573     hapd.set("ext_mgmt_frame_handling", "1")
574     logger.info("Waiting for OBSS scan to occur")
575     ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=15)
576     if ev is None:
577         raise Exception("Timed out while waiting for OBSS scan to start")
578     ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
579     if ev is None:
580         raise Exception("Timed out while waiting for OBSS scan results")
581     received = False
582     for i in range(0, 4):
583         frame = hapd.mgmt_rx(timeout=5)
584         if frame is None:
585             raise Exception("MGMT RX wait timed out")
586         if frame['subtype'] != 13:
587             continue
588         payload = frame['payload']
589         if len(payload) < 3:
590             continue
591         (category, action, ie) = struct.unpack('BBB', payload[0:3])
592         if category != 4:
593             continue
594         if action != 0:
595             continue
596         if ie == 72:
597             logger.info("20/40 BSS Coexistence report received")
598             received = True
599             break
600     if not received:
601         raise Exception("20/40 BSS Coexistence report not seen")
602
603 def test_obss_coex_report_handling(dev, apdev):
604     """Overlapping BSS scan report handling with obss_interval=0"""
605     clear_scan_cache(apdev[0])
606     params = { "ssid": "obss-scan",
607                "channel": "6",
608                "ht_capab": "[HT40-]" }
609     hapd = hostapd.add_ap(apdev[0], params)
610     bssid = apdev[0]['bssid']
611     dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
612
613     sec = hapd.get_status_field("secondary_channel")
614     if sec != "-1":
615         raise Exception("AP is not using 40 MHz channel")
616
617     # 20/40 MHz co-ex report tests: number of invalid reports and a valid report
618     # that forces 20 MHz channel.
619     tests = [ '0400', '040048', '04004801', '0400480000', '0400490100',
620               '040048ff0000', '04004801ff49ff00', '04004801004900',
621               '0400480100490101', '0400480100490201ff',
622               '040048010449020005' ]
623     for msg in tests:
624         req = "MGMT_TX {} {} freq=2437 action={}".format(bssid, bssid, msg)
625         if "OK" not in dev[0].request(req):
626             raise Exception("Could not send management frame")
627     time.sleep(0.5)
628     sec = hapd.get_status_field("secondary_channel")
629     if sec != "0":
630         raise Exception("AP did not move to 20 MHz channel")
631
632 def test_obss_coex_report_handling1(dev, apdev):
633     """Overlapping BSS scan report handling with obss_interval=1"""
634     clear_scan_cache(apdev[0])
635     params = { "ssid": "obss-scan",
636                "channel": "6",
637                "ht_capab": "[HT40+]",
638                "obss_interval": "1" }
639     hapd = hostapd.add_ap(apdev[0], params)
640     bssid = apdev[0]['bssid']
641     dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
642
643     sec = hapd.get_status_field("secondary_channel")
644     if sec != "1":
645         raise Exception("AP is not using 40 MHz channel")
646
647     # 20/40 MHz co-ex report forcing 20 MHz channel
648     msg = '040048010449020005'
649     req = "MGMT_TX {} {} freq=2437 action={}".format(bssid, bssid, msg)
650     if "OK" not in dev[0].request(req):
651         raise Exception("Could not send management frame")
652     time.sleep(0.5)
653     sec = hapd.get_status_field("secondary_channel")
654     if sec != "0":
655         raise Exception("AP did not move to 20 MHz channel")
656
657     # No 20/40 MHz co-ex reports forcing 20 MHz channel during next interval
658     for i in range(20):
659         sec = hapd.get_status_field("secondary_channel")
660         if sec == "1":
661             break
662         time.sleep(0.5)
663     if sec != "1":
664         raise Exception("AP did not return to 40 MHz channel")
665
666 def test_olbc(dev, apdev):
667     """OLBC detection"""
668     params = { "ssid": "test-olbc",
669                "channel": "6",
670                "ht_capab": "[HT40-]",
671                "ap_table_expiration_time": "2" }
672     hapd = hostapd.add_ap(apdev[0], params)
673     status = hapd.get_status()
674     if status['olbc'] != '0' or status['olbc_ht'] != '0':
675         raise Exception("Unexpected OLBC information")
676
677     params = { "ssid": "olbc-ap",
678                "hw_mode": "b",
679                "channel": "6",
680                "wmm_enabled": "0" }
681     hostapd.add_ap(apdev[1], params)
682     time.sleep(0.5)
683     status = hapd.get_status()
684     if status['olbc'] != '1' or status['olbc_ht'] != '1':
685         raise Exception("Missing OLBC information")
686
687     hostapd.remove_bss(apdev[1])
688
689     logger.info("Waiting for OLBC state to time out")
690     cleared = False
691     for i in range(0, 15):
692         time.sleep(1)
693         status = hapd.get_status()
694         if status['olbc'] == '0' and status['olbc_ht'] == '0':
695             cleared = True
696             break
697     if not cleared:
698         raise Exception("OLBC state did nto time out")
699
700 def test_olbc_table_limit(dev, apdev):
701     """OLBC AP table size limit"""
702     ifname1 = apdev[0]['ifname']
703     ifname2 = apdev[0]['ifname'] + '-2'
704     ifname3 = apdev[0]['ifname'] + '-3'
705     hostapd.add_bss(apdev[0], ifname1, 'bss-1.conf')
706     hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf')
707     hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf')
708
709     params = { "ssid": "test-olbc",
710                "channel": "1",
711                "ap_table_max_size": "2" }
712     hapd = hostapd.add_ap(apdev[1], params)
713
714     time.sleep(0.3)
715     with alloc_fail(hapd, 1, "ap_list_process_beacon"):
716         time.sleep(0.3)
717     hapd.set("ap_table_max_size", "1")
718     time.sleep(0.3)
719     hapd.set("ap_table_max_size", "0")
720     time.sleep(0.3)
721
722 def test_olbc_5ghz(dev, apdev):
723     """OLBC detection on 5 GHz"""
724     try:
725         hapd = None
726         hapd2 = None
727         params = { "ssid": "test-olbc",
728                    "country_code": "FI",
729                    "hw_mode": "a",
730                    "channel": "36",
731                    "ht_capab": "[HT40+]" }
732         hapd = hostapd.add_ap(apdev[0], params)
733         status = hapd.get_status()
734         if status['olbc'] != '0' or status['olbc_ht'] != '0':
735             raise Exception("Unexpected OLBC information")
736
737         params = { "ssid": "olbc-ap",
738                    "country_code": "FI",
739                    "hw_mode": "a",
740                    "channel": "36",
741                    "ieee80211n": "0",
742                    "wmm_enabled": "0" }
743         hapd2 = hostapd.add_ap(apdev[1], params)
744         found = False
745         for i in range(20):
746             time.sleep(0.1)
747             status = hapd.get_status()
748             logger.debug('olbc_ht: ' + status['olbc_ht'])
749             if status['olbc_ht'] == '1':
750                 found = True
751                 break
752         if not found:
753             raise Exception("Missing OLBC information")
754     finally:
755         if hapd:
756             hapd.request("DISABLE")
757         if hapd2:
758             hapd2.request("DISABLE")
759         subprocess.call(['iw', 'reg', 'set', '00'])
760
761 def test_ap_require_ht(dev, apdev):
762     """Require HT"""
763     params = { "ssid": "require-ht",
764                "require_ht": "1" }
765     hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
766
767     dev[1].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
768                    disable_ht="1", wait_connect=False)
769     dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412")
770     ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
771     dev[1].request("DISCONNECT")
772     if ev is None:
773         raise Exception("Association rejection timed out")
774     if "status_code=27" not in ev:
775         raise Exception("Unexpected rejection status code")
776     dev[2].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
777                    ht_mcs="0x01 00 00 00 00 00 00 00 00 00",
778                    disable_max_amsdu="1", ampdu_factor="2",
779                    ampdu_density="1", disable_ht40="1", disable_sgi="1",
780                    disable_ldpc="1")
781
782 def test_ap_require_ht_limited_rates(dev, apdev):
783     """Require HT with limited supported rates"""
784     params = { "ssid": "require-ht",
785                "supported_rates": "60 120 240 360 480 540",
786                "require_ht": "1" }
787     hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
788
789     dev[1].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
790                    disable_ht="1", wait_connect=False)
791     dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412")
792     ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
793     dev[1].request("DISCONNECT")
794     if ev is None:
795         raise Exception("Association rejection timed out")
796     if "status_code=27" not in ev:
797         raise Exception("Unexpected rejection status code")
798
799 def test_ap_ht_capab_not_supported(dev, apdev):
800     """HT configuration with driver not supporting all ht_capab entries"""
801     params = { "ssid": "test-ht40",
802                "channel": "5",
803                "ht_capab": "[HT40-][LDPC][SMPS-STATIC][SMPS-DYNAMIC][GF][SHORT-GI-20][SHORT-GI-40][TX-STBC][RX-STBC1][RX-STBC12][RX-STBC123][DELAYED-BA][MAX-AMSDU-7935][DSSS_CCK-40][LSIG-TXOP-PROT]"}
804     hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
805     if "FAIL" not in hapd.request("ENABLE"):
806         raise Exception("Unexpected ENABLE success")
807
808 def test_ap_ht_40mhz_intolerant_sta(dev, apdev):
809     """Associated STA indicating 40 MHz intolerant"""
810     clear_scan_cache(apdev[0])
811     params = { "ssid": "intolerant",
812                "channel": "6",
813                "ht_capab": "[HT40-]" }
814     hapd = hostapd.add_ap(apdev[0], params)
815     if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
816         raise Exception("Unexpected num_sta_ht40_intolerant value")
817     if hapd.get_status_field("secondary_channel") != "-1":
818         raise Exception("Unexpected secondary_channel")
819
820     dev[0].connect("intolerant", key_mgmt="NONE", scan_freq="2437")
821     if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
822         raise Exception("Unexpected num_sta_ht40_intolerant value")
823     if hapd.get_status_field("secondary_channel") != "-1":
824         raise Exception("Unexpected secondary_channel")
825
826     dev[2].connect("intolerant", key_mgmt="NONE", scan_freq="2437",
827                    ht40_intolerant="1")
828     time.sleep(1)
829     if hapd.get_status_field("num_sta_ht40_intolerant") != "1":
830         raise Exception("Unexpected num_sta_ht40_intolerant value (expected 1)")
831     if hapd.get_status_field("secondary_channel") != "0":
832         raise Exception("Unexpected secondary_channel (did not disable 40 MHz)")
833
834     dev[2].request("DISCONNECT")
835     time.sleep(1)
836     if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
837         raise Exception("Unexpected num_sta_ht40_intolerant value (expected 0)")
838     if hapd.get_status_field("secondary_channel") != "-1":
839         raise Exception("Unexpected secondary_channel (did not re-enable 40 MHz)")
840
841 def test_ap_ht_40mhz_intolerant_ap(dev, apdev):
842     """Associated STA reports 40 MHz intolerant AP after association"""
843     clear_scan_cache(apdev[0])
844     params = { "ssid": "ht",
845                "channel": "6",
846                "ht_capab": "[HT40-]",
847                "obss_interval": "3" }
848     hapd = hostapd.add_ap(apdev[0], params)
849
850     dev[0].connect("ht", key_mgmt="NONE", scan_freq="2437")
851
852     if hapd.get_status_field("secondary_channel") != "-1":
853         raise Exception("Unexpected secondary channel information")
854
855     logger.info("Start 40 MHz intolerant AP")
856     params = { "ssid": "intolerant",
857                "channel": "5",
858                "ht_capab": "[40-INTOLERANT]" }
859     hapd2 = hostapd.add_ap(apdev[1], params)
860
861     logger.info("Waiting for co-ex report from STA")
862     ok = False
863     for i in range(0, 20):
864         time.sleep(1)
865         if hapd.get_status_field("secondary_channel") == "0":
866             logger.info("AP moved to 20 MHz channel")
867             ok = True
868             break
869     if not ok:
870         raise Exception("AP did not move to 20 MHz channel")
871
872     if "OK" not in hapd2.request("DISABLE"):
873         raise Exception("Failed to disable 40 MHz intolerant AP")
874
875     # make sure the intolerant AP disappears from scan results more quickly
876     dev[0].scan(type="ONLY", freq="2432", only_new=True)
877     dev[0].scan(type="ONLY", freq="2432", only_new=True)
878     dev[0].dump_monitor()
879
880     logger.info("Waiting for AP to move back to 40 MHz channel")
881     ok = False
882     for i in range(0, 30):
883         time.sleep(1)
884         if hapd.get_status_field("secondary_channel") == "-1":
885             logger.info("AP moved to 40 MHz channel")
886             ok = True
887             break
888     if not ok:
889         raise Exception("AP did not move to 40 MHz channel")
890
891 def test_ap_ht40_csa(dev, apdev):
892     """HT with 40 MHz channel width and CSA"""
893     csa_supported(dev[0])
894     try:
895         hapd = None
896         params = { "ssid": "ht",
897                    "country_code": "US",
898                    "hw_mode": "a",
899                    "channel": "36",
900                    "ht_capab": "[HT40+]",
901                    "ieee80211n": "1" }
902         hapd = hostapd.add_ap(apdev[0], params)
903
904         dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
905         hwsim_utils.test_connectivity(dev[0], hapd)
906
907         hapd.request("CHAN_SWITCH 5 5200 ht sec_channel_offset=-1 bandwidth=40")
908         ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
909         if ev is None:
910             raise Exception("CSA finished event timed out")
911         if "freq=5200" not in ev:
912             raise Exception("Unexpected channel in CSA finished event")
913         ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
914         if ev is not None:
915             raise Exception("Unexpected STA disconnection during CSA")
916         hwsim_utils.test_connectivity(dev[0], hapd)
917
918         hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
919         ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
920         if ev is None:
921             raise Exception("CSA finished event timed out")
922         if "freq=5180" not in ev:
923             raise Exception("Unexpected channel in CSA finished event")
924         ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
925         if ev is not None:
926             raise Exception("Unexpected STA disconnection during CSA")
927         hwsim_utils.test_connectivity(dev[0], hapd)
928     finally:
929         dev[0].request("DISCONNECT")
930         if hapd:
931             hapd.request("DISABLE")
932         subprocess.call(['iw', 'reg', 'set', '00'])
933         dev[0].flush_scan_cache()
934
935 def test_ap_ht40_csa2(dev, apdev):
936     """HT with 40 MHz channel width and CSA"""
937     csa_supported(dev[0])
938     try:
939         hapd = None
940         params = { "ssid": "ht",
941                    "country_code": "US",
942                    "hw_mode": "a",
943                    "channel": "36",
944                    "ht_capab": "[HT40+]",
945                    "ieee80211n": "1" }
946         hapd = hostapd.add_ap(apdev[0], params)
947
948         dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
949         hwsim_utils.test_connectivity(dev[0], hapd)
950
951         hapd.request("CHAN_SWITCH 5 5220 ht sec_channel_offset=1 bandwidth=40")
952         ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
953         if ev is None:
954             raise Exception("CSA finished event timed out")
955         if "freq=5220" not in ev:
956             raise Exception("Unexpected channel in CSA finished event")
957         ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
958         if ev is not None:
959             raise Exception("Unexpected STA disconnection during CSA")
960         hwsim_utils.test_connectivity(dev[0], hapd)
961
962         hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
963         ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
964         if ev is None:
965             raise Exception("CSA finished event timed out")
966         if "freq=5180" not in ev:
967             raise Exception("Unexpected channel in CSA finished event")
968         ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
969         if ev is not None:
970             raise Exception("Unexpected STA disconnection during CSA")
971         hwsim_utils.test_connectivity(dev[0], hapd)
972     finally:
973         dev[0].request("DISCONNECT")
974         if hapd:
975             hapd.request("DISABLE")
976         subprocess.call(['iw', 'reg', 'set', '00'])
977         dev[0].flush_scan_cache()
978
979 def test_ap_ht40_csa3(dev, apdev):
980     """HT with 40 MHz channel width and CSA"""
981     csa_supported(dev[0])
982     try:
983         hapd = None
984         params = { "ssid": "ht",
985                    "country_code": "US",
986                    "hw_mode": "a",
987                    "channel": "36",
988                    "ht_capab": "[HT40+]",
989                    "ieee80211n": "1" }
990         hapd = hostapd.add_ap(apdev[0], params)
991
992         dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
993         hwsim_utils.test_connectivity(dev[0], hapd)
994
995         hapd.request("CHAN_SWITCH 5 5240 ht sec_channel_offset=-1 bandwidth=40")
996         ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
997         if ev is None:
998             raise Exception("CSA finished event timed out")
999         if "freq=5240" not in ev:
1000             raise Exception("Unexpected channel in CSA finished event")
1001         ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
1002         if ev is not None:
1003             raise Exception("Unexpected STA disconnection during CSA")
1004         hwsim_utils.test_connectivity(dev[0], hapd)
1005
1006         hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
1007         ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
1008         if ev is None:
1009             raise Exception("CSA finished event timed out")
1010         if "freq=5180" not in ev:
1011             raise Exception("Unexpected channel in CSA finished event")
1012         ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
1013         if ev is not None:
1014             raise Exception("Unexpected STA disconnection during CSA")
1015         hwsim_utils.test_connectivity(dev[0], hapd)
1016     finally:
1017         dev[0].request("DISCONNECT")
1018         if hapd:
1019             hapd.request("DISABLE")
1020         subprocess.call(['iw', 'reg', 'set', '00'])
1021         dev[0].flush_scan_cache()
1022
1023 def test_ap_ht_smps(dev, apdev):
1024     """SMPS AP configuration options"""
1025     params = { "ssid": "ht1", "ht_capab": "[SMPS-STATIC]" }
1026     try:
1027         hapd = hostapd.add_ap(apdev[0], params)
1028     except:
1029         raise HwsimSkip("Assume mac80211_hwsim was not recent enough to support SMPS")
1030     params = { "ssid": "ht2", "ht_capab": "[SMPS-DYNAMIC]" }
1031     hapd2 = hostapd.add_ap(apdev[1], params)
1032
1033     dev[0].connect("ht1", key_mgmt="NONE", scan_freq="2412")
1034     dev[1].connect("ht2", key_mgmt="NONE", scan_freq="2412")
1035     hwsim_utils.test_connectivity(dev[0], hapd)
1036     hwsim_utils.test_connectivity(dev[1], hapd2)
1037
1038 def test_prefer_ht20(dev, apdev):
1039     """Preference on HT20 over no-HT"""
1040     params = { "ssid": "test",
1041                "channel": "1",
1042                "ieee80211n": "0" }
1043     hapd = hostapd.add_ap(apdev[0], params)
1044     bssid = apdev[0]['bssid']
1045     params = { "ssid": "test",
1046                "channel": "1",
1047                "ieee80211n": "1" }
1048     hapd2 = hostapd.add_ap(apdev[1], params)
1049     bssid2 = apdev[1]['bssid']
1050
1051     dev[0].scan_for_bss(bssid, freq=2412)
1052     dev[0].scan_for_bss(bssid2, freq=2412)
1053     dev[0].connect("test", key_mgmt="NONE", scan_freq="2412")
1054     if dev[0].get_status_field('bssid') != bssid2:
1055         raise Exception("Unexpected BSS selected")
1056
1057     est = dev[0].get_bss(bssid)['est_throughput']
1058     if est != "54000":
1059         raise Exception("Unexpected BSS0 est_throughput: " + est)
1060
1061     est = dev[0].get_bss(bssid2)['est_throughput']
1062     if est != "65000":
1063         raise Exception("Unexpected BSS1 est_throughput: " + est)
1064
1065 def test_prefer_ht40(dev, apdev):
1066     """Preference on HT40 over HT20"""
1067     params = { "ssid": "test",
1068                "channel": "1",
1069                "ieee80211n": "1" }
1070     hapd = hostapd.add_ap(apdev[0], params)
1071     bssid = apdev[0]['bssid']
1072     params = { "ssid": "test",
1073                "channel": "1",
1074                "ieee80211n": "1",
1075                "ht_capab": "[HT40+]" }
1076     hapd2 = hostapd.add_ap(apdev[1], params)
1077     bssid2 = apdev[1]['bssid']
1078
1079     dev[0].scan_for_bss(bssid, freq=2412)
1080     dev[0].scan_for_bss(bssid2, freq=2412)
1081     dev[0].connect("test", key_mgmt="NONE", scan_freq="2412")
1082     if dev[0].get_status_field('bssid') != bssid2:
1083         raise Exception("Unexpected BSS selected")
1084
1085     est = dev[0].get_bss(bssid)['est_throughput']
1086     if est != "65000":
1087         raise Exception("Unexpected BSS0 est_throughput: " + est)
1088
1089     est = dev[0].get_bss(bssid2)['est_throughput']
1090     if est != "135000":
1091         raise Exception("Unexpected BSS1 est_throughput: " + est)
1092
1093 def test_prefer_ht20_during_roam(dev, apdev):
1094     """Preference on HT20 over no-HT in roaming consideration"""
1095     params = { "ssid": "test",
1096                "channel": "1",
1097                "ieee80211n": "0" }
1098     hapd = hostapd.add_ap(apdev[0], params)
1099     bssid = apdev[0]['bssid']
1100
1101     dev[0].scan_for_bss(bssid, freq=2412)
1102     dev[0].connect("test", key_mgmt="NONE", scan_freq="2412")
1103
1104     params = { "ssid": "test",
1105                "channel": "1",
1106                "ieee80211n": "1" }
1107     hapd2 = hostapd.add_ap(apdev[1], params)
1108     bssid2 = apdev[1]['bssid']
1109     dev[0].scan_for_bss(bssid2, freq=2412)
1110     dev[0].scan(freq=2412)
1111     dev[0].wait_connected()
1112
1113     if dev[0].get_status_field('bssid') != bssid2:
1114         raise Exception("Unexpected BSS selected")
1115
1116 def test_ap_ht40_5ghz_invalid_pair(dev, apdev):
1117     """HT40 on 5 GHz with invalid channel pair"""
1118     clear_scan_cache(apdev[0])
1119     try:
1120         params = { "ssid": "test-ht40",
1121                    "hw_mode": "a",
1122                    "channel": "40",
1123                    "country_code": "US",
1124                    "ht_capab": "[HT40+]"}
1125         hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
1126         ev = hapd.wait_event(["AP-DISABLED", "AP-ENABLED"], timeout=10)
1127         if not ev:
1128             raise Exception("AP setup failure timed out")
1129         if "AP-ENABLED" in ev:
1130             sec = hapd.get_status_field("secondary_channel")
1131             if sec != "0":
1132                 raise Exception("Invalid 40 MHz channel accepted")
1133     finally:
1134         subprocess.call(['iw', 'reg', 'set', '00'])
1135
1136 def test_ap_ht40_5ghz_disabled_sec(dev, apdev):
1137     """HT40 on 5 GHz with disabled secondary channel"""
1138     clear_scan_cache(apdev[0])
1139     try:
1140         params = { "ssid": "test-ht40",
1141                    "hw_mode": "a",
1142                    "channel": "48",
1143                    "country_code": "US",
1144                    "ht_capab": "[HT40+]"}
1145         hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
1146         ev = hapd.wait_event(["AP-DISABLED", "AP-ENABLED"], timeout=10)
1147         if not ev:
1148             raise Exception("AP setup failure timed out")
1149         if "AP-ENABLED" in ev:
1150             sec = hapd.get_status_field("secondary_channel")
1151             if sec != "0":
1152                 raise Exception("Invalid 40 MHz channel accepted")
1153     finally:
1154         subprocess.call(['iw', 'reg', 'set', '00'])
1155
1156 def test_ap_ht40_scan_broken_ap(dev, apdev):
1157     """HT40 co-ex scan and broken legacy/HT AP"""
1158     clear_scan_cache(apdev[0])
1159
1160     # Broken AP: Include HT Capabilities element but not HT Operation element
1161     params = { "ssid": "legacy-20",
1162                "channel": "7", "ieee80211n": "0",
1163                "wmm_enabled": "1",
1164                "vendor_elements": "2d1a0e001bffff000000000000000000000100000000000000000000" }
1165     hapd2 = hostapd.add_ap(apdev[1], params)
1166
1167     params = { "ssid": "test-ht40",
1168                "channel": "5",
1169                "ht_capab": "[HT40-]"}
1170     hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
1171
1172     state = hapd.get_status_field("state")
1173     if state != "HT_SCAN":
1174         time.sleep(0.1)
1175         state = hapd.get_status_field("state")
1176         if state != "HT_SCAN":
1177             raise Exception("Unexpected interface state - expected HT_SCAN")
1178
1179     ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
1180     if not ev:
1181         raise Exception("AP setup timed out")
1182
1183     state = hapd.get_status_field("state")
1184     if state != "ENABLED":
1185         raise Exception("Unexpected interface state - expected ENABLED")
1186
1187     freq = hapd.get_status_field("freq")
1188     if freq != "2432":
1189         raise Exception("Unexpected frequency: " + freq)
1190     pri = hapd.get_status_field("channel")
1191     if pri != "5":
1192         raise Exception("Unexpected primary channel: " + pri)
1193     sec = hapd.get_status_field("secondary_channel")
1194     if sec != "-1":
1195         raise Exception("Unexpected secondary channel: " + sec)
1196
1197     dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
1198     dev[1].connect("legacy-20", key_mgmt="NONE", scan_freq="2442")
1199     hwsim_utils.test_connectivity(dev[0], hapd)
1200     hwsim_utils.test_connectivity(dev[1], hapd2)