1 # Test cases for HT operations with hostapd
2 # Copyright (c) 2013-2014, Jouni Malinen <j@w1.fi>
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
9 logger = logging.getLogger()
14 from utils import HwsimSkip, alloc_fail
16 from test_ap_csa import csa_supported
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'])
23 subprocess.call(['ifconfig', ifname, 'down'])
25 def test_ap_ht40_scan(dev, apdev):
27 clear_scan_cache(apdev[0])
28 params = { "ssid": "test-ht40",
30 "ht_capab": "[HT40-]"}
31 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
33 state = hapd.get_status_field("state")
34 if state != "HT_SCAN":
36 state = hapd.get_status_field("state")
37 if state != "HT_SCAN":
38 raise Exception("Unexpected interface state - expected HT_SCAN")
40 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
42 raise Exception("AP setup timed out")
44 state = hapd.get_status_field("state")
45 if state != "ENABLED":
46 raise Exception("Unexpected interface state - expected ENABLED")
48 freq = hapd.get_status_field("freq")
50 raise Exception("Unexpected frequency")
51 pri = hapd.get_status_field("channel")
53 raise Exception("Unexpected primary channel")
54 sec = hapd.get_status_field("secondary_channel")
56 raise Exception("Unexpected secondary channel")
58 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
60 def test_ap_ht40_scan_conflict(dev, apdev):
61 """HT40 co-ex scan conflict"""
62 clear_scan_cache(apdev[0])
63 params = { "ssid": "test-ht40",
65 "ht_capab": "[HT40+]"}
66 hostapd.add_ap(apdev[1], params)
68 params = { "ssid": "test-ht40",
70 "ht_capab": "[HT40-]"}
71 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
73 state = hapd.get_status_field("state")
74 if state != "HT_SCAN":
76 state = hapd.get_status_field("state")
77 if state != "HT_SCAN":
78 raise Exception("Unexpected interface state - expected HT_SCAN")
80 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
82 raise Exception("AP setup timed out")
84 state = hapd.get_status_field("state")
85 if state != "ENABLED":
86 raise Exception("Unexpected interface state - expected ENABLED")
88 freq = hapd.get_status_field("freq")
90 raise Exception("Unexpected frequency")
91 pri = hapd.get_status_field("channel")
93 raise Exception("Unexpected primary channel")
94 sec = hapd.get_status_field("secondary_channel")
96 raise Exception("Unexpected secondary channel: " + sec)
98 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
100 def test_ap_ht40_scan_conflict2(dev, apdev):
101 """HT40 co-ex scan conflict (HT40-)"""
102 clear_scan_cache(apdev[0])
103 params = { "ssid": "test-ht40",
105 "ht_capab": "[HT40-]"}
106 hostapd.add_ap(apdev[1], params)
108 params = { "ssid": "test-ht40",
110 "ht_capab": "[HT40+]"}
111 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
113 state = hapd.get_status_field("state")
114 if state != "HT_SCAN":
116 state = hapd.get_status_field("state")
117 if state != "HT_SCAN":
118 raise Exception("Unexpected interface state - expected HT_SCAN")
120 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
122 raise Exception("AP setup timed out")
124 state = hapd.get_status_field("state")
125 if state != "ENABLED":
126 raise Exception("Unexpected interface state - expected ENABLED")
128 freq = hapd.get_status_field("freq")
130 raise Exception("Unexpected frequency")
131 pri = hapd.get_status_field("channel")
133 raise Exception("Unexpected primary channel")
134 sec = hapd.get_status_field("secondary_channel")
136 raise Exception("Unexpected secondary channel: " + sec)
138 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
140 def test_ap_ht40_scan_not_affected(dev, apdev):
141 """HT40 co-ex scan and other BSS not affected"""
142 clear_scan_cache(apdev[0])
143 params = { "ssid": "test-ht20",
145 hostapd.add_ap(apdev[1], params)
147 subprocess.call(['ifconfig', apdev[0]['ifname'], 'up'])
148 subprocess.call(['iw', apdev[0]['ifname'], 'scan', 'trigger', 'freq', '2462'])
150 subprocess.call(['iw', apdev[0]['ifname'], 'scan', 'dump'],
151 stdout=open('/dev/null', 'w'))
153 subprocess.call(['ifconfig', apdev[0]['ifname'], 'down'])
155 params = { "ssid": "test-ht40",
157 "ht_capab": "[HT40+]"}
158 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
160 state = hapd.get_status_field("state")
161 if state != "HT_SCAN":
163 state = hapd.get_status_field("state")
164 if state != "HT_SCAN":
165 raise Exception("Unexpected interface state - expected HT_SCAN")
167 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
169 raise Exception("AP setup timed out")
171 state = hapd.get_status_field("state")
172 if state != "ENABLED":
173 raise Exception("Unexpected interface state - expected ENABLED")
175 freq = hapd.get_status_field("freq")
177 raise Exception("Unexpected frequency")
178 pri = hapd.get_status_field("channel")
180 raise Exception("Unexpected primary channel")
181 sec = hapd.get_status_field("secondary_channel")
183 raise Exception("Unexpected secondary channel: " + sec)
185 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
187 def test_ap_ht40_scan_legacy_conflict(dev, apdev):
188 """HT40 co-ex scan conflict with legacy 20 MHz AP"""
189 clear_scan_cache(apdev[0])
190 params = { "ssid": "legacy-20",
191 "channel": "7", "ieee80211n": "0" }
192 hostapd.add_ap(apdev[1], params)
194 params = { "ssid": "test-ht40",
196 "ht_capab": "[HT40-]"}
197 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
199 state = hapd.get_status_field("state")
200 if state != "HT_SCAN":
202 state = hapd.get_status_field("state")
203 if state != "HT_SCAN":
204 raise Exception("Unexpected interface state - expected HT_SCAN")
206 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
208 raise Exception("AP setup timed out")
210 state = hapd.get_status_field("state")
211 if state != "ENABLED":
212 raise Exception("Unexpected interface state - expected ENABLED")
214 freq = hapd.get_status_field("freq")
216 raise Exception("Unexpected frequency: " + freq)
217 pri = hapd.get_status_field("channel")
219 raise Exception("Unexpected primary channel: " + pri)
220 sec = hapd.get_status_field("secondary_channel")
222 raise Exception("Unexpected secondary channel: " + sec)
224 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
226 def test_ap_ht40_scan_ht20_conflict(dev, apdev):
227 """HT40 co-ex scan conflict with HT 20 MHz AP"""
228 clear_scan_cache(apdev[0])
229 params = { "ssid": "ht-20",
230 "channel": "7", "ieee80211n": "1" }
231 hostapd.add_ap(apdev[1], params)
233 params = { "ssid": "test-ht40",
235 "ht_capab": "[HT40-]"}
236 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
238 state = hapd.get_status_field("state")
239 if state != "HT_SCAN":
241 state = hapd.get_status_field("state")
242 if state != "HT_SCAN":
243 raise Exception("Unexpected interface state - expected HT_SCAN")
245 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
247 raise Exception("AP setup timed out")
249 state = hapd.get_status_field("state")
250 if state != "ENABLED":
251 raise Exception("Unexpected interface state - expected ENABLED")
253 freq = hapd.get_status_field("freq")
255 raise Exception("Unexpected frequency: " + freq)
256 pri = hapd.get_status_field("channel")
258 raise Exception("Unexpected primary channel: " + pri)
259 sec = hapd.get_status_field("secondary_channel")
261 raise Exception("Unexpected secondary channel: " + sec)
263 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
265 def test_ap_ht40_scan_intolerant(dev, apdev):
266 """HT40 co-ex scan finding an AP advertising 40 MHz intolerant"""
267 clear_scan_cache(apdev[0])
268 params = { "ssid": "another-bss",
270 "ht_capab": "[40-INTOLERANT]" }
271 hostapd.add_ap(apdev[1], params)
273 params = { "ssid": "test-ht40",
275 "ht_capab": "[HT40+]"}
276 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
278 state = hapd.get_status_field("state")
279 if state != "HT_SCAN":
281 state = hapd.get_status_field("state")
282 if state != "HT_SCAN":
283 raise Exception("Unexpected interface state - expected HT_SCAN")
285 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
287 raise Exception("AP setup timed out")
289 state = hapd.get_status_field("state")
290 if state != "ENABLED":
291 raise Exception("Unexpected interface state - expected ENABLED")
293 freq = hapd.get_status_field("freq")
295 raise Exception("Unexpected frequency: " + freq)
296 pri = hapd.get_status_field("channel")
298 raise Exception("Unexpected primary channel: " + pri)
299 sec = hapd.get_status_field("secondary_channel")
301 raise Exception("Unexpected secondary channel: " + sec)
303 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
305 def test_ap_ht40_scan_match(dev, apdev):
306 """HT40 co-ex scan matching configuration"""
307 clear_scan_cache(apdev[0])
308 params = { "ssid": "test-ht40",
310 "ht_capab": "[HT40-]"}
311 hostapd.add_ap(apdev[1], params)
313 params = { "ssid": "test-ht40",
315 "ht_capab": "[HT40-]"}
316 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
318 state = hapd.get_status_field("state")
319 if state != "HT_SCAN":
321 state = hapd.get_status_field("state")
322 if state != "HT_SCAN":
323 raise Exception("Unexpected interface state - expected HT_SCAN")
325 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
327 raise Exception("AP setup timed out")
329 state = hapd.get_status_field("state")
330 if state != "ENABLED":
331 raise Exception("Unexpected interface state - expected ENABLED")
333 freq = hapd.get_status_field("freq")
335 raise Exception("Unexpected frequency")
336 pri = hapd.get_status_field("channel")
338 raise Exception("Unexpected primary channel")
339 sec = hapd.get_status_field("secondary_channel")
341 raise Exception("Unexpected secondary channel: " + sec)
343 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
345 def test_ap_ht40_5ghz_match(dev, apdev):
346 """HT40 co-ex scan on 5 GHz with matching pri/sec channel"""
347 clear_scan_cache(apdev[0])
351 params = { "ssid": "test-ht40",
354 "country_code": "US",
355 "ht_capab": "[HT40+]"}
356 hapd2 = hostapd.add_ap(apdev[1], params)
358 params = { "ssid": "test-ht40",
361 "ht_capab": "[HT40+]"}
362 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
364 state = hapd.get_status_field("state")
365 if state != "HT_SCAN":
367 state = hapd.get_status_field("state")
368 if state != "HT_SCAN":
369 raise Exception("Unexpected interface state - expected HT_SCAN")
371 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
373 raise Exception("AP setup timed out")
375 state = hapd.get_status_field("state")
376 if state != "ENABLED":
377 raise Exception("Unexpected interface state - expected ENABLED")
379 freq = hapd.get_status_field("freq")
381 raise Exception("Unexpected frequency")
382 pri = hapd.get_status_field("channel")
384 raise Exception("Unexpected primary channel")
385 sec = hapd.get_status_field("secondary_channel")
387 raise Exception("Unexpected secondary channel: " + sec)
389 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
391 dev[0].request("DISCONNECT")
393 hapd.request("DISABLE")
395 hapd2.request("DISABLE")
396 subprocess.call(['iw', 'reg', 'set', '00'])
397 dev[0].flush_scan_cache()
399 def test_ap_ht40_5ghz_switch(dev, apdev):
400 """HT40 co-ex scan on 5 GHz switching pri/sec channel"""
401 clear_scan_cache(apdev[0])
405 params = { "ssid": "test-ht40",
408 "country_code": "US",
409 "ht_capab": "[HT40+]"}
410 hapd2 = hostapd.add_ap(apdev[1], params)
412 params = { "ssid": "test-ht40",
415 "ht_capab": "[HT40-]"}
416 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
418 state = hapd.get_status_field("state")
419 if state != "HT_SCAN":
421 state = hapd.get_status_field("state")
422 if state != "HT_SCAN":
423 raise Exception("Unexpected interface state - expected HT_SCAN")
425 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
427 raise Exception("AP setup timed out")
429 state = hapd.get_status_field("state")
430 if state != "ENABLED":
431 raise Exception("Unexpected interface state - expected ENABLED")
433 freq = hapd.get_status_field("freq")
435 raise Exception("Unexpected frequency: " + freq)
436 pri = hapd.get_status_field("channel")
438 raise Exception("Unexpected primary channel: " + pri)
439 sec = hapd.get_status_field("secondary_channel")
441 raise Exception("Unexpected secondary channel: " + sec)
443 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
445 dev[0].request("DISCONNECT")
447 hapd.request("DISABLE")
449 hapd2.request("DISABLE")
450 subprocess.call(['iw', 'reg', 'set', '00'])
452 def test_ap_ht40_5ghz_switch2(dev, apdev):
453 """HT40 co-ex scan on 5 GHz switching pri/sec channel (2)"""
454 clear_scan_cache(apdev[0])
458 params = { "ssid": "test-ht40",
461 "country_code": "US",
462 "ht_capab": "[HT40+]"}
463 hapd2 = hostapd.add_ap(apdev[1], params)
465 id = dev[0].add_network()
466 dev[0].set_network(id, "mode", "2")
467 dev[0].set_network_quoted(id, "ssid", "wpas-ap-open")
468 dev[0].set_network(id, "key_mgmt", "NONE")
469 dev[0].set_network(id, "frequency", "5200")
470 dev[0].set_network(id, "scan_freq", "5200")
471 dev[0].select_network(id)
474 params = { "ssid": "test-ht40",
477 "ht_capab": "[HT40-]"}
478 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
480 state = hapd.get_status_field("state")
481 if state != "HT_SCAN":
483 state = hapd.get_status_field("state")
484 if state != "HT_SCAN":
485 raise Exception("Unexpected interface state - expected HT_SCAN")
487 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
489 raise Exception("AP setup timed out")
491 state = hapd.get_status_field("state")
492 if state != "ENABLED":
493 raise Exception("Unexpected interface state - expected ENABLED")
495 freq = hapd.get_status_field("freq")
497 raise Exception("Unexpected frequency: " + freq)
498 pri = hapd.get_status_field("channel")
500 raise Exception("Unexpected primary channel: " + pri)
501 sec = hapd.get_status_field("secondary_channel")
503 raise Exception("Unexpected secondary channel: " + sec)
505 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
507 dev[0].request("DISCONNECT")
509 hapd.request("DISABLE")
511 hapd2.request("DISABLE")
512 subprocess.call(['iw', 'reg', 'set', '00'])
513 dev[0].flush_scan_cache()
515 def test_obss_scan(dev, apdev):
516 """Overlapping BSS scan request"""
517 params = { "ssid": "obss-scan",
519 "ht_capab": "[HT40-]",
520 "obss_interval": "10" }
521 hapd = hostapd.add_ap(apdev[0], params)
523 params = { "ssid": "another-bss",
526 hostapd.add_ap(apdev[1], params)
528 dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
529 hapd.set("ext_mgmt_frame_handling", "1")
530 logger.info("Waiting for OBSS scan to occur")
531 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=15)
533 raise Exception("Timed out while waiting for OBSS scan to start")
534 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
536 raise Exception("Timed out while waiting for OBSS scan results")
538 for i in range(0, 4):
539 frame = hapd.mgmt_rx(timeout=5)
541 raise Exception("MGMT RX wait timed out")
542 if frame['subtype'] != 13:
544 payload = frame['payload']
547 (category, action, ie) = struct.unpack('BBB', payload[0:3])
553 logger.info("20/40 BSS Coexistence report received")
557 raise Exception("20/40 BSS Coexistence report not seen")
559 def test_obss_scan_40_intolerant(dev, apdev):
560 """Overlapping BSS scan request with 40 MHz intolerant AP"""
561 params = { "ssid": "obss-scan",
563 "ht_capab": "[HT40-]",
564 "obss_interval": "10" }
565 hapd = hostapd.add_ap(apdev[0], params)
567 params = { "ssid": "another-bss",
569 "ht_capab": "[40-INTOLERANT]" }
570 hostapd.add_ap(apdev[1], params)
572 dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
573 hapd.set("ext_mgmt_frame_handling", "1")
574 logger.info("Waiting for OBSS scan to occur")
575 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=15)
577 raise Exception("Timed out while waiting for OBSS scan to start")
578 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
580 raise Exception("Timed out while waiting for OBSS scan results")
582 for i in range(0, 4):
583 frame = hapd.mgmt_rx(timeout=5)
585 raise Exception("MGMT RX wait timed out")
586 if frame['subtype'] != 13:
588 payload = frame['payload']
591 (category, action, ie) = struct.unpack('BBB', payload[0:3])
597 logger.info("20/40 BSS Coexistence report received")
601 raise Exception("20/40 BSS Coexistence report not seen")
603 def test_obss_coex_report_handling(dev, apdev):
604 """Overlapping BSS scan report handling with obss_interval=0"""
605 clear_scan_cache(apdev[0])
606 params = { "ssid": "obss-scan",
608 "ht_capab": "[HT40-]" }
609 hapd = hostapd.add_ap(apdev[0], params)
610 bssid = apdev[0]['bssid']
611 dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
613 sec = hapd.get_status_field("secondary_channel")
615 raise Exception("AP is not using 40 MHz channel")
617 # 20/40 MHz co-ex report tests: number of invalid reports and a valid report
618 # that forces 20 MHz channel.
619 tests = [ '0400', '040048', '04004801', '0400480000', '0400490100',
620 '040048ff0000', '04004801ff49ff00', '04004801004900',
621 '0400480100490101', '0400480100490201ff',
622 '040048010449020005' ]
624 req = "MGMT_TX {} {} freq=2437 action={}".format(bssid, bssid, msg)
625 if "OK" not in dev[0].request(req):
626 raise Exception("Could not send management frame")
628 sec = hapd.get_status_field("secondary_channel")
630 raise Exception("AP did not move to 20 MHz channel")
632 def test_obss_coex_report_handling1(dev, apdev):
633 """Overlapping BSS scan report handling with obss_interval=1"""
634 clear_scan_cache(apdev[0])
635 params = { "ssid": "obss-scan",
637 "ht_capab": "[HT40+]",
638 "obss_interval": "1" }
639 hapd = hostapd.add_ap(apdev[0], params)
640 bssid = apdev[0]['bssid']
641 dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
643 sec = hapd.get_status_field("secondary_channel")
645 raise Exception("AP is not using 40 MHz channel")
647 # 20/40 MHz co-ex report forcing 20 MHz channel
648 msg = '040048010449020005'
649 req = "MGMT_TX {} {} freq=2437 action={}".format(bssid, bssid, msg)
650 if "OK" not in dev[0].request(req):
651 raise Exception("Could not send management frame")
653 sec = hapd.get_status_field("secondary_channel")
655 raise Exception("AP did not move to 20 MHz channel")
657 # No 20/40 MHz co-ex reports forcing 20 MHz channel during next interval
659 sec = hapd.get_status_field("secondary_channel")
664 raise Exception("AP did not return to 40 MHz channel")
666 def test_olbc(dev, apdev):
668 params = { "ssid": "test-olbc",
670 "ht_capab": "[HT40-]",
671 "ap_table_expiration_time": "2" }
672 hapd = hostapd.add_ap(apdev[0], params)
673 status = hapd.get_status()
674 if status['olbc'] != '0' or status['olbc_ht'] != '0':
675 raise Exception("Unexpected OLBC information")
677 params = { "ssid": "olbc-ap",
681 hostapd.add_ap(apdev[1], params)
683 status = hapd.get_status()
684 if status['olbc'] != '1' or status['olbc_ht'] != '1':
685 raise Exception("Missing OLBC information")
687 hostapd.remove_bss(apdev[1])
689 logger.info("Waiting for OLBC state to time out")
691 for i in range(0, 15):
693 status = hapd.get_status()
694 if status['olbc'] == '0' and status['olbc_ht'] == '0':
698 raise Exception("OLBC state did nto time out")
700 def test_olbc_table_limit(dev, apdev):
701 """OLBC AP table size limit"""
702 ifname1 = apdev[0]['ifname']
703 ifname2 = apdev[0]['ifname'] + '-2'
704 ifname3 = apdev[0]['ifname'] + '-3'
705 hostapd.add_bss(apdev[0], ifname1, 'bss-1.conf')
706 hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf')
707 hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf')
709 params = { "ssid": "test-olbc",
711 "ap_table_max_size": "2" }
712 hapd = hostapd.add_ap(apdev[1], params)
715 with alloc_fail(hapd, 1, "ap_list_process_beacon"):
717 hapd.set("ap_table_max_size", "1")
719 hapd.set("ap_table_max_size", "0")
722 def test_olbc_5ghz(dev, apdev):
723 """OLBC detection on 5 GHz"""
727 params = { "ssid": "test-olbc",
728 "country_code": "FI",
731 "ht_capab": "[HT40+]" }
732 hapd = hostapd.add_ap(apdev[0], params)
733 status = hapd.get_status()
734 if status['olbc'] != '0' or status['olbc_ht'] != '0':
735 raise Exception("Unexpected OLBC information")
737 params = { "ssid": "olbc-ap",
738 "country_code": "FI",
743 hapd2 = hostapd.add_ap(apdev[1], params)
747 status = hapd.get_status()
748 logger.debug('olbc_ht: ' + status['olbc_ht'])
749 if status['olbc_ht'] == '1':
753 raise Exception("Missing OLBC information")
756 hapd.request("DISABLE")
758 hapd2.request("DISABLE")
759 subprocess.call(['iw', 'reg', 'set', '00'])
761 def test_ap_require_ht(dev, apdev):
763 params = { "ssid": "require-ht",
765 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
767 dev[1].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
768 disable_ht="1", wait_connect=False)
769 dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412")
770 ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
771 dev[1].request("DISCONNECT")
773 raise Exception("Association rejection timed out")
774 if "status_code=27" not in ev:
775 raise Exception("Unexpected rejection status code")
776 dev[2].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
777 ht_mcs="0x01 00 00 00 00 00 00 00 00 00",
778 disable_max_amsdu="1", ampdu_factor="2",
779 ampdu_density="1", disable_ht40="1", disable_sgi="1",
782 def test_ap_require_ht_limited_rates(dev, apdev):
783 """Require HT with limited supported rates"""
784 params = { "ssid": "require-ht",
785 "supported_rates": "60 120 240 360 480 540",
787 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
789 dev[1].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
790 disable_ht="1", wait_connect=False)
791 dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412")
792 ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
793 dev[1].request("DISCONNECT")
795 raise Exception("Association rejection timed out")
796 if "status_code=27" not in ev:
797 raise Exception("Unexpected rejection status code")
799 def test_ap_ht_capab_not_supported(dev, apdev):
800 """HT configuration with driver not supporting all ht_capab entries"""
801 params = { "ssid": "test-ht40",
803 "ht_capab": "[HT40-][LDPC][SMPS-STATIC][SMPS-DYNAMIC][GF][SHORT-GI-20][SHORT-GI-40][TX-STBC][RX-STBC1][RX-STBC12][RX-STBC123][DELAYED-BA][MAX-AMSDU-7935][DSSS_CCK-40][LSIG-TXOP-PROT]"}
804 hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
805 if "FAIL" not in hapd.request("ENABLE"):
806 raise Exception("Unexpected ENABLE success")
808 def test_ap_ht_40mhz_intolerant_sta(dev, apdev):
809 """Associated STA indicating 40 MHz intolerant"""
810 clear_scan_cache(apdev[0])
811 params = { "ssid": "intolerant",
813 "ht_capab": "[HT40-]" }
814 hapd = hostapd.add_ap(apdev[0], params)
815 if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
816 raise Exception("Unexpected num_sta_ht40_intolerant value")
817 if hapd.get_status_field("secondary_channel") != "-1":
818 raise Exception("Unexpected secondary_channel")
820 dev[0].connect("intolerant", key_mgmt="NONE", scan_freq="2437")
821 if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
822 raise Exception("Unexpected num_sta_ht40_intolerant value")
823 if hapd.get_status_field("secondary_channel") != "-1":
824 raise Exception("Unexpected secondary_channel")
826 dev[2].connect("intolerant", key_mgmt="NONE", scan_freq="2437",
829 if hapd.get_status_field("num_sta_ht40_intolerant") != "1":
830 raise Exception("Unexpected num_sta_ht40_intolerant value (expected 1)")
831 if hapd.get_status_field("secondary_channel") != "0":
832 raise Exception("Unexpected secondary_channel (did not disable 40 MHz)")
834 dev[2].request("DISCONNECT")
836 if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
837 raise Exception("Unexpected num_sta_ht40_intolerant value (expected 0)")
838 if hapd.get_status_field("secondary_channel") != "-1":
839 raise Exception("Unexpected secondary_channel (did not re-enable 40 MHz)")
841 def test_ap_ht_40mhz_intolerant_ap(dev, apdev):
842 """Associated STA reports 40 MHz intolerant AP after association"""
843 clear_scan_cache(apdev[0])
844 params = { "ssid": "ht",
846 "ht_capab": "[HT40-]",
847 "obss_interval": "3" }
848 hapd = hostapd.add_ap(apdev[0], params)
850 dev[0].connect("ht", key_mgmt="NONE", scan_freq="2437")
852 if hapd.get_status_field("secondary_channel") != "-1":
853 raise Exception("Unexpected secondary channel information")
855 logger.info("Start 40 MHz intolerant AP")
856 params = { "ssid": "intolerant",
858 "ht_capab": "[40-INTOLERANT]" }
859 hapd2 = hostapd.add_ap(apdev[1], params)
861 logger.info("Waiting for co-ex report from STA")
863 for i in range(0, 20):
865 if hapd.get_status_field("secondary_channel") == "0":
866 logger.info("AP moved to 20 MHz channel")
870 raise Exception("AP did not move to 20 MHz channel")
872 if "OK" not in hapd2.request("DISABLE"):
873 raise Exception("Failed to disable 40 MHz intolerant AP")
875 # make sure the intolerant AP disappears from scan results more quickly
876 dev[0].scan(type="ONLY", freq="2432", only_new=True)
877 dev[0].scan(type="ONLY", freq="2432", only_new=True)
878 dev[0].dump_monitor()
880 logger.info("Waiting for AP to move back to 40 MHz channel")
882 for i in range(0, 30):
884 if hapd.get_status_field("secondary_channel") == "-1":
885 logger.info("AP moved to 40 MHz channel")
889 raise Exception("AP did not move to 40 MHz channel")
891 def test_ap_ht40_csa(dev, apdev):
892 """HT with 40 MHz channel width and CSA"""
893 csa_supported(dev[0])
896 params = { "ssid": "ht",
897 "country_code": "US",
900 "ht_capab": "[HT40+]",
902 hapd = hostapd.add_ap(apdev[0], params)
904 dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
905 hwsim_utils.test_connectivity(dev[0], hapd)
907 hapd.request("CHAN_SWITCH 5 5200 ht sec_channel_offset=-1 bandwidth=40")
908 ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
910 raise Exception("CSA finished event timed out")
911 if "freq=5200" not in ev:
912 raise Exception("Unexpected channel in CSA finished event")
913 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
915 raise Exception("Unexpected STA disconnection during CSA")
916 hwsim_utils.test_connectivity(dev[0], hapd)
918 hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
919 ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
921 raise Exception("CSA finished event timed out")
922 if "freq=5180" not in ev:
923 raise Exception("Unexpected channel in CSA finished event")
924 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
926 raise Exception("Unexpected STA disconnection during CSA")
927 hwsim_utils.test_connectivity(dev[0], hapd)
929 dev[0].request("DISCONNECT")
931 hapd.request("DISABLE")
932 subprocess.call(['iw', 'reg', 'set', '00'])
933 dev[0].flush_scan_cache()
935 def test_ap_ht40_csa2(dev, apdev):
936 """HT with 40 MHz channel width and CSA"""
937 csa_supported(dev[0])
940 params = { "ssid": "ht",
941 "country_code": "US",
944 "ht_capab": "[HT40+]",
946 hapd = hostapd.add_ap(apdev[0], params)
948 dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
949 hwsim_utils.test_connectivity(dev[0], hapd)
951 hapd.request("CHAN_SWITCH 5 5220 ht sec_channel_offset=1 bandwidth=40")
952 ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
954 raise Exception("CSA finished event timed out")
955 if "freq=5220" not in ev:
956 raise Exception("Unexpected channel in CSA finished event")
957 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
959 raise Exception("Unexpected STA disconnection during CSA")
960 hwsim_utils.test_connectivity(dev[0], hapd)
962 hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
963 ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
965 raise Exception("CSA finished event timed out")
966 if "freq=5180" not in ev:
967 raise Exception("Unexpected channel in CSA finished event")
968 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
970 raise Exception("Unexpected STA disconnection during CSA")
971 hwsim_utils.test_connectivity(dev[0], hapd)
973 dev[0].request("DISCONNECT")
975 hapd.request("DISABLE")
976 subprocess.call(['iw', 'reg', 'set', '00'])
977 dev[0].flush_scan_cache()
979 def test_ap_ht40_csa3(dev, apdev):
980 """HT with 40 MHz channel width and CSA"""
981 csa_supported(dev[0])
984 params = { "ssid": "ht",
985 "country_code": "US",
988 "ht_capab": "[HT40+]",
990 hapd = hostapd.add_ap(apdev[0], params)
992 dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
993 hwsim_utils.test_connectivity(dev[0], hapd)
995 hapd.request("CHAN_SWITCH 5 5240 ht sec_channel_offset=-1 bandwidth=40")
996 ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
998 raise Exception("CSA finished event timed out")
999 if "freq=5240" not in ev:
1000 raise Exception("Unexpected channel in CSA finished event")
1001 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
1003 raise Exception("Unexpected STA disconnection during CSA")
1004 hwsim_utils.test_connectivity(dev[0], hapd)
1006 hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
1007 ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
1009 raise Exception("CSA finished event timed out")
1010 if "freq=5180" not in ev:
1011 raise Exception("Unexpected channel in CSA finished event")
1012 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
1014 raise Exception("Unexpected STA disconnection during CSA")
1015 hwsim_utils.test_connectivity(dev[0], hapd)
1017 dev[0].request("DISCONNECT")
1019 hapd.request("DISABLE")
1020 subprocess.call(['iw', 'reg', 'set', '00'])
1021 dev[0].flush_scan_cache()
1023 def test_ap_ht_smps(dev, apdev):
1024 """SMPS AP configuration options"""
1025 params = { "ssid": "ht1", "ht_capab": "[SMPS-STATIC]" }
1027 hapd = hostapd.add_ap(apdev[0], params)
1029 raise HwsimSkip("Assume mac80211_hwsim was not recent enough to support SMPS")
1030 params = { "ssid": "ht2", "ht_capab": "[SMPS-DYNAMIC]" }
1031 hapd2 = hostapd.add_ap(apdev[1], params)
1033 dev[0].connect("ht1", key_mgmt="NONE", scan_freq="2412")
1034 dev[1].connect("ht2", key_mgmt="NONE", scan_freq="2412")
1035 hwsim_utils.test_connectivity(dev[0], hapd)
1036 hwsim_utils.test_connectivity(dev[1], hapd2)
1038 def test_prefer_ht20(dev, apdev):
1039 """Preference on HT20 over no-HT"""
1040 params = { "ssid": "test",
1043 hapd = hostapd.add_ap(apdev[0], params)
1044 bssid = apdev[0]['bssid']
1045 params = { "ssid": "test",
1048 hapd2 = hostapd.add_ap(apdev[1], params)
1049 bssid2 = apdev[1]['bssid']
1051 dev[0].scan_for_bss(bssid, freq=2412)
1052 dev[0].scan_for_bss(bssid2, freq=2412)
1053 dev[0].connect("test", key_mgmt="NONE", scan_freq="2412")
1054 if dev[0].get_status_field('bssid') != bssid2:
1055 raise Exception("Unexpected BSS selected")
1057 est = dev[0].get_bss(bssid)['est_throughput']
1059 raise Exception("Unexpected BSS0 est_throughput: " + est)
1061 est = dev[0].get_bss(bssid2)['est_throughput']
1063 raise Exception("Unexpected BSS1 est_throughput: " + est)
1065 def test_prefer_ht40(dev, apdev):
1066 """Preference on HT40 over HT20"""
1067 params = { "ssid": "test",
1070 hapd = hostapd.add_ap(apdev[0], params)
1071 bssid = apdev[0]['bssid']
1072 params = { "ssid": "test",
1075 "ht_capab": "[HT40+]" }
1076 hapd2 = hostapd.add_ap(apdev[1], params)
1077 bssid2 = apdev[1]['bssid']
1079 dev[0].scan_for_bss(bssid, freq=2412)
1080 dev[0].scan_for_bss(bssid2, freq=2412)
1081 dev[0].connect("test", key_mgmt="NONE", scan_freq="2412")
1082 if dev[0].get_status_field('bssid') != bssid2:
1083 raise Exception("Unexpected BSS selected")
1085 est = dev[0].get_bss(bssid)['est_throughput']
1087 raise Exception("Unexpected BSS0 est_throughput: " + est)
1089 est = dev[0].get_bss(bssid2)['est_throughput']
1091 raise Exception("Unexpected BSS1 est_throughput: " + est)
1093 def test_prefer_ht20_during_roam(dev, apdev):
1094 """Preference on HT20 over no-HT in roaming consideration"""
1095 params = { "ssid": "test",
1098 hapd = hostapd.add_ap(apdev[0], params)
1099 bssid = apdev[0]['bssid']
1101 dev[0].scan_for_bss(bssid, freq=2412)
1102 dev[0].connect("test", key_mgmt="NONE", scan_freq="2412")
1104 params = { "ssid": "test",
1107 hapd2 = hostapd.add_ap(apdev[1], params)
1108 bssid2 = apdev[1]['bssid']
1109 dev[0].scan_for_bss(bssid2, freq=2412)
1110 dev[0].scan(freq=2412)
1111 dev[0].wait_connected()
1113 if dev[0].get_status_field('bssid') != bssid2:
1114 raise Exception("Unexpected BSS selected")
1116 def test_ap_ht40_5ghz_invalid_pair(dev, apdev):
1117 """HT40 on 5 GHz with invalid channel pair"""
1118 clear_scan_cache(apdev[0])
1120 params = { "ssid": "test-ht40",
1123 "country_code": "US",
1124 "ht_capab": "[HT40+]"}
1125 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
1126 ev = hapd.wait_event(["AP-DISABLED", "AP-ENABLED"], timeout=10)
1128 raise Exception("AP setup failure timed out")
1129 if "AP-ENABLED" in ev:
1130 sec = hapd.get_status_field("secondary_channel")
1132 raise Exception("Invalid 40 MHz channel accepted")
1134 subprocess.call(['iw', 'reg', 'set', '00'])
1136 def test_ap_ht40_5ghz_disabled_sec(dev, apdev):
1137 """HT40 on 5 GHz with disabled secondary channel"""
1138 clear_scan_cache(apdev[0])
1140 params = { "ssid": "test-ht40",
1143 "country_code": "US",
1144 "ht_capab": "[HT40+]"}
1145 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
1146 ev = hapd.wait_event(["AP-DISABLED", "AP-ENABLED"], timeout=10)
1148 raise Exception("AP setup failure timed out")
1149 if "AP-ENABLED" in ev:
1150 sec = hapd.get_status_field("secondary_channel")
1152 raise Exception("Invalid 40 MHz channel accepted")
1154 subprocess.call(['iw', 'reg', 'set', '00'])
1156 def test_ap_ht40_scan_broken_ap(dev, apdev):
1157 """HT40 co-ex scan and broken legacy/HT AP"""
1158 clear_scan_cache(apdev[0])
1160 # Broken AP: Include HT Capabilities element but not HT Operation element
1161 params = { "ssid": "legacy-20",
1162 "channel": "7", "ieee80211n": "0",
1164 "vendor_elements": "2d1a0e001bffff000000000000000000000100000000000000000000" }
1165 hapd2 = hostapd.add_ap(apdev[1], params)
1167 params = { "ssid": "test-ht40",
1169 "ht_capab": "[HT40-]"}
1170 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
1172 state = hapd.get_status_field("state")
1173 if state != "HT_SCAN":
1175 state = hapd.get_status_field("state")
1176 if state != "HT_SCAN":
1177 raise Exception("Unexpected interface state - expected HT_SCAN")
1179 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
1181 raise Exception("AP setup timed out")
1183 state = hapd.get_status_field("state")
1184 if state != "ENABLED":
1185 raise Exception("Unexpected interface state - expected ENABLED")
1187 freq = hapd.get_status_field("freq")
1189 raise Exception("Unexpected frequency: " + freq)
1190 pri = hapd.get_status_field("channel")
1192 raise Exception("Unexpected primary channel: " + pri)
1193 sec = hapd.get_status_field("secondary_channel")
1195 raise Exception("Unexpected secondary channel: " + sec)
1197 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
1198 dev[1].connect("legacy-20", key_mgmt="NONE", scan_freq="2442")
1199 hwsim_utils.test_connectivity(dev[0], hapd)
1200 hwsim_utils.test_connectivity(dev[1], hapd2)