1# AP CSA tests 2# Copyright (c) 2013, Luciano Coelho <luciano.coelho@intel.com> 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 time 9import logging 10logger = logging.getLogger() 11 12import hwsim_utils 13import hostapd 14from utils import * 15 16def connect(dev, apdev, scan_freq="2412", **kwargs): 17 params = {"ssid": "ap-csa", 18 "channel": "1"} 19 params.update(kwargs) 20 ap = hostapd.add_ap(apdev[0], params) 21 dev.connect("ap-csa", key_mgmt="NONE", scan_freq=scan_freq) 22 return ap 23 24def switch_channel(ap, count, freq, extra=None): 25 cmd = "CHAN_SWITCH " + str(count) + " " + str(freq) 26 if extra: 27 cmd += " " + extra 28 ap.request(cmd) 29 30 ev = ap.wait_event(["CTRL-EVENT-STARTED-CHANNEL-SWITCH"], timeout=10) 31 if ev is None: 32 raise Exception("Channel switch start event not seen") 33 if "freq=" + str(freq) not in ev: 34 raise Exception("Unexpected channel in CS started event") 35 36 ev = ap.wait_event(["CTRL-EVENT-CHANNEL-SWITCH"], timeout=10) 37 if ev is None: 38 raise Exception("Channel switch completed event not seen") 39 if "freq=" + str(freq) not in ev: 40 raise Exception("Unexpected channel in CS completed event") 41 42 ev = ap.wait_event(["AP-CSA-FINISHED"], timeout=10) 43 if ev is None: 44 raise Exception("CSA finished event timed out") 45 if "freq=" + str(freq) not in ev: 46 raise Exception("Unexpected channel in CSA finished event") 47 48def wait_channel_switch(dev, freq): 49 ev = dev.wait_event(["CTRL-EVENT-STARTED-CHANNEL-SWITCH"], timeout=5) 50 if ev is None: 51 raise Exception("Channel switch start not reported") 52 if "freq=%d" % freq not in ev: 53 raise Exception("Unexpected frequency in channel switch started: " + ev) 54 55 ev = dev.wait_event(["CTRL-EVENT-CHANNEL-SWITCH"], timeout=5) 56 if ev is None: 57 raise Exception("Channel switch not reported") 58 if "freq=%d" % freq not in ev: 59 raise Exception("Unexpected frequency: " + ev) 60 ev = dev.wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1) 61 if ev is not None: 62 raise Exception("Unexpected disconnection on channel switch") 63 64@remote_compatible 65def test_ap_csa_1_switch(dev, apdev): 66 """AP Channel Switch, one switch""" 67 csa_supported(dev[0]) 68 freq = int(dev[0].get_driver_status_field("freq")) 69 if freq != 0: 70 raise Exception("Unexpected driver freq=%d in beginning" % freq) 71 ap = connect(dev[0], apdev) 72 freq = int(dev[0].get_driver_status_field("freq")) 73 if freq != 2412: 74 raise Exception("Unexpected driver freq=%d after association" % freq) 75 76 hwsim_utils.test_connectivity(dev[0], ap) 77 switch_channel(ap, 10, 2462, extra="ht") 78 wait_channel_switch(dev[0], 2462) 79 hwsim_utils.test_connectivity(dev[0], ap) 80 freq = int(dev[0].get_driver_status_field("freq")) 81 if freq != 2462: 82 raise Exception("Unexpected driver freq=%d after channel switch" % freq) 83 dev[0].request("DISCONNECT") 84 dev[0].wait_disconnected() 85 freq = int(dev[0].get_driver_status_field("freq")) 86 if freq != 0: 87 raise Exception("Unexpected driver freq=%d after disconnection" % freq) 88 89@remote_compatible 90def test_ap_csa_2_switches(dev, apdev): 91 """AP Channel Switch, two switches""" 92 csa_supported(dev[0]) 93 ap = connect(dev[0], apdev) 94 95 hwsim_utils.test_connectivity(dev[0], ap) 96 switch_channel(ap, 10, 2462, extra="ht") 97 wait_channel_switch(dev[0], 2462) 98 hwsim_utils.test_connectivity(dev[0], ap) 99 switch_channel(ap, 10, 2412, extra="ht") 100 wait_channel_switch(dev[0], 2412) 101 hwsim_utils.test_connectivity(dev[0], ap) 102 103@remote_compatible 104def test_ap_csa_1_switch_count_0(dev, apdev): 105 """AP Channel Switch, one switch with count 0""" 106 csa_supported(dev[0]) 107 ap = connect(dev[0], apdev) 108 109 hwsim_utils.test_connectivity(dev[0], ap) 110 switch_channel(ap, 0, 2462) 111 # this does not result in CSA currently, so do not bother checking 112 # connectivity 113 114@remote_compatible 115def test_ap_csa_2_switches_count_0(dev, apdev): 116 """AP Channel Switch, two switches with count 0""" 117 csa_supported(dev[0]) 118 ap = connect(dev[0], apdev) 119 120 hwsim_utils.test_connectivity(dev[0], ap) 121 switch_channel(ap, 0, 2462) 122 # this does not result in CSA currently, so do not bother checking 123 # connectivity 124 switch_channel(ap, 0, 2412) 125 # this does not result in CSA currently, so do not bother checking 126 # connectivity 127 128@remote_compatible 129def test_ap_csa_1_switch_count_1(dev, apdev): 130 """AP Channel Switch, one switch with count 1""" 131 csa_supported(dev[0]) 132 ap = connect(dev[0], apdev) 133 134 hwsim_utils.test_connectivity(dev[0], ap) 135 switch_channel(ap, 1, 2462) 136 # this does not result in CSA currently, so do not bother checking 137 # connectivity 138 139@remote_compatible 140def test_ap_csa_2_switches_count_1(dev, apdev): 141 """AP Channel Switch, two switches with count 1""" 142 csa_supported(dev[0]) 143 ap = connect(dev[0], apdev) 144 145 hwsim_utils.test_connectivity(dev[0], ap) 146 switch_channel(ap, 1, 2462) 147 # this does not result in CSA currently, so do not bother checking 148 # connectivity 149 switch_channel(ap, 1, 2412) 150 # this does not result in CSA currently, so do not bother checking 151 # connectivity 152 153@remote_compatible 154def test_ap_csa_1_switch_count_2(dev, apdev): 155 """AP Channel Switch, one switch with count 2""" 156 csa_supported(dev[0]) 157 ap = connect(dev[0], apdev) 158 159 hwsim_utils.test_connectivity(dev[0], ap) 160 switch_channel(ap, 2, 2462, extra="ht") 161 wait_channel_switch(dev[0], 2462) 162 hwsim_utils.test_connectivity(dev[0], ap) 163 164@remote_compatible 165def test_ap_csa_ecsa_only(dev, apdev): 166 """AP Channel Switch, one switch with only ECSA IE""" 167 csa_supported(dev[0]) 168 ap = connect(dev[0], apdev, ecsa_ie_only="1") 169 170 hwsim_utils.test_connectivity(dev[0], ap) 171 switch_channel(ap, 10, 2462, extra="ht") 172 wait_channel_switch(dev[0], 2462) 173 hwsim_utils.test_connectivity(dev[0], ap) 174 175@remote_compatible 176def test_ap_csa_csa_only(dev, apdev): 177 """AP Channel Switch, one switch with only CSA IE""" 178 csa_supported(dev[0]) 179 ap = connect(dev[0], apdev, csa_ie_only="1") 180 181 hwsim_utils.test_connectivity(dev[0], ap) 182 switch_channel(ap, 10, 2462, extra="ht") 183 wait_channel_switch(dev[0], 2462) 184 hwsim_utils.test_connectivity(dev[0], ap) 185 186@remote_compatible 187def test_ap_csa_invalid(dev, apdev): 188 """AP Channel Switch - invalid channel""" 189 csa_supported(dev[0]) 190 ap = connect(dev[0], apdev) 191 192 vals = [2461, 4900, 4901, 5181, 5746, 5699, 5895, 5899] 193 for val in vals: 194 if "FAIL" not in ap.request("CHAN_SWITCH 1 %d" % val): 195 raise Exception("Invalid channel accepted: %d" % val) 196 197def test_ap_csa_disable(dev, apdev): 198 """AP Channel Switch and DISABLE command before completion""" 199 csa_supported(dev[0]) 200 ap = connect(dev[0], apdev, scan_freq="2412 2462") 201 if "OK" not in ap.request("CHAN_SWITCH 10 2462"): 202 raise Exception("CHAN_SWITCH failed") 203 ap.disable() 204 ap.enable() 205 dev[0].wait_disconnected() 206 dev[0].wait_connected() 207 208def _assoc_while_csa(dev, apdev, freq_to, blocktx): 209 params = { 210 "ssid": "ap-csa", 211 "hw_mode": "a", 212 "country_code": "FI", 213 "channel": "36", 214 "ieee80211n": "0", 215 } 216 ap = hostapd.add_ap(apdev[0], params) 217 count = 100 if blocktx else 20 218 delay = 1 + count / 10 219 cmd = f"CHAN_SWITCH {count} {freq_to}" 220 if blocktx: 221 cmd += " blocktx" 222 ap.request(cmd) 223 224 ev = ap.wait_event(["CTRL-EVENT-STARTED-CHANNEL-SWITCH"], timeout=10) 225 if ev is None: 226 raise Exception("Channel switch start event not seen") 227 if f"freq={freq_to}" not in ev: 228 raise Exception("Unexpected channel in CS started event") 229 try: 230 dev[0].connect("ap-csa", key_mgmt="NONE", scan_freq="5180", 231 wait_connect=False) 232 if blocktx or freq_to != 5180: 233 ev = dev[0].wait_event(["CTRL-EVENT-SSID-TEMP-DISABLED", 234 "CTRL-EVENT-CONNECTED"], timeout=9) 235 if not ev: # this is fine, at least we didn't connect 236 return 237 if not "CTRL-EVENT-SSID-TEMP-DISABLED" in ev: 238 raise Exception("Erroneously connected!") 239 if not 'auth_failures=1' in ev: 240 raise Exception(f'Should have auth failures in "{ev}"') 241 # wait for CSA to finish and connect then 242 time.sleep(delay) 243 dev[0].connect("ap-csa", key_mgmt="NONE", scan_freq=str(freq_to)) 244 else: 245 dev[0].wait_connected() 246 if freq_to != 5180: 247 wait_channel_switch(dev[0], freq_to) 248 finally: 249 dev[0].request("DISCONNECT") 250 dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1) 251 clear_regdom(ap, dev) 252 253@long_duration_test 254def test_assoc_while_csa_same_blocktx(dev, apdev): 255 """Check we don't associate while AP is doing quiet CSA (same channel)""" 256 _assoc_while_csa(dev, apdev, 5180, True) 257 258def test_assoc_while_csa_same(dev, apdev): 259 """Check we _do_ associate while AP is doing CSA (same channel)""" 260 _assoc_while_csa(dev, apdev, 5180, False) 261 262@long_duration_test 263def test_assoc_while_csa_diff_blocktx(dev, apdev): 264 """Check we don't associate while AP is doing quiet CSA (different channel)""" 265 _assoc_while_csa(dev, apdev, 5200, True) 266 267@long_duration_test 268def test_assoc_while_csa_diff(dev, apdev): 269 """Check we don't associate while AP is doing CSA (different channel)""" 270 _assoc_while_csa(dev, apdev, 5200, False) 271 272def test_ap_stuck_ecsa(dev, apdev): 273 """ECSA element stuck in Probe Response frame""" 274 275 # Test behaving like an Asus RT-AC53, firmware 3.0.0.4.380_10760-g21a5898, 276 # which has stuck ECSA element in the Probe Response frames. 277 try: 278 ap = connect(dev[0], apdev, scan_freq=None, 279 hw_mode='a', channel='36', 280 country_code='FI', 281 presp_elements="3c0401732409") 282 ap.wait_sta() 283 hwsim_utils.test_connectivity(dev[0], ap) 284 finally: 285 dev[0].request("DISCONNECT") 286 dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1) 287 clear_regdom(ap, dev) 288