nl80211/mac80211: Report signal average
authorBruno Randolf <br1@einfach.org>
Thu, 2 Dec 2010 10:12:43 +0000 (19:12 +0900)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 7 Dec 2010 21:09:12 +0000 (16:09 -0500)
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: Bruno Randolf <br1@einfach.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
include/linux/nl80211.h
include/net/cfg80211.h
net/mac80211/Kconfig
net/mac80211/cfg.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/wireless/nl80211.c

index 410a06ea551b8520ed8753d1b6a56279bf654e32..8e28053ea4235707427e5d774d9208dc00daed33 100644 (file)
@@ -1191,6 +1191,7 @@ enum nl80211_rate_info {
  *     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_SIGNAL_AVG: signal strength average (u8, dBm)
  */
 enum nl80211_sta_info {
        __NL80211_STA_INFO_INVALID,
@@ -1206,6 +1207,7 @@ enum nl80211_sta_info {
        NL80211_STA_INFO_TX_PACKETS,
        NL80211_STA_INFO_TX_RETRIES,
        NL80211_STA_INFO_TX_FAILED,
+       NL80211_STA_INFO_SIGNAL_AVG,
 
        /* keep last */
        __NL80211_STA_INFO_AFTER_LAST,
index 788c3989a9e8acc4dc66683aa544c05f4b634fa9..8764c9a5bab7ecf4a608784ed6aafe226bf782b4 100644 (file)
@@ -420,6 +420,7 @@ struct station_parameters {
  * @STATION_INFO_TX_RETRIES: @tx_retries filled
  * @STATION_INFO_TX_FAILED: @tx_failed filled
  * @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled
+ * @STATION_INFO_SIGNAL_AVG: @signal_avg filled
  */
 enum station_info_flags {
        STATION_INFO_INACTIVE_TIME      = 1<<0,
@@ -435,6 +436,7 @@ enum station_info_flags {
        STATION_INFO_TX_RETRIES         = 1<<10,
        STATION_INFO_TX_FAILED          = 1<<11,
        STATION_INFO_RX_DROP_MISC       = 1<<12,
+       STATION_INFO_SIGNAL_AVG         = 1<<13,
 };
 
 /**
@@ -481,6 +483,7 @@ struct rate_info {
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
  * @signal: signal strength of last received packet in dBm
+ * @signal_avg: signal strength average in dBm
  * @txrate: current unicast bitrate to this station
  * @rx_packets: packets received from this station
  * @tx_packets: packets transmitted to this station
@@ -501,6 +504,7 @@ struct station_info {
        u16 plid;
        u8 plink_state;
        s8 signal;
+       s8 signal_avg;
        struct rate_info txrate;
        u32 rx_packets;
        u32 tx_packets;
index 4d6f8653ec8819a7e69cdb9cb447b77c1e7e7047..798d9b9462e22e13b7929c8a0a4fe0040d4bc02e 100644 (file)
@@ -6,6 +6,7 @@ config MAC80211
        select CRYPTO_ARC4
        select CRYPTO_AES
        select CRC32
+       select AVERAGE
        ---help---
          This option enables the hardware independent IEEE 802.11
          networking stack.
index 68329d713c02402e53e61f49ed3c24aa6a5d23a7..af96204063218c7d084e82248d488d4b59897660 100644 (file)
@@ -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) ||
            (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_avg = (s8) -ewma_read(&sta->avg_signal);
        }
 
        sinfo->txrate.flags = 0;
index 6289525c09985857b90c3c49930b9cd4f72bc7c4..2fe8f5f86499bc617d98786f3155c9e1e1dfbd81 100644 (file)
@@ -1163,6 +1163,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
        sta->rx_fragments++;
        sta->rx_bytes += rx->skb->len;
        sta->last_signal = status->signal;
+       ewma_add(&sta->avg_signal, -status->signal);
 
        /*
         * Change STA power saving mode only at the end of a frame
index eff58571fd7eb11eef08996c689d605f00585b9a..c426504ed1cfeecddefb3589871668c02448326e 100644 (file)
@@ -244,6 +244,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
        sta->local = local;
        sta->sdata = sdata;
 
+       ewma_init(&sta->avg_signal, 1024, 8);
+
        if (sta_prepare_rate_control(local, sta, gfp)) {
                kfree(sta);
                return NULL;
index 05f11302443b11482d27f010620df023769f5fb7..fdca52cf88de2d57d63821f685d4d78e600006e8 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/types.h>
 #include <linux/if_ether.h>
 #include <linux/workqueue.h>
+#include <linux/average.h>
 #include "key.h"
 
 /**
@@ -223,6 +224,7 @@ enum plink_state {
  * @rx_fragments: number of received MPDUs
  * @rx_dropped: number of dropped MPDUs 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)
  * @tx_filtered_count: number of frames the hardware filtered for this STA
  * @tx_retry_failed: number of frames that failed retry
@@ -291,6 +293,7 @@ struct sta_info {
        unsigned long rx_fragments;
        unsigned long rx_dropped;
        int last_signal;
+       struct ewma avg_signal;
        __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
 
        /* Updated from TX status path only, no locking requirements */
index 56508d40c740cb50acb85eef9d58ca50b00b06f3..2cf03331d4a23d72f1979750ad787debb35743f3 100644 (file)
@@ -1896,6 +1896,9 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
        if (sinfo->filled & STATION_INFO_SIGNAL)
                NLA_PUT_U8(msg, NL80211_STA_INFO_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) {
                txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
                if (!txrate)