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