tests: Fix ap_ht_40mhz_intolerant_ap
[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 import hwsim_utils
15 from test_ap_csa import csa_supported
16
17 def clear_scan_cache(ifname):
18     subprocess.call(['sudo', 'ifconfig', ifname, 'up'])
19     subprocess.call(['sudo', 'iw', ifname, 'scan', 'freq', '2412', 'flush'])
20     time.sleep(0.1)
21     subprocess.call(['sudo', 'ifconfig', ifname, 'down'])
22
23 def test_ap_ht40_scan(dev, apdev):
24     """HT40 co-ex scan"""
25     clear_scan_cache(apdev[0]['ifname'])
26     params = { "ssid": "test-ht40",
27                "channel": "5",
28                "ht_capab": "[HT40-]"}
29     hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
30
31     state = hapd.get_status_field("state")
32     if state != "HT_SCAN":
33         time.sleep(0.1)
34         state = hapd.get_status_field("state")
35         if state != "HT_SCAN":
36             raise Exception("Unexpected interface state - expected HT_SCAN")
37
38     ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
39     if not ev:
40         raise Exception("AP setup timed out")
41
42     state = hapd.get_status_field("state")
43     if state != "ENABLED":
44         raise Exception("Unexpected interface state - expected ENABLED")
45
46     freq = hapd.get_status_field("freq")
47     if freq != "2432":
48         raise Exception("Unexpected frequency")
49     pri = hapd.get_status_field("channel")
50     if pri != "5":
51         raise Exception("Unexpected primary channel")
52     sec = hapd.get_status_field("secondary_channel")
53     if sec != "-1":
54         raise Exception("Unexpected secondary channel")
55
56     dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
57
58 def test_ap_ht40_scan_conflict(dev, apdev):
59     """HT40 co-ex scan conflict"""
60     clear_scan_cache(apdev[0]['ifname'])
61     params = { "ssid": "test-ht40",
62                "channel": "6",
63                "ht_capab": "[HT40+]"}
64     hostapd.add_ap(apdev[1]['ifname'], params)
65
66     params = { "ssid": "test-ht40",
67                "channel": "5",
68                "ht_capab": "[HT40-]"}
69     hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
70
71     state = hapd.get_status_field("state")
72     if state != "HT_SCAN":
73         time.sleep(0.1)
74         state = hapd.get_status_field("state")
75         if state != "HT_SCAN":
76             raise Exception("Unexpected interface state - expected HT_SCAN")
77
78     ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
79     if not ev:
80         raise Exception("AP setup timed out")
81
82     state = hapd.get_status_field("state")
83     if state != "ENABLED":
84         raise Exception("Unexpected interface state - expected ENABLED")
85
86     freq = hapd.get_status_field("freq")
87     if freq != "2432":
88         raise Exception("Unexpected frequency")
89     pri = hapd.get_status_field("channel")
90     if pri != "5":
91         raise Exception("Unexpected primary channel")
92     sec = hapd.get_status_field("secondary_channel")
93     if sec != "0":
94         raise Exception("Unexpected secondary channel: " + sec)
95
96     dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
97
98 def test_ap_ht40_scan_legacy_conflict(dev, apdev):
99     """HT40 co-ex scan conflict with legacy 20 MHz AP"""
100     clear_scan_cache(apdev[0]['ifname'])
101     params = { "ssid": "legacy-20",
102                "channel": "7", "ieee80211n": "0" }
103     hostapd.add_ap(apdev[1]['ifname'], params)
104
105     params = { "ssid": "test-ht40",
106                "channel": "5",
107                "ht_capab": "[HT40-]"}
108     hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
109
110     state = hapd.get_status_field("state")
111     if state != "HT_SCAN":
112         time.sleep(0.1)
113         state = hapd.get_status_field("state")
114         if state != "HT_SCAN":
115             raise Exception("Unexpected interface state - expected HT_SCAN")
116
117     ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
118     if not ev:
119         raise Exception("AP setup timed out")
120
121     state = hapd.get_status_field("state")
122     if state != "ENABLED":
123         raise Exception("Unexpected interface state - expected ENABLED")
124
125     freq = hapd.get_status_field("freq")
126     if freq != "2432":
127         raise Exception("Unexpected frequency: " + freq)
128     pri = hapd.get_status_field("channel")
129     if pri != "5":
130         raise Exception("Unexpected primary channel: " + pri)
131     sec = hapd.get_status_field("secondary_channel")
132     if sec != "0":
133         raise Exception("Unexpected secondary channel: " + sec)
134
135     dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
136
137 def test_ap_ht40_scan_match(dev, apdev):
138     """HT40 co-ex scan matching configuration"""
139     clear_scan_cache(apdev[0]['ifname'])
140     params = { "ssid": "test-ht40",
141                "channel": "5",
142                "ht_capab": "[HT40-]"}
143     hostapd.add_ap(apdev[1]['ifname'], params)
144
145     params = { "ssid": "test-ht40",
146                "channel": "5",
147                "ht_capab": "[HT40-]"}
148     hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
149
150     state = hapd.get_status_field("state")
151     if state != "HT_SCAN":
152         time.sleep(0.1)
153         state = hapd.get_status_field("state")
154         if state != "HT_SCAN":
155             raise Exception("Unexpected interface state - expected HT_SCAN")
156
157     ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
158     if not ev:
159         raise Exception("AP setup timed out")
160
161     state = hapd.get_status_field("state")
162     if state != "ENABLED":
163         raise Exception("Unexpected interface state - expected ENABLED")
164
165     freq = hapd.get_status_field("freq")
166     if freq != "2432":
167         raise Exception("Unexpected frequency")
168     pri = hapd.get_status_field("channel")
169     if pri != "5":
170         raise Exception("Unexpected primary channel")
171     sec = hapd.get_status_field("secondary_channel")
172     if sec != "-1":
173         raise Exception("Unexpected secondary channel: " + sec)
174
175     dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
176
177 def test_ap_ht40_5ghz_match(dev, apdev):
178     """HT40 co-ex scan on 5 GHz with matching pri/sec channel"""
179     clear_scan_cache(apdev[0]['ifname'])
180     try:
181         hapd = None
182         hapd2 = None
183         params = { "ssid": "test-ht40",
184                    "hw_mode": "a",
185                    "channel": "36",
186                    "country_code": "US",
187                    "ht_capab": "[HT40+]"}
188         hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
189
190         params = { "ssid": "test-ht40",
191                    "hw_mode": "a",
192                    "channel": "36",
193                    "ht_capab": "[HT40+]"}
194         hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
195
196         state = hapd.get_status_field("state")
197         if state != "HT_SCAN":
198             time.sleep(0.1)
199             state = hapd.get_status_field("state")
200             if state != "HT_SCAN":
201                 raise Exception("Unexpected interface state - expected HT_SCAN")
202
203         ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
204         if not ev:
205             raise Exception("AP setup timed out")
206
207         state = hapd.get_status_field("state")
208         if state != "ENABLED":
209             raise Exception("Unexpected interface state - expected ENABLED")
210
211         freq = hapd.get_status_field("freq")
212         if freq != "5180":
213             raise Exception("Unexpected frequency")
214         pri = hapd.get_status_field("channel")
215         if pri != "36":
216             raise Exception("Unexpected primary channel")
217         sec = hapd.get_status_field("secondary_channel")
218         if sec != "1":
219             raise Exception("Unexpected secondary channel: " + sec)
220
221         dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
222     finally:
223         dev[0].request("DISCONNECT")
224         if hapd:
225             hapd.request("DISABLE")
226         if hapd2:
227             hapd2.request("DISABLE")
228         subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
229         dev[0].flush_scan_cache()
230
231 def test_ap_ht40_5ghz_switch(dev, apdev):
232     """HT40 co-ex scan on 5 GHz switching pri/sec channel"""
233     clear_scan_cache(apdev[0]['ifname'])
234     try:
235         hapd = None
236         hapd2 = None
237         params = { "ssid": "test-ht40",
238                    "hw_mode": "a",
239                    "channel": "36",
240                    "country_code": "US",
241                    "ht_capab": "[HT40+]"}
242         hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
243
244         params = { "ssid": "test-ht40",
245                    "hw_mode": "a",
246                    "channel": "40",
247                    "ht_capab": "[HT40-]"}
248         hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
249
250         state = hapd.get_status_field("state")
251         if state != "HT_SCAN":
252             time.sleep(0.1)
253             state = hapd.get_status_field("state")
254             if state != "HT_SCAN":
255                 raise Exception("Unexpected interface state - expected HT_SCAN")
256
257         ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
258         if not ev:
259             raise Exception("AP setup timed out")
260
261         state = hapd.get_status_field("state")
262         if state != "ENABLED":
263             raise Exception("Unexpected interface state - expected ENABLED")
264
265         freq = hapd.get_status_field("freq")
266         if freq != "5180":
267             raise Exception("Unexpected frequency: " + freq)
268         pri = hapd.get_status_field("channel")
269         if pri != "36":
270             raise Exception("Unexpected primary channel: " + pri)
271         sec = hapd.get_status_field("secondary_channel")
272         if sec != "1":
273             raise Exception("Unexpected secondary channel: " + sec)
274
275         dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
276     finally:
277         dev[0].request("DISCONNECT")
278         if hapd:
279             hapd.request("DISABLE")
280         if hapd2:
281             hapd2.request("DISABLE")
282         subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
283
284 def test_ap_ht40_5ghz_switch2(dev, apdev):
285     """HT40 co-ex scan on 5 GHz switching pri/sec channel (2)"""
286     clear_scan_cache(apdev[0]['ifname'])
287     try:
288         hapd = None
289         hapd2 = None
290         params = { "ssid": "test-ht40",
291                    "hw_mode": "a",
292                    "channel": "36",
293                    "country_code": "US",
294                    "ht_capab": "[HT40+]"}
295         hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
296
297         id = dev[0].add_network()
298         dev[0].set_network(id, "mode", "2")
299         dev[0].set_network_quoted(id, "ssid", "wpas-ap-open")
300         dev[0].set_network(id, "key_mgmt", "NONE")
301         dev[0].set_network(id, "frequency", "5200")
302         dev[0].set_network(id, "scan_freq", "5200")
303         dev[0].select_network(id)
304         time.sleep(1)
305
306         params = { "ssid": "test-ht40",
307                    "hw_mode": "a",
308                    "channel": "40",
309                    "ht_capab": "[HT40-]"}
310         hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
311
312         state = hapd.get_status_field("state")
313         if state != "HT_SCAN":
314             time.sleep(0.1)
315             state = hapd.get_status_field("state")
316             if state != "HT_SCAN":
317                 raise Exception("Unexpected interface state - expected HT_SCAN")
318
319         ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
320         if not ev:
321             raise Exception("AP setup timed out")
322
323         state = hapd.get_status_field("state")
324         if state != "ENABLED":
325             raise Exception("Unexpected interface state - expected ENABLED")
326
327         freq = hapd.get_status_field("freq")
328         if freq != "5180":
329             raise Exception("Unexpected frequency: " + freq)
330         pri = hapd.get_status_field("channel")
331         if pri != "36":
332             raise Exception("Unexpected primary channel: " + pri)
333         sec = hapd.get_status_field("secondary_channel")
334         if sec != "1":
335             raise Exception("Unexpected secondary channel: " + sec)
336
337         dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
338     finally:
339         dev[0].request("DISCONNECT")
340         if hapd:
341             hapd.request("DISABLE")
342         if hapd2:
343             hapd2.request("DISABLE")
344         subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
345         dev[0].flush_scan_cache()
346
347 def test_obss_scan(dev, apdev):
348     """Overlapping BSS scan request"""
349     params = { "ssid": "obss-scan",
350                "channel": "6",
351                "ht_capab": "[HT40-]",
352                "obss_interval": "10" }
353     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
354
355     params = { "ssid": "another-bss",
356                "channel": "9",
357                "ieee80211n": "0" }
358     hostapd.add_ap(apdev[1]['ifname'], params)
359
360     dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
361     hapd.set("ext_mgmt_frame_handling", "1")
362     logger.info("Waiting for OBSS scan to occur")
363     ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=15)
364     if ev is None:
365         raise Exception("Timed out while waiting for OBSS scan to start")
366     ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
367     if ev is None:
368         raise Exception("Timed out while waiting for OBSS scan results")
369     received = False
370     for i in range(0, 4):
371         frame = hapd.mgmt_rx(timeout=5)
372         if frame is None:
373             raise Exception("MGMT RX wait timed out")
374         if frame['subtype'] != 13:
375             continue
376         payload = frame['payload']
377         if len(payload) < 3:
378             continue
379         (category, action, ie) = struct.unpack('BBB', payload[0:3])
380         if category != 4:
381             continue
382         if action != 0:
383             continue
384         if ie == 72:
385             logger.info("20/40 BSS Coexistence report received")
386             received = True
387             break
388     if not received:
389         raise Exception("20/40 BSS Coexistence report not seen")
390
391 def test_obss_scan_40_intolerant(dev, apdev):
392     """Overlapping BSS scan request with 40 MHz intolerant AP"""
393     params = { "ssid": "obss-scan",
394                "channel": "6",
395                "ht_capab": "[HT40-]",
396                "obss_interval": "10" }
397     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
398
399     params = { "ssid": "another-bss",
400                "channel": "7",
401                "ht_capab": "[40-INTOLERANT]" }
402     hostapd.add_ap(apdev[1]['ifname'], params)
403
404     dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
405     hapd.set("ext_mgmt_frame_handling", "1")
406     logger.info("Waiting for OBSS scan to occur")
407     ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=15)
408     if ev is None:
409         raise Exception("Timed out while waiting for OBSS scan to start")
410     ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
411     if ev is None:
412         raise Exception("Timed out while waiting for OBSS scan results")
413     received = False
414     for i in range(0, 4):
415         frame = hapd.mgmt_rx(timeout=5)
416         if frame is None:
417             raise Exception("MGMT RX wait timed out")
418         if frame['subtype'] != 13:
419             continue
420         payload = frame['payload']
421         if len(payload) < 3:
422             continue
423         (category, action, ie) = struct.unpack('BBB', payload[0:3])
424         if category != 4:
425             continue
426         if action != 0:
427             continue
428         if ie == 72:
429             logger.info("20/40 BSS Coexistence report received")
430             received = True
431             break
432     if not received:
433         raise Exception("20/40 BSS Coexistence report not seen")
434
435 def test_olbc(dev, apdev):
436     """OLBC detection"""
437     params = { "ssid": "test-olbc",
438                "channel": "6",
439                "ht_capab": "[HT40-]",
440                "ap_table_expiration_time": "2" }
441     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
442     status = hapd.get_status()
443     if status['olbc'] != '0' or status['olbc_ht'] != '0':
444         raise Exception("Unexpected OLBC information")
445
446     params = { "ssid": "olbc-ap",
447                "hw_mode": "b",
448                "channel": "6",
449                "wmm_enabled": "0" }
450     hostapd.add_ap(apdev[1]['ifname'], params)
451     time.sleep(0.5)
452     status = hapd.get_status()
453     if status['olbc'] != '1' or status['olbc_ht'] != '1':
454         raise Exception("Missing OLBC information")
455
456     hapd_global = hostapd.HostapdGlobal()
457     hapd_global.remove(apdev[1]['ifname'])
458
459     logger.info("Waiting for OLBC state to time out")
460     cleared = False
461     for i in range(0, 15):
462         time.sleep(1)
463         status = hapd.get_status()
464         if status['olbc'] == '0' and status['olbc_ht'] == '0':
465             cleared = True
466             break
467     if not cleared:
468         raise Exception("OLBC state did nto time out")
469
470 def test_olbc_5ghz(dev, apdev):
471     """OLBC detection on 5 GHz"""
472     try:
473         hapd = None
474         hapd2 = None
475         params = { "ssid": "test-olbc",
476                    "country_code": "FI",
477                    "hw_mode": "a",
478                    "channel": "36",
479                    "ht_capab": "[HT40+]" }
480         hapd = hostapd.add_ap(apdev[0]['ifname'], params)
481         status = hapd.get_status()
482         if status['olbc'] != '0' or status['olbc_ht'] != '0':
483             raise Exception("Unexpected OLBC information")
484
485         params = { "ssid": "olbc-ap",
486                    "country_code": "FI",
487                    "hw_mode": "a",
488                    "channel": "36",
489                    "ieee80211n": "0",
490                    "wmm_enabled": "0" }
491         hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
492         time.sleep(0.5)
493         status = hapd.get_status()
494         if status['olbc_ht'] != '1':
495             raise Exception("Missing OLBC information")
496     finally:
497         if hapd:
498             hapd.request("DISABLE")
499         if hapd2:
500             hapd2.request("DISABLE")
501         subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
502
503 def test_ap_require_ht(dev, apdev):
504     """Require HT"""
505     params = { "ssid": "require-ht",
506                "require_ht": "1" }
507     hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
508
509     dev[1].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
510                    disable_ht="1", wait_connect=False)
511     dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412")
512     ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
513     if ev is None:
514         raise Exception("Association rejection timed out")
515     if "status_code=27" not in ev:
516         raise Exception("Unexpected rejection status code")
517     dev[2].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
518                    ht_mcs="0x01 00 00 00 00 00 00 00 00 00",
519                    disable_max_amsdu="1", ampdu_factor="2",
520                    ampdu_density="1", disable_ht40="1", disable_sgi="1",
521                    disable_ldpc="1")
522
523 def test_ap_require_ht_limited_rates(dev, apdev):
524     """Require HT with limited supported rates"""
525     params = { "ssid": "require-ht",
526                "supported_rates": "60 120 240 360 480 540",
527                "require_ht": "1" }
528     hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
529
530     dev[1].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
531                    disable_ht="1", wait_connect=False)
532     dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412")
533     ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
534     if ev is None:
535         raise Exception("Association rejection timed out")
536     if "status_code=27" not in ev:
537         raise Exception("Unexpected rejection status code")
538
539 def test_ap_ht_capab_not_supported(dev, apdev):
540     """HT configuration with driver not supporting all ht_capab entries"""
541     params = { "ssid": "test-ht40",
542                "channel": "5",
543                "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]"}
544     hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
545     if "FAIL" not in hapd.request("ENABLE"):
546         raise Exception("Unexpected ENABLE success")
547
548 def test_ap_ht_40mhz_intolerant_sta(dev, apdev):
549     """Associated STA indicating 40 MHz intolerant"""
550     clear_scan_cache(apdev[0]['ifname'])
551     params = { "ssid": "intolerant",
552                "channel": "6",
553                "ht_capab": "[HT40-]" }
554     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
555     if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
556         raise Exception("Unexpected num_sta_ht40_intolerant value")
557     if hapd.get_status_field("secondary_channel") != "-1":
558         raise Exception("Unexpected secondary_channel")
559
560     dev[0].connect("intolerant", key_mgmt="NONE", scan_freq="2437")
561     if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
562         raise Exception("Unexpected num_sta_ht40_intolerant value")
563     if hapd.get_status_field("secondary_channel") != "-1":
564         raise Exception("Unexpected secondary_channel")
565
566     dev[2].connect("intolerant", key_mgmt="NONE", scan_freq="2437",
567                    ht40_intolerant="1")
568     time.sleep(1)
569     if hapd.get_status_field("num_sta_ht40_intolerant") != "1":
570         raise Exception("Unexpected num_sta_ht40_intolerant value (expected 1)")
571     if hapd.get_status_field("secondary_channel") != "0":
572         raise Exception("Unexpected secondary_channel (did not disable 40 MHz)")
573
574     dev[2].request("DISCONNECT")
575     time.sleep(1)
576     if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
577         raise Exception("Unexpected num_sta_ht40_intolerant value (expected 0)")
578     if hapd.get_status_field("secondary_channel") != "-1":
579         raise Exception("Unexpected secondary_channel (did not re-enable 40 MHz)")
580
581 def test_ap_ht_40mhz_intolerant_ap(dev, apdev):
582     """Associated STA reports 40 MHz intolerant AP after association"""
583     clear_scan_cache(apdev[0]['ifname'])
584     params = { "ssid": "ht",
585                "channel": "6",
586                "ht_capab": "[HT40-]",
587                "obss_interval": "3" }
588     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
589
590     dev[0].connect("ht", key_mgmt="NONE", scan_freq="2437")
591
592     if hapd.get_status_field("secondary_channel") != "-1":
593         raise Exception("Unexpected secondary channel information")
594
595     logger.info("Start 40 MHz intolerant AP")
596     params = { "ssid": "intolerant",
597                "channel": "5",
598                "ht_capab": "[40-INTOLERANT]" }
599     hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
600
601     logger.info("Waiting for co-ex report from STA")
602     ok = False
603     for i in range(0, 20):
604         time.sleep(1)
605         if hapd.get_status_field("secondary_channel") == "0":
606             logger.info("AP moved to 20 MHz channel")
607             ok = True
608             break
609     if not ok:
610         raise Exception("AP did not move to 20 MHz channel")
611
612     if "OK" not in hapd2.request("DISABLE"):
613         raise Exception("Failed to disable 40 MHz intolerant AP")
614
615     # make sure the intolerant AP disappears from scan results more quickly
616     dev[0].scan(type="ONLY", freq="2432", only_new=True)
617     dev[0].scan(type="ONLY", freq="2432", only_new=True)
618     dev[0].dump_monitor()
619
620     logger.info("Waiting for AP to move back to 40 MHz channel")
621     ok = False
622     for i in range(0, 30):
623         time.sleep(1)
624         if hapd.get_status_field("secondary_channel") == "-1":
625             logger.info("AP moved to 40 MHz channel")
626             ok = True
627             break
628     if not ok:
629         raise Exception("AP did not move to 40 MHz channel")
630
631 def test_ap_ht40_csa(dev, apdev):
632     """HT with 40 MHz channel width and CSA"""
633     if not csa_supported(dev[0]):
634         return "skip"
635     try:
636         hapd = None
637         params = { "ssid": "ht",
638                    "country_code": "US",
639                    "hw_mode": "a",
640                    "channel": "36",
641                    "ht_capab": "[HT40+]",
642                    "ieee80211n": "1" }
643         hapd = hostapd.add_ap(apdev[0]['ifname'], params)
644
645         dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
646         hwsim_utils.test_connectivity(dev[0], hapd)
647
648         hapd.request("CHAN_SWITCH 5 5200 ht sec_channel_offset=-1 bandwidth=40")
649         ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
650         if ev is None:
651             raise Exception("CSA finished event timed out")
652         if "freq=5200" not in ev:
653             raise Exception("Unexpected channel in CSA finished event")
654         ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
655         if ev is not None:
656             raise Exception("Unexpected STA disconnection during CSA")
657         hwsim_utils.test_connectivity(dev[0], hapd)
658
659         hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
660         ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
661         if ev is None:
662             raise Exception("CSA finished event timed out")
663         if "freq=5180" not in ev:
664             raise Exception("Unexpected channel in CSA finished event")
665         ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
666         if ev is not None:
667             raise Exception("Unexpected STA disconnection during CSA")
668         hwsim_utils.test_connectivity(dev[0], hapd)
669     finally:
670         dev[0].request("DISCONNECT")
671         if hapd:
672             hapd.request("DISABLE")
673         subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
674         dev[0].flush_scan_cache()
675
676 def test_ap_ht40_csa2(dev, apdev):
677     """HT with 40 MHz channel width and CSA"""
678     if not csa_supported(dev[0]):
679         return "skip"
680     try:
681         hapd = None
682         params = { "ssid": "ht",
683                    "country_code": "US",
684                    "hw_mode": "a",
685                    "channel": "36",
686                    "ht_capab": "[HT40+]",
687                    "ieee80211n": "1" }
688         hapd = hostapd.add_ap(apdev[0]['ifname'], params)
689
690         dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
691         hwsim_utils.test_connectivity(dev[0], hapd)
692
693         hapd.request("CHAN_SWITCH 5 5220 ht sec_channel_offset=1 bandwidth=40")
694         ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
695         if ev is None:
696             raise Exception("CSA finished event timed out")
697         if "freq=5220" not in ev:
698             raise Exception("Unexpected channel in CSA finished event")
699         ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
700         if ev is not None:
701             raise Exception("Unexpected STA disconnection during CSA")
702         hwsim_utils.test_connectivity(dev[0], hapd)
703
704         hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
705         ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
706         if ev is None:
707             raise Exception("CSA finished event timed out")
708         if "freq=5180" not in ev:
709             raise Exception("Unexpected channel in CSA finished event")
710         ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
711         if ev is not None:
712             raise Exception("Unexpected STA disconnection during CSA")
713         hwsim_utils.test_connectivity(dev[0], hapd)
714     finally:
715         dev[0].request("DISCONNECT")
716         if hapd:
717             hapd.request("DISABLE")
718         subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
719         dev[0].flush_scan_cache()
720
721 def test_ap_ht40_csa3(dev, apdev):
722     """HT with 40 MHz channel width and CSA"""
723     if not csa_supported(dev[0]):
724         return "skip"
725     try:
726         hapd = None
727         params = { "ssid": "ht",
728                    "country_code": "US",
729                    "hw_mode": "a",
730                    "channel": "36",
731                    "ht_capab": "[HT40+]",
732                    "ieee80211n": "1" }
733         hapd = hostapd.add_ap(apdev[0]['ifname'], params)
734
735         dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
736         hwsim_utils.test_connectivity(dev[0], hapd)
737
738         hapd.request("CHAN_SWITCH 5 5240 ht sec_channel_offset=-1 bandwidth=40")
739         ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
740         if ev is None:
741             raise Exception("CSA finished event timed out")
742         if "freq=5240" not in ev:
743             raise Exception("Unexpected channel in CSA finished event")
744         ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
745         if ev is not None:
746             raise Exception("Unexpected STA disconnection during CSA")
747         hwsim_utils.test_connectivity(dev[0], hapd)
748
749         hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
750         ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
751         if ev is None:
752             raise Exception("CSA finished event timed out")
753         if "freq=5180" not in ev:
754             raise Exception("Unexpected channel in CSA finished event")
755         ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
756         if ev is not None:
757             raise Exception("Unexpected STA disconnection during CSA")
758         hwsim_utils.test_connectivity(dev[0], hapd)
759     finally:
760         dev[0].request("DISCONNECT")
761         if hapd:
762             hapd.request("DISABLE")
763         subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
764         dev[0].flush_scan_cache()
765
766 def test_ap_ht_smps(dev, apdev):
767     """SMPS AP configuration options"""
768     params = { "ssid": "ht1", "ht_capab": "[SMPS-STATIC]" }
769     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
770     params = { "ssid": "ht2", "ht_capab": "[SMPS-DYNAMIC]" }
771     hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
772
773     dev[0].connect("ht1", key_mgmt="NONE", scan_freq="2412")
774     dev[1].connect("ht2", key_mgmt="NONE", scan_freq="2412")
775     hwsim_utils.test_connectivity(dev[0], hapd)
776     hwsim_utils.test_connectivity(dev[1], hapd2)