]>
Commit | Line | Data |
---|---|---|
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 | 7 | from remotehost import remote_compatible |
1b3926ef JM |
8 | import time |
9 | import logging | |
10 | logger = logging.getLogger() | |
084316bf | 11 | import struct |
1b3926ef JM |
12 | |
13 | import hostapd | |
cdebd24d | 14 | from utils import HwsimSkip, alloc_fail |
99e5f0e6 JM |
15 | import hwsim_utils |
16 | from test_ap_csa import csa_supported | |
1b3926ef | 17 | |
cb3c0d96 JA |
18 | def 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 |
26 | def 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 |
34 | def 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 |
70 | def 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 |
111 | def 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 |
151 | def 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 |
199 | def 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 |
239 | def 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 |
278 | def 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 |
318 | def 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 | ||
358 | def 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 | |
412 | def 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 | |
465 | def 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 |
528 | def 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 | ||
572 | def 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 |
616 | def 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 | ||
645 | def 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 |
679 | def 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 |
713 | def 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 |
735 | def 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 |
774 | def 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 |
796 | def 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 |
814 | def 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 | |
823 | def 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 | ||
856 | def 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 | |
906 | def 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 | |
950 | def 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 | |
994 | def 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 |
1039 | def 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 |
1055 | def 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 | ||
1082 | def 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 |
1111 | def 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 |
1135 | def 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 |
1156 | def 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 | |
1176 | def 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) |