]> git.ipfire.org Git - thirdparty/hostap.git/blob - tests/hwsim/test_scan.py
tests: Make HS 2.0 test cases more robust
[thirdparty/hostap.git] / tests / hwsim / test_scan.py
1 # Scanning tests
2 # Copyright (c) 2013, Jouni Malinen <j@w1.fi>
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 logging
9 logger = logging.getLogger()
10 import os
11 import subprocess
12
13 import hostapd
14
15 def check_scan(dev, params, other_started=False):
16 if not other_started:
17 dev.dump_monitor()
18 id = dev.request("SCAN " + params)
19 if "FAIL" in id:
20 raise Exception("Failed to start scan")
21 id = int(id)
22
23 if other_started:
24 ev = dev.wait_event(["CTRL-EVENT-SCAN-STARTED"])
25 if ev is None:
26 raise Exception("Other scan did not start")
27 if "id=" + str(id) in ev:
28 raise Exception("Own scan id unexpectedly included in start event")
29
30 ev = dev.wait_event(["CTRL-EVENT-SCAN-RESULTS"])
31 if ev is None:
32 raise Exception("Other scan did not complete")
33 if "id=" + str(id) in ev:
34 raise Exception("Own scan id unexpectedly included in completed event")
35
36 ev = dev.wait_event(["CTRL-EVENT-SCAN-STARTED"])
37 if ev is None:
38 raise Exception("Scan did not start")
39 if "id=" + str(id) not in ev:
40 raise Exception("Scan id not included in start event")
41
42 ev = dev.wait_event(["CTRL-EVENT-SCAN-RESULTS"])
43 if ev is None:
44 raise Exception("Scan did not complete")
45 if "id=" + str(id) not in ev:
46 raise Exception("Scan id not included in completed event")
47
48 def check_scan_retry(dev, params, bssid):
49 for i in range(0, 5):
50 check_scan(dev, "freq=2412-2462,5180 use_id=1")
51 if int(dev.get_bss(bssid)['age']) <= 1:
52 return
53 raise Exception("Unexpectedly old BSS entry")
54
55 def test_scan(dev, apdev):
56 """Control interface behavior on scan parameters"""
57 hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" })
58 bssid = apdev[0]['bssid']
59
60 logger.info("Full scan")
61 check_scan(dev[0], "use_id=1")
62
63 logger.info("Limited channel scan")
64 check_scan_retry(dev[0], "freq=2412-2462,5180 use_id=1", bssid)
65
66 # wait long enough to allow next scans to be verified not to find the AP
67 time.sleep(2)
68
69 logger.info("Passive single-channel scan")
70 check_scan(dev[0], "freq=2457 passive=1 use_id=1")
71 logger.info("Active single-channel scan")
72 check_scan(dev[0], "freq=2452 passive=0 use_id=1")
73 if int(dev[0].get_bss(bssid)['age']) < 2:
74 raise Exception("Unexpectedly updated BSS entry")
75
76 logger.info("Active single-channel scan on AP's operating channel")
77 check_scan_retry(dev[0], "freq=2412 passive=0 use_id=1", bssid)
78
79 def test_scan_only(dev, apdev):
80 """Control interface behavior on scan parameters with type=only"""
81 hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" })
82 bssid = apdev[0]['bssid']
83
84 logger.info("Full scan")
85 check_scan(dev[0], "type=only use_id=1")
86
87 logger.info("Limited channel scan")
88 check_scan_retry(dev[0], "type=only freq=2412-2462,5180 use_id=1", bssid)
89
90 # wait long enough to allow next scans to be verified not to find the AP
91 time.sleep(2)
92
93 logger.info("Passive single-channel scan")
94 check_scan(dev[0], "type=only freq=2457 passive=1 use_id=1")
95 logger.info("Active single-channel scan")
96 check_scan(dev[0], "type=only freq=2452 passive=0 use_id=1")
97 if int(dev[0].get_bss(bssid)['age']) < 2:
98 raise Exception("Unexpectedly updated BSS entry")
99
100 logger.info("Active single-channel scan on AP's operating channel")
101 check_scan_retry(dev[0], "type=only freq=2412 passive=0 use_id=1", bssid)
102
103 def test_scan_external_trigger(dev, apdev):
104 """Avoid operations during externally triggered scan"""
105 hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" })
106 bssid = apdev[0]['bssid']
107 subprocess.call(['sudo', 'iw', dev[0].ifname, 'scan', 'trigger'])
108 check_scan(dev[0], "use_id=1", other_started=True)
109
110 def test_scan_bss_expiration_count(dev, apdev):
111 """BSS entry expiration based on scan results without match"""
112 if "FAIL" not in dev[0].request("BSS_EXPIRE_COUNT 0"):
113 raise Exception("Invalid BSS_EXPIRE_COUNT accepted")
114 if "OK" not in dev[0].request("BSS_EXPIRE_COUNT 2"):
115 raise Exception("BSS_EXPIRE_COUNT failed")
116 hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" })
117 bssid = apdev[0]['bssid']
118 dev[0].scan(freq="2412", only_new=True)
119 if bssid not in dev[0].request("SCAN_RESULTS"):
120 raise Exception("BSS not found in initial scan")
121 hapd.request("DISABLE")
122 dev[0].scan(freq="2412", only_new=True)
123 if bssid not in dev[0].request("SCAN_RESULTS"):
124 raise Exception("BSS not found in first scan without match")
125 dev[0].scan(freq="2412", only_new=True)
126 if bssid in dev[0].request("SCAN_RESULTS"):
127 raise Exception("BSS found after two scans without match")
128
129 def test_scan_bss_expiration_age(dev, apdev):
130 """BSS entry expiration based on age"""
131 try:
132 if "FAIL" not in dev[0].request("BSS_EXPIRE_AGE COUNT 9"):
133 raise Exception("Invalid BSS_EXPIRE_AGE accepted")
134 if "OK" not in dev[0].request("BSS_EXPIRE_AGE 10"):
135 raise Exception("BSS_EXPIRE_AGE failed")
136 hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" })
137 bssid = apdev[0]['bssid']
138 dev[0].scan(freq="2412")
139 if bssid not in dev[0].request("SCAN_RESULTS"):
140 raise Exception("BSS not found in initial scan")
141 hapd.request("DISABLE")
142 logger.info("Waiting for BSS entry to expire")
143 time.sleep(7)
144 if bssid not in dev[0].request("SCAN_RESULTS"):
145 raise Exception("BSS expired too quickly")
146 ev = dev[0].wait_event(["CTRL-EVENT-BSS-REMOVED"], timeout=15)
147 if ev is None:
148 raise Exception("BSS entry expiration timed out")
149 if bssid in dev[0].request("SCAN_RESULTS"):
150 raise Exception("BSS not removed after expiration time")
151 finally:
152 dev[0].request("BSS_EXPIRE_AGE 180")
153
154 def test_scan_filter(dev, apdev):
155 """Filter scan results based on SSID"""
156 try:
157 if "OK" not in dev[0].request("SET filter_ssids 1"):
158 raise Exception("SET failed")
159 dev[0].connect("test-scan", key_mgmt="NONE", only_add_network=True)
160 hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" })
161 bssid = apdev[0]['bssid']
162 hostapd.add_ap(apdev[1]['ifname'], { "ssid": "test-scan2" })
163 bssid2 = apdev[1]['bssid']
164 dev[0].scan(freq="2412", only_new=True)
165 if bssid not in dev[0].request("SCAN_RESULTS"):
166 raise Exception("BSS not found in scan results")
167 if bssid2 in dev[0].request("SCAN_RESULTS"):
168 raise Exception("Unexpected BSS found in scan results")
169 finally:
170 dev[0].request("SET filter_ssids 0")
171
172 def test_scan_int(dev, apdev):
173 """scan interval configuration"""
174 try:
175 if "FAIL" not in dev[0].request("SCAN_INTERVAL -1"):
176 raise Exception("Accepted invalid scan interval")
177 if "OK" not in dev[0].request("SCAN_INTERVAL 1"):
178 raise Exception("Failed to set scan interval")
179 dev[0].connect("not-used", key_mgmt="NONE", scan_freq="2412",
180 wait_connect=False)
181 times = {}
182 for i in range(0, 3):
183 logger.info("Waiting for scan to start")
184 start = os.times()[4]
185 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
186 if ev is None:
187 raise Exception("did not start a scan")
188 stop = os.times()[4]
189 times[i] = stop - start
190 logger.info("Waiting for scan to complete")
191 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 10)
192 if ev is None:
193 raise Exception("did not complete a scan")
194 print times
195 if times[0] > 1 or times[1] < 0.5 or times[1] > 1.5 or times[2] < 0.5 or times[2] > 1.5:
196 raise Exception("Unexpected scan timing: " + str(times))
197 finally:
198 dev[0].request("SCAN_INTERVAL 5")
199
200 def test_scan_bss_operations(dev, apdev):
201 """Control interface behavior on BSS parameters"""
202 hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" })
203 bssid = apdev[0]['bssid']
204 hostapd.add_ap(apdev[1]['ifname'], { "ssid": "test2-scan" })
205 bssid2 = apdev[1]['bssid']
206
207 dev[0].scan(freq="2412")
208 dev[0].scan(freq="2412")
209 dev[0].scan(freq="2412")
210
211 id1 = dev[0].request("BSS FIRST MASK=0x1").splitlines()[0].split('=')[1]
212 id2 = dev[0].request("BSS LAST MASK=0x1").splitlines()[0].split('=')[1]
213
214 res = dev[0].request("BSS RANGE=ALL MASK=0x20001")
215 if "id=" + id1 not in res:
216 raise Exception("Missing BSS " + id1)
217 if "id=" + id2 not in res:
218 raise Exception("Missing BSS " + id2)
219 if "====" not in res:
220 raise Exception("Missing delim")
221 if "####" not in res:
222 raise Exception("Missing end")
223
224 res = dev[0].request("BSS RANGE=ALL MASK=0x1").splitlines()
225 if len(res) != 2:
226 raise Exception("Unexpected result")
227 res = dev[0].request("BSS FIRST MASK=0x1")
228 if "id=" + id1 not in res:
229 raise Exception("Unexpected result: " + res)
230 res = dev[0].request("BSS LAST MASK=0x1")
231 if "id=" + id2 not in res:
232 raise Exception("Unexpected result: " + res)
233 res = dev[0].request("BSS ID-" + id1 + " MASK=0x1")
234 if "id=" + id1 not in res:
235 raise Exception("Unexpected result: " + res)
236 res = dev[0].request("BSS NEXT-" + id1 + " MASK=0x1")
237 if "id=" + id2 not in res:
238 raise Exception("Unexpected result: " + res)
239
240 if len(dev[0].request("BSS RANGE=" + id2 + " MASK=0x1").splitlines()) != 0:
241 raise Exception("Unexpected RANGE=1 result")
242 if len(dev[0].request("BSS RANGE=" + id1 + "- MASK=0x1").splitlines()) != 2:
243 raise Exception("Unexpected RANGE=0- result")
244 if len(dev[0].request("BSS RANGE=-" + id2 + " MASK=0x1").splitlines()) != 2:
245 raise Exception("Unexpected RANGE=-1 result")
246 if len(dev[0].request("BSS RANGE=" + id1 + "-" + id2 + " MASK=0x1").splitlines()) != 2:
247 raise Exception("Unexpected RANGE=0-1 result")
248 if len(dev[0].request("BSS RANGE=" + id2 + "-" + id2 + " MASK=0x1").splitlines()) != 1:
249 raise Exception("Unexpected RANGE=1-1 result")
250 if len(dev[0].request("BSS RANGE=" + str(int(id2) + 1) + "-" + str(int(id2) + 10) + " MASK=0x1").splitlines()) != 0:
251 raise Exception("Unexpected RANGE=2-10 result")
252 if len(dev[0].request("BSS RANGE=0-" + str(int(id2) + 10) + " MASK=0x1").splitlines()) != 2:
253 raise Exception("Unexpected RANGE=0-10 result")