diff --git a/autotests/testPSK-roam/failed_roam_test.py b/autotests/testPSK-roam/failed_roam_test.py index 8a3db662..90f07f6b 100644 --- a/autotests/testPSK-roam/failed_roam_test.py +++ b/autotests/testPSK-roam/failed_roam_test.py @@ -41,9 +41,11 @@ class Test(unittest.TestCase): self.assertRaises(Exception, testutil.test_ifaces_connected, (prev.ifname, device.name, True, True)) - # FT-over-Air failure, should stay connected def test_ft_over_air_failure(self): + self.rule2.enabled = True + self.rule3.enabled = True + wd = IWD(True) device = wd.list_devices(1)[0] @@ -60,12 +62,85 @@ class Test(unittest.TestCase): self.rule0.enabled = False # IWD should then try BSS 2, and succeed + device.wait_for_event('ft-roam', timeout=60) self.verify_roam(wd, device, self.bss_hostapd[0], self.bss_hostapd[2]) self.bss_hostapd[2].deauthenticate(device.address) + + # FT-over-Air failure with Invalid PMKID, should reassociate + def test_ft_over_air_fallback(self): + self.rule_bss0.signal = -8000 + self.rule_bss0.enabled = True + self.rule_bss1.signal = -7500 + self.rule_bss1.enabled = True + self.rule_bss2.signal = -6000 + self.rule_bss2.enabled = True + + # This will cause this BSS to reject any FT roams as its unable to + # get keys from other APs + self.bss_hostapd[2].set_value('ft_psk_generate_local', '0') + self.bss_hostapd[2].reload() + + wd = IWD(True) + + device = wd.list_devices(1)[0] + + self.connect(wd, device, self.bss_hostapd[0]) + + # IWD should connect, then attempt a roam to BSS 1, which should + # fail and cause a fallback to reassociation + device.wait_for_event('ft-fallback-to-reassoc', timeout=60) + device.wait_for_event('reassoc-roam', timeout=60) + + self.verify_roam(wd, device, self.bss_hostapd[0], self.bss_hostapd[2]) + + # Trigger another roam + self.rule_bss2.signal = -8000 + + device.wait_for_event('ft-roam', timeout=60) + + # Ensure an FT roam back to a properly configured AP works. + self.verify_roam(wd, device, self.bss_hostapd[2], self.bss_hostapd[1]) + + self.bss_hostapd[1].deauthenticate(device.address) condition = 'obj.state == DeviceState.disconnected' wd.wait_for_object_condition(device, condition) + # FT-over-Air failure with Invalid PMKID. The ranking is such that other + # FT candidates are available so it should FT elsewhere rather than + # retry with reassociation + def test_ft_over_air_fallback_retry_ft(self): + self.rule_bss0.signal = -8000 + self.rule_bss0.enabled = True + self.rule_bss1.signal = -7300 + self.rule_bss1.enabled = True + self.rule_bss2.signal = -7100 + self.rule_bss2.enabled = True + + # This will cause this BSS to reject any FT roams as its unable to + # get keys from other APs + self.bss_hostapd[2].set_value('ft_psk_generate_local', '0') + self.bss_hostapd[2].reload() + + wd = IWD(True) + + device = wd.list_devices(1)[0] + + self.connect(wd, device, self.bss_hostapd[0]) + + # IWD should connect, then attempt a roam to BSS 1, which should + # fail and cause the rank to be re-computed. This should then put + # bss 1 as the next candidate (since the FT factor is removed) + device.wait_for_event('ft-fallback-to-reassoc', timeout=60) + device.wait_for_event('ft-roam', timeout=60) + + self.verify_roam(wd, device, self.bss_hostapd[0], self.bss_hostapd[1]) + + self.bss_hostapd[1].deauthenticate(device.address) + 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') @@ -75,6 +150,10 @@ class Test(unittest.TestCase): self.rule0.enabled = False self.rule1.enabled = False self.rule2.enabled = False + self.rule3.enabled = False + self.rule_bss0.enabled = False + self.rule_bss1.enabled = False + self.rule_bss2.enabled = False for hapd in self.bss_hostapd: hapd.default() @@ -109,13 +188,18 @@ class Test(unittest.TestCase): cls.rule2 = hwsim.rules.create() cls.rule2.source = hwsim.get_radio('rad0').addresses[0] cls.rule2.signal = -8000 - cls.rule2.enabled = True # Causes IWD to first prefer BSS 1 to roam, then BSS 2. cls.rule3 = hwsim.rules.create() cls.rule3.source = hwsim.get_radio('rad2').addresses[0] cls.rule3.signal = -7000 - cls.rule3.enabled = True + + cls.rule_bss0 = hwsim.rules.create() + cls.rule_bss0.source = hwsim.get_radio('rad0').addresses[0] + cls.rule_bss1 = hwsim.rules.create() + cls.rule_bss1.source = hwsim.get_radio('rad1').addresses[0] + cls.rule_bss2 = hwsim.rules.create() + cls.rule_bss2.source = hwsim.get_radio('rad2').addresses[0] @classmethod def tearDownClass(cls): diff --git a/autotests/testPSK-roam/ft-psk-ccmp-1.conf b/autotests/testPSK-roam/ft-psk-ccmp-1.conf index eec8805f..b46d1f27 100644 --- a/autotests/testPSK-roam/ft-psk-ccmp-1.conf +++ b/autotests/testPSK-roam/ft-psk-ccmp-1.conf @@ -33,6 +33,7 @@ pmk_r1_push=0 # case. Only works with FT-PSK, otherwise brctl needs to be installed and # CONFIG_BRIDGE enabled in the kernel. ft_psk_generate_local=1 +rkh_pull_timeout=50 ft_over_ds=0 ap_table_expiration_time=36000 ap_table_max_size=10 diff --git a/autotests/testPSK-roam/ft-psk-ccmp-2.conf b/autotests/testPSK-roam/ft-psk-ccmp-2.conf index 5992461f..3e215457 100644 --- a/autotests/testPSK-roam/ft-psk-ccmp-2.conf +++ b/autotests/testPSK-roam/ft-psk-ccmp-2.conf @@ -33,6 +33,7 @@ pmk_r1_push=0 # case. Only works with FT-PSK, otherwise brctl needs to be installed and # CONFIG_BRIDGE enabled in the kernel. ft_psk_generate_local=1 +rkh_pull_timeout=50 ft_over_ds=0 ap_table_expiration_time=36000 ap_table_max_size=10 diff --git a/autotests/testPSK-roam/ft-psk-ccmp-3.conf b/autotests/testPSK-roam/ft-psk-ccmp-3.conf index 5992461f..3e215457 100644 --- a/autotests/testPSK-roam/ft-psk-ccmp-3.conf +++ b/autotests/testPSK-roam/ft-psk-ccmp-3.conf @@ -33,6 +33,7 @@ pmk_r1_push=0 # case. Only works with FT-PSK, otherwise brctl needs to be installed and # CONFIG_BRIDGE enabled in the kernel. ft_psk_generate_local=1 +rkh_pull_timeout=50 ft_over_ds=0 ap_table_expiration_time=36000 ap_table_max_size=10