Updated through tag hostap_2_5 from git://w1.fi/hostap.git
[mech_eap.git] / libeap / tests / hwsim / test_dfs.py
1 # Test cases for DFS
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 os
8 import subprocess
9 import time
10 import logging
11 logger = logging.getLogger()
12
13 import hwsim_utils
14 import hostapd
15 from utils import HwsimSkip
16
17 def wait_dfs_event(hapd, event, timeout):
18     dfs_events = [ "DFS-RADAR-DETECTED", "DFS-NEW-CHANNEL",
19                    "DFS-CAC-START", "DFS-CAC-COMPLETED",
20                    "DFS-NOP-FINISHED", "AP-ENABLED", "AP-CSA-FINISHED" ]
21     ev = hapd.wait_event(dfs_events, timeout=timeout)
22     if not ev:
23         raise Exception("DFS event timed out")
24     if event and event not in ev:
25         raise Exception("Unexpected DFS event")
26     return ev
27
28 def start_dfs_ap(ap, allow_failure=False, ssid="dfs", ht=True, ht40=False,
29                  ht40minus=False, vht80=False, vht20=False, chanlist=None):
30     ifname = ap['ifname']
31     logger.info("Starting AP " + ifname + " on DFS channel")
32     hapd_global = hostapd.HostapdGlobal()
33     hapd_global.remove(ifname)
34     hapd_global.add(ifname)
35     hapd = hostapd.Hostapd(ifname)
36     if not hapd.ping():
37         raise Exception("Could not ping hostapd")
38     hapd.set_defaults()
39     hapd.set("ssid", ssid)
40     hapd.set("country_code", "FI")
41     hapd.set("ieee80211d", "1")
42     hapd.set("ieee80211h", "1")
43     hapd.set("hw_mode", "a")
44     hapd.set("channel", "52")
45     if not ht:
46         hapd.set("ieee80211n", "0")
47     if ht40:
48         hapd.set("ht_capab", "[HT40+]")
49     elif ht40minus:
50         hapd.set("ht_capab", "[HT40-]")
51         hapd.set("channel", "56")
52     if vht80:
53         hapd.set("ieee80211ac", "1")
54         hapd.set("vht_oper_chwidth", "1")
55         hapd.set("vht_oper_centr_freq_seg0_idx", "58")
56     if vht20:
57         hapd.set("ieee80211ac", "1")
58         hapd.set("vht_oper_chwidth", "0")
59         hapd.set("vht_oper_centr_freq_seg0_idx", "0")
60     if chanlist:
61         hapd.set("chanlist", chanlist)
62     hapd.enable()
63
64     ev = wait_dfs_event(hapd, "DFS-CAC-START", 5)
65     if "DFS-CAC-START" not in ev:
66         raise Exception("Unexpected DFS event")
67
68     state = hapd.get_status_field("state")
69     if state != "DFS":
70         if allow_failure:
71             logger.info("Interface state not DFS: " + state)
72             if not os.path.exists("dfs"):
73                 raise HwsimSkip("Assume DFS testing not supported")
74             raise Exception("Failed to start DFS AP")
75         raise Exception("Unexpected interface state: " + state)
76
77     return hapd
78
79 def dfs_simulate_radar(hapd):
80     logger.info("Trigger a simulated radar event")
81     phyname = hapd.get_driver_status_field("phyname")
82     radar_file = '/sys/kernel/debug/ieee80211/' + phyname + '/hwsim/dfs_simulate_radar'
83     with open(radar_file, 'w') as f:
84         f.write('1')
85
86 def test_dfs(dev, apdev):
87     """DFS CAC functionality on clear channel"""
88     try:
89         hapd = None
90         hapd = start_dfs_ap(apdev[0], allow_failure=True)
91
92         ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
93         if "success=1" not in ev:
94             raise Exception("CAC failed")
95         if "freq=5260" not in ev:
96             raise Exception("Unexpected DFS freq result")
97
98         ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
99         if not ev:
100             raise Exception("AP setup timed out")
101
102         state = hapd.get_status_field("state")
103         if state != "ENABLED":
104             raise Exception("Unexpected interface state")
105
106         freq = hapd.get_status_field("freq")
107         if freq != "5260":
108             raise Exception("Unexpected frequency")
109
110         dev[0].connect("dfs", key_mgmt="NONE")
111         hwsim_utils.test_connectivity(dev[0], hapd)
112
113         hapd.request("RADAR DETECTED freq=5260 ht_enabled=1 chan_width=1")
114         ev = hapd.wait_event(["DFS-RADAR-DETECTED"], timeout=10)
115         if ev is None:
116             raise Exception("DFS-RADAR-DETECTED event not reported")
117         if "freq=5260" not in ev:
118             raise Exception("Incorrect frequency in radar detected event: " + ev);
119         ev = hapd.wait_event(["DFS-NEW-CHANNEL"], timeout=70)
120         if ev is None:
121             raise Exception("DFS-NEW-CHANNEL event not reported")
122         if "freq=5260" in ev:
123             raise Exception("Channel did not change after radar was detected");
124
125         ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=70)
126         if ev is None:
127             raise Exception("AP-CSA-FINISHED event not reported")
128         if "freq=5260" in ev:
129             raise Exception("Channel did not change after radar was detected(2)");
130         time.sleep(1)
131         hwsim_utils.test_connectivity(dev[0], hapd)
132     finally:
133         dev[0].request("DISCONNECT")
134         if hapd:
135             hapd.request("DISABLE")
136         subprocess.call(['iw', 'reg', 'set', '00'])
137         dev[0].flush_scan_cache()
138
139 def test_dfs_radar(dev, apdev):
140     """DFS CAC functionality with radar detected"""
141     try:
142         hapd = None
143         hapd2 = None
144         hapd = start_dfs_ap(apdev[0], allow_failure=True)
145         time.sleep(1)
146
147         dfs_simulate_radar(hapd)
148
149         hapd2 = start_dfs_ap(apdev[1], ssid="dfs2", ht40=True)
150
151         ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
152         if ev is None:
153             raise Exception("Timeout on DFS aborted event")
154         if "success=0 freq=5260" not in ev:
155             raise Exception("Unexpected DFS aborted event contents: " + ev)
156
157         ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
158         if "freq=5260" not in ev:
159             raise Exception("Unexpected DFS radar detection freq")
160
161         ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
162         if "freq=5260" in ev:
163             raise Exception("Unexpected DFS new freq")
164
165         ev = wait_dfs_event(hapd, None, 5)
166         if "AP-ENABLED" in ev:
167             logger.info("Started AP on non-DFS channel")
168         else:
169             logger.info("Trying to start AP on another DFS channel")
170             if "DFS-CAC-START" not in ev:
171                 raise Exception("Unexpected DFS event")
172             if "freq=5260" in ev:
173                 raise Exception("Unexpected DFS CAC freq")
174
175             ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
176             if "success=1" not in ev:
177                 raise Exception("CAC failed")
178             if "freq=5260" in ev:
179                 raise Exception("Unexpected DFS freq result - radar channel")
180
181             ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
182             if not ev:
183                 raise Exception("AP setup timed out")
184
185             state = hapd.get_status_field("state")
186             if state != "ENABLED":
187                 raise Exception("Unexpected interface state")
188
189             freq = hapd.get_status_field("freq")
190             if freq == "5260":
191                 raise Exception("Unexpected frequency: " + freq)
192
193         dev[0].connect("dfs", key_mgmt="NONE")
194
195         ev = hapd2.wait_event(["AP-ENABLED"], timeout=70)
196         if not ev:
197             raise Exception("AP2 setup timed out")
198
199         dfs_simulate_radar(hapd2)
200
201         ev = wait_dfs_event(hapd2, "DFS-RADAR-DETECTED", 5)
202         if "freq=5260 ht_enabled=1 chan_offset=1 chan_width=2" not in ev:
203             raise Exception("Unexpected DFS radar detection freq from AP2")
204
205         ev = wait_dfs_event(hapd2, "DFS-NEW-CHANNEL", 5)
206         if "freq=5260" in ev:
207             raise Exception("Unexpected DFS new freq for AP2")
208
209         wait_dfs_event(hapd2, None, 5)
210     finally:
211         dev[0].request("DISCONNECT")
212         if hapd:
213             hapd.request("DISABLE")
214         if hapd2:
215             hapd2.request("DISABLE")
216         subprocess.call(['iw', 'reg', 'set', '00'])
217         dev[0].flush_scan_cache()
218
219 def test_dfs_radar_on_non_dfs_channel(dev, apdev):
220     """DFS radar detection test code on non-DFS channel"""
221     params = { "ssid": "radar" }
222     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
223
224     hapd.request("RADAR DETECTED freq=5260 ht_enabled=1 chan_width=1")
225     hapd.request("RADAR DETECTED freq=2412 ht_enabled=1 chan_width=1")
226
227 def test_dfs_radar_chanlist(dev, apdev):
228     """DFS chanlist when radar is detected"""
229     try:
230         hapd = None
231         hapd = start_dfs_ap(apdev[0], chanlist="40 44", allow_failure=True)
232         time.sleep(1)
233
234         dfs_simulate_radar(hapd)
235
236         ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
237         if ev is None:
238             raise Exception("Timeout on DFS aborted event")
239         if "success=0 freq=5260" not in ev:
240             raise Exception("Unexpected DFS aborted event contents: " + ev)
241
242         ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
243         if "freq=5260" not in ev:
244             raise Exception("Unexpected DFS radar detection freq")
245
246         ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
247         if "freq=5200 chan=40" not in ev and "freq=5220 chan=44" not in ev:
248             raise Exception("Unexpected DFS new freq: " + ev)
249
250         ev = wait_dfs_event(hapd, None, 5)
251         if "AP-ENABLED" not in ev:
252             raise Exception("Unexpected DFS event")
253         dev[0].connect("dfs", key_mgmt="NONE")
254     finally:
255         dev[0].request("DISCONNECT")
256         if hapd:
257             hapd.request("DISABLE")
258         subprocess.call(['iw', 'reg', 'set', '00'])
259         dev[0].flush_scan_cache()
260
261 def test_dfs_radar_chanlist_vht80(dev, apdev):
262     """DFS chanlist when radar is detected and VHT80 configured"""
263     try:
264         hapd = None
265         hapd = start_dfs_ap(apdev[0], chanlist="36", ht40=True, vht80=True,
266                             allow_failure=True)
267         time.sleep(1)
268
269         dfs_simulate_radar(hapd)
270
271         ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
272         if ev is None:
273             raise Exception("Timeout on DFS aborted event")
274         if "success=0 freq=5260" not in ev:
275             raise Exception("Unexpected DFS aborted event contents: " + ev)
276
277         ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
278         if "freq=5260" not in ev:
279             raise Exception("Unexpected DFS radar detection freq")
280
281         ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
282         if "freq=5180 chan=36 sec_chan=1" not in ev:
283             raise Exception("Unexpected DFS new freq: " + ev)
284
285         ev = wait_dfs_event(hapd, None, 5)
286         if "AP-ENABLED" not in ev:
287             raise Exception("Unexpected DFS event")
288         dev[0].connect("dfs", key_mgmt="NONE")
289
290         if hapd.get_status_field('vht_oper_centr_freq_seg0_idx') != "42":
291             raise Exception("Unexpected seg0 idx")
292     finally:
293         dev[0].request("DISCONNECT")
294         if hapd:
295             hapd.request("DISABLE")
296         subprocess.call(['iw', 'reg', 'set', '00'])
297         dev[0].flush_scan_cache()
298
299 def test_dfs_radar_chanlist_vht20(dev, apdev):
300     """DFS chanlist when radar is detected and VHT40 configured"""
301     try:
302         hapd = None
303         hapd = start_dfs_ap(apdev[0], chanlist="36", vht20=True,
304                             allow_failure=True)
305         time.sleep(1)
306
307         dfs_simulate_radar(hapd)
308
309         ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
310         if ev is None:
311             raise Exception("Timeout on DFS aborted event")
312         if "success=0 freq=5260" not in ev:
313             raise Exception("Unexpected DFS aborted event contents: " + ev)
314
315         ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
316         if "freq=5260" not in ev:
317             raise Exception("Unexpected DFS radar detection freq")
318
319         ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
320         if "freq=5180 chan=36 sec_chan=0" not in ev:
321             raise Exception("Unexpected DFS new freq: " + ev)
322
323         ev = wait_dfs_event(hapd, None, 5)
324         if "AP-ENABLED" not in ev:
325             raise Exception("Unexpected DFS event")
326         dev[0].connect("dfs", key_mgmt="NONE")
327     finally:
328         dev[0].request("DISCONNECT")
329         if hapd:
330             hapd.request("DISABLE")
331         subprocess.call(['iw', 'reg', 'set', '00'])
332         dev[0].flush_scan_cache()
333
334 def test_dfs_radar_no_ht(dev, apdev):
335     """DFS chanlist when radar is detected and no HT configured"""
336     try:
337         hapd = None
338         hapd = start_dfs_ap(apdev[0], chanlist="36", ht=False,
339                             allow_failure=True)
340         time.sleep(1)
341
342         dfs_simulate_radar(hapd)
343
344         ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
345         if ev is None:
346             raise Exception("Timeout on DFS aborted event")
347         if "success=0 freq=5260" not in ev:
348             raise Exception("Unexpected DFS aborted event contents: " + ev)
349
350         ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
351         if "freq=5260 ht_enabled=0" not in ev:
352             raise Exception("Unexpected DFS radar detection freq: " + ev)
353
354         ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
355         if "freq=5180 chan=36 sec_chan=0" not in ev:
356             raise Exception("Unexpected DFS new freq: " + ev)
357
358         ev = wait_dfs_event(hapd, None, 5)
359         if "AP-ENABLED" not in ev:
360             raise Exception("Unexpected DFS event")
361         dev[0].connect("dfs", key_mgmt="NONE")
362     finally:
363         dev[0].request("DISCONNECT")
364         if hapd:
365             hapd.request("DISABLE")
366         subprocess.call(['iw', 'reg', 'set', '00'])
367         dev[0].flush_scan_cache()
368
369 def test_dfs_radar_ht40minus(dev, apdev):
370     """DFS chanlist when radar is detected and HT40- configured"""
371     try:
372         hapd = None
373         hapd = start_dfs_ap(apdev[0], chanlist="36", ht40minus=True,
374                             allow_failure=True)
375         time.sleep(1)
376
377         dfs_simulate_radar(hapd)
378
379         ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
380         if ev is None:
381             raise Exception("Timeout on DFS aborted event")
382         if "success=0 freq=5280 ht_enabled=1 chan_offset=-1" not in ev:
383             raise Exception("Unexpected DFS aborted event contents: " + ev)
384
385         ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
386         if "freq=5280 ht_enabled=1 chan_offset=-1" not in ev:
387             raise Exception("Unexpected DFS radar detection freq: " + ev)
388
389         ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
390         if "freq=5180 chan=36 sec_chan=1" not in ev:
391             raise Exception("Unexpected DFS new freq: " + ev)
392
393         ev = wait_dfs_event(hapd, None, 5)
394         if "AP-ENABLED" not in ev:
395             raise Exception("Unexpected DFS event")
396         dev[0].connect("dfs", key_mgmt="NONE")
397     finally:
398         dev[0].request("DISCONNECT")
399         if hapd:
400             hapd.request("DISABLE")
401         subprocess.call(['iw', 'reg', 'set', '00'])
402         dev[0].flush_scan_cache()