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_invalid(dev, apdev): 177 """AP Channel Switch - invalid channel""" 178 csa_supported(dev[0]) 179 ap = connect(dev[0], apdev) 180 181 vals = [2461, 4900, 4901, 5181, 5746, 5699, 5895, 5899] 182 for val in vals: 183 if "FAIL" not in ap.request("CHAN_SWITCH 1 %d" % val): 184 raise Exception("Invalid channel accepted: %d" % val) 185 186def test_ap_csa_disable(dev, apdev): 187 """AP Channel Switch and DISABLE command before completion""" 188 csa_supported(dev[0]) 189 ap = connect(dev[0], apdev, scan_freq="2412 2462") 190 if "OK" not in ap.request("CHAN_SWITCH 10 2462"): 191 raise Exception("CHAN_SWITCH failed") 192 ap.disable() 193 ap.enable() 194 dev[0].wait_disconnected() 195 dev[0].wait_connected() 196 197def _assoc_while_csa(dev, apdev, freq_to, blocktx): 198 params = { 199 "ssid": "ap-csa", 200 "hw_mode": "a", 201 "country_code": "FI", 202 "channel": "36", 203 "ieee80211n": "0", 204 } 205 ap = hostapd.add_ap(apdev[0], params) 206 count = 100 if blocktx else 20 207 delay = 1 + count / 10 208 cmd = f"CHAN_SWITCH {count} {freq_to}" 209 if blocktx: 210 cmd += " blocktx" 211 ap.request(cmd) 212 213 ev = ap.wait_event(["CTRL-EVENT-STARTED-CHANNEL-SWITCH"], timeout=10) 214 if ev is None: 215 raise Exception("Channel switch start event not seen") 216 if f"freq={freq_to}" not in ev: 217 raise Exception("Unexpected channel in CS started event") 218 try: 219 dev[0].connect("ap-csa", key_mgmt="NONE", scan_freq="5180", 220 wait_connect=False) 221 if blocktx or freq_to != 5180: 222 ev = dev[0].wait_event(["CTRL-EVENT-SSID-TEMP-DISABLED", 223 "CTRL-EVENT-CONNECTED"], timeout=9) 224 if not ev: # this is fine, at least we didn't connect 225 return 226 if not "CTRL-EVENT-SSID-TEMP-DISABLED" in ev: 227 raise Exception("Erroneously connected!") 228 if not 'auth_failures=1' in ev: 229 raise Exception(f'Should have auth failures in "{ev}"') 230 # wait for CSA to finish and connect then 231 time.sleep(delay) 232 dev[0].connect("ap-csa", key_mgmt="NONE", scan_freq=str(freq_to)) 233 else: 234 dev[0].wait_connected() 235 if freq_to != 5180: 236 wait_channel_switch(dev[0], freq_to) 237 finally: 238 dev[0].request("DISCONNECT") 239 dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1) 240 clear_regdom(ap, dev) 241 242@long_duration_test 243def test_assoc_while_csa_same_blocktx(dev, apdev): 244 """Check we don't associate while AP is doing quiet CSA (same channel)""" 245 _assoc_while_csa(dev, apdev, 5180, True) 246 247def test_assoc_while_csa_same(dev, apdev): 248 """Check we _do_ associate while AP is doing CSA (same channel)""" 249 _assoc_while_csa(dev, apdev, 5180, False) 250 251@long_duration_test 252def test_assoc_while_csa_diff_blocktx(dev, apdev): 253 """Check we don't associate while AP is doing quiet CSA (different channel)""" 254 _assoc_while_csa(dev, apdev, 5200, True) 255 256@long_duration_test 257def test_assoc_while_csa_diff(dev, apdev): 258 """Check we don't associate while AP is doing CSA (different channel)""" 259 _assoc_while_csa(dev, apdev, 5200, False) 260 261def test_ap_stuck_ecsa(dev, apdev): 262 """ECSA element stuck in Probe Response frame""" 263 264 # Test behaving like an Asus RT-AC53, firmware 3.0.0.4.380_10760-g21a5898, 265 # which has stuck ECSA element in the Probe Response frames. 266 try: 267 ap = connect(dev[0], apdev, scan_freq=None, 268 hw_mode='a', channel='36', 269 country_code='FI', 270 presp_elements="3c0401732409") 271 ap.wait_sta() 272 hwsim_utils.test_connectivity(dev[0], ap) 273 finally: 274 dev[0].request("DISCONNECT") 275 dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1) 276 clear_regdom(ap, dev) 277