public inbox for iwd@lists.linux.dev
 help / color / mirror / Atom feed
From: Denis Kenzior <denkenz@gmail.com>
To: James Prestwood <prestwoj@gmail.com>, iwd@lists.linux.dev
Subject: Re: [PATCH 1/4] station: treat netconfig failures as connection failures
Date: Wed, 28 May 2025 12:47:46 -0500	[thread overview]
Message-ID: <1453aee8-9caa-49c9-9492-beaf4ca3e3af@gmail.com> (raw)
In-Reply-To: <20250528142750.498252-1-prestwoj@gmail.com>

Hi James,

On 5/28/25 9:27 AM, James Prestwood wrote:
> 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

It looks like you're fixing this as part of this commit to send the DBus reply 
after the netconfig has been completed.  Can you separate this change into a 
separate commit and document it for posterity?  Not sure if NM relies on this 
behavior (hopefully not), but we should have a Fixes tag as well.

Maybe 72e7d3ceb83d ("station: Handle NETCONFIG_EVENT_FAILED") ?

> 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);
> +		}
> +

Looks like this part should be in a separate commit per above comment.

>   		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);

Hmm, why is this needed? station_reset_connection_state() already invokes this.

>   
> -	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

And this chunk belongs in a separate commit as well.

> @@ -3598,8 +3596,6 @@ static void station_connect_ok(struct station *station)
>   			l_warn("Could not request neighbor report");
>   	}
>   
> -	network_connected(station->connected_network);
> -

I'm not so sure about this part.  network_connected() is mainly about syncing 
the PSK to disk.  Since we connected successfully, that should still happen, 
regardless of whether netconfig succeeds or not.

>   	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,

Regards,
-Denis

      parent reply	other threads:[~2025-05-28 17:47 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 ` Denis Kenzior [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1453aee8-9caa-49c9-9492-beaf4ca3e3af@gmail.com \
    --to=denkenz@gmail.com \
    --cc=iwd@lists.linux.dev \
    --cc=prestwoj@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox