* [PATCH v2 1/3] station: add additional internal state, STATION_STATE_NETCONFIG
@ 2024-01-05 14:47 James Prestwood
2024-01-05 14:47 ` [PATCH v2 2/3] station: add handling for new NETCONFIG state James Prestwood
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: James Prestwood @ 2024-01-05 14:47 UTC (permalink / raw)
To: iwd; +Cc: James Prestwood
This is still treated as "connecting" from a DBus perspective but
will allow for better handling internally for some roaming corner
cases.
---
src/dpp.c | 1 +
src/station.c | 5 +++++
src/station.h | 1 +
src/wsc.c | 1 +
4 files changed, 8 insertions(+)
diff --git a/src/dpp.c b/src/dpp.c
index af6574fb..74b4c2bc 100644
--- a/src/dpp.c
+++ b/src/dpp.c
@@ -3761,6 +3761,7 @@ static void dpp_station_state_watch(enum station_state state, void *user_data)
case STATION_STATE_CONNECTING:
case STATION_STATE_CONNECTED:
case STATION_STATE_CONNECTING_AUTO:
+ case STATION_STATE_NETCONFIG:
if (L_WARN_ON(dpp->role == DPP_CAPABILITY_CONFIGURATOR))
dpp_reset(dpp);
diff --git a/src/station.c b/src/station.c
index ac53bf2a..68cac945 100644
--- a/src/station.c
+++ b/src/station.c
@@ -1497,6 +1497,8 @@ static const char *station_state_to_string(enum station_state state)
return "ft-roaming";
case STATION_STATE_FW_ROAMING:
return "fw-roaming";
+ case STATION_STATE_NETCONFIG:
+ return "connecting (netconfig)";
}
return "invalid";
@@ -1635,6 +1637,7 @@ static void station_enter_state(struct station *station,
station_set_drop_unicast_l2_multicast(station, false);
break;
case STATION_STATE_DISCONNECTING:
+ case STATION_STATE_NETCONFIG:
break;
case STATION_STATE_ROAMING:
case STATION_STATE_FT_ROAMING:
@@ -3342,6 +3345,7 @@ static void station_disconnect_event(struct station *station, void *event_data)
case STATION_STATE_CONNECTED:
case STATION_STATE_FT_ROAMING:
case STATION_STATE_FW_ROAMING:
+ case STATION_STATE_NETCONFIG:
station_disassociated(station);
return;
default:
@@ -4272,6 +4276,7 @@ static bool station_property_get_state(struct l_dbus *dbus,
break;
case STATION_STATE_CONNECTING:
case STATION_STATE_CONNECTING_AUTO:
+ case STATION_STATE_NETCONFIG:
statestr = "connecting";
break;
case STATION_STATE_CONNECTED:
diff --git a/src/station.h b/src/station.h
index 0d502a08..a38327e4 100644
--- a/src/station.h
+++ b/src/station.h
@@ -45,6 +45,7 @@ enum station_state {
STATION_STATE_ROAMING, /* Reassociation */
STATION_STATE_FT_ROAMING, /* Fast transition */
STATION_STATE_FW_ROAMING, /* Firmware roamed by itself */
+ STATION_STATE_NETCONFIG,
};
enum station_event {
diff --git a/src/wsc.c b/src/wsc.c
index cda877cf..f88f5deb 100644
--- a/src/wsc.c
+++ b/src/wsc.c
@@ -654,6 +654,7 @@ static void wsc_check_can_connect(struct wsc_station_dbus *wsc,
case STATION_STATE_CONNECTING:
case STATION_STATE_CONNECTING_AUTO:
case STATION_STATE_CONNECTED:
+ case STATION_STATE_NETCONFIG:
if (station_disconnect(wsc->station) < 0)
goto error;
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 2/3] station: add handling for new NETCONFIG state
2024-01-05 14:47 [PATCH v2 1/3] station: add additional internal state, STATION_STATE_NETCONFIG James Prestwood
@ 2024-01-05 14:47 ` James Prestwood
2024-01-05 14:47 ` [PATCH v2 3/3] auto-t: add test for roaming + netconfig James Prestwood
2024-01-09 4:20 ` [PATCH v2 1/3] station: add additional internal state, STATION_STATE_NETCONFIG Denis Kenzior
2 siblings, 0 replies; 4+ messages in thread
From: James Prestwood @ 2024-01-05 14:47 UTC (permalink / raw)
To: iwd; +Cc: James Prestwood
There was an unhandled corner case if netconfig was running and
multiple roam conditions happened in sequence, all before netconfig
had completed. A single roam before netconfig was already handled
(23f0f5717c) but this did not take into account any additional roam
conditions.
If IWD is in this state, having started netconfig, then roamed, and
again restarted netconfig it is still in a roaming state which will
prevent any further roams. IWD will remain "stuck" on the current
BSS until netconfig completes or gets disconnected.
In addition the general state logic is wrong here. If IWD roams
prior to netconfig it should stay in a connecting state (from the
perspective of DBus).
To fix this a new internal station state was added (no changes to
the DBus API) to distinguish between a purely WiFi connecting state
(STATION_STATE_CONNECTING/AUTO) and netconfig
(STATION_STATE_NETCONFIG). This allows IWD roam as needed if
netconfig is still running. Also, some special handling was added so
the station state property remains in a "connected" state until
netconfig actually completes, regardless of roams.
For some background this scenario happens if the DHCP server goes
down for an extended period, e.g. if its being upgraded/serviced.
---
src/station.c | 36 +++++++++++++++++++++++++++---------
1 file changed, 27 insertions(+), 9 deletions(-)
v2:
* Stay in a "connecting" state if roaming before netconfig from
a DBus property perspective.
* Minor changes using L_IN_SET
There are still improvements needed in this area, but this at
least fixes the major issues related to the state change and allowing
multiple roams. Still TODO:
* Add a netconfig timeout (in ELL)
* Put netconfig behind a wiphy work item. This requires some thought
since we'd still need to allow roam scans, but just not any other
scans/offchannel.
diff --git a/src/station.c b/src/station.c
index 68cac945..a6442d3e 100644
--- a/src/station.c
+++ b/src/station.c
@@ -1770,6 +1770,7 @@ static void station_reset_connection_state(struct station *station)
if (station->state == STATION_STATE_CONNECTED ||
station->state == STATION_STATE_CONNECTING ||
station->state == STATION_STATE_CONNECTING_AUTO ||
+ station->state == STATION_STATE_NETCONFIG ||
station_is_roaming(station))
network_disconnected(network);
}
@@ -2045,8 +2046,7 @@ static void station_netconfig_event_handler(enum netconfig_event event,
dbus_pending_reply(&station->connect_pending, reply);
}
- if (L_IN_SET(station->state, STATION_STATE_CONNECTING,
- STATION_STATE_CONNECTING_AUTO))
+ if (station->state == STATION_STATE_NETCONFIG)
network_connect_failed(station->connected_network,
false);
@@ -2072,9 +2072,14 @@ static bool netconfig_after_roam(struct station *station)
network_get_settings(network)))
return false;
- return netconfig_configure(station->netconfig,
+ if (!netconfig_configure(station->netconfig,
station_netconfig_event_handler,
- station);
+ station))
+ return false;
+
+ station_enter_state(station, STATION_STATE_NETCONFIG);
+
+ return true;
}
static void station_roamed(struct station *station)
@@ -3253,6 +3258,8 @@ static void station_connect_ok(struct station *station)
station_netconfig_event_handler,
station)))
return;
+
+ station_enter_state(station, STATION_STATE_NETCONFIG);
} else
station_enter_state(station, STATION_STATE_CONNECTED);
}
@@ -4064,8 +4071,10 @@ static struct l_dbus_message *station_dbus_scan(struct l_dbus *dbus,
if (station->dbus_scan_id)
return dbus_error_busy(message);
- if (station->state == STATION_STATE_CONNECTING ||
- station->state == STATION_STATE_CONNECTING_AUTO)
+ if (L_IN_SET(station->state, STATION_STATE_CONNECTING,
+ STATION_STATE_CONNECTING_AUTO,
+ STATION_STATE_NETCONFIG) ||
+ station_is_roaming(station))
return dbus_error_busy(message);
station->dbus_scan_subset_idx = 0;
@@ -4288,7 +4297,14 @@ static bool station_property_get_state(struct l_dbus *dbus,
case STATION_STATE_ROAMING:
case STATION_STATE_FT_ROAMING:
case STATION_STATE_FW_ROAMING:
- statestr = "roaming";
+ /*
+ * Stay in a connecting state if roaming before netconfig
+ * has finished
+ */
+ if (station->netconfig_after_roam)
+ statestr = "connecting";
+ else
+ statestr = "roaming";
break;
}
@@ -5022,8 +5038,10 @@ static struct l_dbus_message *station_debug_scan(struct l_dbus *dbus,
if (station->dbus_scan_id)
return dbus_error_busy(message);
- if (station->state == STATION_STATE_CONNECTING ||
- station->state == STATION_STATE_CONNECTING_AUTO)
+ if (L_IN_SET(station->state, STATION_STATE_CONNECTING,
+ STATION_STATE_CONNECTING_AUTO,
+ STATION_STATE_NETCONFIG) ||
+ station_is_roaming(station))
return dbus_error_busy(message);
if (!l_dbus_message_get_arguments(message, "aq", &iter))
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 3/3] auto-t: add test for roaming + netconfig
2024-01-05 14:47 [PATCH v2 1/3] station: add additional internal state, STATION_STATE_NETCONFIG James Prestwood
2024-01-05 14:47 ` [PATCH v2 2/3] station: add handling for new NETCONFIG state James Prestwood
@ 2024-01-05 14:47 ` James Prestwood
2024-01-09 4:20 ` [PATCH v2 1/3] station: add additional internal state, STATION_STATE_NETCONFIG Denis Kenzior
2 siblings, 0 replies; 4+ messages in thread
From: James Prestwood @ 2024-01-05 14:47 UTC (permalink / raw)
To: iwd; +Cc: James Prestwood
This test ensures IWD will continue to roam and restart netconfig if
roam conditions are met prior to netconfig finishing.
---
autotests/testNetconfigRoam/TestFT.psk | 2 +
.../testNetconfigRoam/ft-psk-ccmp-1.conf | 41 +++++++++
.../testNetconfigRoam/ft-psk-ccmp-2.conf | 41 +++++++++
autotests/testNetconfigRoam/hw.conf | 8 ++
autotests/testNetconfigRoam/main.conf | 3 +
.../testNetconfigRoam/netconfig_roam_test.py | 91 +++++++++++++++++++
6 files changed, 186 insertions(+)
create mode 100644 autotests/testNetconfigRoam/TestFT.psk
create mode 100644 autotests/testNetconfigRoam/ft-psk-ccmp-1.conf
create mode 100644 autotests/testNetconfigRoam/ft-psk-ccmp-2.conf
create mode 100644 autotests/testNetconfigRoam/hw.conf
create mode 100644 autotests/testNetconfigRoam/main.conf
create mode 100644 autotests/testNetconfigRoam/netconfig_roam_test.py
v2:
* Updated to check/ensure that IWD remains "connecting" even through
multiple roams.
diff --git a/autotests/testNetconfigRoam/TestFT.psk b/autotests/testNetconfigRoam/TestFT.psk
new file mode 100644
index 00000000..e82d1295
--- /dev/null
+++ b/autotests/testNetconfigRoam/TestFT.psk
@@ -0,0 +1,2 @@
+[Security]
+Passphrase=EasilyGuessedPassword
diff --git a/autotests/testNetconfigRoam/ft-psk-ccmp-1.conf b/autotests/testNetconfigRoam/ft-psk-ccmp-1.conf
new file mode 100644
index 00000000..b46d1f27
--- /dev/null
+++ b/autotests/testNetconfigRoam/ft-psk-ccmp-1.conf
@@ -0,0 +1,41 @@
+hw_mode=g
+channel=1
+ssid=TestFT
+utf8_ssid=1
+ctrl_interface=/var/run/hostapd
+
+r1_key_holder=120000000001
+nas_identifier=dummy1
+
+wpa=2
+# Can support WPA-PSK and FT-PSK (space separated list) and/or EAP at the same
+# time but we want to force FT
+wpa_key_mgmt=FT-PSK
+wpa_pairwise=CCMP
+wpa_passphrase=EasilyGuessedPassword
+ieee80211w=1
+rsn_preauth=1
+rsn_preauth_interfaces=lo
+disable_pmksa_caching=0
+# Allow PMK cache to be shared opportunistically among configured interfaces
+# and BSSes (i.e., all configurations within a single hostapd process).
+okc=1
+mobility_domain=1234
+reassociation_deadline=60000
+r0kh=12:00:00:00:00:01 dummy1 000102030405060708090a0b0c0d0e0f
+r0kh=12:00:00:00:00:02 dummy2 000102030405060708090a0b0c0d0e0f
+r1kh=12:00:00:00:00:01 00:00:00:00:00:01 000102030405060708090a0b0c0d0e0f
+r1kh=12:00:00:00:00:02 00:00:00:00:00:02 000102030405060708090a0b0c0d0e0f
+# Push mode only needed for 8021x, not PSK mode since msk already known
+pmk_r1_push=0
+# Allow locally generated FT response so we don't have to configure push/pull
+# between BSSes running as separate hostapd processes as in the test-runner
+# 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
+rrm_neighbor_report=1
+ocv=1
diff --git a/autotests/testNetconfigRoam/ft-psk-ccmp-2.conf b/autotests/testNetconfigRoam/ft-psk-ccmp-2.conf
new file mode 100644
index 00000000..3e215457
--- /dev/null
+++ b/autotests/testNetconfigRoam/ft-psk-ccmp-2.conf
@@ -0,0 +1,41 @@
+hw_mode=g
+channel=2
+ssid=TestFT
+utf8_ssid=1
+ctrl_interface=/var/run/hostapd
+
+r1_key_holder=120000000002
+nas_identifier=dummy2
+
+wpa=2
+# Can support WPA-PSK and FT-PSK (space separated list) and/or EAP at the same
+# time but we want to force FT
+wpa_key_mgmt=FT-PSK
+wpa_pairwise=CCMP
+wpa_passphrase=EasilyGuessedPassword
+ieee80211w=1
+rsn_preauth=1
+rsn_preauth_interfaces=lo
+disable_pmksa_caching=0
+# Allow PMK cache to be shared opportunistically among configured interfaces
+# and BSSes (i.e., all configurations within a single hostapd process).
+okc=1
+mobility_domain=1234
+reassociation_deadline=60000
+r0kh=12:00:00:00:00:01 dummy1 000102030405060708090a0b0c0d0e0f
+r0kh=12:00:00:00:00:02 dummy2 000102030405060708090a0b0c0d0e0f
+r1kh=12:00:00:00:00:01 00:00:00:00:00:01 000102030405060708090a0b0c0d0e0f
+r1kh=12:00:00:00:00:02 00:00:00:00:00:02 000102030405060708090a0b0c0d0e0f
+# Push mode only needed for 8021x, not PSK mode since msk already known
+pmk_r1_push=0
+# Allow locally generated FT response so we don't have to configure push/pull
+# between BSSes running as separate hostapd processes as in the test-runner
+# 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
+rrm_neighbor_report=1
+ocv=1
diff --git a/autotests/testNetconfigRoam/hw.conf b/autotests/testNetconfigRoam/hw.conf
new file mode 100644
index 00000000..c2b35d6e
--- /dev/null
+++ b/autotests/testNetconfigRoam/hw.conf
@@ -0,0 +1,8 @@
+[SETUP]
+num_radios=3
+start_iwd=0
+hwsim_medium=yes
+
+[HOSTAPD]
+rad0=ft-psk-ccmp-1.conf
+rad1=ft-psk-ccmp-2.conf
diff --git a/autotests/testNetconfigRoam/main.conf b/autotests/testNetconfigRoam/main.conf
new file mode 100644
index 00000000..aedd4ebd
--- /dev/null
+++ b/autotests/testNetconfigRoam/main.conf
@@ -0,0 +1,3 @@
+[General]
+EnableNetworkConfiguration=true
+RoamRetryInterval=1
diff --git a/autotests/testNetconfigRoam/netconfig_roam_test.py b/autotests/testNetconfigRoam/netconfig_roam_test.py
new file mode 100644
index 00000000..63e5eabf
--- /dev/null
+++ b/autotests/testNetconfigRoam/netconfig_roam_test.py
@@ -0,0 +1,91 @@
+#! /usr/bin/python3
+
+import unittest
+import sys, os
+
+sys.path.append('../util')
+import iwd
+from iwd import IWD
+from iwd import PSKAgent
+from iwd import NetworkType
+from iwd import DeviceState
+from hwsim import Hwsim
+from hostapd import HostapdCLI
+import testutil
+
+class Test(unittest.TestCase):
+ def test_roam_before_netconfig(self):
+ wd = IWD(True)
+
+ device = wd.list_devices(1)[0]
+ device.get_ordered_network('TestFT', full_scan=True)
+ device.connect_bssid(self.bss_hostapd[1].bssid)
+
+ self.bss_hostapd[1].wait_for_event(f'AP-STA-CONNECTED {device.address}')
+ device.wait_for_event("connecting (netconfig)")
+
+ roam_to = 0
+ roam_from = 1
+
+ # Roam back and forth, ensuring that the state transitions between
+ # roaming and connecting (netconfig).
+ for _ in range(0, 5):
+ self.rules[roam_to].signal = -2000
+ self.rules[roam_from].signal = -8000
+
+ # Station should internally transition to roaming, but remain in a
+ # connecting state on DBus
+ device.wait_for_event("ft-roaming")
+ self.assertEqual(device.state, DeviceState.connecting)
+
+ self.bss_hostapd[roam_to].wait_for_event(f'AP-STA-CONNECTED {device.address}')
+ device.wait_for_event("connecting (netconfig)")
+
+ tmp = roam_from
+ roam_from = roam_to
+ roam_to = tmp
+
+ self.bss_hostapd[roam_from].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')
+ 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') ]
+
+ rule0 = hwsim.rules.create()
+ rule0.source = cls.bss_hostapd[0].bssid
+ rule0.signal = -6000
+ rule0.enabled = True
+
+ rule1 = hwsim.rules.create()
+ rule1.source = cls.bss_hostapd[1].bssid
+ rule1.signal = -2000
+ rule1.enabled = True
+
+ cls.rules = [rule0, rule1]
+
+ cls.bss_hostapd[0].set_address('12:00:00:00:00:01')
+ cls.bss_hostapd[1].set_address('12:00:00:00:00:02')
+
+ HostapdCLI.group_neighbors(*cls.bss_hostapd)
+
+ @classmethod
+ def tearDownClass(cls):
+ IWD.clear_storage()
+ cls.bss_hostapd = None
+ cls.rules = None
+
+if __name__ == '__main__':
+ unittest.main(exit=True)
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v2 1/3] station: add additional internal state, STATION_STATE_NETCONFIG
2024-01-05 14:47 [PATCH v2 1/3] station: add additional internal state, STATION_STATE_NETCONFIG James Prestwood
2024-01-05 14:47 ` [PATCH v2 2/3] station: add handling for new NETCONFIG state James Prestwood
2024-01-05 14:47 ` [PATCH v2 3/3] auto-t: add test for roaming + netconfig James Prestwood
@ 2024-01-09 4:20 ` Denis Kenzior
2 siblings, 0 replies; 4+ messages in thread
From: Denis Kenzior @ 2024-01-09 4:20 UTC (permalink / raw)
To: James Prestwood, iwd
Hi James,
On 1/5/24 08:47, James Prestwood wrote:
> This is still treated as "connecting" from a DBus perspective but
> will allow for better handling internally for some roaming corner
> cases.
> ---
> src/dpp.c | 1 +
> src/station.c | 5 +++++
> src/station.h | 1 +
> src/wsc.c | 1 +
> 4 files changed, 8 insertions(+)
>
All applied, thanks.
Regards,
-Denis
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2024-01-09 4:21 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-01-05 14:47 [PATCH v2 1/3] station: add additional internal state, STATION_STATE_NETCONFIG James Prestwood
2024-01-05 14:47 ` [PATCH v2 2/3] station: add handling for new NETCONFIG state James Prestwood
2024-01-05 14:47 ` [PATCH v2 3/3] auto-t: add test for roaming + netconfig James Prestwood
2024-01-09 4:20 ` [PATCH v2 1/3] station: add additional internal state, STATION_STATE_NETCONFIG Denis Kenzior
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox