diff --git a/src/devices/wifi/nm-device-iwd.c b/src/devices/wifi/nm-device-iwd.c index f6029ecfa6..2478ac9cd2 100644 --- a/src/devices/wifi/nm-device-iwd.c +++ b/src/devices/wifi/nm-device-iwd.c @@ -433,26 +433,26 @@ periodic_update(NMDeviceIwd *self) platform = nm_device_get_platform(NM_DEVICE(self)); - /* TODO: obtain this through the net.connman.iwd.SignalLevelAgent API. - * For now we're waking up for the rate updates anyway. + /* TODO: obtain quality through the net.connman.iwd.SignalLevelAgent API. + * For now we're waking up for the rate/BSSID updates anyway. */ - percent = nm_platform_wifi_get_quality(platform, ifindex); - if (percent >= 0 && percent <= 100) { - if (nm_wifi_ap_set_strength(priv->current_ap, (gint8) percent)) { -#if NM_MORE_LOGGING - ap_changed = TRUE; -#endif - } + if (!nm_platform_wifi_get_station(platform, ifindex, bssid, &percent, &new_rate)) { + _LOGD(LOGD_WIFI, "BSSID / quality / rate platform query failed"); + return; + } + + if (nm_wifi_ap_set_strength(priv->current_ap, (gint8) percent)) { +#if NM_MORE_LOGGING + ap_changed = TRUE; +#endif } - new_rate = nm_platform_wifi_get_rate(platform, ifindex); if (new_rate != priv->rate) { priv->rate = new_rate; _notify(self, PROP_BITRATE); } - if (nm_platform_wifi_get_bssid(platform, ifindex, bssid) - && nm_ethernet_address_is_valid(bssid, ETH_ALEN) + if (nm_ethernet_address_is_valid(bssid, ETH_ALEN) && memcmp(bssid, priv->current_ap_bssid, ETH_ALEN)) { gs_free char *bssid_str = NULL; memcpy(priv->current_ap_bssid, bssid, ETH_ALEN); diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 24de0cdeca..730b84602b 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -728,6 +728,7 @@ periodic_update(NMDeviceWifi *self) NMDeviceWifiPrivate *priv; int ifindex; guint32 new_rate; + int percent; if (nm_device_get_state(NM_DEVICE(self)) != NM_DEVICE_STATE_ACTIVATED) { /* BSSID and signal strength have meaningful values only if the device @@ -757,23 +758,22 @@ periodic_update(NMDeviceWifi *self) if (ifindex <= 0) g_return_if_reached(); - if (priv->current_ap) { - int percent; - - percent = nm_platform_wifi_get_quality(nm_device_get_platform(NM_DEVICE(self)), ifindex); - if (percent >= 0 && percent <= 100) { - if (nm_wifi_ap_set_strength(priv->current_ap, (gint8) percent)) { + if (priv->current_ap + && nm_platform_wifi_get_station(nm_device_get_platform(NM_DEVICE(self)), + ifindex, + NULL, + &percent, + &new_rate)) { + if (nm_wifi_ap_set_strength(priv->current_ap, (gint8) percent)) { #if NM_MORE_LOGGING - _ap_dump(self, LOGL_TRACE, priv->current_ap, "updated", 0); + _ap_dump(self, LOGL_TRACE, priv->current_ap, "updated", 0); #endif - } } - } - new_rate = nm_platform_wifi_get_rate(nm_device_get_platform(NM_DEVICE(self)), ifindex); - if (new_rate != priv->rate) { - priv->rate = new_rate; - _notify(self, PROP_BITRATE); + if (new_rate != priv->rate) { + priv->rate = new_rate; + _notify(self, PROP_BITRATE); + } } } @@ -3369,31 +3369,36 @@ activation_success_handler(NMDevice *device) g_warn_if_fail(priv->current_ap); if (priv->current_ap) { if (nm_wifi_ap_get_fake(priv->current_ap)) { - gboolean ap_changed = FALSE; + gboolean ap_changed = FALSE; + gboolean update_bssid = !nm_wifi_ap_get_address(priv->current_ap); + gboolean update_rate = !nm_wifi_ap_get_max_bitrate(priv->current_ap); + guint8 bssid[ETH_ALEN]; + guint32 rate; /* If the activation AP hasn't been seen by the supplicant in a scan * yet, it will be "fake". This usually happens for Ad-Hoc and * AP-mode connections. Fill in the details from the device itself * until the supplicant sends the scan result. */ - if (!nm_wifi_ap_get_address(priv->current_ap)) { - guint8 bssid[ETH_ALEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; - gs_free char *bssid_str = NULL; - - if (nm_platform_wifi_get_bssid(nm_device_get_platform(device), ifindex, bssid) - && nm_ethernet_address_is_valid(bssid, ETH_ALEN)) { - bssid_str = nm_utils_hwaddr_ntoa(bssid, ETH_ALEN); - ap_changed |= nm_wifi_ap_set_address(priv->current_ap, bssid_str); - } - } if (!nm_wifi_ap_get_freq(priv->current_ap)) ap_changed |= nm_wifi_ap_set_freq( priv->current_ap, nm_platform_wifi_get_frequency(nm_device_get_platform(device), ifindex)); - if (!nm_wifi_ap_get_max_bitrate(priv->current_ap)) - ap_changed |= nm_wifi_ap_set_max_bitrate( - priv->current_ap, - nm_platform_wifi_get_rate(nm_device_get_platform(device), ifindex)); + + if ((update_bssid || update_rate) + && nm_platform_wifi_get_station(nm_device_get_platform(device), + ifindex, + update_bssid ? bssid : NULL, + NULL, + update_rate ? &rate : NULL)) { + if (update_bssid && nm_ethernet_address_is_valid(bssid, ETH_ALEN)) { + gs_free char *bssid_str = NULL; + bssid_str = nm_utils_hwaddr_ntoa(bssid, ETH_ALEN); + ap_changed |= nm_wifi_ap_set_address(priv->current_ap, bssid_str); + } + if (update_rate) + ap_changed |= nm_wifi_ap_set_max_bitrate(priv->current_ap, rate); + } if (ap_changed) _ap_dump(self, LOGL_DEBUG, priv->current_ap, "updated", 0); diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index b377c85e7a..55e46cd5ef 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -8281,13 +8281,6 @@ wifi_get_capabilities(NMPlatform *platform, int ifindex, NMDeviceWifiCapabilitie return TRUE; } -static gboolean -wifi_get_bssid(NMPlatform *platform, int ifindex, guint8 *bssid) -{ - WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); - return nm_wifi_utils_get_bssid(wifi_data, bssid); -} - static guint32 wifi_get_frequency(NMPlatform *platform, int ifindex) { @@ -8296,17 +8289,14 @@ wifi_get_frequency(NMPlatform *platform, int ifindex) } static gboolean -wifi_get_quality(NMPlatform *platform, int ifindex) +wifi_get_station(NMPlatform *platform, + int ifindex, + guint8 * out_bssid, + int * out_quality, + guint32 * out_rate) { WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); - return nm_wifi_utils_get_qual(wifi_data); -} - -static guint32 -wifi_get_rate(NMPlatform *platform, int ifindex) -{ - WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); - return nm_wifi_utils_get_rate(wifi_data); + return nm_wifi_utils_get_station(wifi_data, out_bssid, out_quality, out_rate); } static NM80211Mode @@ -9669,10 +9659,8 @@ nm_linux_platform_class_init(NMLinuxPlatformClass *klass) platform_class->infiniband_partition_delete = infiniband_partition_delete; platform_class->wifi_get_capabilities = wifi_get_capabilities; - platform_class->wifi_get_bssid = wifi_get_bssid; platform_class->wifi_get_frequency = wifi_get_frequency; - platform_class->wifi_get_quality = wifi_get_quality; - platform_class->wifi_get_rate = wifi_get_rate; + platform_class->wifi_get_station = wifi_get_station; platform_class->wifi_get_mode = wifi_get_mode; platform_class->wifi_set_mode = wifi_set_mode; platform_class->wifi_set_powersave = wifi_set_powersave; diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index c843ad91fe..87b761ff25 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -3051,16 +3051,6 @@ nm_platform_wifi_get_capabilities(NMPlatform *self, int ifindex, NMDeviceWifiCap return klass->wifi_get_capabilities(self, ifindex, caps); } -gboolean -nm_platform_wifi_get_bssid(NMPlatform *self, int ifindex, guint8 *bssid) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - return klass->wifi_get_bssid(self, ifindex, bssid); -} - guint32 nm_platform_wifi_get_frequency(NMPlatform *self, int ifindex) { @@ -3071,24 +3061,18 @@ nm_platform_wifi_get_frequency(NMPlatform *self, int ifindex) return klass->wifi_get_frequency(self, ifindex); } -int -nm_platform_wifi_get_quality(NMPlatform *self, int ifindex) +gboolean +nm_platform_wifi_get_station(NMPlatform *self, + int ifindex, + guint8 * out_bssid, + int * out_quality, + guint32 * out_rate) { - _CHECK_SELF(self, klass, 0); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail(ifindex > 0, 0); + g_return_val_if_fail(ifindex > 0, FALSE); - return klass->wifi_get_quality(self, ifindex); -} - -guint32 -nm_platform_wifi_get_rate(NMPlatform *self, int ifindex) -{ - _CHECK_SELF(self, klass, 0); - - g_return_val_if_fail(ifindex > 0, 0); - - return klass->wifi_get_rate(self, ifindex); + return klass->wifi_get_station(self, ifindex, out_bssid, out_quality, out_rate); } NM80211Mode diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 8a0ead61d7..ae326a86a4 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -1182,6 +1182,11 @@ typedef struct { gboolean (*wifi_get_capabilities)(NMPlatform * self, int ifindex, NMDeviceWifiCapabilities *caps); + gboolean (*wifi_get_station)(NMPlatform *self, + int ifindex, + guint8 * out_bssid, + int * out_quality, + guint32 * out_rate); gboolean (*wifi_get_bssid)(NMPlatform *self, int ifindex, guint8 *bssid); guint32 (*wifi_get_frequency)(NMPlatform *self, int ifindex); int (*wifi_get_quality)(NMPlatform *self, int ifindex); @@ -1962,10 +1967,12 @@ gboolean nm_platform_link_tun_get_properties(NMPlatform * self, gboolean nm_platform_wifi_get_capabilities(NMPlatform *self, int ifindex, NMDeviceWifiCapabilities *caps); -gboolean nm_platform_wifi_get_bssid(NMPlatform *self, int ifindex, guint8 *bssid); guint32 nm_platform_wifi_get_frequency(NMPlatform *self, int ifindex); -int nm_platform_wifi_get_quality(NMPlatform *self, int ifindex); -guint32 nm_platform_wifi_get_rate(NMPlatform *self, int ifindex); +gboolean nm_platform_wifi_get_station(NMPlatform *self, + int ifindex, + guint8 * out_bssid, + int * out_quality, + guint32 * out_rate); NM80211Mode nm_platform_wifi_get_mode(NMPlatform *self, int ifindex); void nm_platform_wifi_set_mode(NMPlatform *self, int ifindex, NM80211Mode mode); void nm_platform_wifi_set_powersave(NMPlatform *self, int ifindex, guint32 powersave); diff --git a/src/platform/wifi/nm-wifi-utils-nl80211.c b/src/platform/wifi/nm-wifi-utils-nl80211.c index 841f621e7c..0071c67ea5 100644 --- a/src/platform/wifi/nm-wifi-utils-nl80211.c +++ b/src/platform/wifi/nm-wifi-utils-nl80211.c @@ -41,16 +41,6 @@ } \ G_STMT_END -struct nl80211_station_info { - gboolean valid; - guint8 bssid[ETH_ALEN]; - guint32 txrate; - gboolean txrate_valid; - guint8 signal; - gboolean signal_valid; - gint64 timestamp; -}; - typedef struct { NMWifiUtils parent; struct nl_sock *nl_sock; @@ -59,8 +49,6 @@ typedef struct { int num_freqs; int phy; bool can_wowlan : 1; - - struct nl80211_station_info sta_info; } NMWifiUtilsNl80211; typedef struct { @@ -422,6 +410,15 @@ nl80211_xbm_to_percent(gint32 xbm, guint32 divisor) / ((float) SIGNAL_MAX_DBM - (float) NOISE_FLOOR_DBM)); } +struct nl80211_station_info { + gboolean valid; + guint8 bssid[ETH_ALEN]; + guint32 txrate; + gboolean txrate_valid; + guint8 signal; + gboolean signal_valid; +}; + static int nl80211_station_dump_handler(struct nl_msg *msg, void *arg) { @@ -496,53 +493,31 @@ nl80211_station_dump_handler(struct nl_msg *msg, void *arg) return NL_SKIP; } -static void -nl80211_get_sta_info(NMWifiUtilsNl80211 *self) +static gboolean +wifi_nl80211_get_station(NMWifiUtils *data, guint8 *out_bssid, int *out_quality, guint32 *out_rate) { - nm_auto_nlmsg struct nl_msg *msg = NULL; - gint64 now = nm_utils_get_monotonic_timestamp_msec(); - - if (self->sta_info.valid && now - self->sta_info.timestamp < 500) - return; - - memset(&self->sta_info, 0, sizeof(self->sta_info)); + NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; + nm_auto_nlmsg struct nl_msg *msg = NULL; + struct nl80211_station_info sta_info = {}; msg = nl80211_alloc_msg(self, NL80211_CMD_GET_STATION, NLM_F_DUMP); - nl80211_send_and_recv(self, msg, nl80211_station_dump_handler, &self->sta_info); - self->sta_info.timestamp = now; -} + nl80211_send_and_recv(self, msg, nl80211_station_dump_handler, &sta_info); -static gboolean -wifi_nl80211_get_bssid(NMWifiUtils *data, guint8 *out_bssid) -{ - NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; + if (!sta_info.valid || (out_quality && !sta_info.signal_valid) + || (out_rate && !sta_info.txrate_valid)) + return FALSE; - nl80211_get_sta_info(self); + if (out_bssid) + memcpy(out_bssid, sta_info.bssid, ETH_ALEN); - if (self->sta_info.valid) - memcpy(out_bssid, self->sta_info.bssid, ETH_ALEN); + if (out_quality) + *out_quality = sta_info.signal; - return self->sta_info.valid; -} + if (out_rate) + *out_rate = sta_info.txrate; -static guint32 -wifi_nl80211_get_rate(NMWifiUtils *data) -{ - NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; - - nl80211_get_sta_info(self); - - return self->sta_info.txrate; -} - -static int -wifi_nl80211_get_qual(NMWifiUtils *data) -{ - NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; - - nl80211_get_sta_info(self); - return self->sta_info.signal; + return TRUE; } static gboolean @@ -857,9 +832,7 @@ nm_wifi_utils_nl80211_class_init(NMWifiUtilsNl80211Class *klass) wifi_utils_class->set_wake_on_wlan = wifi_nl80211_set_wake_on_wlan, wifi_utils_class->get_freq = wifi_nl80211_get_freq; wifi_utils_class->find_freq = wifi_nl80211_find_freq; - wifi_utils_class->get_bssid = wifi_nl80211_get_bssid; - wifi_utils_class->get_rate = wifi_nl80211_get_rate; - wifi_utils_class->get_qual = wifi_nl80211_get_qual; + wifi_utils_class->get_station = wifi_nl80211_get_station; wifi_utils_class->indicate_addressing_running = wifi_nl80211_indicate_addressing_running; wifi_utils_class->get_mesh_channel = wifi_nl80211_get_mesh_channel; wifi_utils_class->set_mesh_channel = wifi_nl80211_set_mesh_channel; diff --git a/src/platform/wifi/nm-wifi-utils-private.h b/src/platform/wifi/nm-wifi-utils-private.h index 1a5303a668..f175523b87 100644 --- a/src/platform/wifi/nm-wifi-utils-private.h +++ b/src/platform/wifi/nm-wifi-utils-private.h @@ -41,6 +41,18 @@ typedef struct { */ int (*get_qual)(NMWifiUtils *data); + /* + * @out_bssid: must be NULL or an ETH_ALEN-byte buffer + * @out_quality: receives signal strength percentage 0 - 100% for the current BSSID, if not NULL + * @out_rate: receives current bitrate in Kbps if not NULL + * + * Returns %TRUE on succcess, %FALSE on errors or if not associated. + */ + gboolean (*get_station)(NMWifiUtils *data, + guint8 * out_bssid, + int * out_quality, + guint32 * out_rate); + /* OLPC Mesh-only functions */ guint32 (*get_mesh_channel)(NMWifiUtils *data); diff --git a/src/platform/wifi/nm-wifi-utils.c b/src/platform/wifi/nm-wifi-utils.c index 3f9d3a48f5..8566a95807 100644 --- a/src/platform/wifi/nm-wifi-utils.c +++ b/src/platform/wifi/nm-wifi-utils.c @@ -132,27 +132,36 @@ nm_wifi_utils_find_freq(NMWifiUtils *data, const guint32 *freqs) } gboolean -nm_wifi_utils_get_bssid(NMWifiUtils *data, guint8 *out_bssid) +nm_wifi_utils_get_station(NMWifiUtils *data, guint8 *out_bssid, int *out_quality, guint32 *out_rate) { + NMWifiUtilsClass *klass; + g_return_val_if_fail(data != NULL, FALSE); - g_return_val_if_fail(out_bssid != NULL, FALSE); - memset(out_bssid, 0, ETH_ALEN); - return NM_WIFI_UTILS_GET_CLASS(data)->get_bssid(data, out_bssid); -} + klass = NM_WIFI_UTILS_GET_CLASS(data); -guint32 -nm_wifi_utils_get_rate(NMWifiUtils *data) -{ - g_return_val_if_fail(data != NULL, 0); - return NM_WIFI_UTILS_GET_CLASS(data)->get_rate(data); -} + if (klass->get_station != NULL) + return klass->get_station(data, out_bssid, out_quality, out_rate); -int -nm_wifi_utils_get_qual(NMWifiUtils *data) -{ - g_return_val_if_fail(data != NULL, 0); - return NM_WIFI_UTILS_GET_CLASS(data)->get_qual(data); + if (out_bssid) { + memset(out_bssid, 0, ETH_ALEN); + if (!klass->get_bssid(data, out_bssid)) + return FALSE; + } + + if (out_quality) { + *out_quality = klass->get_qual(data); + if (*out_quality < 0) + return FALSE; + } + + if (out_rate) { + *out_rate = klass->get_rate(data); + if (*out_rate == 0) + return FALSE; + } + + return TRUE; } gboolean diff --git a/src/platform/wifi/nm-wifi-utils.h b/src/platform/wifi/nm-wifi-utils.h index d1df2fb822..be943edf96 100644 --- a/src/platform/wifi/nm-wifi-utils.h +++ b/src/platform/wifi/nm-wifi-utils.h @@ -43,14 +43,17 @@ guint32 nm_wifi_utils_get_freq(NMWifiUtils *data); * Frequencies are specified in MHz. */ guint32 nm_wifi_utils_find_freq(NMWifiUtils *data, const guint32 *freqs); -/* out_bssid must be ETH_ALEN bytes */ -gboolean nm_wifi_utils_get_bssid(NMWifiUtils *data, guint8 *out_bssid); - -/* Returns current bitrate in Kbps */ -guint32 nm_wifi_utils_get_rate(NMWifiUtils *data); - -/* Returns quality 0 - 100% on success, or -1 on error */ -int nm_wifi_utils_get_qual(NMWifiUtils *data); +/* + * @out_bssid: must be NULL or an ETH_ALEN-byte buffer + * @out_quality: receives signal quality in 0 - 100% range if not NULL + * @out_rate: receives current bitrate in Kbps if not NULL + * + * Returns %TRUE on succcess. + */ +gboolean nm_wifi_utils_get_station(NMWifiUtils *data, + guint8 * out_bssid, + int * out_quality, + guint32 * out_rate); /* Tells the driver DHCP or SLAAC is running */ gboolean nm_wifi_utils_indicate_addressing_running(NMWifiUtils *data, gboolean running);