Add more nl80211 info to struct wpa_signal_info

Facilitate emitting more station information over D-Bus for use by the
connection manager.

* Add storage for more NL80211_STA_INFO_* fields to data structures, and
  move them through the system.
* Reorder NL80211_STA_INFO_* fields in driver_nl80211.c to match the
  ordering in nl80211.h.
* Convert signal field to an integer to support holding WPA_INVALID_NOISE
  and avoid changing logging.

* Add fields to hostap_sta_driver_data to capture more information
	* fcs_error_count
	* beacon_loss_count
	* expected_throughput
	* rx_drop_misc
	* rx_mpdus
	* rx_hemcs
	* tx_hemcs
	* rx_he_nss
	* tx_he_nss
	* avg_signal
	* avg_beacon_signal
	* avg_ack_signal
* Add struct hostap_sta_driver_data to struct wpa_signal_info and remove
  redundant fields and redundant attribute parsing
	* Change logging when printing txrate to handle unsigned long
	  value

Signed-off-by: David Ruth <druth@chromium.org>
This commit is contained in:
David Ruth 2022-11-30 23:33:09 +00:00 committed by Jouni Malinen
parent 090f0f8c70
commit ad4fa5dd3c
12 changed files with 178 additions and 158 deletions

View file

@ -99,7 +99,7 @@ static int hostapd_get_sta_info(struct hostapd_data *hapd,
len += ret; len += ret;
ret = os_snprintf(buf + len, buflen - len, "rx_rate_info=%lu", ret = os_snprintf(buf + len, buflen - len, "rx_rate_info=%lu",
data.current_rx_rate); data.current_rx_rate / 100);
if (os_snprintf_error(buflen - len, ret)) if (os_snprintf_error(buflen - len, ret))
return len; return len;
len += ret; len += ret;
@ -131,7 +131,7 @@ static int hostapd_get_sta_info(struct hostapd_data *hapd,
len += ret; len += ret;
ret = os_snprintf(buf + len, buflen - len, "tx_rate_info=%lu", ret = os_snprintf(buf + len, buflen - len, "tx_rate_info=%lu",
data.current_tx_rate); data.current_tx_rate / 100);
if (os_snprintf_error(buflen - len, ret)) if (os_snprintf_error(buflen - len, ret))
return len; return len;
len += ret; len += ret;

View file

@ -2272,14 +2272,19 @@ struct hostapd_data;
#define STA_DRV_DATA_RX_SHORT_GI BIT(7) #define STA_DRV_DATA_RX_SHORT_GI BIT(7)
#define STA_DRV_DATA_LAST_ACK_RSSI BIT(8) #define STA_DRV_DATA_LAST_ACK_RSSI BIT(8)
#define STA_DRV_DATA_CONN_TIME BIT(9) #define STA_DRV_DATA_CONN_TIME BIT(9)
#define STA_DRV_DATA_TX_HE_MCS BIT(10)
#define STA_DRV_DATA_RX_HE_MCS BIT(11)
#define STA_DRV_DATA_TX_HE_NSS BIT(12)
#define STA_DRV_DATA_RX_HE_NSS BIT(13)
struct hostap_sta_driver_data { struct hostap_sta_driver_data {
unsigned long rx_packets, tx_packets; unsigned long rx_packets, tx_packets;
unsigned long long rx_bytes, tx_bytes; unsigned long long rx_bytes, tx_bytes;
unsigned long long rx_airtime, tx_airtime; unsigned long long rx_airtime, tx_airtime;
unsigned long long beacons_count;
int bytes_64bit; /* whether 64-bit byte counters are supported */ int bytes_64bit; /* whether 64-bit byte counters are supported */
unsigned long current_tx_rate; unsigned long current_tx_rate; /* in kbps */
unsigned long current_rx_rate; unsigned long current_rx_rate; /* in kbps */
unsigned long inactive_msec; unsigned long inactive_msec;
unsigned long connected_sec; unsigned long connected_sec;
unsigned long flags; /* bitfield of STA_DRV_DATA_* */ unsigned long flags; /* bitfield of STA_DRV_DATA_* */
@ -2289,13 +2294,25 @@ struct hostap_sta_driver_data {
s8 last_ack_rssi; s8 last_ack_rssi;
unsigned long backlog_packets; unsigned long backlog_packets;
unsigned long backlog_bytes; unsigned long backlog_bytes;
s8 signal; unsigned long fcs_error_count;
unsigned long beacon_loss_count;
unsigned long expected_throughput;
unsigned long rx_drop_misc;
unsigned long rx_mpdus;
int signal; /* dBm; or -WPA_INVALID_NOISE */
u8 rx_hemcs;
u8 tx_hemcs;
u8 rx_vhtmcs; u8 rx_vhtmcs;
u8 tx_vhtmcs; u8 tx_vhtmcs;
u8 rx_mcs; u8 rx_mcs;
u8 tx_mcs; u8 tx_mcs;
u8 rx_he_nss;
u8 tx_he_nss;
u8 rx_vht_nss; u8 rx_vht_nss;
u8 tx_vht_nss; u8 tx_vht_nss;
s8 avg_signal; /* dBm */
s8 avg_beacon_signal; /* dBm */
s8 avg_ack_signal; /* dBm */
}; };
struct hostapd_sta_add_params { struct hostapd_sta_add_params {
@ -2422,11 +2439,8 @@ enum smps_mode {
* @frequency: control frequency * @frequency: control frequency
* @above_threshold: true if the above threshold was crossed * @above_threshold: true if the above threshold was crossed
* (relevant for a CQM event) * (relevant for a CQM event)
* @current_signal: in dBm * @data: STA information
* @avg_signal: in dBm
* @avg_beacon_signal: in dBm
* @current_noise: %WPA_INVALID_NOISE if not supported * @current_noise: %WPA_INVALID_NOISE if not supported
* @current_txrate: current TX rate
* @chanwidth: channel width * @chanwidth: channel width
* @center_frq1: center frequency for the first segment * @center_frq1: center frequency for the first segment
* @center_frq2: center frequency for the second segment (if relevant) * @center_frq2: center frequency for the second segment (if relevant)
@ -2434,11 +2448,8 @@ enum smps_mode {
struct wpa_signal_info { struct wpa_signal_info {
u32 frequency; u32 frequency;
int above_threshold; int above_threshold;
int current_signal; struct hostap_sta_driver_data data;
int avg_signal;
int avg_beacon_signal;
int current_noise; int current_noise;
int current_txrate;
enum chan_width chanwidth; enum chan_width chanwidth;
int center_frq1; int center_frq1;
int center_frq2; int center_frq2;

View file

@ -1638,86 +1638,6 @@ try_again:
} }
static int get_link_signal(struct nl_msg *msg, void *arg)
{
struct nlattr *tb[NL80211_ATTR_MAX + 1];
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
static struct nla_policy policy[NL80211_STA_INFO_MAX + 1] = {
[NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
[NL80211_STA_INFO_SIGNAL_AVG] = { .type = NLA_U8 },
[NL80211_STA_INFO_BEACON_SIGNAL_AVG] = { .type = NLA_U8 },
};
struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
[NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
[NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
[NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
[NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
};
struct wpa_signal_info *sig_change = arg;
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
genlmsg_attrlen(gnlh, 0), NULL);
if (!tb[NL80211_ATTR_STA_INFO] ||
nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
tb[NL80211_ATTR_STA_INFO], policy))
return NL_SKIP;
if (!sinfo[NL80211_STA_INFO_SIGNAL])
return NL_SKIP;
sig_change->current_signal =
(s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
if (sinfo[NL80211_STA_INFO_SIGNAL_AVG])
sig_change->avg_signal =
(s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
else
sig_change->avg_signal = 0;
if (sinfo[NL80211_STA_INFO_BEACON_SIGNAL_AVG])
sig_change->avg_beacon_signal =
(s8)
nla_get_u8(sinfo[NL80211_STA_INFO_BEACON_SIGNAL_AVG]);
else
sig_change->avg_beacon_signal = 0;
if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
sinfo[NL80211_STA_INFO_TX_BITRATE],
rate_policy)) {
sig_change->current_txrate = 0;
} else {
if (rinfo[NL80211_RATE_INFO_BITRATE]) {
sig_change->current_txrate =
nla_get_u16(rinfo[
NL80211_RATE_INFO_BITRATE]) * 100;
}
}
}
return NL_SKIP;
}
int nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv,
const u8 *bssid, struct wpa_signal_info *sig)
{
struct nl_msg *msg;
sig->current_signal = -WPA_INVALID_NOISE;
sig->current_txrate = 0;
if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_STATION)) ||
nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid)) {
nlmsg_free(msg);
return -ENOBUFS;
}
return send_and_recv_msgs(drv, msg, get_link_signal, sig, NULL, NULL);
}
static int get_link_noise(struct nl_msg *msg, void *arg) static int get_link_noise(struct nl_msg *msg, void *arg)
{ {
struct nlattr *tb[NL80211_ATTR_MAX + 1]; struct nlattr *tb[NL80211_ATTR_MAX + 1];
@ -7272,16 +7192,26 @@ static int get_sta_handler(struct nl_msg *msg, void *arg)
[NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 }, [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
[NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 }, [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
[NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 }, [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
[NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
[NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 }, [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
[NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 }, [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
[NL80211_STA_INFO_TX_RETRIES] = { .type = NLA_U32 },
[NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 }, [NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },
[NL80211_STA_INFO_SIGNAL_AVG] = { .type = NLA_U8 },
[NL80211_STA_INFO_CONNECTED_TIME] = { .type = NLA_U32 },
[NL80211_STA_INFO_BEACON_LOSS] = { .type = NLA_U32 },
[NL80211_STA_INFO_RX_BYTES64] = { .type = NLA_U64 }, [NL80211_STA_INFO_RX_BYTES64] = { .type = NLA_U64 },
[NL80211_STA_INFO_TX_BYTES64] = { .type = NLA_U64 }, [NL80211_STA_INFO_TX_BYTES64] = { .type = NLA_U64 },
[NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 }, [NL80211_STA_INFO_EXPECTED_THROUGHPUT] = { .type = NLA_U32 },
[NL80211_STA_INFO_ACK_SIGNAL] = { .type = NLA_U8 }, [NL80211_STA_INFO_RX_DROP_MISC] = { .type = NLA_U64 },
[NL80211_STA_INFO_BEACON_RX] = { .type = NLA_U64 },
[NL80211_STA_INFO_BEACON_SIGNAL_AVG] = { .type = NLA_U8},
[NL80211_STA_INFO_RX_DURATION] = { .type = NLA_U64 }, [NL80211_STA_INFO_RX_DURATION] = { .type = NLA_U64 },
[NL80211_STA_INFO_ACK_SIGNAL] = { .type = NLA_U8 },
[NL80211_STA_INFO_ACK_SIGNAL_AVG] = { .type = NLA_S8 },
[NL80211_STA_INFO_RX_MPDUS] = { .type = NLA_U32 },
[NL80211_STA_INFO_FCS_ERROR_COUNT] = { .type = NLA_U32 },
[NL80211_STA_INFO_TX_DURATION] = { .type = NLA_U64 }, [NL80211_STA_INFO_TX_DURATION] = { .type = NLA_U64 },
[NL80211_STA_INFO_CONNECTED_TIME] = { .type = NLA_U32 },
}; };
struct nlattr *rate[NL80211_RATE_INFO_MAX + 1]; struct nlattr *rate[NL80211_RATE_INFO_MAX + 1];
static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = { static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
@ -7291,6 +7221,8 @@ static int get_sta_handler(struct nl_msg *msg, void *arg)
[NL80211_RATE_INFO_VHT_MCS] = { .type = NLA_U8 }, [NL80211_RATE_INFO_VHT_MCS] = { .type = NLA_U8 },
[NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG }, [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
[NL80211_RATE_INFO_VHT_NSS] = { .type = NLA_U8 }, [NL80211_RATE_INFO_VHT_NSS] = { .type = NLA_U8 },
[NL80211_RATE_INFO_HE_MCS] = { .type = NLA_U8 },
[NL80211_RATE_INFO_HE_NSS] = { .type = NLA_U8 },
}; };
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
@ -7333,34 +7265,62 @@ static int get_sta_handler(struct nl_msg *msg, void *arg)
nla_get_u64(stats[NL80211_STA_INFO_TX_BYTES64]); nla_get_u64(stats[NL80211_STA_INFO_TX_BYTES64]);
data->bytes_64bit = 1; data->bytes_64bit = 1;
} }
if (stats[NL80211_STA_INFO_SIGNAL])
data->signal = (s8) nla_get_u8(stats[NL80211_STA_INFO_SIGNAL]);
if (stats[NL80211_STA_INFO_RX_PACKETS]) if (stats[NL80211_STA_INFO_RX_PACKETS])
data->rx_packets = data->rx_packets =
nla_get_u32(stats[NL80211_STA_INFO_RX_PACKETS]); nla_get_u32(stats[NL80211_STA_INFO_RX_PACKETS]);
if (stats[NL80211_STA_INFO_TX_PACKETS]) if (stats[NL80211_STA_INFO_TX_PACKETS])
data->tx_packets = data->tx_packets =
nla_get_u32(stats[NL80211_STA_INFO_TX_PACKETS]); nla_get_u32(stats[NL80211_STA_INFO_TX_PACKETS]);
if (stats[NL80211_STA_INFO_RX_DURATION]) if (stats[NL80211_STA_INFO_TX_RETRIES])
data->rx_airtime = data->tx_retry_count =
nla_get_u64(stats[NL80211_STA_INFO_RX_DURATION]); nla_get_u32(stats[NL80211_STA_INFO_TX_FAILED]);
if (stats[NL80211_STA_INFO_TX_DURATION])
data->tx_airtime =
nla_get_u64(stats[NL80211_STA_INFO_TX_DURATION]);
if (stats[NL80211_STA_INFO_TX_FAILED]) if (stats[NL80211_STA_INFO_TX_FAILED])
data->tx_retry_failed = data->tx_retry_failed =
nla_get_u32(stats[NL80211_STA_INFO_TX_FAILED]); nla_get_u32(stats[NL80211_STA_INFO_TX_FAILED]);
if (stats[NL80211_STA_INFO_SIGNAL]) if (stats[NL80211_STA_INFO_SIGNAL_AVG])
data->signal = nla_get_u8(stats[NL80211_STA_INFO_SIGNAL]); data->avg_signal =
if (stats[NL80211_STA_INFO_ACK_SIGNAL]) { (s8) nla_get_u8(stats[NL80211_STA_INFO_SIGNAL_AVG]);
data->last_ack_rssi =
nla_get_u8(stats[NL80211_STA_INFO_ACK_SIGNAL]);
data->flags |= STA_DRV_DATA_LAST_ACK_RSSI;
}
if (stats[NL80211_STA_INFO_CONNECTED_TIME]) { if (stats[NL80211_STA_INFO_CONNECTED_TIME]) {
data->connected_sec = data->connected_sec =
nla_get_u32(stats[NL80211_STA_INFO_CONNECTED_TIME]); nla_get_u32(stats[NL80211_STA_INFO_CONNECTED_TIME]);
data->flags |= STA_DRV_DATA_CONN_TIME; data->flags |= STA_DRV_DATA_CONN_TIME;
} }
if (stats[NL80211_STA_INFO_BEACON_LOSS])
data->beacon_loss_count =
nla_get_u32(stats[NL80211_STA_INFO_BEACON_LOSS]);
if (stats[NL80211_STA_INFO_EXPECTED_THROUGHPUT])
data->expected_throughput =
nla_get_u32(stats[NL80211_STA_INFO_EXPECTED_THROUGHPUT]);
if (stats[NL80211_STA_INFO_RX_DROP_MISC])
data->rx_drop_misc =
nla_get_u64(stats[NL80211_STA_INFO_RX_DROP_MISC]);
if (stats[NL80211_STA_INFO_BEACON_RX])
data->beacons_count =
nla_get_u64(stats[NL80211_STA_INFO_BEACON_RX]);
if (stats[NL80211_STA_INFO_BEACON_SIGNAL_AVG])
data->avg_beacon_signal =
(s8) nla_get_u8(stats[NL80211_STA_INFO_BEACON_SIGNAL_AVG]);
if (stats[NL80211_STA_INFO_RX_DURATION])
data->rx_airtime =
nla_get_u64(stats[NL80211_STA_INFO_RX_DURATION]);
if (stats[NL80211_STA_INFO_ACK_SIGNAL]) {
data->last_ack_rssi =
nla_get_u8(stats[NL80211_STA_INFO_ACK_SIGNAL]);
data->flags |= STA_DRV_DATA_LAST_ACK_RSSI;
}
if (stats[NL80211_STA_INFO_ACK_SIGNAL_AVG])
data->avg_ack_signal =
nla_get_s8(stats[NL80211_STA_INFO_ACK_SIGNAL_AVG]);
if (stats[NL80211_STA_INFO_RX_MPDUS])
data->rx_mpdus = nla_get_u32(stats[NL80211_STA_INFO_RX_MPDUS]);
if (stats[NL80211_STA_INFO_FCS_ERROR_COUNT])
data->fcs_error_count =
nla_get_u32(stats[NL80211_STA_INFO_FCS_ERROR_COUNT]);
if (stats[NL80211_STA_INFO_TX_DURATION])
data->tx_airtime =
nla_get_u64(stats[NL80211_STA_INFO_TX_DURATION]);
if (stats[NL80211_STA_INFO_TX_BITRATE] && if (stats[NL80211_STA_INFO_TX_BITRATE] &&
nla_parse_nested(rate, NL80211_RATE_INFO_MAX, nla_parse_nested(rate, NL80211_RATE_INFO_MAX,
@ -7373,6 +7333,10 @@ static int get_sta_handler(struct nl_msg *msg, void *arg)
data->current_tx_rate = data->current_tx_rate =
nla_get_u16(rate[NL80211_RATE_INFO_BITRATE]); nla_get_u16(rate[NL80211_RATE_INFO_BITRATE]);
/* Convert from 100 kbps to kbps; it's a more convenient unit.
* It's also safe up until ~1Tbps. */
data->current_tx_rate = data->current_tx_rate * 100;
if (rate[NL80211_RATE_INFO_MCS]) { if (rate[NL80211_RATE_INFO_MCS]) {
data->tx_mcs = nla_get_u8(rate[NL80211_RATE_INFO_MCS]); data->tx_mcs = nla_get_u8(rate[NL80211_RATE_INFO_MCS]);
data->flags |= STA_DRV_DATA_TX_MCS; data->flags |= STA_DRV_DATA_TX_MCS;
@ -7389,6 +7353,16 @@ static int get_sta_handler(struct nl_msg *msg, void *arg)
nla_get_u8(rate[NL80211_RATE_INFO_VHT_NSS]); nla_get_u8(rate[NL80211_RATE_INFO_VHT_NSS]);
data->flags |= STA_DRV_DATA_TX_VHT_NSS; data->flags |= STA_DRV_DATA_TX_VHT_NSS;
} }
if (rate[NL80211_RATE_INFO_HE_MCS]) {
data->tx_hemcs =
nla_get_u8(rate[NL80211_RATE_INFO_HE_MCS]);
data->flags |= STA_DRV_DATA_TX_HE_MCS;
}
if (rate[NL80211_RATE_INFO_HE_NSS]) {
data->tx_he_nss =
nla_get_u8(rate[NL80211_RATE_INFO_HE_NSS]);
data->flags |= STA_DRV_DATA_TX_HE_NSS;
}
} }
if (stats[NL80211_STA_INFO_RX_BITRATE] && if (stats[NL80211_STA_INFO_RX_BITRATE] &&
@ -7402,9 +7376,12 @@ static int get_sta_handler(struct nl_msg *msg, void *arg)
data->current_rx_rate = data->current_rx_rate =
nla_get_u16(rate[NL80211_RATE_INFO_BITRATE]); nla_get_u16(rate[NL80211_RATE_INFO_BITRATE]);
/* Convert from 100 kbps to kbps; it's a more convenient unit.
* It's also safe up until ~1Tbps. */
data->current_rx_rate = data->current_rx_rate * 100;
if (rate[NL80211_RATE_INFO_MCS]) { if (rate[NL80211_RATE_INFO_MCS]) {
data->rx_mcs = data->rx_mcs = nla_get_u8(rate[NL80211_RATE_INFO_MCS]);
nla_get_u8(rate[NL80211_RATE_INFO_MCS]);
data->flags |= STA_DRV_DATA_RX_MCS; data->flags |= STA_DRV_DATA_RX_MCS;
} }
if (rate[NL80211_RATE_INFO_VHT_MCS]) { if (rate[NL80211_RATE_INFO_VHT_MCS]) {
@ -7419,6 +7396,16 @@ static int get_sta_handler(struct nl_msg *msg, void *arg)
nla_get_u8(rate[NL80211_RATE_INFO_VHT_NSS]); nla_get_u8(rate[NL80211_RATE_INFO_VHT_NSS]);
data->flags |= STA_DRV_DATA_RX_VHT_NSS; data->flags |= STA_DRV_DATA_RX_VHT_NSS;
} }
if (rate[NL80211_RATE_INFO_HE_MCS]) {
data->rx_hemcs =
nla_get_u8(rate[NL80211_RATE_INFO_HE_MCS]);
data->flags |= STA_DRV_DATA_RX_HE_MCS;
}
if (rate[NL80211_RATE_INFO_HE_NSS]) {
data->rx_he_nss =
nla_get_u8(rate[NL80211_RATE_INFO_HE_NSS]);
data->flags |= STA_DRV_DATA_RX_HE_NSS;
}
} }
if (stats[NL80211_STA_INFO_TID_STATS]) if (stats[NL80211_STA_INFO_TID_STATS])
@ -7427,6 +7414,26 @@ static int get_sta_handler(struct nl_msg *msg, void *arg)
return NL_SKIP; return NL_SKIP;
} }
int nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv,
const u8 *bssid,
struct hostap_sta_driver_data *data)
{
struct nl_msg *msg;
data->signal = -WPA_INVALID_NOISE;
data->current_tx_rate = 0;
if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_STATION)) ||
nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid)) {
nlmsg_free(msg);
return -ENOBUFS;
}
return send_and_recv_msgs(drv, msg, get_sta_handler, data, NULL, NULL);
}
static int i802_read_sta_data(struct i802_bss *bss, static int i802_read_sta_data(struct i802_bss *bss,
struct hostap_sta_driver_data *data, struct hostap_sta_driver_data *data,
const u8 *addr) const u8 *addr)
@ -8841,12 +8848,12 @@ static int nl80211_signal_poll(void *priv, struct wpa_signal_info *si)
int res; int res;
os_memset(si, 0, sizeof(*si)); os_memset(si, 0, sizeof(*si));
res = nl80211_get_link_signal(drv, drv->bssid, si); res = nl80211_get_link_signal(drv, drv->bssid, &si->data);
if (res) { if (res) {
if (drv->nlmode != NL80211_IFTYPE_ADHOC && if (drv->nlmode != NL80211_IFTYPE_ADHOC &&
drv->nlmode != NL80211_IFTYPE_MESH_POINT) drv->nlmode != NL80211_IFTYPE_MESH_POINT)
return res; return res;
si->current_signal = 0; si->data.signal = 0;
} }
res = nl80211_get_channel_width(drv, si); res = nl80211_get_channel_width(drv, si);
@ -8995,7 +9002,7 @@ static int nl80211_mlo_signal_poll(void *priv,
res = nl80211_get_link_signal(drv, res = nl80211_get_link_signal(drv,
drv->sta_mlo_info.links[i].bssid, drv->sta_mlo_info.links[i].bssid,
&mlo_si->links[i]); &mlo_si->links[i].data);
if (res != 0) if (res != 0)
return res; return res;

View file

@ -269,7 +269,8 @@ int is_ap_interface(enum nl80211_iftype nlmode);
int is_sta_interface(enum nl80211_iftype nlmode); int is_sta_interface(enum nl80211_iftype nlmode);
int wpa_driver_nl80211_authenticate_retry(struct wpa_driver_nl80211_data *drv); int wpa_driver_nl80211_authenticate_retry(struct wpa_driver_nl80211_data *drv);
int nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv, int nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv,
const u8 *bssid, struct wpa_signal_info *sig); const u8 *bssid,
struct hostap_sta_driver_data *data);
int nl80211_get_link_noise(struct wpa_driver_nl80211_data *drv, int nl80211_get_link_noise(struct wpa_driver_nl80211_data *drv,
struct wpa_signal_info *sig_change); struct wpa_signal_info *sig_change);
int nl80211_get_wiphy_index(struct i802_bss *bss); int nl80211_get_wiphy_index(struct i802_bss *bss);

View file

@ -1834,11 +1834,11 @@ static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv,
* nl80211_get_link_signal() and nl80211_get_link_noise() set default * nl80211_get_link_signal() and nl80211_get_link_noise() set default
* values in case querying the driver fails. * values in case querying the driver fails.
*/ */
res = nl80211_get_link_signal(drv, drv->bssid, &ed.signal_change); res = nl80211_get_link_signal(drv, drv->bssid, &ed.signal_change.data);
if (res == 0) { if (res == 0) {
wpa_printf(MSG_DEBUG, "nl80211: Signal: %d dBm txrate: %d", wpa_printf(MSG_DEBUG, "nl80211: Signal: %d dBm txrate: %lu",
ed.signal_change.current_signal, ed.signal_change.data.signal,
ed.signal_change.current_txrate); ed.signal_change.data.current_tx_rate);
} else { } else {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"nl80211: Querying the driver for signal info failed"); "nl80211: Querying the driver for signal info failed");

View file

@ -2424,7 +2424,7 @@ static int wpa_driver_wext_signal_poll(void *priv, struct wpa_signal_info *si)
struct iwreq iwr; struct iwreq iwr;
os_memset(si, 0, sizeof(*si)); os_memset(si, 0, sizeof(*si));
si->current_signal = -WPA_INVALID_NOISE; si->data.signal = -WPA_INVALID_NOISE;
si->current_noise = WPA_INVALID_NOISE; si->current_noise = WPA_INVALID_NOISE;
si->chanwidth = CHAN_WIDTH_UNKNOWN; si->chanwidth = CHAN_WIDTH_UNKNOWN;
@ -2440,7 +2440,7 @@ static int wpa_driver_wext_signal_poll(void *priv, struct wpa_signal_info *si)
return -1; return -1;
} }
si->current_signal = stats.qual.level - si->data.signal = stats.qual.level -
((stats.qual.updated & IW_QUAL_DBM) ? 0x100 : 0); ((stats.qual.updated & IW_QUAL_DBM) ? 0x100 : 0);
si->current_noise = stats.qual.noise - si->current_noise = stats.qual.noise -
((stats.qual.updated & IW_QUAL_DBM) ? 0x100 : 0); ((stats.qual.updated & IW_QUAL_DBM) ? 0x100 : 0);

View file

@ -422,7 +422,7 @@ static void * bgscan_learn_init(struct wpa_supplicant *wpa_s,
/* Poll for signal info to set initial scan interval */ /* Poll for signal info to set initial scan interval */
struct wpa_signal_info siginfo; struct wpa_signal_info siginfo;
if (wpa_drv_signal_poll(wpa_s, &siginfo) == 0 && if (wpa_drv_signal_poll(wpa_s, &siginfo) == 0 &&
siginfo.current_signal >= data->signal_threshold) siginfo.data.signal >= data->signal_threshold)
data->scan_interval = data->long_interval; data->scan_interval = data->long_interval;
} }

View file

@ -137,7 +137,7 @@ static void * bgscan_simple_init(struct wpa_supplicant *wpa_s,
/* Poll for signal info to set initial scan interval */ /* Poll for signal info to set initial scan interval */
struct wpa_signal_info siginfo; struct wpa_signal_info siginfo;
if (wpa_drv_signal_poll(wpa_s, &siginfo) == 0 && if (wpa_drv_signal_poll(wpa_s, &siginfo) == 0 &&
siginfo.current_signal >= data->signal_threshold) siginfo.data.signal >= data->signal_threshold)
data->scan_interval = data->long_interval; data->scan_interval = data->long_interval;
} }
wpa_printf(MSG_DEBUG, "bgscan simple: Init scan interval: %d", wpa_printf(MSG_DEBUG, "bgscan simple: Init scan interval: %d",

View file

@ -8101,9 +8101,9 @@ static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
pos = buf; pos = buf;
end = buf + buflen; end = buf + buflen;
ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%d\n" ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%lu\n"
"NOISE=%d\nFREQUENCY=%u\n", "NOISE=%d\nFREQUENCY=%u\n",
si.current_signal, si.current_txrate / 1000, si.data.signal, si.data.current_tx_rate / 1000,
si.current_noise, si.frequency); si.current_noise, si.frequency);
if (os_snprintf_error(end - pos, ret)) if (os_snprintf_error(end - pos, ret))
return -1; return -1;
@ -8133,17 +8133,18 @@ static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
pos += ret; pos += ret;
} }
if (si.avg_signal) { if (si.data.avg_signal) {
ret = os_snprintf(pos, end - pos, ret = os_snprintf(pos, end - pos,
"AVG_RSSI=%d\n", si.avg_signal); "AVG_RSSI=%d\n", si.data.avg_signal);
if (os_snprintf_error(end - pos, ret)) if (os_snprintf_error(end - pos, ret))
return -1; return -1;
pos += ret; pos += ret;
} }
if (si.avg_beacon_signal) { if (si.data.avg_beacon_signal) {
ret = os_snprintf(pos, end - pos, ret = os_snprintf(pos, end - pos,
"AVG_BEACON_RSSI=%d\n", si.avg_beacon_signal); "AVG_BEACON_RSSI=%d\n",
si.data.avg_beacon_signal);
if (os_snprintf_error(end - pos, ret)) if (os_snprintf_error(end - pos, ret))
return -1; return -1;
pos += ret; pos += ret;
@ -11565,10 +11566,10 @@ static int wpas_ctrl_iface_mlo_signal_poll(struct wpa_supplicant *wpa_s,
continue; continue;
ret = os_snprintf(pos, end - pos, ret = os_snprintf(pos, end - pos,
"LINK_ID=%d\nRSSI=%d\nLINKSPEED=%d\n" "LINK_ID=%d\nRSSI=%d\nLINKSPEED=%lu\n"
"NOISE=%d\nFREQUENCY=%u\n", "NOISE=%d\nFREQUENCY=%u\n",
i, mlo_si.links[i].current_signal, i, mlo_si.links[i].data.signal,
mlo_si.links[i].current_txrate / 1000, mlo_si.links[i].data.current_tx_rate / 1000,
mlo_si.links[i].current_noise, mlo_si.links[i].current_noise,
mlo_si.links[i].frequency); mlo_si.links[i].frequency);
if (os_snprintf_error(end - pos, ret)) if (os_snprintf_error(end - pos, ret))
@ -11600,19 +11601,19 @@ static int wpas_ctrl_iface_mlo_signal_poll(struct wpa_supplicant *wpa_s,
pos += ret; pos += ret;
} }
if (mlo_si.links[i].avg_signal) { if (mlo_si.links[i].data.avg_signal) {
ret = os_snprintf(pos, end - pos, ret = os_snprintf(pos, end - pos,
"AVG_RSSI=%d\n", "AVG_RSSI=%d\n",
mlo_si.links[i].avg_signal); mlo_si.links[i].data.avg_signal);
if (os_snprintf_error(end - pos, ret)) if (os_snprintf_error(end - pos, ret))
return -1; return -1;
pos += ret; pos += ret;
} }
if (mlo_si.links[i].avg_beacon_signal) { if (mlo_si.links[i].data.avg_beacon_signal) {
ret = os_snprintf(pos, end - pos, ret = os_snprintf(
"AVG_BEACON_RSSI=%d\n", pos, end - pos, "AVG_BEACON_RSSI=%d\n",
mlo_si.links[i].avg_beacon_signal); mlo_si.links[i].data.avg_beacon_signal);
if (os_snprintf_error(end - pos, ret)) if (os_snprintf_error(end - pos, ret))
return -1; return -1;
pos += ret; pos += ret;

View file

@ -1969,9 +1969,9 @@ DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message,
"a{sv}", &variant_iter) || "a{sv}", &variant_iter) ||
!wpa_dbus_dict_open_write(&variant_iter, &iter_dict) || !wpa_dbus_dict_open_write(&variant_iter, &iter_dict) ||
!wpa_dbus_dict_append_int32(&iter_dict, "rssi", !wpa_dbus_dict_append_int32(&iter_dict, "rssi",
si.current_signal) || si.data.signal) ||
!wpa_dbus_dict_append_int32(&iter_dict, "linkspeed", !wpa_dbus_dict_append_int32(&iter_dict, "linkspeed",
si.current_txrate / 1000) || si.data.current_tx_rate / 1000) ||
!wpa_dbus_dict_append_int32(&iter_dict, "noise", !wpa_dbus_dict_append_int32(&iter_dict, "noise",
si.current_noise) || si.current_noise) ||
!wpa_dbus_dict_append_uint32(&iter_dict, "frequency", !wpa_dbus_dict_append_uint32(&iter_dict, "frequency",
@ -1985,9 +1985,9 @@ DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message,
si.center_frq1) || si.center_frq1) ||
!wpa_dbus_dict_append_int32(&iter_dict, "center-frq2", !wpa_dbus_dict_append_int32(&iter_dict, "center-frq2",
si.center_frq2))) || si.center_frq2))) ||
(si.avg_signal && (si.data.avg_signal &&
!wpa_dbus_dict_append_int32(&iter_dict, "avg-rssi", !wpa_dbus_dict_append_int32(&iter_dict, "avg-rssi",
si.avg_signal)) || si.data.avg_signal)) ||
!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) || !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
!dbus_message_iter_close_container(&iter, &variant_iter)) !dbus_message_iter_close_container(&iter, &variant_iter))
goto nomem; goto nomem;

View file

@ -2004,9 +2004,9 @@ int wpa_supplicant_need_to_roam_within_ess(struct wpa_supplicant *wpa_s,
* information about our currently associated AP. * information about our currently associated AP.
*/ */
if (wpa_drv_signal_poll(wpa_s, &si) == 0 && if (wpa_drv_signal_poll(wpa_s, &si) == 0 &&
(si.avg_beacon_signal || si.avg_signal)) { (si.data.avg_beacon_signal || si.data.avg_signal)) {
cur_level = si.avg_beacon_signal ? si.avg_beacon_signal : cur_level = si.data.avg_beacon_signal ?
si.avg_signal; si.data.avg_beacon_signal : si.data.avg_signal;
cur_snr = wpas_get_snr_signal_info(si.frequency, cur_level, cur_snr = wpas_get_snr_signal_info(si.frequency, cur_level,
si.current_noise); si.current_noise);
@ -5769,18 +5769,18 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break; break;
case EVENT_SIGNAL_CHANGE: case EVENT_SIGNAL_CHANGE:
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SIGNAL_CHANGE wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SIGNAL_CHANGE
"above=%d signal=%d noise=%d txrate=%d", "above=%d signal=%d noise=%d txrate=%lu",
data->signal_change.above_threshold, data->signal_change.above_threshold,
data->signal_change.current_signal, data->signal_change.data.signal,
data->signal_change.current_noise, data->signal_change.current_noise,
data->signal_change.current_txrate); data->signal_change.data.current_tx_rate);
wpa_bss_update_level(wpa_s->current_bss, wpa_bss_update_level(wpa_s->current_bss,
data->signal_change.current_signal); data->signal_change.data.signal);
bgscan_notify_signal_change( bgscan_notify_signal_change(
wpa_s, data->signal_change.above_threshold, wpa_s, data->signal_change.above_threshold,
data->signal_change.current_signal, data->signal_change.data.signal,
data->signal_change.current_noise, data->signal_change.current_noise,
data->signal_change.current_txrate); data->signal_change.data.current_tx_rate);
break; break;
case EVENT_INTERFACE_MAC_CHANGED: case EVENT_INTERFACE_MAC_CHANGED:
wpa_supplicant_update_mac_addr(wpa_s); wpa_supplicant_update_mac_addr(wpa_s);

View file

@ -8964,17 +8964,17 @@ int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
continue; continue;
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d", "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
si->current_signal, si->data.signal,
dso->si_current_signal, dso->si_current_signal,
si->avg_signal, si->data.avg_signal,
dso->si_avg_signal, dso->si_avg_signal,
si->avg_beacon_signal, si->data.avg_beacon_signal,
dso->si_avg_beacon_signal, dso->si_avg_beacon_signal,
si->current_noise, si->current_noise,
dso->si_current_noise); dso->si_current_noise);
si->current_signal = dso->si_current_signal; si->data.signal = dso->si_current_signal;
si->avg_signal = dso->si_avg_signal; si->data.avg_signal = dso->si_avg_signal;
si->avg_beacon_signal = dso->si_avg_beacon_signal; si->data.avg_beacon_signal = dso->si_avg_beacon_signal;
si->current_noise = dso->si_current_noise; si->current_noise = dso->si_current_noise;
break; break;
} }