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