All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] d80211: Fix wireless statistics reporting
@ 2007-02-12  3:09 Michael Wu
  2007-02-12  4:09 ` Pavel Roskin
  2007-02-19 20:22 ` Jiri Benc
  0 siblings, 2 replies; 5+ messages in thread
From: Michael Wu @ 2007-02-12  3:09 UTC (permalink / raw)
  To: Jiri Benc; +Cc: linux-wireless

[-- Attachment #1: Type: text/plain, Size: 8235 bytes --]

d80211: Fix wireless statistics reporting

This fixes statistics reporting. It allows drivers to specify what type of
values they support, makes scan results return correct statistics, and
generally fixes the brain damaged statistics reporting code.

Signed-off-by: Michael Wu <flamingice@sourmilk.net>
---

 include/net/d80211.h         |    9 ++++++---
 net/d80211/ieee80211.c       |   18 +++++++++++++++---
 net/d80211/ieee80211_i.h     |    3 ++-
 net/d80211/ieee80211_ioctl.c |   42 ++++++++++++++++++------------------------
 net/d80211/ieee80211_sta.c   |   19 +++++++++++++++++++
 5 files changed, 60 insertions(+), 31 deletions(-)

diff --git a/include/net/d80211.h b/include/net/d80211.h
index 0b7b963..25a4dca 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -230,7 +230,7 @@ struct ieee80211_rx_status {
         int channel;
         int phymode;
         int ssi;
-	int signal;
+	int signal; /* used as qual in statistics reporting */
 	int noise;
         int antenna;
         int rate;
@@ -541,8 +541,11 @@ struct ieee80211_hw {
         /* This is the time in us to change channels
          */
         int channel_change_time;
-	/* This is maximum value for rssi reported by this device */
-	int maxssi;
+	/* Maximum values for various statistics.
+	 * Leave at 0 to indicate no support. Use negative numbers for dBm. */
+	char max_rssi;
+	char max_signal;
+	char max_noise;
 
 	/* Number of available hardware TX queues for data packets.
 	 * WMM requires at least four queues. */
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index c83520e..0e5f23f 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -3334,9 +3334,12 @@ ieee80211_rx_h_sta_process(struct ieee80
 
 	sta->rx_fragments++;
 	sta->rx_bytes += rx->skb->len;
-	sta->last_rssi = rx->u.rx.status->ssi;
-	sta->last_signal = rx->u.rx.status->signal;
-	sta->last_noise = rx->u.rx.status->noise;
+	sta->last_rssi = (sta->last_rssi * 15 +
+			  rx->u.rx.status->ssi) / 16;
+	sta->last_signal = (sta->last_signal * 15 +
+			    rx->u.rx.status->signal) / 16;
+	sta->last_noise = (sta->last_noise * 15 +
+			   rx->u.rx.status->noise) / 16;
 
 	if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) {
 		/* Change STA power saving mode only in the end of a frame
@@ -4624,6 +4627,15 @@ int ieee80211_register_hw(struct ieee802
 
 	local->hw.conf.beacon_int = 1000;
 
+	local->wstats_flags |= local->hw.max_rssi ?
+			       IW_QUAL_LEVEL_UPDATED : IW_QUAL_LEVEL_INVALID;
+	local->wstats_flags |= local->hw.max_signal ?
+			       IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID;
+	local->wstats_flags |= local->hw.max_noise ?
+			       IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID;
+	if (local->hw.max_rssi < 0 || local->hw.max_noise < 0)
+		local->wstats_flags |= IW_QUAL_DBM;
+
 	result = sta_info_start(local);
 	if (result < 0)
 		goto fail_sta_info;
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 3c59a1f..d965704 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -83,7 +83,7 @@ struct ieee80211_sta_bss {
 	int hw_mode;
 	int channel;
 	int freq;
-	int rssi;
+	int rssi, signal, noise;
 	u8 *wpa_ie;
 	size_t wpa_ie_len;
 	u8 *rsn_ie;
@@ -355,6 +355,7 @@ struct ieee80211_local {
 	int open_count;
 	int monitors;
 	struct iw_statistics wstats;
+	u8 wstats_flags;
 
 	struct class_device class_dev;
 
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index fa85fb0..cad4d54 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -1578,6 +1578,7 @@ static int ieee80211_ioctl_giwrange(stru
 				 struct iw_request_info *info,
 				 struct iw_point *data, char *extra)
 {
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct iw_range *range = (struct iw_range *) extra;
 
 	data->length = sizeof(struct iw_range);
@@ -1594,15 +1595,15 @@ static int ieee80211_ioctl_giwrange(stru
 	range->min_frag = 256;
 	range->max_frag = 2346;
 
-	range->max_qual.qual = 100;
-	range->max_qual.level = 146;  /* set floor at -110 dBm (146 - 256) */
-	range->max_qual.noise = 146;
-	range->max_qual.updated = IW_QUAL_ALL_UPDATED;
+	range->max_qual.qual = local->hw.max_signal;
+	range->max_qual.level = local->hw.max_rssi;
+	range->max_qual.noise = local->hw.max_noise;
+	range->max_qual.updated = local->wstats_flags;
 
-	range->avg_qual.qual = 50;
+	range->avg_qual.qual = local->hw.max_signal/2;
 	range->avg_qual.level = 0;
 	range->avg_qual.noise = 0;
-	range->avg_qual.updated = IW_QUAL_ALL_UPDATED;
+	range->avg_qual.updated = local->wstats_flags;
 
 	return 0;
 }
@@ -3052,16 +3053,16 @@ static int ieee80211_ioctl_siwauth(struc
 }
 
 /* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */
-static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *net_dev)
+static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
 {
-	struct ieee80211_local *local = net_dev->ieee80211_ptr;
-	struct iw_statistics * wstats = &local->wstats;
-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(net_dev);
-	struct sta_info *sta;
-	static int tmp_level = 0;
-	static int tmp_qual = 0;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
+	struct iw_statistics *wstats = &local->wstats;
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct sta_info *sta = NULL;
 
-	sta = sta_info_get(local, sdata->u.sta.bssid);
+	if (sdata->type == IEEE80211_IF_TYPE_STA ||
+	    sdata->type == IEEE80211_IF_TYPE_IBSS)
+		sta = sta_info_get(local, sdata->u.sta.bssid);
 	if (!sta) {
 		wstats->discard.fragment = 0;
 		wstats->discard.misc = 0;
@@ -3070,17 +3071,10 @@ static struct iw_statistics *ieee80211_g
 		wstats->qual.noise = 0;
 		wstats->qual.updated = IW_QUAL_ALL_INVALID;
 	} else {
-		if (!tmp_level) {	/* get initial values */
-			tmp_level = sta->last_signal;
-			tmp_qual = sta->last_rssi;
-		} else {		/* smooth results */
-			tmp_level = (15 * tmp_level + sta->last_signal)/16;
-			tmp_qual = (15 * tmp_qual + sta->last_rssi)/16;
-		}
-		wstats->qual.level = tmp_level;
-		wstats->qual.qual = 100*tmp_qual/local->hw.maxssi;
+		wstats->qual.level = sta->last_rssi;
+		wstats->qual.qual = sta->last_signal;
 		wstats->qual.noise = sta->last_noise;
-		wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+		wstats->qual.updated = local->wstats_flags;
 		sta_info_put(sta);
 	}
 	return wstats;
diff --git a/net/d80211/ieee80211_sta.c b/net/d80211/ieee80211_sta.c
index 78d5cf5..fc71cb2 100644
--- a/net/d80211/ieee80211_sta.c
+++ b/net/d80211/ieee80211_sta.c
@@ -1175,12 +1175,20 @@ static void ieee80211_rx_mgmt_assoc_resp
 	/* Add STA entry for the AP */
 	sta = sta_info_get(local, ifsta->bssid);
 	if (!sta) {
+		struct ieee80211_sta_bss *bss;
 		sta = sta_info_add(local, dev, ifsta->bssid, GFP_ATOMIC);
 		if (!sta) {
 			printk(KERN_DEBUG "%s: failed to add STA entry for the"
 			       " AP\n", dev->name);
 			return;
 		}
+		bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
+		if (bss) {
+			sta->last_rssi = bss->rssi;
+			sta->last_signal = bss->signal;
+			sta->last_noise = bss->noise;
+			ieee80211_rx_bss_put(dev, bss);
+		}
 	}
 
 	sta->dev = dev;
@@ -1566,6 +1574,8 @@ static void ieee80211_rx_bss_info(struct
 	bss->timestamp = timestamp;
 	bss->last_update = jiffies;
 	bss->rssi = rx_status->ssi;
+	bss->signal = rx_status->signal;
+	bss->noise = rx_status->noise;
 	if (!beacon)
 		bss->probe_resp++;
 	ieee80211_rx_bss_put(dev, bss);
@@ -2751,6 +2761,15 @@ ieee80211_sta_scan_result(struct net_dev
 					  IW_EV_FREQ_LEN);
 
 	memset(&iwe, 0, sizeof(iwe));
+	iwe.cmd = IWEVQUAL;
+	iwe.u.qual.qual = bss->signal;
+	iwe.u.qual.level = bss->rssi;
+	iwe.u.qual.noise = bss->noise;
+	iwe.u.qual.updated = local->wstats_flags;
+	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+					  IW_EV_QUAL_LEN);
+
+	memset(&iwe, 0, sizeof(iwe));
 	iwe.cmd = SIOCGIWENCODE;
 	if (bss->capability & WLAN_CAPABILITY_PRIVACY)
 		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] d80211: Fix wireless statistics reporting
  2007-02-12  3:09 [PATCH] d80211: Fix wireless statistics reporting Michael Wu
@ 2007-02-12  4:09 ` Pavel Roskin
  2007-02-12  4:29   ` Michael Wu
  2007-02-19 20:22 ` Jiri Benc
  1 sibling, 1 reply; 5+ messages in thread
From: Pavel Roskin @ 2007-02-12  4:09 UTC (permalink / raw)
  To: Michael Wu; +Cc: Jiri Benc, linux-wireless

Hi, Michael!

On Sun, 2007-02-11 at 22:09 -0500, Michael Wu wrote:
> d80211: Fix wireless statistics reporting
> 
> This fixes statistics reporting. It allows drivers to specify what type of
> values they support, makes scan results return correct statistics, and
> generally fixes the brain damaged statistics reporting code.
> 
> Signed-off-by: Michael Wu <flamingice@sourmilk.net>
[skip]
> -	int signal;
> +	int signal; /* used as qual in statistics reporting */

I'm sorry but that the thing I have always hated about wireless
extensions.  Such tricks make the API context sensitive and loaded with
assumptions.

> +	/* Maximum values for various statistics.
> +	 * Leave at 0 to indicate no support. Use negative numbers for dBm. */

That's another context sensitive API.

I've actually worked with the hardware capable of receiving more that 0
dBm (1mW).  It had to be worked around.  Please keep in mind that Linux
is used not only on FCC approved Part 15 devices, but also on embedded
systems operating on licensed frequencies.

"One milliwatt should be enough for everyone" is an approach flawed from
the outset.  It's limiting even for existing equipment running Linux.
One megawatt would be enough though :)

Note that Jean actually added a flag to indicate that a value is in dBm
in the latest versions of Wireless Extensions.

I understand d80211 still has to interact with Wireless Extensions, but
let's not make things even worse.

-- 
Regards,
Pavel Roskin


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] d80211: Fix wireless statistics reporting
  2007-02-12  4:09 ` Pavel Roskin
@ 2007-02-12  4:29   ` Michael Wu
  2007-02-12  4:40     ` Pavel Roskin
  0 siblings, 1 reply; 5+ messages in thread
From: Michael Wu @ 2007-02-12  4:29 UTC (permalink / raw)
  To: Pavel Roskin; +Cc: Jiri Benc, linux-wireless

[-- Attachment #1: Type: text/plain, Size: 1004 bytes --]

On Sunday 11 February 2007 23:09, Pavel Roskin wrote:
> > -	int signal;
> > +	int signal; /* used as qual in statistics reporting */
>
> I'm sorry but that the thing I have always hated about wireless
> extensions.  Such tricks make the API context sensitive and loaded with
> assumptions.
>
Ok, but I was merely clarifying the current situation. That problem has always 
been there since the patch for statistics reporting went in.

> I understand d80211 still has to interact with Wireless Extensions, but
> let's not make things even worse.
I'm making things better. Statistics reporting is pretty bad right now in 
d80211 with drivers reporting bogus values when they don't know, and 
statistics reporting of different d80211 drivers interacting with each other 
when multiple devices are plugged in. This patch attempts to fix the worst 
issues while attempting to avoid regressions. Feel free to follow up with 
another patch to make statistics reporting perfect.

-Michael Wu

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] d80211: Fix wireless statistics reporting
  2007-02-12  4:29   ` Michael Wu
@ 2007-02-12  4:40     ` Pavel Roskin
  0 siblings, 0 replies; 5+ messages in thread
From: Pavel Roskin @ 2007-02-12  4:40 UTC (permalink / raw)
  To: Michael Wu; +Cc: Jiri Benc, linux-wireless

On Sun, 2007-02-11 at 23:29 -0500, Michael Wu wrote:
> On Sunday 11 February 2007 23:09, Pavel Roskin wrote:
> > > -	int signal;
> > > +	int signal; /* used as qual in statistics reporting */
> >
> > I'm sorry but that the thing I have always hated about wireless
> > extensions.  Such tricks make the API context sensitive and loaded with
> > assumptions.
> >
> Ok, but I was merely clarifying the current situation. That problem has always 
> been there since the patch for statistics reporting went in.

Sorry, I should have made it clear that my post was more a reaction to
the comments than to the actual code changes.

> > I understand d80211 still has to interact with Wireless Extensions, but
> > let's not make things even worse.
> I'm making things better. Statistics reporting is pretty bad right now in 
> d80211 with drivers reporting bogus values when they don't know, and 
> statistics reporting of different d80211 drivers interacting with each other 
> when multiple devices are plugged in. This patch attempts to fix the worst 
> issues while attempting to avoid regressions. Feel free to follow up with 
> another patch to make statistics reporting perfect.

This effort is very much appreciated.  I'll have a closer look if I see
any issues after your patch is applied.

-- 
Regards,
Pavel Roskin


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] d80211: Fix wireless statistics reporting
  2007-02-12  3:09 [PATCH] d80211: Fix wireless statistics reporting Michael Wu
  2007-02-12  4:09 ` Pavel Roskin
@ 2007-02-19 20:22 ` Jiri Benc
  1 sibling, 0 replies; 5+ messages in thread
From: Jiri Benc @ 2007-02-19 20:22 UTC (permalink / raw)
  To: Michael Wu; +Cc: linux-wireless

On Sun, 11 Feb 2007 22:09:41 -0500, Michael Wu wrote:
> This fixes statistics reporting. It allows drivers to specify what type of
> values they support, makes scan results return correct statistics, and
> generally fixes the brain damaged statistics reporting code.

Applied, thanks for the patch!

 Jiri

-- 
Jiri Benc
SUSE Labs

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2007-02-19 20:22 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-12  3:09 [PATCH] d80211: Fix wireless statistics reporting Michael Wu
2007-02-12  4:09 ` Pavel Roskin
2007-02-12  4:29   ` Michael Wu
2007-02-12  4:40     ` Pavel Roskin
2007-02-19 20:22 ` Jiri Benc

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.