tests: FTM capability indication
[mech_eap.git] / tests / hwsim / test_rrm.py
1 # Radio measurement
2 # Copyright(c) 2013 - 2016 Intel Mobile Communications GmbH.
3 # Copyright(c) 2011 - 2016 Intel Corporation. All rights reserved.
4 #
5 # This software may be distributed under the terms of the BSD license.
6 # See README for more details.
7
8 import re
9 import logging
10 logger = logging.getLogger()
11
12 import hostapd
13 from utils import HwsimSkip
14
15 nr="00112233445500000000510107"
16 lci="01000800101298c0b512926666f6c2f1001c00004104050000c00012"
17 civic="01000b0011223344556677889900998877665544332211aabbccddeeff"
18
19 def check_nr_results(dev, bssids=None, lci=False, civic=False):
20     if bssids is None:
21         ev = dev.wait_event(["RRM-NEIGHBOR-REP-REQUEST-FAILED" ], timeout=10)
22         if ev is None:
23             raise Exception("RRM neighbor report failure not received")
24         return
25
26     received = []
27     for bssid in bssids:
28         ev = dev.wait_event(["RRM-NEIGHBOR-REP-RECEIVED"], timeout=10)
29         if ev is None:
30             raise Exception("RRM report result not indicated")
31         received.append(ev)
32
33     for bssid in bssids:
34         found = False
35         for r in received:
36             if "RRM-NEIGHBOR-REP-RECEIVED bssid=" + bssid in r:
37                 if lci and "lci=" not in r:
38                     raise Exception("LCI data not reported for %s" % bssid)
39                 if civic and "civic=" not in r:
40                     raise Exception("civic data not reported for %s" % bssid)
41                 received.remove(r)
42                 found = True
43                 break
44         if not found:
45             raise Exception("RRM report result for %s not indicated" % bssid)
46
47 def test_rrm_neighbor_db(dev, apdev):
48     """hostapd ctrl_iface SET_NEIGHBOR"""
49     params = { "ssid": "test", "rrm_neighbor_report": "1" }
50     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
51
52     # Bad BSSID
53     if "FAIL" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:gg ssid=\"test1\" nr=" + nr):
54         raise Exception("Set neighbor succeeded unexpectedly")
55
56     # Bad SSID
57     if "FAIL" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 ssid=test1 nr=" + nr):
58         raise Exception("Set neighbor succeeded unexpectedly")
59
60     # No SSID
61     if "FAIL" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 nr=" + nr):
62         raise Exception("Set neighbor succeeded unexpectedly")
63
64     # No NR
65     if "FAIL" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\""):
66         raise Exception("Set neighbor succeeded unexpectedly")
67
68     # Odd length of NR
69     if "FAIL" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\" nr=" + nr[:-1]):
70         raise Exception("Set neighbor succeeded unexpectedly")
71
72     # No entry yet in database
73     if "FAIL" not in hapd.request("REMOVE_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\""):
74         raise Exception("Remove neighbor succeeded unexpectedly")
75
76     # Add a neighbor entry
77     if "OK" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\" nr=" + nr + " lci=" + lci + " civic=" + civic):
78         raise Exception("Set neighbor failed")
79
80     # Another BSSID with the same SSID
81     if "OK" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:56 ssid=\"test1\" nr=" + nr + " lci=" + lci + " civic=" + civic):
82         raise Exception("Set neighbor failed")
83
84     # Fewer parameters
85     if "OK" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\" nr=" + nr):
86         raise Exception("Set neighbor failed")
87
88     # SSID in hex format
89     if "OK" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 ssid=7465737431 nr=" + nr):
90         raise Exception("Set neighbor failed")
91
92     # With more parameters
93     if "OK" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\" nr=" + nr + " civic=" + civic):
94         raise Exception("Set neighbor failed")
95
96     # With all parameters
97     if "OK" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\" nr=" + nr + " lci=" + lci + " civic=" + civic):
98         raise Exception("Set neighbor failed")
99
100     # Another SSID on the same BSSID
101     if "OK" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 ssid=\"test2\" nr=" + nr + " lci=" + lci):
102         raise Exception("Set neighbor failed")
103
104     if "OK" not in hapd.request("REMOVE_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\""):
105         raise Exception("Remove neighbor failed")
106
107     if "OK" not in hapd.request("REMOVE_NEIGHBOR 00:11:22:33:44:56 ssid=\"test1\""):
108         raise Exception("Remove neighbor failed")
109
110     if "OK" not in hapd.request("REMOVE_NEIGHBOR 00:11:22:33:44:55 ssid=\"test2\""):
111         raise Exception("Remove neighbor failed")
112
113     # Double remove
114     if "FAIL" not in hapd.request("REMOVE_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\""):
115         raise Exception("Remove neighbor succeeded unexpectedly")
116
117 def test_rrm_neighbor_rep_req(dev, apdev):
118     """wpa_supplicant ctrl_iface NEIGHBOR_REP_REQUEST"""
119     nr1="00112233445500000000510107"
120     nr2="00112233445600000000510107"
121     nr3="dd112233445500000000510107"
122
123     params = { "ssid": "test" }
124     hostapd.add_ap(apdev[0]['ifname'], params)
125     params = { "ssid": "test2", "rrm_neighbor_report": "1" }
126     hapd = hostapd.add_ap(apdev[1]['ifname'], params)
127
128     bssid1 = apdev[1]['bssid']
129
130     dev[0].connect("test", key_mgmt="NONE", scan_freq="2412")
131     if "FAIL" not in dev[0].request("NEIGHBOR_REP_REQUEST"):
132         raise Exception("Request succeeded unexpectedly (AP without RRM)")
133     if "FAIL" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"abcdef\""):
134         raise Exception("Request succeeded unexpectedly (AP without RRM 2)")
135     dev[0].request("DISCONNECT")
136
137     rrm = int(dev[0].get_driver_status_field("capa.rrm_flags"), 16)
138     if rrm & 0x5 != 0x5 and rrm & 0x10 != 0x10:
139         raise HwsimSkip("Required RRM capabilities are not supported")
140
141     dev[0].connect("test2", key_mgmt="NONE", scan_freq="2412")
142
143     if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST"):
144         raise Exception("Request failed")
145     check_nr_results(dev[0], [bssid1])
146
147     if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST lci"):
148         raise Exception("Request failed")
149     check_nr_results(dev[0], [bssid1])
150
151     if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST lci civic"):
152         raise Exception("Request failed")
153     check_nr_results(dev[0], [bssid1])
154
155     if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test3\""):
156         raise Exception("Request failed")
157     check_nr_results(dev[0])
158
159     if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test3\" lci civic"):
160         raise Exception("Request failed")
161     check_nr_results(dev[0])
162
163     if "OK" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 ssid=\"test3\" nr=" + nr1 + " lci=" + lci + " civic=" + civic):
164         raise Exception("Set neighbor failed")
165     if "OK" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:56 ssid=\"test3\" nr=" + nr2 + " lci=" + lci + " civic=" + civic):
166         raise Exception("Set neighbor failed")
167     if "OK" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:56 ssid=\"test4\" nr=" + nr2 + " lci=" + lci + " civic=" + civic):
168         raise Exception("Set neighbor failed")
169     if "OK" not in hapd.request("SET_NEIGHBOR dd:11:22:33:44:55 ssid=\"test5\" nr=" + nr3 + " lci=" + lci):
170         raise Exception("Set neighbor failed")
171
172     if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test3\""):
173         raise Exception("Request failed")
174     check_nr_results(dev[0], ["00:11:22:33:44:55", "00:11:22:33:44:56"])
175
176     if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test3\" lci"):
177         raise Exception("Request failed")
178     check_nr_results(dev[0], ["00:11:22:33:44:55", "00:11:22:33:44:56"],
179                      lci=True)
180
181     if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test3\" civic"):
182         raise Exception("Request failed")
183     check_nr_results(dev[0], ["00:11:22:33:44:55", "00:11:22:33:44:56"],
184                      civic=True)
185
186     if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test3\" lci civic"):
187         raise Exception("Request failed")
188     check_nr_results(dev[0], ["00:11:22:33:44:55", "00:11:22:33:44:56"],
189                      lci=True, civic=True)
190
191     if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test4\""):
192         raise Exception("Request failed")
193     check_nr_results(dev[0], ["00:11:22:33:44:56"])
194
195     if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test4\" lci"):
196         raise Exception("Request failed")
197     check_nr_results(dev[0], ["00:11:22:33:44:56"], lci=True)
198
199     if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test4\" civic"):
200         raise Exception("Request failed")
201     check_nr_results(dev[0], ["00:11:22:33:44:56"], civic=True)
202
203     if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test4\" lci civic"):
204         raise Exception("Request failed")
205     check_nr_results(dev[0], ["00:11:22:33:44:56"], lci=True, civic=True)
206
207     if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test5\""):
208         raise Exception("Request failed")
209     check_nr_results(dev[0], ["dd:11:22:33:44:55"])
210
211     if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test5\" lci"):
212         raise Exception("Request failed")
213     check_nr_results(dev[0], ["dd:11:22:33:44:55"], lci=True)
214
215     if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test5\" civic"):
216         raise Exception("Request failed")
217     check_nr_results(dev[0], ["dd:11:22:33:44:55"])
218
219     if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test5\" lci civic"):
220         raise Exception("Request failed")
221     check_nr_results(dev[0], ["dd:11:22:33:44:55"], lci=True)
222
223 def test_rrm_lci_req(dev, apdev):
224     """hostapd lci request"""
225
226     rrm = int(dev[0].get_driver_status_field("capa.rrm_flags"), 16)
227     if rrm & 0x5 != 0x5 and rrm & 0x10 != 0x10:
228         raise HwsimSkip("Required RRM capabilities are not supported")
229
230     params = { "ssid": "rrm", "rrm_neighbor_report": "1" }
231     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
232
233     # station not specified
234     if "FAIL" not in hapd.request("REQ_LCI "):
235         raise Exception("REQ_LCI with no station succeeded unexpectedly")
236
237     # station that is not connected specified
238     if "FAIL" not in hapd.request("REQ_LCI " + dev[0].own_addr()):
239         raise Exception("REQ_LCI succeeded unexpectedly (station not connected)")
240
241     dev[0].request("SET LCI ")
242     dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
243
244     # station connected without LCI
245     if "FAIL" not in hapd.request("REQ_LCI " + dev[0].own_addr()):
246         raise Exception("REQ_LCI succeeded unexpectedly (station without lci)")
247
248     dev[0].request("DISCONNECT")
249     dev[0].wait_disconnected(timeout=2)
250
251     dev[0].request("SET LCI " + lci)
252
253     dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
254
255     # station connected with LCI
256     if "OK" not in hapd.request("REQ_LCI " + dev[0].own_addr()):
257         raise Exception("REQ_LCI failed unexpectedly")
258
259 def test_rrm_ftm_range_req(dev, apdev):
260     """hostapd FTM range request command"""
261
262     rrm = int(dev[0].get_driver_status_field("capa.rrm_flags"), 16)
263     if rrm & 0x5 != 0x5 and rrm & 0x10 != 0x10:
264         raise HwsimSkip("Required RRM capabilities are not supported")
265
266     params = { "ssid": "rrm", "rrm_neighbor_report": "1" }
267     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
268
269     # station not specified
270     if "FAIL" not in hapd.request("REQ_RANGE "):
271         raise Exception("REQ_RANGE with no station succeeded unexpectedly")
272
273     # station that is not connected specified
274     if "FAIL" not in hapd.request("REQ_RANGE " + dev[0].own_addr()):
275         raise Exception("REQ_RANGE succeeded unexpectedly (station not connected)")
276
277     # No responders specified
278     if "FAIL" not in hapd.request("REQ_RANGE " + dev[0].own_addr() + " 10 10"):
279         raise Exception("REQ_RANGE succeeded unexpectedly (no responder)")
280
281     # Bad responder address
282     if "FAIL" not in hapd.request("REQ_RANGE " + dev[0].own_addr() + " 10 10 00:11:22:33:44:"):
283         raise Exception("REQ_RANGE succeeded unexpectedly (bad responder address)")
284
285     # Bad responder address
286     if "FAIL" not in hapd.request("REQ_RANGE " + dev[0].own_addr() + " 10 10 00:11:22:33:44:55 00:11:22:33:44"):
287         raise Exception("REQ_RANGE succeeded unexpectedly (bad responder address 2)")
288
289     # Bad min_ap value
290     if "FAIL" not in hapd.request("REQ_RANGE " + dev[0].own_addr() + " 20 10 00:11:22:33:44:55"):
291         raise Exception("REQ_RANGE succeeded unexpectedly (invalid min_ap value)")
292
293     # Bad rand value
294     if "FAIL" not in hapd.request("REQ_RANGE " + dev[0].own_addr() + " 10 300 00:11:22:33:44:55"):
295         raise Exception("REQ_RANGE succeeded unexpectedly (invalid rand value)")
296
297     dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
298
299     # Responder not in database
300     # Note: this check would pass since the station does not support FTM range
301     # request and not because the responder is not in the database.
302     if "FAIL" not in hapd.request("REQ_RANGE " + dev[0].own_addr() + " 10 10 00:11:22:33:44:55"):
303         raise Exception("REQ_RANGE succeeded unexpectedly (responder not in database)")
304
305 def test_rrm_ftm_capa_indication(dev, apdev):
306     """FTM capability indication"""
307     try:
308         _test_rrm_ftm_capa_indication(dev, apdev)
309     finally:
310         dev[0].request("SET ftm_initiator 0")
311         dev[0].request("SET ftm_responder 0")
312
313 def _test_rrm_ftm_capa_indication(dev, apdev):
314     params = { "ssid": "ftm",
315                "ftm_responder": "1",
316                "ftm_initiator": "1", }
317     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
318
319     if "OK" not in dev[0].request("SET ftm_initiator 1"):
320         raise Exception("could not set ftm_initiator")
321     if "OK" not in dev[0].request("SET ftm_responder 1"):
322         raise Exception("could not set ftm_responder")
323     dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412, force_scan=True)