The crash itself is caused by new roam scans overwriting the previous
scan ID. To simulate this both BSS's are set to very low signal strength
which will cause IWD to attempt a roam but find no better BSS candidates.
IWD will then attempt a roam scan again. During this we kill hostapd which
sends a disconnect and should trigger a crash without the fix.
---
.../testPSK-roam/roam_ap_disconnect_test.py | 96 +++++++++++++++++++
1 file changed, 96 insertions(+)
create mode 100644 autotests/testPSK-roam/roam_ap_disconnect_test.py
diff --git a/autotests/testPSK-roam/roam_ap_disconnect_test.py
b/autotests/testPSK-roam/roam_ap_disconnect_test.py
new file mode 100644
index 00000000..f11fe5bb
--- /dev/null
+++ b/autotests/testPSK-roam/roam_ap_disconnect_test.py
@@ -0,0 +1,96 @@
+#! /usr/bin/python3
+
+import unittest
+import sys, os
+
+sys.path.append('../util')
+from iwd import IWD
+from iwd import NetworkType
+from hwsim import Hwsim
+from hostapd import HostapdCLI
+
+class Test(unittest.TestCase):
+ #
+ # Tests a crash reported where multiple roam scans combined with an AP
+ # disconnect result in a crash getting scan results.
+ #
+ def test_ap_disconnect(self):
+ wd = IWD(True)
+ device = wd.list_devices(1)[0]
+
+ ordered_network = device.get_ordered_network('TestFT')
+
+ self.assertEqual(ordered_network.type, NetworkType.psk)
+
+ condition = 'not obj.connected'
+ wd.wait_for_object_condition(ordered_network.network_object, condition)
+
+ device.connect_bssid(self.bss_hostapd[0].bssid)
+
+ condition = 'obj.state == DeviceState.connected'
+ wd.wait_for_object_condition(device, condition)
+
+ # Since both BSS's have low signal, the roam should fail and trigger
+ # another roam scan.
+ device.wait_for_event('no-roam-candidates')
+
+ # Hostapd sends disconnect
+ self.bss_hostapd[0].disable()
+
+ # IWD should recover, and not crash
+ condition = 'obj.state == DeviceState.disconnected'
+ wd.wait_for_object_condition(device, condition)
+
+ def tearDown(self):
+ os.system('ip link set "' + self.bss_hostapd[0].ifname + '"
down')
+ os.system('ip link set "' + self.bss_hostapd[1].ifname + '"
down')
+ os.system('ip link set "' + self.bss_hostapd[0].ifname + '"
up')
+ os.system('ip link set "' + self.bss_hostapd[1].ifname + '"
up')
+
+ @classmethod
+ def setUpClass(cls):
+ hwsim = Hwsim()
+
+ IWD.copy_to_storage('TestFT.psk')
+
+ cls.bss_hostapd = [ HostapdCLI(config='ft-psk-ccmp-1.conf'),
+ HostapdCLI(config='ft-psk-ccmp-2.conf') ]
+
+ cls.rule0 = hwsim.rules.create()
+ cls.rule0.source = cls.bss_hostapd[0].bssid
+ cls.rule0.signal = -8000
+ cls.rule0.enabled = True
+
+ cls.rule1 = hwsim.rules.create()
+ cls.rule1.source = cls.bss_hostapd[1].bssid
+ cls.rule1.signal = -9000
+ cls.rule1.enabled = True
+
+ # Set interface addresses to those expected by hostapd config files
+ os.system('ip link set dev "' + cls.bss_hostapd[0].ifname +
'" down')
+ os.system('ip link set dev "' + cls.bss_hostapd[0].ifname +
'" addr 12:00:00:00:00:01 up')
+ os.system('ip link set dev "' + cls.bss_hostapd[1].ifname +
'" down')
+ os.system('ip link set dev "' + cls.bss_hostapd[1].ifname +
'" addr 12:00:00:00:00:02 up')
+
+ cls.bss_hostapd[0].reload()
+ cls.bss_hostapd[0].wait_for_event("AP-ENABLED")
+ cls.bss_hostapd[1].reload()
+ cls.bss_hostapd[1].wait_for_event("AP-ENABLED")
+
+ # Fill in the neighbor AP tables in both BSSes. By default each
+ # instance knows only about current BSS, even inside one hostapd
+ # process.
+ # FT still works without the neighbor AP table but neighbor reports
+ # have to be disabled in the .conf files
+ cls.bss_hostapd[0].set_neighbor('12:00:00:00:00:02', 'TestFT',
+ '1200000000028f0000005102060603000000')
+ cls.bss_hostapd[1].set_neighbor('12:00:00:00:00:01', 'TestFT',
+ '1200000000018f0000005101060603000000')
+
+ @classmethod
+ def tearDownClass(cls):
+ IWD.clear_storage()
+ cls.bss_hostapd = None
+
+if __name__ == '__main__':
+ unittest.main(exit=True)
--
2.31.1
Show replies by date