Add TX/RX rate info and signal strength into STA output
These allow external programs to fetch the TX and RX rate information and signal strength for a specific STA through the hostapd control interface command "STA <addr>". The values of these attributes are filled in the response of nl80211 command NL80211_CMD_GET_STATION. Signed-off-by: bhagavathi perumal s <bperumal@qti.qualcomm.com>
This commit is contained in:
parent
fa4b605a0d
commit
3567641ebb
3 changed files with 161 additions and 4 deletions
|
@ -32,17 +32,86 @@ static int hostapd_get_sta_tx_rx(struct hostapd_data *hapd,
|
|||
{
|
||||
struct hostap_sta_driver_data data;
|
||||
int ret;
|
||||
int len = 0;
|
||||
|
||||
if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
|
||||
return 0;
|
||||
|
||||
ret = os_snprintf(buf, buflen, "rx_packets=%lu\ntx_packets=%lu\n"
|
||||
"rx_bytes=%llu\ntx_bytes=%llu\ninactive_msec=%lu\n",
|
||||
"rx_bytes=%llu\ntx_bytes=%llu\ninactive_msec=%lu\n"
|
||||
"signal=%d\n",
|
||||
data.rx_packets, data.tx_packets,
|
||||
data.rx_bytes, data.tx_bytes, data.inactive_msec);
|
||||
data.rx_bytes, data.tx_bytes, data.inactive_msec,
|
||||
data.signal);
|
||||
if (os_snprintf_error(buflen, ret))
|
||||
return 0;
|
||||
return ret;
|
||||
len += ret;
|
||||
|
||||
ret = os_snprintf(buf + len, buflen - len, "rx_rate_info=%lu",
|
||||
data.current_rx_rate);
|
||||
if (os_snprintf_error(buflen - len, ret))
|
||||
return len;
|
||||
len += ret;
|
||||
if (data.flags & STA_DRV_DATA_RX_MCS) {
|
||||
ret = os_snprintf(buf + len, buflen - len, " mcs %u",
|
||||
data.rx_mcs);
|
||||
if (!os_snprintf_error(buflen - len, ret))
|
||||
len += ret;
|
||||
}
|
||||
if (data.flags & STA_DRV_DATA_RX_VHT_MCS) {
|
||||
ret = os_snprintf(buf + len, buflen - len, " vhtmcs %u",
|
||||
data.rx_vhtmcs);
|
||||
if (!os_snprintf_error(buflen - len, ret))
|
||||
len += ret;
|
||||
}
|
||||
if (data.flags & STA_DRV_DATA_RX_VHT_NSS) {
|
||||
ret = os_snprintf(buf + len, buflen - len, " vhtnss %u",
|
||||
data.rx_vht_nss);
|
||||
if (!os_snprintf_error(buflen - len, ret))
|
||||
len += ret;
|
||||
}
|
||||
if (data.flags & STA_DRV_DATA_RX_SHORT_GI) {
|
||||
ret = os_snprintf(buf + len, buflen - len, " shortGI");
|
||||
if (!os_snprintf_error(buflen - len, ret))
|
||||
len += ret;
|
||||
}
|
||||
ret = os_snprintf(buf + len, buflen - len, "\n");
|
||||
if (!os_snprintf_error(buflen - len, ret))
|
||||
len += ret;
|
||||
|
||||
ret = os_snprintf(buf + len, buflen - len, "tx_rate_info=%lu",
|
||||
data.current_tx_rate);
|
||||
if (os_snprintf_error(buflen - len, ret))
|
||||
return len;
|
||||
len += ret;
|
||||
if (data.flags & STA_DRV_DATA_TX_MCS) {
|
||||
ret = os_snprintf(buf + len, buflen - len, " mcs %u",
|
||||
data.tx_mcs);
|
||||
if (!os_snprintf_error(buflen - len, ret))
|
||||
len += ret;
|
||||
}
|
||||
if (data.flags & STA_DRV_DATA_TX_VHT_MCS) {
|
||||
ret = os_snprintf(buf + len, buflen - len, " vhtmcs %u",
|
||||
data.tx_vhtmcs);
|
||||
if (!os_snprintf_error(buflen - len, ret))
|
||||
len += ret;
|
||||
}
|
||||
if (data.flags & STA_DRV_DATA_TX_VHT_NSS) {
|
||||
ret = os_snprintf(buf + len, buflen - len, " vhtnss %u",
|
||||
data.tx_vht_nss);
|
||||
if (!os_snprintf_error(buflen - len, ret))
|
||||
len += ret;
|
||||
}
|
||||
if (data.flags & STA_DRV_DATA_TX_SHORT_GI) {
|
||||
ret = os_snprintf(buf + len, buflen - len, " shortGI");
|
||||
if (!os_snprintf_error(buflen - len, ret))
|
||||
len += ret;
|
||||
}
|
||||
ret = os_snprintf(buf + len, buflen - len, "\n");
|
||||
if (!os_snprintf_error(buflen - len, ret))
|
||||
len += ret;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1684,18 +1684,35 @@ struct wpa_driver_capa {
|
|||
|
||||
struct hostapd_data;
|
||||
|
||||
#define STA_DRV_DATA_TX_MCS BIT(0)
|
||||
#define STA_DRV_DATA_RX_MCS BIT(1)
|
||||
#define STA_DRV_DATA_TX_VHT_MCS BIT(2)
|
||||
#define STA_DRV_DATA_RX_VHT_MCS BIT(3)
|
||||
#define STA_DRV_DATA_TX_VHT_NSS BIT(4)
|
||||
#define STA_DRV_DATA_RX_VHT_NSS BIT(5)
|
||||
#define STA_DRV_DATA_TX_SHORT_GI BIT(6)
|
||||
#define STA_DRV_DATA_RX_SHORT_GI BIT(7)
|
||||
|
||||
struct hostap_sta_driver_data {
|
||||
unsigned long rx_packets, tx_packets;
|
||||
unsigned long long rx_bytes, tx_bytes;
|
||||
int bytes_64bit; /* whether 64-bit byte counters are supported */
|
||||
unsigned long current_tx_rate;
|
||||
unsigned long current_rx_rate;
|
||||
unsigned long inactive_msec;
|
||||
unsigned long flags;
|
||||
unsigned long flags; /* bitfield of STA_DRV_DATA_* */
|
||||
unsigned long num_ps_buf_frames;
|
||||
unsigned long tx_retry_failed;
|
||||
unsigned long tx_retry_count;
|
||||
int last_rssi;
|
||||
int last_ack_rssi;
|
||||
s8 signal;
|
||||
u8 rx_vhtmcs;
|
||||
u8 tx_vhtmcs;
|
||||
u8 rx_mcs;
|
||||
u8 tx_mcs;
|
||||
u8 rx_vht_nss;
|
||||
u8 tx_vht_nss;
|
||||
};
|
||||
|
||||
struct hostapd_sta_add_params {
|
||||
|
|
|
@ -5941,6 +5941,16 @@ static int get_sta_handler(struct nl_msg *msg, void *arg)
|
|||
[NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },
|
||||
[NL80211_STA_INFO_RX_BYTES64] = { .type = NLA_U64 },
|
||||
[NL80211_STA_INFO_TX_BYTES64] = { .type = NLA_U64 },
|
||||
[NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
|
||||
};
|
||||
struct nlattr *rate[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_BITRATE32] = { .type = NLA_U32 },
|
||||
[NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
|
||||
[NL80211_RATE_INFO_VHT_MCS] = { .type = NLA_U8 },
|
||||
[NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
|
||||
[NL80211_RATE_INFO_VHT_NSS] = { .type = NLA_U8 },
|
||||
};
|
||||
|
||||
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
|
||||
|
@ -5992,6 +6002,67 @@ static int get_sta_handler(struct nl_msg *msg, void *arg)
|
|||
if (stats[NL80211_STA_INFO_TX_FAILED])
|
||||
data->tx_retry_failed =
|
||||
nla_get_u32(stats[NL80211_STA_INFO_TX_FAILED]);
|
||||
if (stats[NL80211_STA_INFO_SIGNAL])
|
||||
data->signal = nla_get_u8(stats[NL80211_STA_INFO_SIGNAL]);
|
||||
|
||||
if (stats[NL80211_STA_INFO_TX_BITRATE] &&
|
||||
nla_parse_nested(rate, NL80211_RATE_INFO_MAX,
|
||||
stats[NL80211_STA_INFO_TX_BITRATE],
|
||||
rate_policy) == 0) {
|
||||
if (rate[NL80211_RATE_INFO_BITRATE32])
|
||||
data->current_tx_rate =
|
||||
nla_get_u32(rate[NL80211_RATE_INFO_BITRATE32]);
|
||||
else if (rate[NL80211_RATE_INFO_BITRATE])
|
||||
data->current_tx_rate =
|
||||
nla_get_u16(rate[NL80211_RATE_INFO_BITRATE]);
|
||||
|
||||
if (rate[NL80211_RATE_INFO_MCS]) {
|
||||
data->tx_mcs = nla_get_u8(rate[NL80211_RATE_INFO_MCS]);
|
||||
data->flags |= STA_DRV_DATA_TX_MCS;
|
||||
}
|
||||
if (rate[NL80211_RATE_INFO_VHT_MCS]) {
|
||||
data->tx_vhtmcs =
|
||||
nla_get_u8(rate[NL80211_RATE_INFO_VHT_MCS]);
|
||||
data->flags |= STA_DRV_DATA_TX_VHT_MCS;
|
||||
}
|
||||
if (rate[NL80211_RATE_INFO_SHORT_GI])
|
||||
data->flags |= STA_DRV_DATA_TX_SHORT_GI;
|
||||
if (rate[NL80211_RATE_INFO_VHT_NSS]) {
|
||||
data->tx_vht_nss =
|
||||
nla_get_u8(rate[NL80211_RATE_INFO_VHT_NSS]);
|
||||
data->flags |= STA_DRV_DATA_TX_VHT_NSS;
|
||||
}
|
||||
}
|
||||
|
||||
if (stats[NL80211_STA_INFO_RX_BITRATE] &&
|
||||
nla_parse_nested(rate, NL80211_RATE_INFO_MAX,
|
||||
stats[NL80211_STA_INFO_RX_BITRATE],
|
||||
rate_policy) == 0) {
|
||||
if (rate[NL80211_RATE_INFO_BITRATE32])
|
||||
data->current_rx_rate =
|
||||
nla_get_u32(rate[NL80211_RATE_INFO_BITRATE32]);
|
||||
else if (rate[NL80211_RATE_INFO_BITRATE])
|
||||
data->current_rx_rate =
|
||||
nla_get_u16(rate[NL80211_RATE_INFO_BITRATE]);
|
||||
|
||||
if (rate[NL80211_RATE_INFO_MCS]) {
|
||||
data->rx_mcs =
|
||||
nla_get_u8(rate[NL80211_RATE_INFO_MCS]);
|
||||
data->flags |= STA_DRV_DATA_RX_MCS;
|
||||
}
|
||||
if (rate[NL80211_RATE_INFO_VHT_MCS]) {
|
||||
data->rx_vhtmcs =
|
||||
nla_get_u8(rate[NL80211_RATE_INFO_VHT_MCS]);
|
||||
data->flags |= STA_DRV_DATA_RX_VHT_MCS;
|
||||
}
|
||||
if (rate[NL80211_RATE_INFO_SHORT_GI])
|
||||
data->flags |= STA_DRV_DATA_RX_SHORT_GI;
|
||||
if (rate[NL80211_RATE_INFO_VHT_NSS]) {
|
||||
data->rx_vht_nss =
|
||||
nla_get_u8(rate[NL80211_RATE_INFO_VHT_NSS]);
|
||||
data->flags |= STA_DRV_DATA_RX_VHT_NSS;
|
||||
}
|
||||
}
|
||||
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue