public inbox for iwd@lists.linux.dev
 help / color / mirror / Atom feed
* [PATCH 1/4] station: treat netconfig failures as connection failures
@ 2025-05-28 14:27 James Prestwood
  2025-05-28 14:27 ` [PATCH 2/4] auto-t: allow configurable DBus timeout/callbacks on connect{_bssid} James Prestwood
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: James Prestwood @ 2025-05-28 14:27 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

Currently the netconfig functionality is somewhat separated from
IWD's "connection" process. Regardless if netconfig is enabled
the method return from Connect() will happen after IWD has completed
the 4-way handshake. If netconfig fails its shows externally as an
IWD state change rather than part of the method return from
Connect(). Overall this doesn't pose a significant problem since a
netconfig failure essentially appears as if IWD became disconnected
but more critical is that IWD will not iteratively try more BSS's if
netconfig fails.

For example a BSS may be misconfigured, or not able to communicate to
the DHCP server. IWD could connect to it, and fail netconfig thereby
restarting the autoconnect logic. IWD will then choose the "best" BSS
which may be the one it just failed on. This would then repeat
indefinitely or until a better BSS comes around which could be never.

To improve this netconfig has been adopted into the IWD's BSS retry
logic. If netconfig fails this will not result in IWD transitioning
to a disconnected state, and instead the BSS will be network
blacklisted and the next will be tried. Only once all BSS's have been
tried will IWD go into a disconnected state and start autoconnect
over.
---
 src/station.c | 104 +++++++++++++++++++++++++-------------------------
 1 file changed, 51 insertions(+), 53 deletions(-)

diff --git a/src/station.c b/src/station.c
index 2b6a18f8..81c1e595 100644
--- a/src/station.c
+++ b/src/station.c
@@ -1795,6 +1795,13 @@ static void station_enter_state(struct station *station,
 		periodic_scan_stop(station);
 		break;
 	case STATION_STATE_CONNECTED:
+		if (station->connect_pending) {
+			struct l_dbus_message *reply =
+				l_dbus_message_new_method_return(
+						station->connect_pending);
+			dbus_pending_reply(&station->connect_pending, reply);
+		}
+
 		l_dbus_object_add_interface(dbus,
 					netdev_get_path(station->netdev),
 					IWD_STATION_DIAGNOSTIC_INTERFACE,
@@ -2214,6 +2221,26 @@ static void station_early_neighbor_report_cb(struct netdev *netdev, int err,
 				&station->roam_freqs);
 }
 
+static bool station_try_next_bss(struct station *station)
+{
+	struct scan_bss *next;
+	int ret;
+
+	next = network_bss_select(station->connected_network, false);
+
+	if (!next)
+		return false;
+
+	ret = __station_connect_network(station, station->connected_network,
+						next, station->state);
+	if (ret < 0)
+		return false;
+
+	l_debug("Attempting to connect to next BSS "MAC, MAC_STR(next->addr));
+
+	return true;
+}
+
 static bool station_can_fast_transition(struct station *station,
 					struct handshake_state *hs,
 					struct scan_bss *bss)
@@ -2256,28 +2283,28 @@ static bool station_can_fast_transition(struct station *station,
 	return true;
 }
 
-static void station_disconnect_on_error_cb(struct netdev *netdev, bool success,
-					void *user_data)
+static void station_disconnect_on_netconfig_failed(struct netdev *netdev,
+							bool success,
+							void *user_data)
 {
 	struct station *station = user_data;
-	bool continue_autoconnect;
 
-	station_enter_state(station, STATION_STATE_DISCONNECTED);
+	if (station_try_next_bss(station))
+		return;
 
-	continue_autoconnect = station->state == STATION_STATE_CONNECTING_AUTO;
+	network_disconnected(station->connected_network);
 
-	if (continue_autoconnect) {
-		if (station_autoconnect_next(station) < 0) {
-			l_debug("Nothing left on autoconnect list");
-			station_enter_state(station,
-					STATION_STATE_AUTOCONNECT_FULL);
-		}
+	if (station->connect_pending) {
+		struct l_dbus_message *reply = dbus_error_failed(
+						station->connect_pending);
 
-		return;
+		dbus_pending_reply(&station->connect_pending, reply);
 	}
 
-	if (station->autoconnect)
-		station_enter_state(station, STATION_STATE_AUTOCONNECT_QUICK);
+	station_reset_connection_state(station);
+
+	station_enter_state(station, STATION_STATE_DISCONNECTED);
+	station_enter_state(station, STATION_STATE_AUTOCONNECT_FULL);
 }
 
 static void station_netconfig_event_handler(enum netconfig_event event,
@@ -2287,26 +2314,24 @@ static void station_netconfig_event_handler(enum netconfig_event event,
 
 	switch (event) {
 	case NETCONFIG_EVENT_CONNECTED:
+		network_connected(station->connected_network);
 		station_enter_state(station, STATION_STATE_CONNECTED);
 		break;
 	case NETCONFIG_EVENT_FAILED:
-		if (station->connect_pending) {
-			struct l_dbus_message *reply = dbus_error_failed(
-						station->connect_pending);
+		station_debug_event(station, "netconfig-failed");
 
-			dbus_pending_reply(&station->connect_pending, reply);
-		}
+		netconfig_reset(station->netconfig);
 
 		if (station->state == STATION_STATE_NETCONFIG)
 			network_connect_failed(station->connected_network,
 						false);
 
+		network_blacklist_add(station->connected_network,
+						station->connected_bss);
+
 		netdev_disconnect(station->netdev,
-					station_disconnect_on_error_cb,
+					station_disconnect_on_netconfig_failed,
 					station);
-		station_reset_connection_state(station);
-
-		station_enter_state(station, STATION_STATE_DISCONNECTING);
 		break;
 	default:
 		l_error("station: Unsupported netconfig event: %d.", event);
@@ -3409,26 +3434,6 @@ static void station_event_channel_switched(struct station *station,
 	network_bss_update(network, station->connected_bss);
 }
 
-static bool station_try_next_bss(struct station *station)
-{
-	struct scan_bss *next;
-	int ret;
-
-	next = network_bss_select(station->connected_network, false);
-
-	if (!next)
-		return false;
-
-	ret = __station_connect_network(station, station->connected_network,
-						next, station->state);
-	if (ret < 0)
-		return false;
-
-	l_debug("Attempting to connect to next BSS "MAC, MAC_STR(next->addr));
-
-	return true;
-}
-
 static bool station_retry_owe_default_group(struct station *station)
 {
 	/*
@@ -3581,13 +3586,6 @@ static void station_connect_ok(struct station *station)
 
 	l_debug("");
 
-	if (station->connect_pending) {
-		struct l_dbus_message *reply =
-			l_dbus_message_new_method_return(
-						station->connect_pending);
-		dbus_pending_reply(&station->connect_pending, reply);
-	}
-
 	/*
 	 * Get a neighbor report now so future roams can avoid waiting for
 	 * a report at that time
@@ -3598,8 +3596,6 @@ static void station_connect_ok(struct station *station)
 			l_warn("Could not request neighbor report");
 	}
 
-	network_connected(station->connected_network);
-
 	if (station->netconfig) {
 		if (hs->fils_ip_req_ie && hs->fils_ip_resp_ie) {
 			struct ie_fils_ip_addr_response_info info;
@@ -3639,8 +3635,10 @@ static void station_connect_ok(struct station *station)
 			return;
 
 		station_enter_state(station, STATION_STATE_NETCONFIG);
-	} else
+	} else {
+		network_connected(station->connected_network);
 		station_enter_state(station, STATION_STATE_CONNECTED);
+	}
 }
 
 static void station_connect_cb(struct netdev *netdev, enum netdev_result result,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2025-05-28 17:47 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-28 14:27 [PATCH 1/4] station: treat netconfig failures as connection failures James Prestwood
2025-05-28 14:27 ` [PATCH 2/4] auto-t: allow configurable DBus timeout/callbacks on connect{_bssid} James Prestwood
2025-05-28 14:27 ` [PATCH 3/4] auto-t: update serveral tests to work with netconfig refactor James Prestwood
2025-05-28 14:40   ` Paul Menzel
2025-05-28 14:42     ` James Prestwood
2025-05-28 14:27 ` [PATCH 4/4] doc: add note about timeouts to Network.Connect() James Prestwood
2025-05-28 17:47 ` [PATCH 1/4] station: treat netconfig failures as connection failures Denis Kenzior

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox