]>
Commit | Line | Data |
---|---|---|
709f18d5 JM |
1 | # Test cases for dynamic BSS changes with hostapd |
2 | # Copyright (c) 2013, Qualcomm Atheros, Inc. | |
3 | # | |
4 | # This software may be distributed under the terms of the BSD license. | |
5 | # See README for more details. | |
6 | ||
7 | import time | |
8 | import subprocess | |
9 | import logging | |
c9aa4308 | 10 | logger = logging.getLogger() |
709f18d5 JM |
11 | |
12 | import hwsim_utils | |
13 | import hostapd | |
14 | ||
15 | def test_ap_change_ssid(dev, apdev): | |
16 | """Dynamic SSID change with hostapd and WPA2-PSK""" | |
17 | params = hostapd.wpa2_params(ssid="test-wpa2-psk-start", | |
18 | passphrase="12345678") | |
19 | hostapd.add_ap(apdev[0]['ifname'], params) | |
c65f23ab JM |
20 | id = dev[0].connect("test-wpa2-psk-start", psk="12345678", |
21 | scan_freq="2412") | |
709f18d5 JM |
22 | dev[0].request("DISCONNECT") |
23 | ||
24 | logger.info("Change SSID dynamically") | |
25 | hapd = hostapd.Hostapd(apdev[0]['ifname']) | |
26 | res = hapd.request("SET ssid test-wpa2-psk-new") | |
27 | if "OK" not in res: | |
28 | raise Exception("SET command failed") | |
29 | res = hapd.request("RELOAD") | |
30 | if "OK" not in res: | |
31 | raise Exception("RELOAD command failed") | |
32 | ||
33 | dev[0].set_network_quoted(id, "ssid", "test-wpa2-psk-new") | |
34 | dev[0].connect_network(id) | |
a6333977 | 35 | |
78060b25 JM |
36 | def multi_check(dev, check): |
37 | id = [] | |
dd6f538e JM |
38 | num_bss = len(check) |
39 | for i in range(0, num_bss): | |
78060b25 JM |
40 | dev[i].request("BSS_FLUSH 0") |
41 | dev[i].dump_monitor() | |
42 | id.append(dev[i].connect("bss-" + str(i + 1), key_mgmt="NONE", | |
43 | scan_freq="2412", wait_connect=check[i])) | |
dd6f538e | 44 | for i in range(0, num_bss): |
78060b25 JM |
45 | if not check[i]: |
46 | ev = dev[i].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.2) | |
47 | if ev: | |
48 | raise Exception("Unexpected connection") | |
49 | ||
dd6f538e | 50 | for i in range(0, num_bss): |
78060b25 | 51 | dev[i].remove_network(id[i]) |
a6333977 JM |
52 | |
53 | time.sleep(0.3) | |
54 | ||
78060b25 | 55 | res = '' |
dd6f538e | 56 | for i in range(0, num_bss): |
78060b25 | 57 | res = res + dev[i].request("BSS RANGE=ALL MASK=0x2") |
a6333977 | 58 | |
dd6f538e | 59 | for i in range(0, num_bss): |
78060b25 JM |
60 | if not check[i]: |
61 | bssid = '02:00:00:00:03:0' + str(i) | |
62 | if bssid in res: | |
63 | raise Exception("Unexpected BSS" + str(i) + " in scan results") | |
a6333977 JM |
64 | |
65 | def test_ap_bss_add_remove(dev, apdev): | |
66 | """Dynamic BSS add/remove operations with hostapd""" | |
a6333977 JM |
67 | ifname1 = apdev[0]['ifname'] |
68 | ifname2 = apdev[0]['ifname'] + '-2' | |
69 | ifname3 = apdev[0]['ifname'] + '-3' | |
70 | logger.info("Set up three BSSes one by one") | |
71 | hostapd.add_bss('phy3', ifname1, 'bss-1.conf') | |
78060b25 | 72 | multi_check(dev, [ True, False, False ]) |
a6333977 | 73 | hostapd.add_bss('phy3', ifname2, 'bss-2.conf') |
78060b25 | 74 | multi_check(dev, [ True, True, False ]) |
a6333977 | 75 | hostapd.add_bss('phy3', ifname3, 'bss-3.conf') |
78060b25 | 76 | multi_check(dev, [ True, True, True ]) |
a6333977 JM |
77 | |
78 | logger.info("Remove the last BSS and re-add it") | |
79 | hostapd.remove_bss(ifname3) | |
78060b25 | 80 | multi_check(dev, [ True, True, False ]) |
a6333977 | 81 | hostapd.add_bss('phy3', ifname3, 'bss-3.conf') |
78060b25 | 82 | multi_check(dev, [ True, True, True ]) |
a6333977 JM |
83 | |
84 | logger.info("Remove the middle BSS and re-add it") | |
85 | hostapd.remove_bss(ifname2) | |
78060b25 | 86 | multi_check(dev, [ True, False, True ]) |
a6333977 | 87 | hostapd.add_bss('phy3', ifname2, 'bss-2.conf') |
78060b25 | 88 | multi_check(dev, [ True, True, True ]) |
a6333977 | 89 | |
a364852b | 90 | logger.info("Remove the first BSS and re-add it and other BSSs") |
a6333977 | 91 | hostapd.remove_bss(ifname1) |
a364852b | 92 | multi_check(dev, [ False, False, False ]) |
a6333977 | 93 | hostapd.add_bss('phy3', ifname1, 'bss-1.conf') |
a6333977 | 94 | hostapd.add_bss('phy3', ifname2, 'bss-2.conf') |
a6333977 | 95 | hostapd.add_bss('phy3', ifname3, 'bss-3.conf') |
78060b25 | 96 | multi_check(dev, [ True, True, True ]) |
a6333977 | 97 | |
a364852b | 98 | logger.info("Remove two BSSes and re-add them") |
a6333977 | 99 | hostapd.remove_bss(ifname2) |
a364852b | 100 | multi_check(dev, [ True, False, True ]) |
a6333977 | 101 | hostapd.remove_bss(ifname3) |
78060b25 | 102 | multi_check(dev, [ True, False, False ]) |
a6333977 | 103 | hostapd.add_bss('phy3', ifname2, 'bss-2.conf') |
78060b25 | 104 | multi_check(dev, [ True, True, False ]) |
a6333977 | 105 | hostapd.add_bss('phy3', ifname3, 'bss-3.conf') |
78060b25 | 106 | multi_check(dev, [ True, True, True ]) |
a6333977 | 107 | |
a364852b | 108 | logger.info("Remove three BSSes in and re-add them") |
a6333977 | 109 | hostapd.remove_bss(ifname3) |
78060b25 | 110 | multi_check(dev, [ True, True, False ]) |
a6333977 | 111 | hostapd.remove_bss(ifname2) |
78060b25 | 112 | multi_check(dev, [ True, False, False ]) |
a6333977 | 113 | hostapd.remove_bss(ifname1) |
77990cd7 | 114 | multi_check(dev, [ False, False, False ]) |
a6333977 | 115 | hostapd.add_bss('phy3', ifname1, 'bss-1.conf') |
78060b25 | 116 | multi_check(dev, [ True, False, False ]) |
a6333977 | 117 | hostapd.add_bss('phy3', ifname2, 'bss-2.conf') |
78060b25 | 118 | multi_check(dev, [ True, True, False ]) |
a6333977 | 119 | hostapd.add_bss('phy3', ifname3, 'bss-3.conf') |
78060b25 | 120 | multi_check(dev, [ True, True, True ]) |
a6333977 JM |
121 | |
122 | logger.info("Test error handling if a duplicate ifname is tried") | |
123 | hostapd.add_bss('phy3', ifname3, 'bss-3.conf', ignore_error=True) | |
78060b25 | 124 | multi_check(dev, [ True, True, True ]) |
5230bf64 | 125 | |
dd6f538e JM |
126 | def test_ap_bss_add_remove_during_ht_scan(dev, apdev): |
127 | """Dynamic BSS add during HT40 co-ex scan""" | |
dd6f538e JM |
128 | ifname1 = apdev[0]['ifname'] |
129 | ifname2 = apdev[0]['ifname'] + '-2' | |
130 | hostapd.add_bss('phy3', ifname1, 'bss-ht40-1.conf') | |
131 | hostapd.add_bss('phy3', ifname2, 'bss-ht40-2.conf') | |
132 | multi_check(dev, [ True, True ]) | |
133 | hostapd.remove_bss(ifname2) | |
134 | hostapd.remove_bss(ifname1) | |
135 | ||
136 | hostapd.add_bss('phy3', ifname1, 'bss-ht40-1.conf') | |
137 | hostapd.add_bss('phy3', ifname2, 'bss-ht40-2.conf') | |
138 | hostapd.remove_bss(ifname2) | |
139 | multi_check(dev, [ True, False ]) | |
140 | hostapd.remove_bss(ifname1) | |
141 | ||
142 | hostapd.add_bss('phy3', ifname1, 'bss-ht40-1.conf') | |
143 | hostapd.add_bss('phy3', ifname2, 'bss-ht40-2.conf') | |
144 | hostapd.remove_bss(ifname1) | |
145 | multi_check(dev, [ False, False ]) | |
146 | ||
77990cd7 JM |
147 | def test_ap_multi_bss_config(dev, apdev): |
148 | """hostapd start with a multi-BSS configuration file""" | |
77990cd7 JM |
149 | ifname1 = apdev[0]['ifname'] |
150 | ifname2 = apdev[0]['ifname'] + '-2' | |
151 | ifname3 = apdev[0]['ifname'] + '-3' | |
152 | logger.info("Set up three BSSes with one configuration file") | |
153 | hostapd.add_iface(ifname1, 'multi-bss.conf') | |
154 | hapd = hostapd.Hostapd(ifname1) | |
155 | hapd.enable() | |
156 | multi_check(dev, [ True, True, True ]) | |
77990cd7 | 157 | hostapd.remove_bss(ifname2) |
a364852b | 158 | multi_check(dev, [ True, False, True ]) |
77990cd7 | 159 | hostapd.remove_bss(ifname3) |
a364852b JM |
160 | multi_check(dev, [ True, False, False ]) |
161 | hostapd.remove_bss(ifname1) | |
162 | multi_check(dev, [ False, False, False ]) | |
163 | ||
164 | hostapd.add_iface(ifname1, 'multi-bss.conf') | |
165 | hapd = hostapd.Hostapd(ifname1) | |
166 | hapd.enable() | |
167 | hostapd.remove_bss(ifname1) | |
77990cd7 JM |
168 | multi_check(dev, [ False, False, False ]) |
169 | ||
5230bf64 JM |
170 | def invalid_ap(hapd_global, ifname): |
171 | logger.info("Trying to start AP " + ifname + " with invalid configuration") | |
172 | hapd_global.remove(ifname) | |
173 | hapd_global.add(ifname) | |
174 | hapd = hostapd.Hostapd(ifname) | |
175 | if not hapd.ping(): | |
176 | raise Exception("Could not ping hostapd") | |
177 | hapd.set_defaults() | |
178 | hapd.set("ssid", "invalid-config") | |
179 | hapd.set("channel", "12345") | |
180 | try: | |
181 | hapd.enable() | |
182 | started = True | |
183 | except Exception, e: | |
184 | started = False | |
185 | if started: | |
186 | raise Exception("ENABLE command succeeded unexpectedly") | |
187 | return hapd | |
188 | ||
189 | def test_ap_invalid_config(dev, apdev): | |
190 | """Try to start AP with invalid configuration and fix configuration""" | |
191 | hapd_global = hostapd.HostapdGlobal() | |
192 | ifname = apdev[0]['ifname'] | |
193 | hapd = invalid_ap(hapd_global, ifname) | |
194 | ||
195 | logger.info("Fix configuration and start AP again") | |
196 | hapd.set("channel", "1") | |
197 | hapd.enable() | |
198 | dev[0].connect("invalid-config", key_mgmt="NONE", scan_freq="2412") | |
199 | ||
200 | def test_ap_invalid_config2(dev, apdev): | |
201 | """Try to start AP with invalid configuration and remove interface""" | |
202 | hapd_global = hostapd.HostapdGlobal() | |
203 | ifname = apdev[0]['ifname'] | |
204 | hapd = invalid_ap(hapd_global, ifname) | |
205 | logger.info("Remove interface with failed configuration") | |
206 | hapd_global.remove(ifname) | |
742117ad JM |
207 | |
208 | def test_ap_remove_during_acs(dev, apdev): | |
209 | """Remove interface during ACS""" | |
210 | params = hostapd.wpa2_params(ssid="test-acs-remove", passphrase="12345678") | |
211 | params['channel'] = '0' | |
212 | ifname = apdev[0]['ifname'] | |
213 | hapd = hostapd.HostapdGlobal() | |
214 | hostapd.add_ap(ifname, params) | |
215 | hapd.remove(ifname) | |
216 | ||
217 | def test_ap_remove_during_acs2(dev, apdev): | |
218 | """Remove BSS during ACS in multi-BSS configuration""" | |
219 | ifname = apdev[0]['ifname'] | |
220 | ifname2 = ifname + "-2" | |
221 | hapd_global = hostapd.HostapdGlobal() | |
222 | hapd_global.add(ifname) | |
223 | hapd = hostapd.Hostapd(ifname) | |
224 | hapd.set_defaults() | |
225 | hapd.set("ssid", "test-acs-remove") | |
226 | hapd.set("channel", "0") | |
227 | hapd.set("bss", ifname2) | |
228 | hapd.set("ssid", "test-acs-remove2") | |
229 | hapd.enable() | |
230 | hapd_global.remove(ifname) | |
231 | ||
232 | def test_ap_remove_during_acs3(dev, apdev): | |
233 | """Remove second BSS during ACS in multi-BSS configuration""" | |
234 | ifname = apdev[0]['ifname'] | |
235 | ifname2 = ifname + "-2" | |
236 | hapd_global = hostapd.HostapdGlobal() | |
237 | hapd_global.add(ifname) | |
238 | hapd = hostapd.Hostapd(ifname) | |
239 | hapd.set_defaults() | |
240 | hapd.set("ssid", "test-acs-remove") | |
241 | hapd.set("channel", "0") | |
242 | hapd.set("bss", ifname2) | |
243 | hapd.set("ssid", "test-acs-remove2") | |
244 | hapd.enable() | |
245 | hapd_global.remove(ifname2) | |
246 | ||
247 | def test_ap_remove_during_ht_coex_scan(dev, apdev): | |
248 | """Remove interface during HT co-ex scan""" | |
249 | params = hostapd.wpa2_params(ssid="test-ht-remove", passphrase="12345678") | |
250 | params['channel'] = '1' | |
251 | params['ht_capab'] = "[HT40+]" | |
252 | ifname = apdev[0]['ifname'] | |
253 | hapd = hostapd.HostapdGlobal() | |
254 | hostapd.add_ap(ifname, params) | |
255 | hapd.remove(ifname) | |
256 | ||
257 | def test_ap_remove_during_ht_coex_scan2(dev, apdev): | |
258 | """Remove BSS during HT co-ex scan in multi-BSS configuration""" | |
259 | ifname = apdev[0]['ifname'] | |
260 | ifname2 = ifname + "-2" | |
261 | hapd_global = hostapd.HostapdGlobal() | |
262 | hapd_global.add(ifname) | |
263 | hapd = hostapd.Hostapd(ifname) | |
264 | hapd.set_defaults() | |
265 | hapd.set("ssid", "test-ht-remove") | |
266 | hapd.set("channel", "1") | |
267 | hapd.set("ht_capab", "[HT40+]") | |
268 | hapd.set("bss", ifname2) | |
269 | hapd.set("ssid", "test-ht-remove2") | |
270 | hapd.enable() | |
271 | hapd_global.remove(ifname) | |
272 | ||
273 | def test_ap_remove_during_ht_coex_scan3(dev, apdev): | |
274 | """Remove second BSS during HT co-ex scan in multi-BSS configuration""" | |
275 | ifname = apdev[0]['ifname'] | |
276 | ifname2 = ifname + "-2" | |
277 | hapd_global = hostapd.HostapdGlobal() | |
278 | hapd_global.add(ifname) | |
279 | hapd = hostapd.Hostapd(ifname) | |
280 | hapd.set_defaults() | |
281 | hapd.set("ssid", "test-ht-remove") | |
282 | hapd.set("channel", "1") | |
283 | hapd.set("ht_capab", "[HT40+]") | |
284 | hapd.set("bss", ifname2) | |
285 | hapd.set("ssid", "test-ht-remove2") | |
286 | hapd.enable() | |
287 | hapd_global.remove(ifname2) | |
00f74dbd JM |
288 | |
289 | def test_ap_enable_disable_reenable(dev, apdev): | |
290 | """Enable, disable, re-enable AP""" | |
291 | ifname = apdev[0]['ifname'] | |
292 | hapd_global = hostapd.HostapdGlobal() | |
293 | hapd_global.add(ifname) | |
294 | hapd = hostapd.Hostapd(ifname) | |
295 | hapd.set_defaults() | |
296 | hapd.set("ssid", "dynamic") | |
297 | hapd.enable() | |
298 | ev = hapd.wait_event(["AP-ENABLED"], timeout=30) | |
299 | if ev is None: | |
300 | raise Exception("AP startup timed out") | |
301 | dev[0].connect("dynamic", key_mgmt="NONE", scan_freq="2412") | |
302 | hapd.disable() | |
303 | ev = hapd.wait_event(["AP-DISABLED"], timeout=30) | |
304 | if ev is None: | |
305 | raise Exception("AP disabling timed out") | |
5f35a5e2 | 306 | dev[0].wait_disconnected(timeout=10) |
00f74dbd JM |
307 | hapd.enable() |
308 | ev = hapd.wait_event(["AP-ENABLED"], timeout=30) | |
309 | if ev is None: | |
310 | raise Exception("AP startup timed out") | |
311 | dev[1].connect("dynamic", key_mgmt="NONE", scan_freq="2412") | |
5f35a5e2 | 312 | dev[0].wait_connected(timeout=10) |
de93da91 JM |
313 | |
314 | def test_ap_double_disable(dev, apdev): | |
315 | """Double DISABLE regression test""" | |
316 | hostapd.add_bss('phy3', apdev[0]['ifname'], 'bss-1.conf') | |
317 | hostapd.add_bss('phy3', apdev[0]['ifname'] + '-2', 'bss-2.conf') | |
318 | hapd = hostapd.Hostapd(apdev[0]['ifname']) | |
319 | hapd.disable() | |
320 | if "FAIL" not in hapd.request("DISABLE"): | |
321 | raise Exception("Second DISABLE accepted unexpectedly") | |
322 | hapd.enable() | |
323 | hapd.disable() | |
324 | if "FAIL" not in hapd.request("DISABLE"): | |
325 | raise Exception("Second DISABLE accepted unexpectedly") |