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