nl80211: fix code calculating average signal and rate

Using average of previous average and the next value is highly
imprecise. E.g. for values 20, 20, 20, 180 it would result in /average/
of 100 (instead of 60). Fix it by storing & using an info of how many
samples were used for the previous calculation.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
This commit is contained in:
Rafał Miłecki 2018-03-28 10:30:07 +02:00
parent 223e09bf3f
commit 77c32f0eb6
2 changed files with 9 additions and 7 deletions

View file

@ -1279,7 +1279,8 @@ static int nl80211_fill_signal_cb(struct nl_msg *msg, void *arg)
if (sinfo[NL80211_STA_INFO_SIGNAL]) if (sinfo[NL80211_STA_INFO_SIGNAL])
{ {
dbm = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]); dbm = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
rr->rssi = rr->rssi ? (int8_t)((rr->rssi + dbm) / 2) : dbm; rr->rssi = (rr->rssi * rr->rssi_samples + dbm) / (rr->rssi_samples + 1);
rr->rssi_samples++;
} }
if (sinfo[NL80211_STA_INFO_TX_BITRATE]) if (sinfo[NL80211_STA_INFO_TX_BITRATE])
@ -1291,8 +1292,8 @@ static int nl80211_fill_signal_cb(struct nl_msg *msg, void *arg)
if (rinfo[NL80211_RATE_INFO_BITRATE]) if (rinfo[NL80211_RATE_INFO_BITRATE])
{ {
mbit = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]); mbit = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
rr->rate = rr->rate rr->rate = (rr->rate * rr->rate_samples + mbit) / (rr->rate_samples + 1);
? (int16_t)((rr->rate + mbit) / 2) : mbit; rr->rate_samples++;
} }
} }
} }
@ -1307,8 +1308,7 @@ static void nl80211_fill_signal(const char *ifname, struct nl80211_rssi_rate *r)
DIR *d; DIR *d;
struct dirent *de; struct dirent *de;
r->rssi = 0; memset(r, 0, sizeof(*r));
r->rate = 0;
if ((d = opendir("/sys/class/net")) != NULL) if ((d = opendir("/sys/class/net")) != NULL)
{ {
@ -1333,7 +1333,7 @@ static int nl80211_get_bitrate(const char *ifname, int *buf)
nl80211_fill_signal(ifname, &rr); nl80211_fill_signal(ifname, &rr);
if (rr.rate) if (rr.rate_samples)
{ {
*buf = (rr.rate * 100); *buf = (rr.rate * 100);
return 0; return 0;
@ -1348,7 +1348,7 @@ static int nl80211_get_signal(const char *ifname, int *buf)
nl80211_fill_signal(ifname, &rr); nl80211_fill_signal(ifname, &rr);
if (rr.rssi) if (rr.rssi_samples)
{ {
*buf = rr.rssi; *buf = rr.rssi;
return 0; return 0;

View file

@ -59,7 +59,9 @@ struct nl80211_group_conveyor {
struct nl80211_rssi_rate { struct nl80211_rssi_rate {
int16_t rate; int16_t rate;
int rate_samples;
int8_t rssi; int8_t rssi;
int rssi_samples;
}; };
struct nl80211_array_buf { struct nl80211_array_buf {