Commit 541a45a1 authored by Bruno Randolf's avatar Bruno Randolf Committed by John W. Linville

nl80211/mac80211: Report signal average

Extend nl80211 to report an exponential weighted moving average (EWMA) of the
signal value. Since the signal value usually fluctuates between different
packets, an average can be more useful than the value of the last packet.

This uses the recently added generic EWMA library function.

--
v2:	fix ABI breakage and change factor to be a power of 2.
Signed-off-by: default avatarBruno Randolf <br1@einfach.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 22de94de
...@@ -1191,6 +1191,7 @@ enum nl80211_rate_info { ...@@ -1191,6 +1191,7 @@ enum nl80211_rate_info {
* station) * station)
* @NL80211_STA_INFO_TX_RETRIES: total retries (u32, to this station) * @NL80211_STA_INFO_TX_RETRIES: total retries (u32, to this station)
* @NL80211_STA_INFO_TX_FAILED: total failed packets (u32, to this station) * @NL80211_STA_INFO_TX_FAILED: total failed packets (u32, to this station)
* @NL80211_STA_INFO_SIGNAL_AVG: signal strength average (u8, dBm)
*/ */
enum nl80211_sta_info { enum nl80211_sta_info {
__NL80211_STA_INFO_INVALID, __NL80211_STA_INFO_INVALID,
...@@ -1206,6 +1207,7 @@ enum nl80211_sta_info { ...@@ -1206,6 +1207,7 @@ enum nl80211_sta_info {
NL80211_STA_INFO_TX_PACKETS, NL80211_STA_INFO_TX_PACKETS,
NL80211_STA_INFO_TX_RETRIES, NL80211_STA_INFO_TX_RETRIES,
NL80211_STA_INFO_TX_FAILED, NL80211_STA_INFO_TX_FAILED,
NL80211_STA_INFO_SIGNAL_AVG,
/* keep last */ /* keep last */
__NL80211_STA_INFO_AFTER_LAST, __NL80211_STA_INFO_AFTER_LAST,
......
...@@ -420,6 +420,7 @@ struct station_parameters { ...@@ -420,6 +420,7 @@ struct station_parameters {
* @STATION_INFO_TX_RETRIES: @tx_retries filled * @STATION_INFO_TX_RETRIES: @tx_retries filled
* @STATION_INFO_TX_FAILED: @tx_failed filled * @STATION_INFO_TX_FAILED: @tx_failed filled
* @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled * @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled
* @STATION_INFO_SIGNAL_AVG: @signal_avg filled
*/ */
enum station_info_flags { enum station_info_flags {
STATION_INFO_INACTIVE_TIME = 1<<0, STATION_INFO_INACTIVE_TIME = 1<<0,
...@@ -435,6 +436,7 @@ enum station_info_flags { ...@@ -435,6 +436,7 @@ enum station_info_flags {
STATION_INFO_TX_RETRIES = 1<<10, STATION_INFO_TX_RETRIES = 1<<10,
STATION_INFO_TX_FAILED = 1<<11, STATION_INFO_TX_FAILED = 1<<11,
STATION_INFO_RX_DROP_MISC = 1<<12, STATION_INFO_RX_DROP_MISC = 1<<12,
STATION_INFO_SIGNAL_AVG = 1<<13,
}; };
/** /**
...@@ -481,6 +483,7 @@ struct rate_info { ...@@ -481,6 +483,7 @@ struct rate_info {
* @plid: mesh peer link id * @plid: mesh peer link id
* @plink_state: mesh peer link state * @plink_state: mesh peer link state
* @signal: signal strength of last received packet in dBm * @signal: signal strength of last received packet in dBm
* @signal_avg: signal strength average in dBm
* @txrate: current unicast bitrate to this station * @txrate: current unicast bitrate to this station
* @rx_packets: packets received from this station * @rx_packets: packets received from this station
* @tx_packets: packets transmitted to this station * @tx_packets: packets transmitted to this station
...@@ -501,6 +504,7 @@ struct station_info { ...@@ -501,6 +504,7 @@ struct station_info {
u16 plid; u16 plid;
u8 plink_state; u8 plink_state;
s8 signal; s8 signal;
s8 signal_avg;
struct rate_info txrate; struct rate_info txrate;
u32 rx_packets; u32 rx_packets;
u32 tx_packets; u32 tx_packets;
......
...@@ -6,6 +6,7 @@ config MAC80211 ...@@ -6,6 +6,7 @@ config MAC80211
select CRYPTO_ARC4 select CRYPTO_ARC4
select CRYPTO_AES select CRYPTO_AES
select CRC32 select CRC32
select AVERAGE
---help--- ---help---
This option enables the hardware independent IEEE 802.11 This option enables the hardware independent IEEE 802.11
networking stack. networking stack.
......
...@@ -342,8 +342,9 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) ...@@ -342,8 +342,9 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) ||
(sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) {
sinfo->filled |= STATION_INFO_SIGNAL; sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG;
sinfo->signal = (s8)sta->last_signal; sinfo->signal = (s8)sta->last_signal;
sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
} }
sinfo->txrate.flags = 0; sinfo->txrate.flags = 0;
......
...@@ -1163,6 +1163,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) ...@@ -1163,6 +1163,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
sta->rx_fragments++; sta->rx_fragments++;
sta->rx_bytes += rx->skb->len; sta->rx_bytes += rx->skb->len;
sta->last_signal = status->signal; sta->last_signal = status->signal;
ewma_add(&sta->avg_signal, -status->signal);
/* /*
* Change STA power saving mode only at the end of a frame * Change STA power saving mode only at the end of a frame
......
...@@ -244,6 +244,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, ...@@ -244,6 +244,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
sta->local = local; sta->local = local;
sta->sdata = sdata; sta->sdata = sdata;
ewma_init(&sta->avg_signal, 1024, 8);
if (sta_prepare_rate_control(local, sta, gfp)) { if (sta_prepare_rate_control(local, sta, gfp)) {
kfree(sta); kfree(sta);
return NULL; return NULL;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/average.h>
#include "key.h" #include "key.h"
/** /**
...@@ -223,6 +224,7 @@ enum plink_state { ...@@ -223,6 +224,7 @@ enum plink_state {
* @rx_fragments: number of received MPDUs * @rx_fragments: number of received MPDUs
* @rx_dropped: number of dropped MPDUs from this STA * @rx_dropped: number of dropped MPDUs from this STA
* @last_signal: signal of last received frame from this STA * @last_signal: signal of last received frame from this STA
* @avg_signal: moving average of signal of received frames from this STA
* @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue)
* @tx_filtered_count: number of frames the hardware filtered for this STA * @tx_filtered_count: number of frames the hardware filtered for this STA
* @tx_retry_failed: number of frames that failed retry * @tx_retry_failed: number of frames that failed retry
...@@ -291,6 +293,7 @@ struct sta_info { ...@@ -291,6 +293,7 @@ struct sta_info {
unsigned long rx_fragments; unsigned long rx_fragments;
unsigned long rx_dropped; unsigned long rx_dropped;
int last_signal; int last_signal;
struct ewma avg_signal;
__le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
/* Updated from TX status path only, no locking requirements */ /* Updated from TX status path only, no locking requirements */
......
...@@ -1896,6 +1896,9 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, ...@@ -1896,6 +1896,9 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
if (sinfo->filled & STATION_INFO_SIGNAL) if (sinfo->filled & STATION_INFO_SIGNAL)
NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL, NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
sinfo->signal); sinfo->signal);
if (sinfo->filled & STATION_INFO_SIGNAL_AVG)
NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG,
sinfo->signal_avg);
if (sinfo->filled & STATION_INFO_TX_BITRATE) { if (sinfo->filled & STATION_INFO_TX_BITRATE) {
txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE); txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
if (!txrate) if (!txrate)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment