From: James Prestwood <prestwoj@gmail.com>
To: iwd@lists.linux.dev
Cc: James Prestwood <prestwoj@gmail.com>
Subject: [PATCH 7/9] station: Use Affinities property for roaming/ranking decisions
Date: Tue, 13 Aug 2024 08:56:36 -0700 [thread overview]
Message-ID: <20240813155638.74987-7-prestwoj@gmail.com> (raw)
In-Reply-To: <20240813155638.74987-1-prestwoj@gmail.com>
There are two pieces where the affinity to a BSS will come into play:
The first is while connected to a BSS with the affinity set. In this
scenario station will lower the roaming threshold in order to loosly
lock IWD to this BSS. By lowering the roaming threshold we can avoid
roaming/scanning in cases where the device is not moving i.e. if an
external client knows this information.
The second effect BSS affinity has is to modify ranking when choosing
a roam candidate. A new ranking modifier has been added that will be
applied to a BSS rank given:
- The BSS is in the Affinities array
- The BSS signal is above the critical threshold (set in main.conf
[General].CriticalRoamThreshold{_5GHZ}).
---
src/station.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/src/station.c b/src/station.c
index 75dd13bb..ab04dcf2 100644
--- a/src/station.c
+++ b/src/station.c
@@ -1682,6 +1682,11 @@ static void station_enter_state(struct station *station,
if (station->connected_bss->hs20_dgaf_disable)
station_set_drop_unicast_l2_multicast(station, true);
+ if (l_strv_contains(station->affinities,
+ network_bss_get_path(station->connected_network,
+ station->connected_bss)))
+ netdev_lower_signal_threshold(station->netdev);
+
break;
case STATION_STATE_DISCONNECTED:
periodic_scan_stop(station);
@@ -2673,6 +2678,23 @@ static void station_update_roam_bss(struct station *station,
scan_bss_free(old);
}
+static bool station_apply_bss_affinity(struct station *station,
+ struct scan_bss *bss)
+{
+ struct network *network = station->connected_network;
+ const char *path = network_bss_get_path(network, bss);
+
+ /*
+ * Even if the BSS has the affinity set, don't apply the factor if its
+ * RSSI is below the critical threshold.
+ */
+ if (bss->signal_strength / 100 <
+ netdev_get_critical_signal_threshold(station->netdev))
+ return false;
+
+ return l_strv_contains(station->affinities, path);
+}
+
static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
const struct scan_freq_set *freqs,
void *userdata)
@@ -2684,6 +2706,7 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
struct scan_bss *bss;
double cur_bss_rank = 0.0;
static const double RANK_FT_FACTOR = 1.3;
+ static const double RANK_AFFINITY_FACTOR = 1.7;
uint16_t mdid;
enum security orig_security, security;
@@ -2715,6 +2738,9 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
if (hs->mde && bss->mde_present && l_get_le16(bss->mde) == mdid)
cur_bss_rank *= RANK_FT_FACTOR;
+
+ if (station_apply_bss_affinity(station, bss))
+ cur_bss_rank *= RANK_AFFINITY_FACTOR;
}
/*
@@ -2765,6 +2791,9 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
if (hs->mde && bss->mde_present && l_get_le16(bss->mde) == mdid)
rank *= RANK_FT_FACTOR;
+ if (station_apply_bss_affinity(station, bss))
+ rank *= RANK_AFFINITY_FACTOR;
+
if (rank <= cur_bss_rank)
goto next;
@@ -4506,6 +4535,9 @@ static void station_affinity_disconnected_cb(struct l_dbus *dbus,
station->affinity_watch = 0;
l_debug("client that set affinity has disconnected");
+
+ /* The client who set the affinity disconnected, raise the threshold */
+ netdev_raise_signal_threshold(station->netdev);
}
static void station_affinity_watch_destroy(void *user_data)
@@ -4531,6 +4563,8 @@ static struct l_dbus_message *station_property_set_affinities(
const char *sender = l_dbus_message_get_sender(message);
const char *path;
char **new_affinities;
+ const char *connected_path;
+ bool lower_threshold = false;
if (!station->connected_network)
return dbus_error_not_connected(message);
@@ -4550,6 +4584,8 @@ static struct l_dbus_message *station_property_set_affinities(
if (!l_dbus_message_iter_get_variant(new_value, "ao", &array))
return dbus_error_invalid_args(message);
+ connected_path = network_bss_get_path(station->connected_network,
+ station->connected_bss);
new_affinities = l_strv_new();
while (l_dbus_message_iter_next_entry(&array, &path)) {
@@ -4566,6 +4602,9 @@ static struct l_dbus_message *station_property_set_affinities(
return dbus_error_invalid_args(message);
}
+ if (!strcmp(path, connected_path))
+ lower_threshold = true;
+
new_affinities = l_strv_append(new_affinities, path);
}
@@ -4575,6 +4614,17 @@ static struct l_dbus_message *station_property_set_affinities(
l_dbus_property_changed(dbus, netdev_get_path(station->netdev),
IWD_STATION_INTERFACE, "Affinities");
+ /*
+ * If affinity was set to the current BSS, lower the roam threshold. If
+ * the connected BSS was not in the list raise the signal threshold.
+ * The threshold may already be raised, in which case netdev will detect
+ * this and do nothing.
+ */
+ if (lower_threshold)
+ netdev_lower_signal_threshold(station->netdev);
+ else
+ netdev_raise_signal_threshold(station->netdev);
+
complete(dbus, message, NULL);
return NULL;
--
2.34.1
next prev parent reply other threads:[~2024-08-13 15:56 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-13 15:56 [PATCH 1/9] doc: Document station Affinities property James Prestwood
2024-08-13 15:56 ` [PATCH 2/9] netdev: store signal threshold in netdev object, not globally James Prestwood
2024-08-13 15:56 ` [PATCH 3/9] netdev: add critical signal threshold level James Prestwood
2024-08-13 15:56 ` [PATCH 4/9] netdev: add netdev_get_critical_signal_threshold James Prestwood
2024-08-13 15:56 ` [PATCH 5/9] station: emit property changed for ConnectedAccessPoint James Prestwood
2024-08-13 15:56 ` [PATCH 6/9] station: add Affinities DBus property James Prestwood
2024-08-13 15:56 ` James Prestwood [this message]
2024-08-13 15:56 ` [PATCH 8/9] auto-t: add affinities property for station, and extended_service_set James Prestwood
2024-08-13 15:56 ` [PATCH 9/9] auto-t: add tests for Affinities behavior James Prestwood
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=20240813155638.74987-7-prestwoj@gmail.com \
--to=prestwoj@gmail.com \
--cc=iwd@lists.linux.dev \
/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