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 v4 5/8] station: add Affinities DBus property
Date: Tue, 27 Aug 2024 21:57:10 -0500	[thread overview]
Message-ID: <cf53e0e8-4ec4-48ce-8abd-b0c2f2b39d9c@gmail.com> (raw)
In-Reply-To: <20240823222339.328006-5-prestwoj@gmail.com>

Hi James,

On 8/23/24 5:23 PM, James Prestwood wrote:
> This property will hold an array of object paths for
> BasicServiceSet (BSS) objects. For the purpose of this patch
> only the setter/getter and client watch is implemented. The
> purpose of this array is to guide or loosly lock IWD to certain

typo: 'loosely'

> BSS's provided that some external client has more information
> about the environment than what IWD takes into account for its
> roaming decisions.
> 
> For the time being, the array is limited to only the connected
> BSS path, and any roams or disconnects will clear the array.
> 
> The intended use case for this is if the device is stationary
> an external client could reduce the likelihood of roaming by
> setting the affinity to the current BSS.
> ---
>   src/station.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 145 insertions(+)
> 
> diff --git a/src/station.c b/src/station.c
> index 30a1232a..c72d42ae 100644
> --- a/src/station.c
> +++ b/src/station.c
> @@ -128,6 +128,10 @@ struct station {
>   
>   	uint64_t last_roam_scan;
>   
> +	struct l_queue *affinities;
> +	unsigned int affinity_watch;
> +	char *affinity_client;
> +
>   	bool preparing_roam : 1;
>   	bool roam_scan_full : 1;
>   	bool signal_low : 1;
> @@ -449,6 +453,14 @@ static const char *station_get_bss_path(struct station *station,
>   	return __network_path_append_bss(network_path, bss);
>   }
>   
> +static bool match_bss_path(const void *data, const void *user_data)
> +{
> +	const char *path1 = data;
> +	const char *path2 = user_data;
> +
> +	return !strcmp(path1, path2);
> +}
> +
>   static bool station_unregister_bss(struct station *station,
>   					struct scan_bss *bss)
>   {
> @@ -457,6 +469,8 @@ static bool station_unregister_bss(struct station *station,
>   	if (L_WARN_ON(!path))
>   		return false;
>   
> +	l_queue_remove_if(station->affinities, match_bss_path, path);
> +
>   	return l_dbus_unregister_object(dbus_get_bus(), path);
>   }
>   
> @@ -1740,6 +1754,13 @@ static void station_enter_state(struct station *station,
>   		station_set_evict_nocarrier(station, true);
>   		station_set_drop_neighbor_discovery(station, false);
>   		station_set_drop_unicast_l2_multicast(station, false);
> +
> +		if (station->affinity_watch) {
> +			l_dbus_remove_watch(dbus_get_bus(),
> +						station->affinity_watch);
> +			station->affinity_watch = 0;
> +		}
> +

Hmm, but not resetting affinities?

>   		break;
>   	case STATION_STATE_DISCONNECTING:
>   	case STATION_STATE_NETCONFIG:
> @@ -1747,6 +1768,12 @@ static void station_enter_state(struct station *station,
>   	case STATION_STATE_ROAMING:
>   	case STATION_STATE_FT_ROAMING:
>   	case STATION_STATE_FW_ROAMING:
> +		if (station->affinity_watch) {
> +			l_dbus_remove_watch(dbus_get_bus(),
> +						station->affinity_watch);
> +			station->affinity_watch = 0;

Okay.  This reminds me that for hardware supporting FW roaming we may want to 
return NotCapable when setting Affinities.

> +		}
> +
>   		station_set_evict_nocarrier(station, false);
>   		break;
>   	}

<snip>

> +static void station_affinity_watch_destroy(void *user_data)
> +{
> +	struct station *station = user_data;
> +
> +	l_free(station->affinity_client);
> +	station->affinity_client = NULL;
> +
> +	l_queue_destroy(station->affinities, l_free);
> +	station->affinities = NULL;
> +
> +	l_dbus_property_changed(dbus_get_bus(),
> +				netdev_get_path(station->netdev),
> +				IWD_STATION_INTERFACE, "Affinities");

What if the list was empty?

> +}
> +
> +static struct l_dbus_message *station_property_set_affinities(
> +					struct l_dbus *dbus,
> +					struct l_dbus_message *message,
> +					struct l_dbus_message_iter *new_value,
> +					l_dbus_property_complete_cb_t complete,
> +					void *user_data)
> +{
> +	struct station *station = user_data;
> +	struct l_dbus_message_iter array;
> +	const char *sender = l_dbus_message_get_sender(message);
> +	const char *path;
> +	struct l_queue *new_affinities;
> +
> +	if (!station->connected_network)
> +		return dbus_error_not_connected(message);
> +
> +	if (!station->affinity_watch) {
> +		station->affinity_client = l_strdup(sender);
> +		station->affinity_watch = l_dbus_add_disconnect_watch(dbus,
> +					sender,
> +					station_affinity_disconnected_cb,
> +					station,
> +					station_affinity_watch_destroy);
> +	} else if (strcmp(station->affinity_client, sender)) {
> +		l_warn("Only one client may manage Affinities property");
> +		return dbus_error_not_available(message);

Hmm, we probably need a new error for 'permission denied or something'

> +	}
> +
> +	if (!l_dbus_message_iter_get_variant(new_value, "ao", &array))
> +		return dbus_error_invalid_args(message);

So what happens to affinity_client / affinity_watch above?

> +
> +	new_affinities = l_queue_new();
> +
> +	while (l_dbus_message_iter_next_entry(&array, &path)) {
> +		struct scan_bss *bss = l_dbus_object_get_data(dbus_get_bus(),
> +						path,
> +						IWD_BSS_INTERFACE);
> +
> +		/*
> +		 * TODO: For now only allow the affinities array to contain the
> +		 *       connected BSS path. Any other values will be rejected.
> +		 *       This could change in the future.
> +		 */
> +		if (bss != station->connected_bss) {
> +			l_queue_destroy(new_affinities, l_free);
> +			return dbus_error_invalid_args(message);

same as above?

You may want to make your life easier by just looking for an empty list or list 
of size 1 with the connected bss.

> +		}
> +
> +		l_queue_push_head(new_affinities, l_strdup(path));
> +	}
> +
> +	l_queue_destroy(station->affinities, l_free);
> +	station->affinities = new_affinities;

If the list is empty, should you unregister the watch?

> +
> +	l_dbus_property_changed(dbus, netdev_get_path(station->netdev),
> +				IWD_STATION_INTERFACE, "Affinities");
> +
> +	complete(dbus, message, NULL);

It is the other way around, we send the 'message_return' first, then the signal. 
  Do you want to spuriously emit if the two lists are the same?

> +
> +	return NULL;
> +}
> +
>   void station_foreach(station_foreach_func_t func, void *user_data)
>   {
>   	const struct l_queue_entry *entry;

Regards,
-Denis


  reply	other threads:[~2024-08-28  2:57 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-23 22:23 [PATCH v4 1/8] doc: Document station Affinities property James Prestwood
2024-08-23 22:23 ` [PATCH v4 2/8] netdev: define netdev settings in netdev.h James Prestwood
2024-08-28  2:44   ` Denis Kenzior
2024-08-23 22:23 ` [PATCH v4 3/8] netdev: store signal threshold in netdev object, not globally James Prestwood
2024-08-23 22:23 ` [PATCH v4 4/8] netdev: add critical signal threshold level James Prestwood
2024-08-23 22:23 ` [PATCH v4 5/8] station: add Affinities DBus property James Prestwood
2024-08-28  2:57   ` Denis Kenzior [this message]
2024-08-23 22:23 ` [PATCH v4 6/8] station: Use Affinities property to change roaming threshold James Prestwood
2024-08-23 22:23 ` [PATCH v4 7/8] auto-t: add affinities property for station, and extended_service_set James Prestwood
2024-08-23 22:23 ` [PATCH v4 8/8] auto-t: add tests for Affinities behavior James Prestwood
2024-08-28  2:39 ` [PATCH v4 1/8] doc: Document station Affinities property Denis Kenzior

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=cf53e0e8-4ec4-48ce-8abd-b0c2f2b39d9c@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