1# Test cases for DFS
2# Copyright (c) 2013-2019, 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
7from remotehost import remote_compatible
8import os
9import subprocess
10import time
11import logging
12logger = logging.getLogger()
13
14import hwsim_utils
15import hostapd
16from utils import *
17
18def wait_dfs_event(hapd, event, timeout):
19    dfs_events = ["DFS-RADAR-DETECTED", "DFS-NEW-CHANNEL",
20                  "DFS-CAC-START", "DFS-CAC-COMPLETED",
21                  "DFS-NOP-FINISHED", "AP-ENABLED", "AP-CSA-FINISHED"]
22    ev = hapd.wait_event(dfs_events, timeout=timeout)
23    if not ev:
24        raise Exception("DFS event timed out")
25    if event and event not in ev:
26        raise Exception("Unexpected DFS event: " + ev + " (expected: %s)" % event)
27    return ev
28
29def start_dfs_ap(ap, ssid="dfs", ht=True, ht40=False,
30                 ht40minus=False, vht80=False, vht20=False, chanlist=None,
31                 channel=None, country="FI", rrm_beacon_report=False,
32                 chan100=False):
33    ifname = ap['ifname']
34    logger.info("Starting AP " + ifname + " on DFS channel")
35    hapd = hostapd.add_ap(ap, {}, no_enable=True)
36    hapd.set("ssid", ssid)
37    hapd.set("country_code", country)
38    hapd.set("ieee80211d", "1")
39    hapd.set("ieee80211h", "1")
40    hapd.set("hw_mode", "a")
41    if chan100:
42        hapd.set("channel", "100")
43    else:
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        if chan100:
56            hapd.set("vht_oper_centr_freq_seg0_idx", "106")
57        else:
58            hapd.set("vht_oper_centr_freq_seg0_idx", "58")
59    if vht20:
60        hapd.set("ieee80211ac", "1")
61        hapd.set("vht_oper_chwidth", "0")
62        hapd.set("vht_oper_centr_freq_seg0_idx", "0")
63    if chanlist:
64        hapd.set("chanlist", chanlist)
65    if channel:
66        hapd.set("channel", str(channel))
67    if rrm_beacon_report:
68        hapd.set("rrm_beacon_report", "1")
69    hapd.enable()
70
71    ev = wait_dfs_event(hapd, "DFS-CAC-START", 5)
72    if "DFS-CAC-START" not in ev:
73        raise Exception("Unexpected DFS event: " + ev)
74
75    state = hapd.get_status_field("state")
76    if state != "DFS":
77        raise Exception("Unexpected interface state: " + state)
78
79    return hapd
80
81def dfs_simulate_radar(hapd):
82    logger.info("Trigger a simulated radar event")
83    phyname = hapd.get_driver_status_field("phyname")
84    radar_file = '/sys/kernel/debug/ieee80211/' + phyname + '/hwsim/dfs_simulate_radar'
85    with open(radar_file, 'w') as f:
86        f.write('1')
87
88def test_dfs(dev, apdev):
89    """DFS CAC functionality on clear channel"""
90    try:
91        hapd = None
92        hapd = start_dfs_ap(apdev[0], country="US")
93
94        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
95        if "success=1" not in ev:
96            raise Exception("CAC failed")
97        if "freq=5260" not in ev:
98            raise Exception("Unexpected DFS freq result")
99
100        ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
101        if not ev:
102            raise Exception("AP setup timed out")
103
104        state = hapd.get_status_field("state")
105        if state != "ENABLED":
106            raise Exception("Unexpected interface state")
107
108        freq = hapd.get_status_field("freq")
109        if freq != "5260":
110            raise Exception("Unexpected frequency")
111
112        dev[0].connect("dfs", key_mgmt="NONE")
113        dev[0].wait_regdom(country_ie=True)
114        hwsim_utils.test_connectivity(dev[0], hapd)
115
116        hapd.request("RADAR DETECTED freq=5260 ht_enabled=1 chan_width=1")
117        ev = hapd.wait_event(["DFS-RADAR-DETECTED"], timeout=10)
118        if ev is None:
119            raise Exception("DFS-RADAR-DETECTED event not reported")
120        if "freq=5260" not in ev:
121            raise Exception("Incorrect frequency in radar detected event: " + ev)
122        ev = hapd.wait_event(["DFS-NEW-CHANNEL"], timeout=70)
123        if ev is None:
124            raise Exception("DFS-NEW-CHANNEL event not reported")
125        if "freq=5260" in ev:
126            raise Exception("Channel did not change after radar was detected")
127
128        ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=70)
129        if ev is None:
130            raise Exception("AP-CSA-FINISHED event not reported")
131        if "freq=5260" in ev:
132            raise Exception("Channel did not change after radar was detected(2)")
133        time.sleep(1)
134        hwsim_utils.test_connectivity(dev[0], hapd)
135    finally:
136        clear_regdom(hapd, dev)
137
138@long_duration_test
139def test_dfs_etsi(dev, apdev):
140    """DFS and uniform spreading requirement for ETSI"""
141    try:
142        hapd = None
143        hapd = start_dfs_ap(apdev[0])
144
145        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
146        if "success=1" not in ev:
147            raise Exception("CAC failed")
148        if "freq=5260" not in ev:
149            raise Exception("Unexpected DFS freq result")
150
151        ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
152        if not ev:
153            raise Exception("AP setup timed out")
154
155        state = hapd.get_status_field("state")
156        if state != "ENABLED":
157            raise Exception("Unexpected interface state")
158
159        freq = hapd.get_status_field("freq")
160        if freq != "5260":
161            raise Exception("Unexpected frequency")
162
163        dev[0].connect("dfs", key_mgmt="NONE")
164        dev[0].wait_regdom(country_ie=True)
165        hwsim_utils.test_connectivity(dev[0], hapd)
166
167        hapd.request("RADAR DETECTED freq=%s ht_enabled=1 chan_width=1" % freq)
168        ev = hapd.wait_event(["DFS-RADAR-DETECTED"], timeout=5)
169        if ev is None:
170            raise Exception("DFS-RADAR-DETECTED event not reported")
171        if "freq=%s" % freq not in ev:
172            raise Exception("Incorrect frequency in radar detected event: " + ev)
173        ev = hapd.wait_event(["DFS-NEW-CHANNEL"], timeout=5)
174        if ev is None:
175            raise Exception("DFS-NEW-CHANNEL event not reported")
176        if "freq=%s" % freq in ev:
177            raise Exception("Channel did not change after radar was detected")
178
179        ev = hapd.wait_event(["AP-CSA-FINISHED", "DFS-CAC-START"], timeout=10)
180        if ev is None:
181            raise Exception("AP-CSA-FINISHED or DFS-CAC-START event not reported")
182        if "DFS-CAC-START" in ev:
183            # The selected new channel requires CAC
184            ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
185            if "success=1" not in ev:
186                raise Exception("CAC failed")
187
188            ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
189            if not ev:
190                raise Exception("AP setup timed out")
191            ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=30)
192            if not ev:
193                raise Exception("STA did not reconnect on new DFS channel")
194        else:
195            # The new channel did not require CAC - try again
196            if "freq=%s" % freq in ev:
197                raise Exception("Channel did not change after radar was detected(2)")
198            time.sleep(1)
199        hwsim_utils.test_connectivity(dev[0], hapd)
200    finally:
201        clear_regdom(hapd, dev)
202
203def test_dfs_radar1(dev, apdev):
204    """DFS CAC functionality with radar detected during initial CAC"""
205    try:
206        hapd = None
207        hapd = start_dfs_ap(apdev[0])
208        time.sleep(1)
209
210        dfs_simulate_radar(hapd)
211
212        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
213        if ev is None:
214            raise Exception("Timeout on DFS aborted event")
215        if "success=0 freq=5260" not in ev:
216            raise Exception("Unexpected DFS aborted event contents: " + ev)
217
218        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
219        if "freq=5260" not in ev:
220            raise Exception("Unexpected DFS radar detection freq")
221
222        ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
223        if "freq=5260" in ev:
224            raise Exception("Unexpected DFS new freq")
225
226        ev = wait_dfs_event(hapd, None, 5)
227        if "AP-ENABLED" in ev:
228            logger.info("Started AP on non-DFS channel")
229        else:
230            logger.info("Trying to start AP on another DFS channel")
231            if "DFS-CAC-START" not in ev:
232                raise Exception("Unexpected DFS event: " + ev)
233            if "freq=5260" in ev:
234                raise Exception("Unexpected DFS CAC freq")
235
236            ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
237            if "success=1" not in ev:
238                raise Exception("CAC failed")
239            if "freq=5260" in ev:
240                raise Exception("Unexpected DFS freq result - radar channel")
241
242            ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
243            if not ev:
244                raise Exception("AP setup timed out")
245
246            state = hapd.get_status_field("state")
247            if state != "ENABLED":
248                raise Exception("Unexpected interface state")
249
250            freq = hapd.get_status_field("freq")
251            if freq == "5260":
252                raise Exception("Unexpected frequency: " + freq)
253
254        dev[0].connect("dfs", key_mgmt="NONE")
255        dev[0].wait_regdom(country_ie=True)
256    finally:
257        clear_regdom(hapd, dev)
258
259def test_dfs_radar2(dev, apdev):
260    """DFS CAC functionality with radar detected after initial CAC"""
261    try:
262        hapd = None
263        hapd = start_dfs_ap(apdev[0], ssid="dfs2", ht40=True)
264
265        ev = hapd.wait_event(["AP-ENABLED"], timeout=70)
266        if not ev:
267            raise Exception("AP2 setup timed out")
268
269        dfs_simulate_radar(hapd)
270
271        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
272        if "freq=5260 ht_enabled=1 chan_offset=1 chan_width=2" not in ev:
273            raise Exception("Unexpected DFS radar detection freq from AP2")
274
275        ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
276        if "freq=5260" in ev:
277            raise Exception("Unexpected DFS new freq for AP2")
278
279        wait_dfs_event(hapd, None, 5)
280    finally:
281        clear_regdom(hapd, dev)
282
283@remote_compatible
284def test_dfs_radar_on_non_dfs_channel(dev, apdev):
285    """DFS radar detection test code on non-DFS channel"""
286    params = {"ssid": "radar"}
287    hapd = hostapd.add_ap(apdev[0], params)
288
289    hapd.request("RADAR DETECTED freq=5260 ht_enabled=1 chan_width=1")
290    hapd.request("RADAR DETECTED freq=2412 ht_enabled=1 chan_width=1")
291
292def test_dfs_radar_chanlist(dev, apdev):
293    """DFS chanlist when radar is detected"""
294    try:
295        hapd = None
296        hapd = start_dfs_ap(apdev[0], chanlist="40 44")
297        time.sleep(1)
298
299        dfs_simulate_radar(hapd)
300
301        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
302        if ev is None:
303            raise Exception("Timeout on DFS aborted event")
304        if "success=0 freq=5260" not in ev:
305            raise Exception("Unexpected DFS aborted event contents: " + ev)
306
307        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
308        if "freq=5260" not in ev:
309            raise Exception("Unexpected DFS radar detection freq")
310
311        ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
312        if "freq=5200 chan=40" not in ev and "freq=5220 chan=44" not in ev:
313            raise Exception("Unexpected DFS new freq: " + ev)
314
315        ev = wait_dfs_event(hapd, None, 5)
316        if "AP-ENABLED" not in ev:
317            raise Exception("Unexpected DFS event: " + ev)
318        dev[0].connect("dfs", key_mgmt="NONE")
319        dev[0].wait_regdom(country_ie=True)
320    finally:
321        clear_regdom(hapd, dev)
322
323def test_dfs_radar_chanlist_vht80(dev, apdev):
324    """DFS chanlist when radar is detected and VHT80 configured"""
325    try:
326        hapd = None
327        hapd = start_dfs_ap(apdev[0], chanlist="36", ht40=True, vht80=True)
328        time.sleep(1)
329
330        dfs_simulate_radar(hapd)
331
332        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
333        if ev is None:
334            raise Exception("Timeout on DFS aborted event")
335        if "success=0 freq=5260" not in ev:
336            raise Exception("Unexpected DFS aborted event contents: " + ev)
337
338        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
339        if "freq=5260" not in ev:
340            raise Exception("Unexpected DFS radar detection freq")
341
342        ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
343        if "freq=5180 chan=36 sec_chan=1" not in ev:
344            raise Exception("Unexpected DFS new freq: " + ev)
345
346        ev = wait_dfs_event(hapd, None, 5)
347        if "AP-ENABLED" not in ev:
348            raise Exception("Unexpected DFS event: " + ev)
349        dev[0].connect("dfs", key_mgmt="NONE")
350        dev[0].wait_regdom(country_ie=True)
351
352        if hapd.get_status_field('vht_oper_centr_freq_seg0_idx') != "42":
353            raise Exception("Unexpected seg0 idx")
354    finally:
355        clear_regdom(hapd, dev)
356
357def test_dfs_radar_chanlist_vht20(dev, apdev):
358    """DFS chanlist when radar is detected and VHT40 configured"""
359    try:
360        hapd = None
361        hapd = start_dfs_ap(apdev[0], chanlist="36", vht20=True)
362        time.sleep(1)
363
364        dfs_simulate_radar(hapd)
365
366        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
367        if ev is None:
368            raise Exception("Timeout on DFS aborted event")
369        if "success=0 freq=5260" not in ev:
370            raise Exception("Unexpected DFS aborted event contents: " + ev)
371
372        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
373        if "freq=5260" not in ev:
374            raise Exception("Unexpected DFS radar detection freq")
375
376        ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
377        if "freq=5180 chan=36 sec_chan=0" not in ev:
378            raise Exception("Unexpected DFS new freq: " + ev)
379
380        ev = wait_dfs_event(hapd, None, 5)
381        if "AP-ENABLED" not in ev:
382            raise Exception("Unexpected DFS event: " + ev)
383        dev[0].connect("dfs", key_mgmt="NONE")
384        dev[0].wait_regdom(country_ie=True)
385    finally:
386        clear_regdom(hapd, dev)
387
388def test_dfs_radar_no_ht(dev, apdev):
389    """DFS chanlist when radar is detected and no HT configured"""
390    try:
391        hapd = None
392        hapd = start_dfs_ap(apdev[0], chanlist="36", ht=False)
393        time.sleep(1)
394
395        dfs_simulate_radar(hapd)
396
397        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
398        if ev is None:
399            raise Exception("Timeout on DFS aborted event")
400        if "success=0 freq=5260" not in ev:
401            raise Exception("Unexpected DFS aborted event contents: " + ev)
402
403        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
404        if "freq=5260 ht_enabled=0" not in ev:
405            raise Exception("Unexpected DFS radar detection freq: " + ev)
406
407        ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
408        if "freq=5180 chan=36 sec_chan=0" not in ev:
409            raise Exception("Unexpected DFS new freq: " + ev)
410
411        ev = wait_dfs_event(hapd, None, 5)
412        if "AP-ENABLED" not in ev:
413            raise Exception("Unexpected DFS event: " + ev)
414        dev[0].connect("dfs", key_mgmt="NONE")
415        dev[0].wait_regdom(country_ie=True)
416    finally:
417        clear_regdom(hapd, dev)
418
419def test_dfs_radar_ht40minus(dev, apdev):
420    """DFS chanlist when radar is detected and HT40- configured"""
421    try:
422        hapd = None
423        hapd = start_dfs_ap(apdev[0], chanlist="36", ht40minus=True)
424        time.sleep(1)
425
426        dfs_simulate_radar(hapd)
427
428        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
429        if ev is None:
430            raise Exception("Timeout on DFS aborted event")
431        if "success=0 freq=5280 ht_enabled=1 chan_offset=-1" not in ev:
432            raise Exception("Unexpected DFS aborted event contents: " + ev)
433
434        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
435        if "freq=5280 ht_enabled=1 chan_offset=-1" not in ev:
436            raise Exception("Unexpected DFS radar detection freq: " + ev)
437
438        ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
439        if "freq=5180 chan=36 sec_chan=1" not in ev:
440            raise Exception("Unexpected DFS new freq: " + ev)
441
442        ev = wait_dfs_event(hapd, None, 5)
443        if "AP-ENABLED" not in ev:
444            raise Exception("Unexpected DFS event: " + ev)
445        dev[0].connect("dfs", key_mgmt="NONE")
446        dev[0].wait_regdom(country_ie=True)
447        dev[0].request("STA_AUTOCONNECT 0")
448    finally:
449        clear_regdom(hapd, dev)
450        dev[0].request("STA_AUTOCONNECT 1")
451
452@long_duration_test
453def test_dfs_ht40_minus(dev, apdev):
454    """DFS CAC functionality on channel 104 HT40-"""
455    try:
456        hapd = None
457        hapd = start_dfs_ap(apdev[0], ht40minus=True, channel=104)
458
459        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
460        if "success=1" not in ev:
461            raise Exception("CAC failed")
462        if "freq=5520" not in ev:
463            raise Exception("Unexpected DFS freq result")
464
465        ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
466        if not ev:
467            raise Exception("AP setup timed out")
468
469        state = hapd.get_status_field("state")
470        if state != "ENABLED":
471            raise Exception("Unexpected interface state")
472
473        freq = hapd.get_status_field("freq")
474        if freq != "5520":
475            raise Exception("Unexpected frequency")
476
477        dev[0].connect("dfs", key_mgmt="NONE", scan_freq="5520")
478        dev[0].wait_regdom(country_ie=True)
479        hwsim_utils.test_connectivity(dev[0], hapd)
480    finally:
481        clear_regdom(hapd, dev)
482
483def test_dfs_cac_restart_on_enable(dev, apdev):
484    """DFS CAC interrupted and restarted"""
485    try:
486        hapd = None
487        hapd = start_dfs_ap(apdev[0])
488        time.sleep(0.1)
489        subprocess.check_call(['ip', 'link', 'set', 'dev', hapd.ifname, 'down'])
490        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
491        if ev is None:
492            raise Exception("Timeout on DFS aborted event")
493        if "success=0 freq=5260" not in ev:
494            raise Exception("Unexpected DFS aborted event contents: " + ev)
495        time.sleep(0.1)
496        subprocess.check_call(['ip', 'link', 'set', 'dev', hapd.ifname, 'up'])
497
498        ev = wait_dfs_event(hapd, "DFS-CAC-START", 5)
499        if "DFS-CAC-START" not in ev:
500            raise Exception("Unexpected DFS event: " + ev)
501        hapd.disable()
502
503    finally:
504        clear_regdom(hapd, dev)
505
506@long_duration_test
507def test_dfs_rrm(dev, apdev):
508    """DFS with RRM"""
509    try:
510        hapd = None
511        hapd = start_dfs_ap(apdev[0], country="US", rrm_beacon_report=True)
512
513        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
514        if "success=1" not in ev or "freq=5260" not in ev:
515            raise Exception("Unexpected DFS freq result")
516        ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
517        if not ev:
518            raise Exception("AP setup timed out")
519
520        dev[0].connect("dfs", key_mgmt="NONE", scan_freq="5260")
521        dev[0].wait_regdom(country_ie=True)
522        hapd.wait_sta()
523        hwsim_utils.test_connectivity(dev[0], hapd)
524        addr = dev[0].own_addr()
525        token = hapd.request("REQ_BEACON " + addr + " " + "51000000000002ffffffffffff")
526        if "FAIL" in token:
527            raise Exception("REQ_BEACON failed")
528        ev = hapd.wait_event(["BEACON-RESP-RX"], timeout=10)
529        if ev is None:
530            raise Exception("Beacon report response not received")
531    finally:
532        clear_regdom(hapd, dev)
533
534@long_duration_test
535def test_dfs_radar_vht80_downgrade(dev, apdev):
536    """DFS channel bandwidth downgrade from VHT80 to VHT40"""
537    try:
538        # Start with 80 MHz channel 100 (5500 MHz) to find a radar
539        hapd = None
540        hapd = start_dfs_ap(apdev[0], chanlist="100-140",
541                            ht40=True, vht80=True, chan100=True)
542        time.sleep(1)
543        dfs_simulate_radar(hapd)
544
545        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
546        if ev is None:
547            raise Exception("Timeout on DFS aborted event")
548        if "success=0 freq=5500" not in ev:
549            raise Exception("Unexpected DFS aborted event contents: " + ev)
550
551        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
552        if "freq=5500" not in ev:
553            raise Exception("Unexpected DFS radar detection freq: " + ev)
554
555        # The only other available 80 MHz channel in the chanlist is
556        # 116 (5580 MHz), so that will be selected next.
557        ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
558        if "freq=5580 chan=116 sec_chan=1" not in ev:
559            raise Exception("Unexpected DFS new freq: " + ev)
560
561        ev = wait_dfs_event(hapd, None, 5)
562        if "DFS-CAC-START" not in ev:
563            raise Exception("Unexpected DFS event: " + ev)
564        if "freq=5580" not in ev:
565            raise Exception("Unexpected DFS CAC freq: " + ev)
566
567        time.sleep(1)
568        dfs_simulate_radar(hapd)
569        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
570        if ev is None:
571            raise Exception("Timeout on DFS aborted event (2)")
572        if "success=0 freq=5580" not in ev:
573            raise Exception("Unexpected DFS aborted event (2) contents: " + ev)
574
575        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
576        if "freq=5580" not in ev:
577            raise Exception("Unexpected DFS radar detection (2) freq: " + ev)
578
579        # No more 80 MHz channels are available, so have to downgrade to 40 MHz
580        # channels and the only remaining one is channel 132 (5660 MHz).
581        ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
582        if "freq=5660 chan=132 sec_chan=1" not in ev:
583            raise Exception("Unexpected DFS new freq (2): " + ev)
584
585        ev = wait_dfs_event(hapd, None, 5)
586        if "DFS-CAC-START" not in ev:
587            raise Exception("Unexpected DFS event: " + ev)
588        if "freq=5660" not in ev:
589            raise Exception("Unexpected DFS CAC freq (2): " + ev)
590
591        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
592        if "success=1" not in ev:
593            raise Exception("CAC failed")
594        if "freq=5660" not in ev:
595            raise Exception("Unexpected DFS freq result: " + ev)
596
597        ev = wait_dfs_event(hapd, None, 5)
598        if "AP-ENABLED" not in ev:
599            raise Exception("Unexpected DFS event: " + ev)
600        dev[0].connect("dfs", key_mgmt="NONE", scan_freq="5660")
601        dev[0].wait_regdom(country_ie=True)
602        sig = dev[0].request("SIGNAL_POLL").splitlines()
603        if "FREQUENCY=5660" not in sig or "WIDTH=40 MHz" not in sig:
604            raise Exception("Unexpected SIGNAL_POLL value: " + str(sig))
605    finally:
606        clear_regdom(hapd, dev)
607
608@long_duration_test
609def test_dfs_chan_switch(dev, apdev):
610    """DFS channel switch"""
611    try:
612        hapd = None
613        hapd = start_dfs_ap(apdev[0], country="US")
614
615        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
616        if "success=1" not in ev:
617            raise Exception("CAC failed")
618        if "freq=5260" not in ev:
619            raise Exception("Unexpected DFS freq result")
620        ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
621        if not ev:
622            raise Exception("AP setup timed out")
623        freq = hapd.get_status_field("freq")
624        if freq != "5260":
625            raise Exception("Unexpected frequency")
626
627        dev[0].connect("dfs", key_mgmt="NONE", scan_freq="5260 5280")
628        dev[0].wait_regdom(country_ie=True)
629        hwsim_utils.test_connectivity(dev[0], hapd)
630
631        if "OK" not in hapd.request("CHAN_SWITCH 5 5280 ht"):
632            raise Exception("CHAN_SWITCH failed")
633        # This results in BSS going down before restart, so the STA is expected
634        # to report disconnection.
635        dev[0].wait_disconnected()
636        ev = wait_dfs_event(hapd, "DFS-CAC-START", 5)
637        if "freq=5280" not in ev:
638            raise Exception("Unexpected channel: " + ev)
639        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
640        if "success=1" not in ev:
641            raise Exception("CAC failed")
642        if "freq=5280" not in ev:
643            raise Exception("Unexpected DFS freq result")
644        ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
645        if not ev:
646            raise Exception("AP setup timed out")
647        freq = hapd.get_status_field("freq")
648        if freq != "5280":
649            raise Exception("Unexpected frequency")
650
651        dev[0].wait_connected(timeout=30)
652        hwsim_utils.test_connectivity(dev[0], hapd)
653    finally:
654        clear_regdom(hapd, dev)
655
656@long_duration_test
657def test_dfs_no_available_channel(dev, apdev):
658    """DFS and no available channel after radar detection"""
659    try:
660        hapd = None
661        hapd = start_dfs_ap(apdev[0], chanlist="56")
662
663        ev = hapd.wait_event(["AP-ENABLED"], timeout=70)
664        if not ev:
665            raise Exception("AP2 setup timed out")
666
667        dfs_simulate_radar(hapd)
668        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
669        if "freq=5260 ht_enabled=1 chan_offset=0 chan_width=1" not in ev:
670            raise Exception("Unexpected DFS radar detection freq from AP")
671
672        ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
673        if "freq=5280 chan=56" not in ev:
674            raise Exception("Unexpected DFS new freq: " + ev)
675        ev = wait_dfs_event(hapd, "DFS-CAC-START", 5)
676        if "freq=5280" not in ev:
677            raise Exception("Unexpected channel: " + ev)
678        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
679        if "success=1" not in ev:
680            raise Exception("CAC failed")
681        if "freq=5280" not in ev:
682            raise Exception("Unexpected DFS freq result")
683        ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
684        if not ev:
685            raise Exception("AP setup timed out")
686
687        dfs_simulate_radar(hapd)
688        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
689        if "freq=5280 ht_enabled=1 chan_offset=0 chan_width=1" not in ev:
690            raise Exception("Unexpected DFS radar detection freq from AP [2]")
691
692        ev = hapd.wait_event(["AP-DISABLED"], timeout=10)
693        if ev is None:
694            raise Exception("AP was not disabled")
695    finally:
696        clear_regdom(hapd, dev)
697
698def dfs_chan_switch_precac(dev, apdev, country):
699    """DFS channel switch pre CAC"""
700    try:
701        hapd = None
702
703        # Toggle regulatory - clean all preCAC
704        hostapd.cmd_execute(apdev[0], ['iw', 'reg', 'set', 'US'])
705
706        hapd = start_dfs_ap(apdev[0], country=country)
707
708        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
709        if "success=1" not in ev:
710            raise Exception("CAC failed")
711        if "freq=5260" not in ev:
712            raise Exception("Unexpected DFS freq result")
713        ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
714        if not ev:
715            raise Exception("AP setup timed out")
716        freq = hapd.get_status_field("freq")
717        if freq != "5260":
718            raise Exception("Unexpected frequency")
719
720        # TODO add/connect station here
721        # Today skip this step while dev[0].connect()
722        # for some reason toggle regulatory to US
723        # and clean preCAC
724
725        # Back to non DFS channel
726        if "OK" not in hapd.request("CHAN_SWITCH 5 5180 ht"):
727            raise Exception("CHAN_SWITCH 5180 failed")
728
729        ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=5)
730        if not ev:
731            raise Exception("No CSA finished event - 5180")
732        freq = hapd.get_status_field("freq")
733        if freq != "5180":
734            raise Exception("Unexpected frequency")
735
736        # Today cfg80211 first send AP-CSA-FINISHED and next
737        # DFS-PRE-CAC-EXPIRED
738        ev = hapd.wait_event(["DFS-PRE-CAC-EXPIRED"], timeout=3)
739        if not ev and country == 'US':
740            raise Exception("US - no CAC-EXPIRED event")
741
742	# Back again to DFS channel (CAC passed)
743        if "OK" not in hapd.request("CHAN_SWITCH 5 5260 ht"):
744            raise Exception("CHAN_SWITCH 5260 failed")
745
746        if country == 'US':
747            # For non EU we should start CAC again
748            ev = wait_dfs_event(hapd, "DFS-CAC-START", 5)
749            if not ev:
750                raise Exception("No DFS CAC start event")
751        else:
752            # For EU preCAC should be used
753            ev = wait_dfs_event(hapd, "AP-CSA-FINISHED", 5)
754            if not ev:
755                raise Exception("No CSA finished event - 5260")
756    finally:
757        clear_regdom(hapd, dev)
758
759@long_duration_test
760def test_dfs_eu_chan_switch_precac(dev, apdev):
761    """DFS channel switch pre CAC - ETSI domain"""
762    dfs_chan_switch_precac(dev, apdev, 'PL')
763
764@long_duration_test
765def test_dfs_us_chan_switch_precac(dev, apdev):
766    """DFS channel switch pre CAC - FCC domain"""
767    dfs_chan_switch_precac(dev, apdev, 'US')
768