mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-30 21:20:10 +01:00
wifi: merge branch 'balrog-kun/NetworkManager-iwd-query-speed'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/652
This commit is contained in:
commit
880fe31ef2
2 changed files with 172 additions and 196 deletions
|
|
@ -54,6 +54,7 @@ typedef struct {
|
|||
NMDeviceWifiCapabilities capabilities;
|
||||
NMActRequestGetSecretsCallId *wifi_secrets_id;
|
||||
guint periodic_scan_id;
|
||||
guint periodic_update_id;
|
||||
bool enabled : 1;
|
||||
bool can_scan : 1;
|
||||
bool can_connect : 1;
|
||||
|
|
@ -65,6 +66,8 @@ typedef struct {
|
|||
bool networks_changed : 1;
|
||||
gint64 last_scan;
|
||||
uint32_t ap_id;
|
||||
guint32 rate;
|
||||
uint8_t current_ap_bssid[ETH_ALEN];
|
||||
} NMDeviceIwdPrivate;
|
||||
|
||||
struct _NMDeviceIwd {
|
||||
|
|
@ -163,6 +166,7 @@ set_current_ap(NMDeviceIwd *self, NMWifiAP *new_ap, gboolean recheck_available_c
|
|||
g_object_unref(old_ap);
|
||||
}
|
||||
|
||||
memset(priv->current_ap_bssid, 0, ETH_ALEN);
|
||||
_notify(self, PROP_ACTIVE_ACCESS_POINT);
|
||||
_notify(self, PROP_MODE);
|
||||
schedule_periodic_scan(self, TRUE);
|
||||
|
|
@ -177,8 +181,6 @@ remove_all_aps(NMDeviceIwd *self)
|
|||
if (c_list_is_empty(&priv->aps_lst_head))
|
||||
return;
|
||||
|
||||
set_current_ap(self, NULL, FALSE);
|
||||
|
||||
c_list_for_each_entry_safe (ap, ap_safe, &priv->aps_lst_head, aps_lst)
|
||||
ap_add_remove(self, FALSE, ap, FALSE);
|
||||
|
||||
|
|
@ -403,6 +405,63 @@ update_aps(NMDeviceIwd *self)
|
|||
priv->networks_requested = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
periodic_update(NMDeviceIwd *self)
|
||||
{
|
||||
NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
|
||||
int ifindex;
|
||||
guint32 new_rate;
|
||||
int percent;
|
||||
guint8 bssid[ETH_ALEN];
|
||||
gboolean ap_changed = FALSE;
|
||||
NMPlatform * platform;
|
||||
|
||||
ifindex = nm_device_get_ifindex(NM_DEVICE(self));
|
||||
if (ifindex <= 0)
|
||||
g_return_if_reached();
|
||||
|
||||
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.
|
||||
*/
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
&& memcmp(bssid, priv->current_ap_bssid, ETH_ALEN)) {
|
||||
gs_free char *bssid_str = NULL;
|
||||
memcpy(priv->current_ap_bssid, bssid, ETH_ALEN);
|
||||
bssid_str = nm_utils_hwaddr_ntoa(bssid, ETH_ALEN);
|
||||
ap_changed |= nm_wifi_ap_set_address(priv->current_ap, bssid_str);
|
||||
ap_changed |= nm_wifi_ap_set_freq(priv->current_ap,
|
||||
nm_platform_wifi_get_frequency(platform, ifindex));
|
||||
}
|
||||
|
||||
if (ap_changed)
|
||||
_ap_dump(self, LOGL_DEBUG, priv->current_ap, "updated");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
periodic_update_cb(gpointer user_data)
|
||||
{
|
||||
periodic_update(user_data);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
send_disconnect(NMDeviceIwd *self)
|
||||
{
|
||||
|
|
@ -436,6 +495,7 @@ cleanup_association_attempt(NMDeviceIwd *self, gboolean disconnect)
|
|||
wifi_secrets_cancel(self);
|
||||
|
||||
set_current_ap(self, NULL, TRUE);
|
||||
nm_clear_g_source(&priv->periodic_update_id);
|
||||
|
||||
if (disconnect && priv->dbus_station_proxy)
|
||||
send_disconnect(self);
|
||||
|
|
@ -1450,6 +1510,11 @@ network_connect_cb(GObject *source, GAsyncResult *res, gpointer user_data)
|
|||
ssid_utf8);
|
||||
nm_device_activate_schedule_stage3_ip_config_start(device);
|
||||
|
||||
if (!priv->periodic_update_id) {
|
||||
priv->periodic_update_id = g_timeout_add_seconds(6, periodic_update_cb, self);
|
||||
periodic_update(self);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
failed:
|
||||
|
|
@ -1499,11 +1564,12 @@ act_start_cb(GObject *source, GAsyncResult *res, gpointer user_data)
|
|||
NMSettingWireless * s_wireless;
|
||||
GBytes * ssid;
|
||||
gs_free char * ssid_utf8 = NULL;
|
||||
const char * mode;
|
||||
|
||||
variant = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error);
|
||||
if (!variant) {
|
||||
_LOGE(LOGD_DEVICE | LOGD_WIFI,
|
||||
"Activation: (wifi) Network.Connect failed: %s",
|
||||
"Activation: (wifi) {AccessPoint,AdHoc}.Start() failed: %s",
|
||||
error->message);
|
||||
|
||||
if (nm_utils_error_is_cancelled(error))
|
||||
|
|
@ -1530,8 +1596,14 @@ act_start_cb(GObject *source, GAsyncResult *res, gpointer user_data)
|
|||
_LOGI(LOGD_DEVICE | LOGD_WIFI,
|
||||
"Activation: (wifi) Stage 2 of 5 (Device Configure) successful. Started '%s'.",
|
||||
ssid_utf8);
|
||||
|
||||
nm_device_activate_schedule_stage3_ip_config_start(device);
|
||||
|
||||
mode = nm_setting_wireless_get_mode(s_wireless);
|
||||
if (!priv->periodic_update_id && nm_streq0(mode, NM_SETTING_WIRELESS_MODE_ADHOC)) {
|
||||
priv->periodic_update_id = g_timeout_add_seconds(6, periodic_update_cb, self);
|
||||
periodic_update(self);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
|
|
@ -2153,7 +2225,7 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
|||
|
||||
break;
|
||||
case PROP_BITRATE:
|
||||
g_value_set_uint(value, 65000);
|
||||
g_value_set_uint(value, priv->rate);
|
||||
break;
|
||||
case PROP_CAPABILITIES:
|
||||
g_value_set_uint(value, priv->capabilities);
|
||||
|
|
|
|||
|
|
@ -41,6 +41,16 @@
|
|||
} \
|
||||
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;
|
||||
|
|
@ -49,6 +59,8 @@ typedef struct {
|
|||
int num_freqs;
|
||||
int phy;
|
||||
bool can_wowlan : 1;
|
||||
|
||||
struct nl80211_station_info sta_info;
|
||||
} NMWifiUtilsNl80211;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -163,6 +175,7 @@ dispose(GObject *object)
|
|||
|
||||
struct nl80211_iface_info {
|
||||
NM80211Mode mode;
|
||||
uint32_t freq;
|
||||
};
|
||||
|
||||
static int
|
||||
|
|
@ -193,6 +206,9 @@ nl80211_iface_info_handler(struct nl_msg *msg, void *arg)
|
|||
break;
|
||||
}
|
||||
|
||||
if (tb[NL80211_ATTR_WIPHY_FREQ] != NULL)
|
||||
info->freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
|
||||
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
|
|
@ -359,142 +375,19 @@ nla_put_failure:
|
|||
g_return_val_if_reached(FALSE);
|
||||
}
|
||||
|
||||
/* @divisor: pass what value @xbm should be divided by to get dBm */
|
||||
static guint32
|
||||
nl80211_xbm_to_percent(gint32 xbm, guint32 divisor)
|
||||
{
|
||||
#define NOISE_FLOOR_DBM -90
|
||||
#define SIGNAL_MAX_DBM -20
|
||||
|
||||
xbm /= divisor;
|
||||
xbm = CLAMP(xbm, NOISE_FLOOR_DBM, SIGNAL_MAX_DBM);
|
||||
|
||||
return 100
|
||||
- 70
|
||||
* (((float) SIGNAL_MAX_DBM - (float) xbm)
|
||||
/ ((float) SIGNAL_MAX_DBM - (float) NOISE_FLOOR_DBM));
|
||||
}
|
||||
|
||||
struct nl80211_bss_info {
|
||||
guint32 freq;
|
||||
guint8 bssid[ETH_ALEN];
|
||||
guint8 ssid[32];
|
||||
guint32 ssid_len;
|
||||
guint32 beacon_signal;
|
||||
gboolean valid;
|
||||
};
|
||||
|
||||
#define WLAN_EID_SSID 0
|
||||
|
||||
static void
|
||||
find_ssid(guint8 *ies, guint32 ies_len, guint8 **ssid, guint32 *ssid_len)
|
||||
{
|
||||
*ssid = NULL;
|
||||
*ssid_len = 0;
|
||||
|
||||
while (ies_len > 2 && ies[0] != WLAN_EID_SSID) {
|
||||
ies_len -= ies[1] + 2;
|
||||
ies += ies[1] + 2;
|
||||
}
|
||||
if (ies_len < 2)
|
||||
return;
|
||||
if (ies_len < 2 + ies[1])
|
||||
return;
|
||||
|
||||
*ssid_len = ies[1];
|
||||
*ssid = ies + 2;
|
||||
}
|
||||
|
||||
static int
|
||||
nl80211_bss_dump_handler(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
static const struct nla_policy bss_policy[] = {
|
||||
[NL80211_BSS_TSF] = {.type = NLA_U64},
|
||||
[NL80211_BSS_FREQUENCY] = {.type = NLA_U32},
|
||||
[NL80211_BSS_BSSID] = {.minlen = ETH_ALEN},
|
||||
[NL80211_BSS_BEACON_INTERVAL] = {.type = NLA_U16},
|
||||
[NL80211_BSS_CAPABILITY] = {.type = NLA_U16},
|
||||
[NL80211_BSS_INFORMATION_ELEMENTS] = {},
|
||||
[NL80211_BSS_SIGNAL_MBM] = {.type = NLA_U32},
|
||||
[NL80211_BSS_SIGNAL_UNSPEC] = {.type = NLA_U8},
|
||||
[NL80211_BSS_STATUS] = {.type = NLA_U32},
|
||||
};
|
||||
struct nl80211_bss_info *info = arg;
|
||||
struct genlmsghdr * gnlh = nlmsg_data(nlmsg_hdr(msg));
|
||||
struct nlattr * tb[NL80211_ATTR_MAX + 1];
|
||||
struct nlattr * bss[G_N_ELEMENTS(bss_policy)];
|
||||
guint32 status;
|
||||
|
||||
if (nla_parse_arr(tb, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL) < 0)
|
||||
return NL_SKIP;
|
||||
|
||||
if (tb[NL80211_ATTR_BSS] == NULL)
|
||||
return NL_SKIP;
|
||||
|
||||
if (nla_parse_nested_arr(bss, tb[NL80211_ATTR_BSS], bss_policy))
|
||||
return NL_SKIP;
|
||||
|
||||
if (bss[NL80211_BSS_STATUS] == NULL)
|
||||
return NL_SKIP;
|
||||
|
||||
status = nla_get_u32(bss[NL80211_BSS_STATUS]);
|
||||
|
||||
if (status != NL80211_BSS_STATUS_ASSOCIATED && status != NL80211_BSS_STATUS_IBSS_JOINED)
|
||||
return NL_SKIP;
|
||||
|
||||
if (bss[NL80211_BSS_BSSID] == NULL)
|
||||
return NL_SKIP;
|
||||
memcpy(info->bssid, nla_data(bss[NL80211_BSS_BSSID]), ETH_ALEN);
|
||||
|
||||
if (bss[NL80211_BSS_FREQUENCY])
|
||||
info->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
|
||||
|
||||
if (bss[NL80211_BSS_SIGNAL_UNSPEC])
|
||||
info->beacon_signal = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]);
|
||||
|
||||
if (bss[NL80211_BSS_SIGNAL_MBM])
|
||||
info->beacon_signal = nl80211_xbm_to_percent(nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]), 100);
|
||||
|
||||
if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
|
||||
guint8 *ssid;
|
||||
guint32 ssid_len;
|
||||
|
||||
find_ssid(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
|
||||
nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
|
||||
&ssid,
|
||||
&ssid_len);
|
||||
if (ssid && ssid_len && ssid_len <= sizeof(info->ssid)) {
|
||||
memcpy(info->ssid, ssid, ssid_len);
|
||||
info->ssid_len = ssid_len;
|
||||
}
|
||||
}
|
||||
|
||||
info->valid = TRUE;
|
||||
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
static void
|
||||
nl80211_get_bss_info(NMWifiUtilsNl80211 *self, struct nl80211_bss_info *bss_info)
|
||||
{
|
||||
nm_auto_nlmsg struct nl_msg *msg = NULL;
|
||||
|
||||
memset(bss_info, 0, sizeof(*bss_info));
|
||||
|
||||
msg = nl80211_alloc_msg(self, NL80211_CMD_GET_SCAN, NLM_F_DUMP);
|
||||
|
||||
nl80211_send_and_recv(self, msg, nl80211_bss_dump_handler, bss_info);
|
||||
}
|
||||
|
||||
static guint32
|
||||
wifi_nl80211_get_freq(NMWifiUtils *data)
|
||||
{
|
||||
NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data;
|
||||
struct nl80211_bss_info bss_info;
|
||||
NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data;
|
||||
struct nl80211_iface_info iface_info = {};
|
||||
nm_auto_nlmsg struct nl_msg *msg = NULL;
|
||||
|
||||
nl80211_get_bss_info(self, &bss_info);
|
||||
msg = nl80211_alloc_msg(self, NL80211_CMD_GET_INTERFACE, 0);
|
||||
|
||||
return bss_info.freq;
|
||||
if (nl80211_send_and_recv(self, msg, nl80211_iface_info_handler, &iface_info) < 0)
|
||||
return 0;
|
||||
|
||||
return iface_info.freq;
|
||||
}
|
||||
|
||||
static guint32
|
||||
|
|
@ -513,41 +406,38 @@ wifi_nl80211_find_freq(NMWifiUtils *data, const guint32 *freqs)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
wifi_nl80211_get_bssid(NMWifiUtils *data, guint8 *out_bssid)
|
||||
/* @divisor: pass what value @xbm should be divided by to get dBm */
|
||||
static guint32
|
||||
nl80211_xbm_to_percent(gint32 xbm, guint32 divisor)
|
||||
{
|
||||
NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data;
|
||||
struct nl80211_bss_info bss_info;
|
||||
#define NOISE_FLOOR_DBM -90
|
||||
#define SIGNAL_MAX_DBM -20
|
||||
|
||||
nl80211_get_bss_info(self, &bss_info);
|
||||
xbm /= divisor;
|
||||
xbm = CLAMP(xbm, NOISE_FLOOR_DBM, SIGNAL_MAX_DBM);
|
||||
|
||||
if (bss_info.valid)
|
||||
memcpy(out_bssid, bss_info.bssid, ETH_ALEN);
|
||||
|
||||
return bss_info.valid;
|
||||
return 100
|
||||
- 70
|
||||
* (((float) SIGNAL_MAX_DBM - (float) xbm)
|
||||
/ ((float) SIGNAL_MAX_DBM - (float) NOISE_FLOOR_DBM));
|
||||
}
|
||||
|
||||
struct nl80211_station_info {
|
||||
guint32 txrate;
|
||||
gboolean txrate_valid;
|
||||
guint8 signal;
|
||||
gboolean signal_valid;
|
||||
};
|
||||
|
||||
static int
|
||||
nl80211_station_handler(struct nl_msg *msg, void *arg)
|
||||
nl80211_station_dump_handler(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
static const struct nla_policy stats_policy[] = {
|
||||
[NL80211_STA_INFO_INACTIVE_TIME] = {.type = NLA_U32},
|
||||
[NL80211_STA_INFO_RX_BYTES] = {.type = NLA_U32},
|
||||
[NL80211_STA_INFO_TX_BYTES] = {.type = NLA_U32},
|
||||
[NL80211_STA_INFO_RX_PACKETS] = {.type = NLA_U32},
|
||||
[NL80211_STA_INFO_TX_PACKETS] = {.type = NLA_U32},
|
||||
[NL80211_STA_INFO_SIGNAL] = {.type = NLA_U8},
|
||||
[NL80211_STA_INFO_TX_BITRATE] = {.type = NLA_NESTED},
|
||||
[NL80211_STA_INFO_LLID] = {.type = NLA_U16},
|
||||
[NL80211_STA_INFO_PLID] = {.type = NLA_U16},
|
||||
[NL80211_STA_INFO_PLINK_STATE] = {.type = NLA_U8},
|
||||
[NL80211_STA_INFO_INACTIVE_TIME] = {.type = NLA_U32},
|
||||
[NL80211_STA_INFO_RX_BYTES] = {.type = NLA_U32},
|
||||
[NL80211_STA_INFO_TX_BYTES] = {.type = NLA_U32},
|
||||
[NL80211_STA_INFO_RX_PACKETS] = {.type = NLA_U32},
|
||||
[NL80211_STA_INFO_TX_PACKETS] = {.type = NLA_U32},
|
||||
[NL80211_STA_INFO_SIGNAL] = {.type = NLA_U8},
|
||||
[NL80211_STA_INFO_TX_BITRATE] = {.type = NLA_NESTED},
|
||||
[NL80211_STA_INFO_LLID] = {.type = NLA_U16},
|
||||
[NL80211_STA_INFO_PLID] = {.type = NLA_U16},
|
||||
[NL80211_STA_INFO_PLINK_STATE] = {.type = NLA_U8},
|
||||
[NL80211_STA_INFO_STA_FLAGS] = {.minlen = sizeof(struct nl80211_sta_flag_update)},
|
||||
[NL80211_STA_INFO_BEACON_SIGNAL_AVG] = {.type = NLA_U8},
|
||||
};
|
||||
static const struct nla_policy rate_policy[] = {
|
||||
[NL80211_RATE_INFO_BITRATE] = {.type = NLA_U16},
|
||||
|
|
@ -564,80 +454,94 @@ nl80211_station_handler(struct nl_msg *msg, void *arg)
|
|||
if (nla_parse_arr(tb, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL) < 0)
|
||||
return NL_SKIP;
|
||||
|
||||
if (tb[NL80211_ATTR_MAC] == NULL)
|
||||
return NL_SKIP;
|
||||
|
||||
if (tb[NL80211_ATTR_STA_INFO] == NULL)
|
||||
return NL_SKIP;
|
||||
|
||||
if (nla_parse_nested_arr(sinfo, tb[NL80211_ATTR_STA_INFO], stats_policy))
|
||||
return NL_SKIP;
|
||||
|
||||
if (sinfo[NL80211_STA_INFO_TX_BITRATE] == NULL)
|
||||
return NL_SKIP;
|
||||
if (sinfo[NL80211_STA_INFO_STA_FLAGS] != NULL) {
|
||||
const struct nl80211_sta_flag_update *flags = nla_data(sinfo[NL80211_STA_INFO_STA_FLAGS]);
|
||||
|
||||
if (nla_parse_nested_arr(rinfo, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy))
|
||||
return NL_SKIP;
|
||||
if (flags->mask & ~flags->set & (1 << NL80211_STA_FLAG_ASSOCIATED))
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
if (rinfo[NL80211_RATE_INFO_BITRATE] == NULL)
|
||||
return NL_SKIP;
|
||||
memcpy(info->bssid, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
|
||||
info->valid = TRUE;
|
||||
|
||||
/* convert from nl80211's units of 100kbps to NM's kbps */
|
||||
info->txrate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]) * 100;
|
||||
info->txrate_valid = TRUE;
|
||||
if (sinfo[NL80211_STA_INFO_TX_BITRATE] != NULL
|
||||
&& !nla_parse_nested_arr(rinfo, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)
|
||||
&& rinfo[NL80211_RATE_INFO_BITRATE] != NULL) {
|
||||
/* convert from nl80211's units of 100kbps to NM's kbps */
|
||||
info->txrate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]) * 100;
|
||||
info->txrate_valid = TRUE;
|
||||
}
|
||||
|
||||
if (sinfo[NL80211_STA_INFO_SIGNAL] != NULL) {
|
||||
info->signal =
|
||||
nl80211_xbm_to_percent((gint8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]), 1);
|
||||
info->signal_valid = TRUE;
|
||||
} else if (sinfo[NL80211_STA_INFO_BEACON_SIGNAL_AVG] != NULL) {
|
||||
/* Fall back to beacon signal strength */
|
||||
info->signal =
|
||||
nl80211_xbm_to_percent((gint8) nla_get_u8(sinfo[NL80211_STA_INFO_BEACON_SIGNAL_AVG]), 1);
|
||||
info->signal_valid = TRUE;
|
||||
}
|
||||
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
static void
|
||||
nl80211_get_ap_info(NMWifiUtilsNl80211 *self, struct nl80211_station_info *sta_info)
|
||||
nl80211_get_sta_info(NMWifiUtilsNl80211 *self)
|
||||
{
|
||||
nm_auto_nlmsg struct nl_msg *msg = NULL;
|
||||
struct nl80211_bss_info bss_info;
|
||||
gint64 now = nm_utils_get_monotonic_timestamp_msec();
|
||||
|
||||
memset(sta_info, 0, sizeof(*sta_info));
|
||||
|
||||
nl80211_get_bss_info(self, &bss_info);
|
||||
if (!bss_info.valid)
|
||||
if (self->sta_info.valid && now - self->sta_info.timestamp < 500)
|
||||
return;
|
||||
|
||||
msg = nl80211_alloc_msg(self, NL80211_CMD_GET_STATION, 0);
|
||||
NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bss_info.bssid);
|
||||
memset(&self->sta_info, 0, sizeof(self->sta_info));
|
||||
|
||||
nl80211_send_and_recv(self, msg, nl80211_station_handler, sta_info);
|
||||
if (!sta_info->signal_valid) {
|
||||
/* Fall back to bss_info signal quality (both are in percent) */
|
||||
sta_info->signal = bss_info.beacon_signal;
|
||||
}
|
||||
msg = nl80211_alloc_msg(self, NL80211_CMD_GET_STATION, NLM_F_DUMP);
|
||||
|
||||
return;
|
||||
nl80211_send_and_recv(self, msg, nl80211_station_dump_handler, &self->sta_info);
|
||||
self->sta_info.timestamp = now;
|
||||
}
|
||||
|
||||
nla_put_failure:
|
||||
g_return_if_reached();
|
||||
static gboolean
|
||||
wifi_nl80211_get_bssid(NMWifiUtils *data, guint8 *out_bssid)
|
||||
{
|
||||
NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data;
|
||||
|
||||
nl80211_get_sta_info(self);
|
||||
|
||||
if (self->sta_info.valid)
|
||||
memcpy(out_bssid, self->sta_info.bssid, ETH_ALEN);
|
||||
|
||||
return self->sta_info.valid;
|
||||
}
|
||||
|
||||
static guint32
|
||||
wifi_nl80211_get_rate(NMWifiUtils *data)
|
||||
{
|
||||
NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data;
|
||||
struct nl80211_station_info sta_info;
|
||||
NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data;
|
||||
|
||||
nl80211_get_ap_info(self, &sta_info);
|
||||
nl80211_get_sta_info(self);
|
||||
|
||||
return sta_info.txrate;
|
||||
return self->sta_info.txrate;
|
||||
}
|
||||
|
||||
static int
|
||||
wifi_nl80211_get_qual(NMWifiUtils *data)
|
||||
{
|
||||
NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data;
|
||||
struct nl80211_station_info sta_info;
|
||||
NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data;
|
||||
|
||||
nl80211_get_ap_info(self, &sta_info);
|
||||
return sta_info.signal;
|
||||
nl80211_get_sta_info(self);
|
||||
return self->sta_info.signal;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue