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", timeout=30)
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        hapd.dump_monitor()
164        dev[0].dump_monitor()
165
166        dev[0].connect("dfs", key_mgmt="NONE")
167        dev[0].wait_regdom(country_ie=True)
168        time.sleep(1)
169        hwsim_utils.test_connectivity(dev[0], hapd)
170
171        hapd.dump_monitor()
172        dev[0].dump_monitor()
173
174        hapd.request("RADAR DETECTED freq=%s ht_enabled=1 chan_width=1" % freq)
175        ev = hapd.wait_event(["DFS-RADAR-DETECTED"], timeout=5)
176        if ev is None:
177            raise Exception("DFS-RADAR-DETECTED event not reported")
178        if "freq=%s" % freq not in ev:
179            raise Exception("Incorrect frequency in radar detected event: " + ev)
180        ev = hapd.wait_event(["DFS-NEW-CHANNEL"], timeout=5)
181        if ev is None:
182            raise Exception("DFS-NEW-CHANNEL event not reported")
183        if "freq=%s" % freq in ev:
184            raise Exception("Channel did not change after radar was detected")
185
186        ev = hapd.wait_event(["AP-CSA-FINISHED", "DFS-CAC-START"], timeout=10)
187        if ev is None:
188            raise Exception("AP-CSA-FINISHED or DFS-CAC-START event not reported")
189        if "DFS-CAC-START" in ev:
190            # The selected new channel requires CAC
191            dev[0].wait_disconnected()
192            ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
193            if "success=1" not in ev:
194                raise Exception("CAC failed")
195
196            ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
197            if not ev:
198                raise Exception("AP setup timed out")
199            ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=30)
200            if not ev:
201                raise Exception("STA did not reconnect on new DFS channel")
202            dev[0].wait_connected()
203        else:
204            # The new channel did not require CAC - try again
205            if "freq=%s" % freq in ev:
206                raise Exception("Channel did not change after radar was detected(2)")
207            ev = dev[0].wait_event(["CTRL-EVENT-CHANNEL-SWITCH"], timeout=10)
208            if ev is None:
209                raise Exception("Channel switch not reported on STA")
210            time.sleep(1)
211
212        hapd.dump_monitor()
213        dev[0].dump_monitor()
214        time.sleep(1)
215        hwsim_utils.test_connectivity(dev[0], hapd)
216    finally:
217        clear_regdom(hapd, dev)
218
219def test_dfs_radar1(dev, apdev):
220    """DFS CAC functionality with radar detected during initial CAC"""
221    try:
222        hapd = None
223        hapd = start_dfs_ap(apdev[0])
224        time.sleep(1)
225
226        dfs_simulate_radar(hapd)
227
228        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
229        if ev is None:
230            raise Exception("Timeout on DFS aborted event")
231        if "success=0 freq=5260" not in ev:
232            raise Exception("Unexpected DFS aborted event contents: " + ev)
233
234        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
235        if "freq=5260" not in ev:
236            raise Exception("Unexpected DFS radar detection freq")
237
238        ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
239        if "freq=5260" in ev:
240            raise Exception("Unexpected DFS new freq")
241
242        ev = wait_dfs_event(hapd, None, 5)
243        if "AP-ENABLED" in ev:
244            logger.info("Started AP on non-DFS channel")
245        else:
246            logger.info("Trying to start AP on another DFS channel")
247            if "DFS-CAC-START" not in ev:
248                raise Exception("Unexpected DFS event: " + ev)
249            if "freq=5260" in ev:
250                raise Exception("Unexpected DFS CAC freq")
251
252            ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
253            if "success=1" not in ev:
254                raise Exception("CAC failed")
255            if "freq=5260" in ev:
256                raise Exception("Unexpected DFS freq result - radar channel")
257
258            ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
259            if not ev:
260                raise Exception("AP setup timed out")
261
262            state = hapd.get_status_field("state")
263            if state != "ENABLED":
264                raise Exception("Unexpected interface state")
265
266            freq = hapd.get_status_field("freq")
267            if freq == "5260":
268                raise Exception("Unexpected frequency: " + freq)
269
270        dev[0].connect("dfs", key_mgmt="NONE")
271        dev[0].wait_regdom(country_ie=True)
272    finally:
273        clear_regdom(hapd, dev)
274
275def test_dfs_radar2(dev, apdev):
276    """DFS CAC functionality with radar detected after initial CAC"""
277    try:
278        hapd = None
279        hapd = start_dfs_ap(apdev[0], ssid="dfs2", ht40=True)
280
281        ev = hapd.wait_event(["AP-ENABLED"], timeout=70)
282        if not ev:
283            raise Exception("AP2 setup timed out")
284
285        dfs_simulate_radar(hapd)
286
287        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
288        if "freq=5260 ht_enabled=1 chan_offset=1 chan_width=2" not in ev:
289            raise Exception("Unexpected DFS radar detection freq from AP2")
290
291        ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
292        if "freq=5260" in ev:
293            raise Exception("Unexpected DFS new freq for AP2")
294
295        wait_dfs_event(hapd, None, 5)
296    finally:
297        clear_regdom(hapd, dev)
298
299@remote_compatible
300def test_dfs_radar_on_non_dfs_channel(dev, apdev):
301    """DFS radar detection test code on non-DFS channel"""
302    params = {"ssid": "radar"}
303    hapd = hostapd.add_ap(apdev[0], params)
304
305    hapd.request("RADAR DETECTED freq=5260 ht_enabled=1 chan_width=1")
306    hapd.request("RADAR DETECTED freq=2412 ht_enabled=1 chan_width=1")
307
308def test_dfs_radar_chanlist(dev, apdev):
309    """DFS chanlist when radar is detected"""
310    try:
311        hapd = None
312        hapd = start_dfs_ap(apdev[0], chanlist="40 44")
313        time.sleep(1)
314
315        dfs_simulate_radar(hapd)
316
317        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
318        if ev is None:
319            raise Exception("Timeout on DFS aborted event")
320        if "success=0 freq=5260" not in ev:
321            raise Exception("Unexpected DFS aborted event contents: " + ev)
322
323        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
324        if "freq=5260" not in ev:
325            raise Exception("Unexpected DFS radar detection freq")
326
327        ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
328        if "freq=5200 chan=40" not in ev and "freq=5220 chan=44" not in ev:
329            raise Exception("Unexpected DFS new freq: " + ev)
330
331        ev = wait_dfs_event(hapd, None, 5)
332        if "AP-ENABLED" not in ev:
333            raise Exception("Unexpected DFS event: " + ev)
334        dev[0].connect("dfs", key_mgmt="NONE")
335        dev[0].wait_regdom(country_ie=True)
336    finally:
337        clear_regdom(hapd, dev)
338
339def test_dfs_radar_chanlist_vht80(dev, apdev):
340    """DFS chanlist when radar is detected and VHT80 configured"""
341    try:
342        hapd = None
343        hapd = start_dfs_ap(apdev[0], chanlist="36", ht40=True, vht80=True)
344        time.sleep(1)
345
346        dfs_simulate_radar(hapd)
347
348        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
349        if ev is None:
350            raise Exception("Timeout on DFS aborted event")
351        if "success=0 freq=5260" not in ev:
352            raise Exception("Unexpected DFS aborted event contents: " + ev)
353
354        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
355        if "freq=5260" not in ev:
356            raise Exception("Unexpected DFS radar detection freq")
357
358        ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
359        if "freq=5180 chan=36 sec_chan=1" not in ev:
360            raise Exception("Unexpected DFS new freq: " + ev)
361
362        ev = wait_dfs_event(hapd, None, 5)
363        if "AP-ENABLED" not in ev:
364            raise Exception("Unexpected DFS event: " + ev)
365        dev[0].connect("dfs", key_mgmt="NONE")
366        dev[0].wait_regdom(country_ie=True)
367
368        if hapd.get_status_field('vht_oper_centr_freq_seg0_idx') != "42":
369            raise Exception("Unexpected seg0 idx")
370    finally:
371        clear_regdom(hapd, dev)
372
373def test_dfs_radar_chanlist_vht20(dev, apdev):
374    """DFS chanlist when radar is detected and VHT40 configured"""
375    try:
376        hapd = None
377        hapd = start_dfs_ap(apdev[0], chanlist="36", vht20=True)
378        time.sleep(1)
379
380        dfs_simulate_radar(hapd)
381
382        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
383        if ev is None:
384            raise Exception("Timeout on DFS aborted event")
385        if "success=0 freq=5260" not in ev:
386            raise Exception("Unexpected DFS aborted event contents: " + ev)
387
388        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
389        if "freq=5260" not in ev:
390            raise Exception("Unexpected DFS radar detection freq")
391
392        ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
393        if "freq=5180 chan=36 sec_chan=0" not in ev:
394            raise Exception("Unexpected DFS new freq: " + ev)
395
396        ev = wait_dfs_event(hapd, None, 5)
397        if "AP-ENABLED" not in ev:
398            raise Exception("Unexpected DFS event: " + ev)
399        dev[0].connect("dfs", key_mgmt="NONE")
400        dev[0].wait_regdom(country_ie=True)
401    finally:
402        clear_regdom(hapd, dev)
403
404def test_dfs_radar_no_ht(dev, apdev):
405    """DFS chanlist when radar is detected and no HT configured"""
406    try:
407        hapd = None
408        hapd = start_dfs_ap(apdev[0], chanlist="36", ht=False)
409        time.sleep(1)
410
411        dfs_simulate_radar(hapd)
412
413        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
414        if ev is None:
415            raise Exception("Timeout on DFS aborted event")
416        if "success=0 freq=5260" not in ev:
417            raise Exception("Unexpected DFS aborted event contents: " + ev)
418
419        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
420        if "freq=5260 ht_enabled=0" not in ev:
421            raise Exception("Unexpected DFS radar detection freq: " + ev)
422
423        ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
424        if "freq=5180 chan=36 sec_chan=0" not in ev:
425            raise Exception("Unexpected DFS new freq: " + ev)
426
427        ev = wait_dfs_event(hapd, None, 5)
428        if "AP-ENABLED" not in ev:
429            raise Exception("Unexpected DFS event: " + ev)
430        dev[0].connect("dfs", key_mgmt="NONE")
431        dev[0].wait_regdom(country_ie=True)
432    finally:
433        clear_regdom(hapd, dev)
434
435def test_dfs_radar_ht40minus(dev, apdev):
436    """DFS chanlist when radar is detected and HT40- configured"""
437    try:
438        hapd = None
439        hapd = start_dfs_ap(apdev[0], chanlist="36", ht40minus=True)
440        time.sleep(1)
441
442        dfs_simulate_radar(hapd)
443
444        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
445        if ev is None:
446            raise Exception("Timeout on DFS aborted event")
447        if "success=0 freq=5280 ht_enabled=1 chan_offset=-1" not in ev:
448            raise Exception("Unexpected DFS aborted event contents: " + ev)
449
450        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
451        if "freq=5280 ht_enabled=1 chan_offset=-1" not in ev:
452            raise Exception("Unexpected DFS radar detection freq: " + ev)
453
454        ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
455        if "freq=5180 chan=36 sec_chan=1" not in ev:
456            raise Exception("Unexpected DFS new freq: " + ev)
457
458        ev = wait_dfs_event(hapd, None, 5)
459        if "AP-ENABLED" not in ev:
460            raise Exception("Unexpected DFS event: " + ev)
461        dev[0].connect("dfs", key_mgmt="NONE")
462        dev[0].wait_regdom(country_ie=True)
463        dev[0].request("STA_AUTOCONNECT 0")
464    finally:
465        clear_regdom(hapd, dev)
466        dev[0].request("STA_AUTOCONNECT 1")
467
468@long_duration_test
469def test_dfs_ht40_minus(dev, apdev):
470    """DFS CAC functionality on channel 104 HT40-"""
471    try:
472        hapd = None
473        hapd = start_dfs_ap(apdev[0], ht40minus=True, channel=104)
474
475        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
476        if "success=1" not in ev:
477            raise Exception("CAC failed")
478        if "freq=5520" not in ev:
479            raise Exception("Unexpected DFS freq result")
480
481        ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
482        if not ev:
483            raise Exception("AP setup timed out")
484
485        state = hapd.get_status_field("state")
486        if state != "ENABLED":
487            raise Exception("Unexpected interface state")
488
489        freq = hapd.get_status_field("freq")
490        if freq != "5520":
491            raise Exception("Unexpected frequency")
492
493        dev[0].connect("dfs", key_mgmt="NONE", scan_freq="5520")
494        dev[0].wait_regdom(country_ie=True)
495        hwsim_utils.test_connectivity(dev[0], hapd)
496    finally:
497        clear_regdom(hapd, dev)
498
499def test_dfs_cac_restart_on_enable(dev, apdev):
500    """DFS CAC interrupted and restarted"""
501    try:
502        hapd = None
503        hapd = start_dfs_ap(apdev[0])
504        time.sleep(0.1)
505        subprocess.check_call(['ip', 'link', 'set', 'dev', hapd.ifname, 'down'])
506        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
507        if ev is None:
508            raise Exception("Timeout on DFS aborted event")
509        if "success=0 freq=5260" not in ev:
510            raise Exception("Unexpected DFS aborted event contents: " + ev)
511        time.sleep(0.1)
512        subprocess.check_call(['ip', 'link', 'set', 'dev', hapd.ifname, 'up'])
513
514        ev = wait_dfs_event(hapd, "DFS-CAC-START", 5)
515        if "DFS-CAC-START" not in ev:
516            raise Exception("Unexpected DFS event: " + ev)
517        hapd.disable()
518
519    finally:
520        clear_regdom(hapd, dev)
521
522@long_duration_test
523def test_dfs_rrm(dev, apdev):
524    """DFS with RRM"""
525    try:
526        hapd = None
527        hapd = start_dfs_ap(apdev[0], country="US", rrm_beacon_report=True)
528
529        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
530        if "success=1" not in ev or "freq=5260" not in ev:
531            raise Exception("Unexpected DFS freq result")
532        ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
533        if not ev:
534            raise Exception("AP setup timed out")
535
536        dev[0].connect("dfs", key_mgmt="NONE", scan_freq="5260")
537        dev[0].wait_regdom(country_ie=True)
538        hapd.wait_sta()
539        hwsim_utils.test_connectivity(dev[0], hapd)
540        addr = dev[0].own_addr()
541        token = hapd.request("REQ_BEACON " + addr + " " + "51000000000002ffffffffffff")
542        if "FAIL" in token:
543            raise Exception("REQ_BEACON failed")
544        ev = hapd.wait_event(["BEACON-RESP-RX"], timeout=10)
545        if ev is None:
546            raise Exception("Beacon report response not received")
547    finally:
548        clear_regdom(hapd, dev)
549
550@long_duration_test
551def test_dfs_radar_vht80_downgrade(dev, apdev):
552    """DFS channel bandwidth downgrade from VHT80 to VHT40"""
553    try:
554        # Start with 80 MHz channel 100 (5500 MHz) to find a radar
555        hapd = None
556        hapd = start_dfs_ap(apdev[0], chanlist="100-140",
557                            ht40=True, vht80=True, chan100=True)
558        time.sleep(1)
559        dfs_simulate_radar(hapd)
560
561        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
562        if ev is None:
563            raise Exception("Timeout on DFS aborted event")
564        if "success=0 freq=5500" not in ev:
565            raise Exception("Unexpected DFS aborted event contents: " + ev)
566
567        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
568        if "freq=5500" not in ev:
569            raise Exception("Unexpected DFS radar detection freq: " + ev)
570
571        # The only other available 80 MHz channel in the chanlist is
572        # 116 (5580 MHz), so that will be selected next.
573        ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
574        if "freq=5580 chan=116 sec_chan=1" not in ev:
575            raise Exception("Unexpected DFS new freq: " + ev)
576
577        ev = wait_dfs_event(hapd, None, 5)
578        if "DFS-CAC-START" not in ev:
579            raise Exception("Unexpected DFS event: " + ev)
580        if "freq=5580" not in ev:
581            raise Exception("Unexpected DFS CAC freq: " + ev)
582
583        time.sleep(1)
584        dfs_simulate_radar(hapd)
585        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5)
586        if ev is None:
587            raise Exception("Timeout on DFS aborted event (2)")
588        if "success=0 freq=5580" not in ev:
589            raise Exception("Unexpected DFS aborted event (2) contents: " + ev)
590
591        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
592        if "freq=5580" not in ev:
593            raise Exception("Unexpected DFS radar detection (2) freq: " + ev)
594
595        # No more 80 MHz channels are available, so have to downgrade to 40 MHz
596        # channels and the only remaining one is channel 132 (5660 MHz).
597        ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
598        if "freq=5660 chan=132 sec_chan=1" not in ev:
599            raise Exception("Unexpected DFS new freq (2): " + ev)
600
601        ev = wait_dfs_event(hapd, None, 5)
602        if "DFS-CAC-START" not in ev:
603            raise Exception("Unexpected DFS event: " + ev)
604        if "freq=5660" not in ev:
605            raise Exception("Unexpected DFS CAC freq (2): " + ev)
606
607        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
608        if "success=1" not in ev:
609            raise Exception("CAC failed")
610        if "freq=5660" not in ev:
611            raise Exception("Unexpected DFS freq result: " + ev)
612
613        ev = wait_dfs_event(hapd, None, 5)
614        if "AP-ENABLED" not in ev:
615            raise Exception("Unexpected DFS event: " + ev)
616        dev[0].connect("dfs", key_mgmt="NONE", scan_freq="5660")
617        dev[0].wait_regdom(country_ie=True)
618        sig = dev[0].request("SIGNAL_POLL").splitlines()
619        if "FREQUENCY=5660" not in sig or "WIDTH=40 MHz" not in sig:
620            raise Exception("Unexpected SIGNAL_POLL value: " + str(sig))
621    finally:
622        clear_regdom(hapd, dev)
623
624@long_duration_test
625def test_dfs_chan_switch(dev, apdev):
626    """DFS channel switch"""
627    try:
628        hapd = None
629        hapd = start_dfs_ap(apdev[0], country="US")
630
631        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
632        if "success=1" not in ev:
633            raise Exception("CAC failed")
634        if "freq=5260" not in ev:
635            raise Exception("Unexpected DFS freq result")
636        ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
637        if not ev:
638            raise Exception("AP setup timed out")
639        freq = hapd.get_status_field("freq")
640        if freq != "5260":
641            raise Exception("Unexpected frequency")
642
643        dev[0].connect("dfs", key_mgmt="NONE", scan_freq="5260 5280 5180 5500")
644        dev[0].wait_regdom(country_ie=True)
645        hwsim_utils.test_connectivity(dev[0], hapd)
646
647        if "OK" not in hapd.request("CHAN_SWITCH 5 5280 ht"):
648            raise Exception("CHAN_SWITCH failed")
649        # This results in BSS going down before restart, so the STA is expected
650        # to report disconnection.
651        dev[0].wait_disconnected()
652        ev = wait_dfs_event(hapd, "DFS-CAC-START", 5)
653        if "freq=5280" not in ev:
654            raise Exception("Unexpected channel: " + ev)
655        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
656        if "success=1" not in ev:
657            raise Exception("CAC failed")
658        if "freq=5280" not in ev:
659            raise Exception("Unexpected DFS freq result")
660        ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
661        if not ev:
662            raise Exception("AP setup timed out")
663        freq = hapd.get_status_field("freq")
664        if freq != "5280":
665            raise Exception("Unexpected frequency")
666
667        dev[0].wait_connected(timeout=30)
668        hwsim_utils.test_connectivity(dev[0], hapd)
669
670        # Move to non DFS channel: 36, opclass 115
671        if "OK" not in hapd.request("CHAN_SWITCH 5 5180"):
672                raise Exception("CHAN_SWITCH failed")
673        ev = wait_dfs_event(hapd, "AP-CSA-FINISHED", 5)
674
675        if "freq=5180" not in ev:
676            raise Exception("Unexpected channel: " + ev)
677        time.sleep(1)
678        hwsim_utils.test_connectivity(dev[0], hapd)
679
680        # Move to channel 100, opclass 121
681        if "OK" not in hapd.request("CHAN_SWITCH 5 5500 ht"):
682            raise Exception("CHAN_SWITCH failed")
683        # This results in BSS going down before restart, so the STA is expected
684        # to report disconnection.
685        dev[0].wait_disconnected()
686        ev = wait_dfs_event(hapd, "DFS-CAC-START", 5)
687        if "freq=5500" not in ev:
688            raise Exception("Unexpected channel: " + ev)
689        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
690        if "success=1" not in ev:
691            raise Exception("CAC failed")
692        if "freq=5500" not in ev:
693            raise Exception("Unexpected DFS freq result")
694        ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
695        if not ev:
696            raise Exception("AP setup timed out")
697        freq = hapd.get_status_field("freq")
698        if freq != "5500":
699            raise Exception("Unexpected frequency")
700
701        dev[0].wait_connected(timeout=30)
702        hwsim_utils.test_connectivity(dev[0], hapd)
703    finally:
704        clear_regdom(hapd, dev)
705
706@long_duration_test
707def test_dfs_chan_switch_to_vht80(dev, apdev):
708    """DFS channel switch to VHT80"""
709    run_dfs_chan_switch_to_vht(dev, apdev, vht80=True)
710
711@long_duration_test
712def test_dfs_chan_switch_to_vht80p80(dev, apdev):
713    """DFS channel switch to VHT80+80"""
714    run_dfs_chan_switch_to_vht(dev, apdev, vht80p80=True)
715
716@long_duration_test
717def test_dfs_chan_switch_to_vht160(dev, apdev):
718    """DFS channel switch to VHT160"""
719    run_dfs_chan_switch_to_vht(dev, apdev, vht160=True)
720
721@long_duration_test
722def test_dfs_chan_switch_to_vht160b(dev, apdev):
723    """DFS channel switch to VHT160 from non-DFS"""
724    run_dfs_chan_switch_to_vht(dev, apdev, vht160=True, start_dfs=False)
725
726def run_dfs_chan_switch_to_vht(dev, apdev, vht80=False, vht80p80=False,
727                               vht160=False, start_dfs=True):
728    try:
729        hapd = None
730        if start_dfs:
731            hapd = start_dfs_ap(apdev[0], country="US")
732
733            ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
734            if "success=1" not in ev:
735                raise Exception("CAC failed")
736            if "freq=5260" not in ev:
737                raise Exception("Unexpected DFS freq result")
738            ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
739            if not ev:
740                raise Exception("AP setup timed out")
741            freq = hapd.get_status_field("freq")
742            if freq != "5260":
743                raise Exception("Unexpected frequency")
744
745            dev[0].connect("dfs", key_mgmt="NONE", scan_freq="5260 5180")
746        else:
747            params = {"ssid": "dfs",
748                      "country_code": "US",
749                      "ieee80211d": "1",
750                      "hw_mode": "a",
751                      "channel": "40"}
752            hapd = hostapd.add_ap(apdev[0], params)
753            dev[0].connect("dfs", key_mgmt="NONE", scan_freq="5260 5180 5200")
754        dev[0].wait_regdom(country_ie=True)
755        hwsim_utils.test_connectivity(dev[0], hapd)
756
757        if vht160:
758            if not start_dfs:
759                hapd.set("ieee80211h", "1")
760            cmd = "CHAN_SWITCH 5 5180 sec_channel_offset=1 center_freq1=5250 bandwidth=160 ht vht"
761        if vht80p80:
762            cmd = "CHAN_SWITCH 5 5180 sec_channel_offset=1 center_freq1=5210 center_freq2=5775 bandwidth=80 ht vht"
763        if vht80:
764            cmd = "CHAN_SWITCH 5 5180 sec_channel_offset=1 center_freq1=5210 bandwidth=80 ht vht"
765        if "OK" not in hapd.request(cmd):
766            raise Exception("CHAN_SWITCH command failed")
767        if vht160:
768            # This results in BSS going down before restart, so the STA is
769            # expected to report disconnection.
770            dev[0].wait_disconnected()
771            ev = wait_dfs_event(hapd, "DFS-CAC-START", 5)
772            if "freq=5180" not in ev:
773                raise Exception("Unexpected channel: " + ev)
774            ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
775            if "success=1" not in ev:
776                raise Exception("CAC failed")
777        else:
778            ev = wait_dfs_event(hapd, "AP-CSA-FINISHED", 5)
779        if "freq=5180" not in ev:
780            raise Exception("Unexpected channel: " + ev)
781        if vht160:
782            ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
783            if not ev:
784                raise Exception("AP setup timed out")
785
786        freq = hapd.get_status_field("freq")
787        if freq != "5180":
788            raise Exception("Unexpected frequency")
789
790        status = hapd.get_status()
791        logger.info("hostapd STATUS: " + str(status))
792        if status["ieee80211n"] != "1":
793            raise Exception("Unexpected STATUS ieee80211n value")
794        if status["ieee80211ac"] != "1":
795            raise Exception("Unexpected STATUS ieee80211ac value")
796        if status["secondary_channel"] != "1":
797            raise Exception("Unexpected STATUS secondary_channel value")
798        if vht80 and status["vht_oper_chwidth"] != "1":
799            raise Exception("Unexpected STATUS vht_oper_chwidth value")
800        if vht80p80 and status["vht_oper_chwidth"] != "3":
801            raise Exception("Unexpected STATUS vht_oper_chwidth value")
802        if vht160 and status["vht_oper_chwidth"] != "2":
803            raise Exception("Unexpected STATUS vht_oper_chwidth value")
804        if vht160:
805            if status["vht_oper_centr_freq_seg0_idx"] != "50":
806                raise Exception("Unexpected STATUS vht_oper_centr_freq_seg0_idx value")
807        else:
808            if status["vht_oper_centr_freq_seg0_idx"] != "42":
809                raise Exception("Unexpected STATUS vht_oper_centr_freq_seg0_idx value")
810        if vht80p80 and status["vht_oper_centr_freq_seg1_idx"] != "155":
811            raise Exception("Unexpected STATUS vht_oper_centr_freq_seg1_idx value")
812        if "vht_caps_info" not in status:
813            raise Exception("Missing vht_caps_info")
814
815        if vht160:
816            dev[0].wait_connected(timeout=30)
817        else:
818            ev = dev[0].wait_event(["CTRL-EVENT-CHANNEL-SWITCH"], timeout=10)
819            if ev is None:
820                raise Exception("Channel switch not reported")
821            if "freq=5180" not in ev:
822                raise Exception("Unexpected frequency: " + ev)
823        sig = dev[0].request("SIGNAL_POLL").splitlines()
824        logger.info("STA0: " + str(sig))
825        if "FREQUENCY=5180" not in sig:
826            raise Exception("Unexpected channel: " + str(sig))
827        if vht160 and "WIDTH=160 MHz" not in sig:
828            raise Exception("Unexpected channel[1]: " + str(sig))
829        hwsim_utils.test_connectivity(dev[0], hapd)
830
831        dev[1].connect("dfs", key_mgmt="NONE", scan_freq="5180")
832        sig = dev[1].request("SIGNAL_POLL").splitlines()
833        logger.info("STA1: " + str(sig))
834        if "FREQUENCY=5180" not in sig:
835            raise Exception("Unexpected channel[1]: " + str(sig))
836        if vht80 and "WIDTH=80 MHz" not in sig:
837            raise Exception("Unexpected channel[1]: " + str(sig))
838        if vht80p80 and "WIDTH=80+80 MHz" not in sig:
839            raise Exception("Unexpected channel[1]: " + str(sig))
840        if vht160 and "WIDTH=160 MHz" not in sig:
841            raise Exception("Unexpected channel[1]: " + str(sig))
842    finally:
843        clear_regdom(hapd, dev)
844
845@long_duration_test
846def test_dfs_no_available_channel(dev, apdev):
847    """DFS and no available channel after radar detection"""
848    try:
849        hapd = None
850        hapd = start_dfs_ap(apdev[0], chanlist="56")
851
852        ev = hapd.wait_event(["AP-ENABLED"], timeout=70)
853        if not ev:
854            raise Exception("AP2 setup timed out")
855
856        dfs_simulate_radar(hapd)
857        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
858        if "freq=5260 ht_enabled=1 chan_offset=0 chan_width=1" not in ev:
859            raise Exception("Unexpected DFS radar detection freq from AP")
860
861        ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5)
862        if "freq=5280 chan=56" not in ev:
863            raise Exception("Unexpected DFS new freq: " + ev)
864        ev = wait_dfs_event(hapd, "DFS-CAC-START", 5)
865        if "freq=5280" not in ev:
866            raise Exception("Unexpected channel: " + ev)
867        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
868        if "success=1" not in ev:
869            raise Exception("CAC failed")
870        if "freq=5280" not in ev:
871            raise Exception("Unexpected DFS freq result")
872        ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
873        if not ev:
874            raise Exception("AP setup timed out")
875
876        dfs_simulate_radar(hapd)
877        ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5)
878        if "freq=5280 ht_enabled=1 chan_offset=0 chan_width=1" not in ev:
879            raise Exception("Unexpected DFS radar detection freq from AP [2]")
880
881        ev = hapd.wait_event(["AP-DISABLED"], timeout=10)
882        if ev is None:
883            raise Exception("AP was not disabled")
884    finally:
885        clear_regdom(hapd, dev)
886
887def dfs_chan_switch_precac(dev, apdev, country):
888    """DFS channel switch pre CAC"""
889    try:
890        hapd = None
891
892        # Toggle regulatory - clean all preCAC
893        hostapd.cmd_execute(apdev[0], ['iw', 'reg', 'set', 'US'])
894
895        hapd = start_dfs_ap(apdev[0], country=country)
896
897        ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
898        if "success=1" not in ev:
899            raise Exception("CAC failed")
900        if "freq=5260" not in ev:
901            raise Exception("Unexpected DFS freq result")
902        ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
903        if not ev:
904            raise Exception("AP setup timed out")
905        freq = hapd.get_status_field("freq")
906        if freq != "5260":
907            raise Exception("Unexpected frequency")
908
909        # TODO add/connect station here
910        # Today skip this step while dev[0].connect()
911        # for some reason toggle regulatory to US
912        # and clean preCAC
913
914        # Back to non DFS channel
915        if "OK" not in hapd.request("CHAN_SWITCH 5 5180 ht"):
916            raise Exception("CHAN_SWITCH 5180 failed")
917
918        ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=5)
919        if not ev:
920            raise Exception("No CSA finished event - 5180")
921        freq = hapd.get_status_field("freq")
922        if freq != "5180":
923            raise Exception("Unexpected frequency")
924
925        # Today cfg80211 first send AP-CSA-FINISHED and next
926        # DFS-PRE-CAC-EXPIRED
927        ev = hapd.wait_event(["DFS-PRE-CAC-EXPIRED"], timeout=3)
928        if not ev and country == 'US':
929            raise Exception("US - no CAC-EXPIRED event")
930
931	# Back again to DFS channel (CAC passed)
932        if "OK" not in hapd.request("CHAN_SWITCH 5 5260 ht"):
933            raise Exception("CHAN_SWITCH 5260 failed")
934
935        if country == 'US':
936            # For non EU we should start CAC again
937            ev = wait_dfs_event(hapd, "DFS-CAC-START", 5)
938            if not ev:
939                raise Exception("No DFS CAC start event")
940        else:
941            # For EU preCAC should be used
942            ev = wait_dfs_event(hapd, "AP-CSA-FINISHED", 5)
943            if not ev:
944                raise Exception("No CSA finished event - 5260")
945    finally:
946        clear_regdom(hapd, dev)
947
948@long_duration_test
949def test_dfs_eu_chan_switch_precac(dev, apdev):
950    """DFS channel switch pre CAC - ETSI domain"""
951    dfs_chan_switch_precac(dev, apdev, 'PL')
952
953@long_duration_test
954def test_dfs_us_chan_switch_precac(dev, apdev):
955    """DFS channel switch pre CAC - FCC domain"""
956    dfs_chan_switch_precac(dev, apdev, 'US')
957