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 set_world_reg(apdev0=None, apdev1=None, dev0=None):
27 hostapd.cmd_execute(apdev0, ['iw', 'reg', 'set', '00'])
29 hostapd.cmd_execute(apdev1, ['iw', 'reg', 'set', '00'])
31 dev0.cmd_execute(['iw', 'reg', 'set', '00'])
33 def test_ap_ht40_scan(dev, apdev):
35 clear_scan_cache(apdev[0])
36 params = { "ssid": "test-ht40",
38 "ht_capab": "[HT40-]"}
39 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
41 state = hapd.get_status_field("state")
42 if state != "HT_SCAN":
44 state = hapd.get_status_field("state")
45 if state != "HT_SCAN":
46 raise Exception("Unexpected interface state - expected HT_SCAN")
48 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
50 raise Exception("AP setup timed out")
52 state = hapd.get_status_field("state")
53 if state != "ENABLED":
54 raise Exception("Unexpected interface state - expected ENABLED")
56 freq = hapd.get_status_field("freq")
58 raise Exception("Unexpected frequency")
59 pri = hapd.get_status_field("channel")
61 raise Exception("Unexpected primary channel")
62 sec = hapd.get_status_field("secondary_channel")
64 raise Exception("Unexpected secondary channel")
66 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
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",
73 "ht_capab": "[HT40+]"}
74 hostapd.add_ap(apdev[1], params)
76 params = { "ssid": "test-ht40",
78 "ht_capab": "[HT40-]"}
79 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
81 state = hapd.get_status_field("state")
82 if state != "HT_SCAN":
84 state = hapd.get_status_field("state")
85 if state != "HT_SCAN":
86 raise Exception("Unexpected interface state - expected HT_SCAN")
88 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
90 raise Exception("AP setup timed out")
92 state = hapd.get_status_field("state")
93 if state != "ENABLED":
94 raise Exception("Unexpected interface state - expected ENABLED")
96 freq = hapd.get_status_field("freq")
98 raise Exception("Unexpected frequency")
99 pri = hapd.get_status_field("channel")
101 raise Exception("Unexpected primary channel")
102 sec = hapd.get_status_field("secondary_channel")
104 raise Exception("Unexpected secondary channel: " + sec)
106 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
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",
113 "ht_capab": "[HT40-]"}
114 hostapd.add_ap(apdev[1], params)
116 params = { "ssid": "test-ht40",
118 "ht_capab": "[HT40+]"}
119 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
121 state = hapd.get_status_field("state")
122 if state != "HT_SCAN":
124 state = hapd.get_status_field("state")
125 if state != "HT_SCAN":
126 raise Exception("Unexpected interface state - expected HT_SCAN")
128 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
130 raise Exception("AP setup timed out")
132 state = hapd.get_status_field("state")
133 if state != "ENABLED":
134 raise Exception("Unexpected interface state - expected ENABLED")
136 freq = hapd.get_status_field("freq")
138 raise Exception("Unexpected frequency")
139 pri = hapd.get_status_field("channel")
141 raise Exception("Unexpected primary channel")
142 sec = hapd.get_status_field("secondary_channel")
144 raise Exception("Unexpected secondary channel: " + sec)
146 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
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",
153 hostapd.add_ap(apdev[1], params)
155 hostapd.cmd_execute(apdev[0], ['ifconfig', apdev[0]['ifname'], 'up'])
156 hostapd.cmd_execute(apdev[0], ['iw', apdev[0]['ifname'], 'scan', 'trigger',
159 hostapd.cmd_execute(apdev[0], ['iw', apdev[0]['ifname'], 'scan', 'dump'])
161 hostapd.cmd_execute(apdev[0], ['ifconfig', apdev[0]['ifname'], 'down'])
163 params = { "ssid": "test-ht40",
165 "ht_capab": "[HT40+]"}
166 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
168 state = hapd.get_status_field("state")
169 if state != "HT_SCAN":
171 state = hapd.get_status_field("state")
172 if state != "HT_SCAN":
173 raise Exception("Unexpected interface state - expected HT_SCAN")
175 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
177 raise Exception("AP setup timed out")
179 state = hapd.get_status_field("state")
180 if state != "ENABLED":
181 raise Exception("Unexpected interface state - expected ENABLED")
183 freq = hapd.get_status_field("freq")
185 raise Exception("Unexpected frequency")
186 pri = hapd.get_status_field("channel")
188 raise Exception("Unexpected primary channel")
189 sec = hapd.get_status_field("secondary_channel")
191 raise Exception("Unexpected secondary channel: " + sec)
193 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
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)
202 params = { "ssid": "test-ht40",
204 "ht_capab": "[HT40-]"}
205 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
207 state = hapd.get_status_field("state")
208 if state != "HT_SCAN":
210 state = hapd.get_status_field("state")
211 if state != "HT_SCAN":
212 raise Exception("Unexpected interface state - expected HT_SCAN")
214 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
216 raise Exception("AP setup timed out")
218 state = hapd.get_status_field("state")
219 if state != "ENABLED":
220 raise Exception("Unexpected interface state - expected ENABLED")
222 freq = hapd.get_status_field("freq")
224 raise Exception("Unexpected frequency: " + freq)
225 pri = hapd.get_status_field("channel")
227 raise Exception("Unexpected primary channel: " + pri)
228 sec = hapd.get_status_field("secondary_channel")
230 raise Exception("Unexpected secondary channel: " + sec)
232 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
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)
241 params = { "ssid": "test-ht40",
243 "ht_capab": "[HT40-]"}
244 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
246 state = hapd.get_status_field("state")
247 if state != "HT_SCAN":
249 state = hapd.get_status_field("state")
250 if state != "HT_SCAN":
251 raise Exception("Unexpected interface state - expected HT_SCAN")
253 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
255 raise Exception("AP setup timed out")
257 state = hapd.get_status_field("state")
258 if state != "ENABLED":
259 raise Exception("Unexpected interface state - expected ENABLED")
261 freq = hapd.get_status_field("freq")
263 raise Exception("Unexpected frequency: " + freq)
264 pri = hapd.get_status_field("channel")
266 raise Exception("Unexpected primary channel: " + pri)
267 sec = hapd.get_status_field("secondary_channel")
269 raise Exception("Unexpected secondary channel: " + sec)
271 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
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",
278 "ht_capab": "[40-INTOLERANT]" }
279 hostapd.add_ap(apdev[1], params)
281 params = { "ssid": "test-ht40",
283 "ht_capab": "[HT40+]"}
284 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
286 state = hapd.get_status_field("state")
287 if state != "HT_SCAN":
289 state = hapd.get_status_field("state")
290 if state != "HT_SCAN":
291 raise Exception("Unexpected interface state - expected HT_SCAN")
293 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
295 raise Exception("AP setup timed out")
297 state = hapd.get_status_field("state")
298 if state != "ENABLED":
299 raise Exception("Unexpected interface state - expected ENABLED")
301 freq = hapd.get_status_field("freq")
303 raise Exception("Unexpected frequency: " + freq)
304 pri = hapd.get_status_field("channel")
306 raise Exception("Unexpected primary channel: " + pri)
307 sec = hapd.get_status_field("secondary_channel")
309 raise Exception("Unexpected secondary channel: " + sec)
311 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
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",
318 "ht_capab": "[HT40-]"}
319 hostapd.add_ap(apdev[1], params)
321 params = { "ssid": "test-ht40",
323 "ht_capab": "[HT40-]"}
324 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
326 state = hapd.get_status_field("state")
327 if state != "HT_SCAN":
329 state = hapd.get_status_field("state")
330 if state != "HT_SCAN":
331 raise Exception("Unexpected interface state - expected HT_SCAN")
333 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
335 raise Exception("AP setup timed out")
337 state = hapd.get_status_field("state")
338 if state != "ENABLED":
339 raise Exception("Unexpected interface state - expected ENABLED")
341 freq = hapd.get_status_field("freq")
343 raise Exception("Unexpected frequency")
344 pri = hapd.get_status_field("channel")
346 raise Exception("Unexpected primary channel")
347 sec = hapd.get_status_field("secondary_channel")
349 raise Exception("Unexpected secondary channel: " + sec)
351 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
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])
359 params = { "ssid": "test-ht40",
362 "country_code": "US",
363 "ht_capab": "[HT40+]"}
364 hapd2 = hostapd.add_ap(apdev[1], params)
366 params = { "ssid": "test-ht40",
369 "ht_capab": "[HT40+]"}
370 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
372 state = hapd.get_status_field("state")
373 if state != "HT_SCAN":
375 state = hapd.get_status_field("state")
376 if state != "HT_SCAN":
377 raise Exception("Unexpected interface state - expected HT_SCAN")
379 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
381 raise Exception("AP setup timed out")
383 state = hapd.get_status_field("state")
384 if state != "ENABLED":
385 raise Exception("Unexpected interface state - expected ENABLED")
387 freq = hapd.get_status_field("freq")
389 raise Exception("Unexpected frequency")
390 pri = hapd.get_status_field("channel")
392 raise Exception("Unexpected primary channel")
393 sec = hapd.get_status_field("secondary_channel")
395 raise Exception("Unexpected secondary channel: " + sec)
397 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
399 dev[0].request("DISCONNECT")
401 hapd.request("DISABLE")
403 hapd2.request("DISABLE")
404 set_world_reg(apdev[0], apdev[1], dev[0])
405 dev[0].flush_scan_cache()
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])
413 params = { "ssid": "test-ht40",
416 "country_code": "US",
417 "ht_capab": "[HT40+]"}
418 hapd2 = hostapd.add_ap(apdev[1], params)
420 params = { "ssid": "test-ht40",
423 "ht_capab": "[HT40-]"}
424 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
426 state = hapd.get_status_field("state")
427 if state != "HT_SCAN":
429 state = hapd.get_status_field("state")
430 if state != "HT_SCAN":
431 raise Exception("Unexpected interface state - expected HT_SCAN")
433 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
435 raise Exception("AP setup timed out")
437 state = hapd.get_status_field("state")
438 if state != "ENABLED":
439 raise Exception("Unexpected interface state - expected ENABLED")
441 freq = hapd.get_status_field("freq")
443 raise Exception("Unexpected frequency: " + freq)
444 pri = hapd.get_status_field("channel")
446 raise Exception("Unexpected primary channel: " + pri)
447 sec = hapd.get_status_field("secondary_channel")
449 raise Exception("Unexpected secondary channel: " + sec)
451 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
453 dev[0].request("DISCONNECT")
455 hapd.request("DISABLE")
457 hapd2.request("DISABLE")
458 set_world_reg(apdev[0], apdev[1], dev[0])
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])
466 params = { "ssid": "test-ht40",
469 "country_code": "US",
470 "ht_capab": "[HT40+]"}
471 hapd2 = hostapd.add_ap(apdev[1], params)
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)
482 params = { "ssid": "test-ht40",
485 "ht_capab": "[HT40-]"}
486 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
488 state = hapd.get_status_field("state")
489 if state != "HT_SCAN":
491 state = hapd.get_status_field("state")
492 if state != "HT_SCAN":
493 raise Exception("Unexpected interface state - expected HT_SCAN")
495 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
497 raise Exception("AP setup timed out")
499 state = hapd.get_status_field("state")
500 if state != "ENABLED":
501 raise Exception("Unexpected interface state - expected ENABLED")
503 freq = hapd.get_status_field("freq")
505 raise Exception("Unexpected frequency: " + freq)
506 pri = hapd.get_status_field("channel")
508 raise Exception("Unexpected primary channel: " + pri)
509 sec = hapd.get_status_field("secondary_channel")
511 raise Exception("Unexpected secondary channel: " + sec)
513 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
515 dev[0].request("DISCONNECT")
517 hapd.request("DISABLE")
519 hapd2.request("DISABLE")
520 set_world_reg(apdev[0], apdev[1], dev[0])
521 dev[0].flush_scan_cache()
523 def test_obss_scan(dev, apdev):
524 """Overlapping BSS scan request"""
525 params = { "ssid": "obss-scan",
527 "ht_capab": "[HT40-]",
528 "obss_interval": "10" }
529 hapd = hostapd.add_ap(apdev[0], params)
531 params = { "ssid": "another-bss",
534 hostapd.add_ap(apdev[1], params)
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)
541 raise Exception("Timed out while waiting for OBSS scan to start")
542 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
544 raise Exception("Timed out while waiting for OBSS scan results")
546 for i in range(0, 4):
547 frame = hapd.mgmt_rx(timeout=5)
549 raise Exception("MGMT RX wait timed out")
550 if frame['subtype'] != 13:
552 payload = frame['payload']
555 (category, action, ie) = struct.unpack('BBB', payload[0:3])
561 logger.info("20/40 BSS Coexistence report received")
565 raise Exception("20/40 BSS Coexistence report not seen")
567 def test_obss_scan_40_intolerant(dev, apdev):
568 """Overlapping BSS scan request with 40 MHz intolerant AP"""
569 params = { "ssid": "obss-scan",
571 "ht_capab": "[HT40-]",
572 "obss_interval": "10" }
573 hapd = hostapd.add_ap(apdev[0], params)
575 params = { "ssid": "another-bss",
577 "ht_capab": "[40-INTOLERANT]" }
578 hostapd.add_ap(apdev[1], params)
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)
585 raise Exception("Timed out while waiting for OBSS scan to start")
586 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
588 raise Exception("Timed out while waiting for OBSS scan results")
590 for i in range(0, 4):
591 frame = hapd.mgmt_rx(timeout=5)
593 raise Exception("MGMT RX wait timed out")
594 if frame['subtype'] != 13:
596 payload = frame['payload']
599 (category, action, ie) = struct.unpack('BBB', payload[0:3])
605 logger.info("20/40 BSS Coexistence report received")
609 raise Exception("20/40 BSS Coexistence report not seen")
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",
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")
621 sec = hapd.get_status_field("secondary_channel")
623 raise Exception("AP is not using 40 MHz channel")
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' ]
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")
636 sec = hapd.get_status_field("secondary_channel")
638 raise Exception("AP did not move to 20 MHz channel")
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",
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")
651 sec = hapd.get_status_field("secondary_channel")
653 raise Exception("AP is not using 40 MHz channel")
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")
661 sec = hapd.get_status_field("secondary_channel")
663 raise Exception("AP did not move to 20 MHz channel")
665 # No 20/40 MHz co-ex reports forcing 20 MHz channel during next interval
667 sec = hapd.get_status_field("secondary_channel")
672 raise Exception("AP did not return to 40 MHz channel")
674 def test_olbc(dev, apdev):
676 params = { "ssid": "test-olbc",
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")
685 params = { "ssid": "olbc-ap",
689 hostapd.add_ap(apdev[1], params)
691 status = hapd.get_status()
692 if status['olbc'] != '1' or status['olbc_ht'] != '1':
693 raise Exception("Missing OLBC information")
695 hostapd.remove_bss(apdev[1])
697 logger.info("Waiting for OLBC state to time out")
699 for i in range(0, 15):
701 status = hapd.get_status()
702 if status['olbc'] == '0' and status['olbc_ht'] == '0':
706 raise Exception("OLBC state did nto time out")
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')
717 params = { "ssid": "test-olbc",
719 "ap_table_max_size": "2" }
720 hapd = hostapd.add_ap(apdev[1], params)
723 with alloc_fail(hapd, 1, "ap_list_process_beacon"):
725 hapd.set("ap_table_max_size", "1")
727 hapd.set("ap_table_max_size", "0")
730 def test_olbc_5ghz(dev, apdev):
731 """OLBC detection on 5 GHz"""
735 params = { "ssid": "test-olbc",
736 "country_code": "FI",
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")
745 params = { "ssid": "olbc-ap",
746 "country_code": "FI",
751 hapd2 = hostapd.add_ap(apdev[1], params)
755 status = hapd.get_status()
756 logger.debug('olbc_ht: ' + status['olbc_ht'])
757 if status['olbc_ht'] == '1':
761 raise Exception("Missing OLBC information")
764 hapd.request("DISABLE")
766 hapd2.request("DISABLE")
767 set_world_reg(apdev[0], apdev[1], None)
769 def test_ap_require_ht(dev, apdev):
771 params = { "ssid": "require-ht",
773 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
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")
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",
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",
795 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
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")
803 raise Exception("Association rejection timed out")
804 if "status_code=27" not in ev:
805 raise Exception("Unexpected rejection status code")
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",
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")
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",
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")
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")
834 dev[2].connect("intolerant", key_mgmt="NONE", scan_freq="2437",
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)")
842 dev[2].request("DISCONNECT")
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)")
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",
854 "ht_capab": "[HT40-]",
855 "obss_interval": "3" }
856 hapd = hostapd.add_ap(apdev[0], params)
858 dev[0].connect("ht", key_mgmt="NONE", scan_freq="2437")
860 if hapd.get_status_field("secondary_channel") != "-1":
861 raise Exception("Unexpected secondary channel information")
863 logger.info("Start 40 MHz intolerant AP")
864 params = { "ssid": "intolerant",
866 "ht_capab": "[40-INTOLERANT]" }
867 hapd2 = hostapd.add_ap(apdev[1], params)
869 logger.info("Waiting for co-ex report from STA")
871 for i in range(0, 20):
873 if hapd.get_status_field("secondary_channel") == "0":
874 logger.info("AP moved to 20 MHz channel")
878 raise Exception("AP did not move to 20 MHz channel")
880 if "OK" not in hapd2.request("DISABLE"):
881 raise Exception("Failed to disable 40 MHz intolerant AP")
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()
888 logger.info("Waiting for AP to move back to 40 MHz channel")
890 for i in range(0, 30):
892 if hapd.get_status_field("secondary_channel") == "-1":
893 logger.info("AP moved to 40 MHz channel")
897 raise Exception("AP did not move to 40 MHz channel")
899 def test_ap_ht40_csa(dev, apdev):
900 """HT with 40 MHz channel width and CSA"""
901 csa_supported(dev[0])
904 params = { "ssid": "ht",
905 "country_code": "US",
908 "ht_capab": "[HT40+]",
910 hapd = hostapd.add_ap(apdev[0], params)
912 dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
913 hwsim_utils.test_connectivity(dev[0], hapd)
915 hapd.request("CHAN_SWITCH 5 5200 ht sec_channel_offset=-1 bandwidth=40")
916 ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
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)
923 raise Exception("Unexpected STA disconnection during CSA")
924 hwsim_utils.test_connectivity(dev[0], hapd)
926 hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
927 ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
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)
934 raise Exception("Unexpected STA disconnection during CSA")
935 hwsim_utils.test_connectivity(dev[0], hapd)
937 dev[0].request("DISCONNECT")
939 hapd.request("DISABLE")
940 set_world_reg(apdev[0], None, dev[0])
941 dev[0].flush_scan_cache()
943 def test_ap_ht40_csa2(dev, apdev):
944 """HT with 40 MHz channel width and CSA"""
945 csa_supported(dev[0])
948 params = { "ssid": "ht",
949 "country_code": "US",
952 "ht_capab": "[HT40+]",
954 hapd = hostapd.add_ap(apdev[0], params)
956 dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
957 hwsim_utils.test_connectivity(dev[0], hapd)
959 hapd.request("CHAN_SWITCH 5 5220 ht sec_channel_offset=1 bandwidth=40")
960 ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
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)
967 raise Exception("Unexpected STA disconnection during CSA")
968 hwsim_utils.test_connectivity(dev[0], hapd)
970 hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
971 ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
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)
978 raise Exception("Unexpected STA disconnection during CSA")
979 hwsim_utils.test_connectivity(dev[0], hapd)
981 dev[0].request("DISCONNECT")
983 hapd.request("DISABLE")
984 set_world_reg(apdev[0], None, dev[0])
985 dev[0].flush_scan_cache()
987 def test_ap_ht40_csa3(dev, apdev):
988 """HT with 40 MHz channel width and CSA"""
989 csa_supported(dev[0])
992 params = { "ssid": "ht",
993 "country_code": "US",
996 "ht_capab": "[HT40+]",
998 hapd = hostapd.add_ap(apdev[0], params)
1000 dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
1001 hwsim_utils.test_connectivity(dev[0], hapd)
1003 hapd.request("CHAN_SWITCH 5 5240 ht sec_channel_offset=-1 bandwidth=40")
1004 ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
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)
1011 raise Exception("Unexpected STA disconnection during CSA")
1012 hwsim_utils.test_connectivity(dev[0], hapd)
1014 hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
1015 ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
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)
1022 raise Exception("Unexpected STA disconnection during CSA")
1023 hwsim_utils.test_connectivity(dev[0], hapd)
1025 dev[0].request("DISCONNECT")
1027 hapd.request("DISABLE")
1028 set_world_reg(apdev[0], None, dev[0])
1029 dev[0].flush_scan_cache()
1031 def test_ap_ht_smps(dev, apdev):
1032 """SMPS AP configuration options"""
1033 params = { "ssid": "ht1", "ht_capab": "[SMPS-STATIC]" }
1035 hapd = hostapd.add_ap(apdev[0], params)
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)
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)
1046 def test_prefer_ht20(dev, apdev):
1047 """Preference on HT20 over no-HT"""
1048 params = { "ssid": "test",
1051 hapd = hostapd.add_ap(apdev[0], params)
1052 bssid = apdev[0]['bssid']
1053 params = { "ssid": "test",
1056 hapd2 = hostapd.add_ap(apdev[1], params)
1057 bssid2 = apdev[1]['bssid']
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")
1065 est = dev[0].get_bss(bssid)['est_throughput']
1067 raise Exception("Unexpected BSS0 est_throughput: " + est)
1069 est = dev[0].get_bss(bssid2)['est_throughput']
1071 raise Exception("Unexpected BSS1 est_throughput: " + est)
1073 def test_prefer_ht40(dev, apdev):
1074 """Preference on HT40 over HT20"""
1075 params = { "ssid": "test",
1078 hapd = hostapd.add_ap(apdev[0], params)
1079 bssid = apdev[0]['bssid']
1080 params = { "ssid": "test",
1083 "ht_capab": "[HT40+]" }
1084 hapd2 = hostapd.add_ap(apdev[1], params)
1085 bssid2 = apdev[1]['bssid']
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")
1093 est = dev[0].get_bss(bssid)['est_throughput']
1095 raise Exception("Unexpected BSS0 est_throughput: " + est)
1097 est = dev[0].get_bss(bssid2)['est_throughput']
1099 raise Exception("Unexpected BSS1 est_throughput: " + est)
1101 def test_prefer_ht20_during_roam(dev, apdev):
1102 """Preference on HT20 over no-HT in roaming consideration"""
1103 params = { "ssid": "test",
1106 hapd = hostapd.add_ap(apdev[0], params)
1107 bssid = apdev[0]['bssid']
1109 dev[0].scan_for_bss(bssid, freq=2412)
1110 dev[0].connect("test", key_mgmt="NONE", scan_freq="2412")
1112 params = { "ssid": "test",
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()
1121 if dev[0].get_status_field('bssid') != bssid2:
1122 raise Exception("Unexpected BSS selected")
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])
1128 params = { "ssid": "test-ht40",
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)
1136 raise Exception("AP setup failure timed out")
1137 if "AP-ENABLED" in ev:
1138 sec = hapd.get_status_field("secondary_channel")
1140 raise Exception("Invalid 40 MHz channel accepted")
1142 set_world_reg(apdev[0], None, None)
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])
1148 params = { "ssid": "test-ht40",
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)
1156 raise Exception("AP setup failure timed out")
1157 if "AP-ENABLED" in ev:
1158 sec = hapd.get_status_field("secondary_channel")
1160 raise Exception("Invalid 40 MHz channel accepted")
1162 set_world_reg(apdev[0], None, None)
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])
1168 # Broken AP: Include HT Capabilities element but not HT Operation element
1169 params = { "ssid": "legacy-20",
1170 "channel": "7", "ieee80211n": "0",
1172 "vendor_elements": "2d1a0e001bffff000000000000000000000100000000000000000000" }
1173 hapd2 = hostapd.add_ap(apdev[1], params)
1175 params = { "ssid": "test-ht40",
1177 "ht_capab": "[HT40-]"}
1178 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
1180 state = hapd.get_status_field("state")
1181 if state != "HT_SCAN":
1183 state = hapd.get_status_field("state")
1184 if state != "HT_SCAN":
1185 raise Exception("Unexpected interface state - expected HT_SCAN")
1187 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
1189 raise Exception("AP setup timed out")
1191 state = hapd.get_status_field("state")
1192 if state != "ENABLED":
1193 raise Exception("Unexpected interface state - expected ENABLED")
1195 freq = hapd.get_status_field("freq")
1197 raise Exception("Unexpected frequency: " + freq)
1198 pri = hapd.get_status_field("channel")
1200 raise Exception("Unexpected primary channel: " + pri)
1201 sec = hapd.get_status_field("secondary_channel")
1203 raise Exception("Unexpected secondary channel: " + sec)
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)